来源:心路

Crack_MySQL.def


LIBRARY    "Crack_MySQL"
EXPORTS
    GetPluginInfo
    PluginFunc
[、code]

Crack_MySQL.cpp

#include "D:\MySQL\include\mysql.h"

#ifdef __cplusplus
    extern "C" {
#endif // __cplusplus

#include "XScanLib\XScanLib.h"

#ifdef __cplusplus
    }
#endif // __cplusplus

extern "C" __declspec(dllexport) BOOL __stdcall GetPluginInfo(PLUGIN_INFO *);
extern "C" __declspec(dllexport) BOOL __stdcall PluginFunc (VOID *);
extern "C" DWORD WINAPI CrackMySQL (VOID *);
extern "C" DWORD WINAPI CheckPort ( char *Host, int Port );

#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "XScanLib\XScanLib.lib")
#pragma comment( lib, "D:\MySQL\lib\opt\libmysql.lib" )

#define    VULN_MEMBER_NAME    "MySQL弱口令"
#define    CHECKING_STRING        "正在猜解MySQL数据库口令..."
#define VERSION                "0.1"
#define    CMD_PARMAS            "-mysql"
#define    PROMPT                "检测MySQL数据库弱口令"
#define    AUTHOR                "云舒"
#define    DESCRIPTION            "这个插件通过字典猜解MySQL数据库的脆弱密码"
#define    TIMEOUT                0
#define    ICON                "www.bmp"
#define FILENAME            "Crack_MySQL.xpn"

#define    MYSQL_PORT            3306
#define    DB_NAME                "mysql"

BOOL APIENTRY DLLMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
    return TRUE;
}

BOOL __stdcall GetPluginInfo (PLUGIN_INFO *Info)
{
    // 设置插件信息
    strcpy( Info->szClassName, VULN_MEMBER_NAME );
    strcpy( Info->szMemberName, VULN_MEMBER_NAME );
    strcpy( Info->szVersion, VERSION );
    strcpy( Info->szFileName, FILENAME );
    strcpy( Info->szParamsRequest, CMD_PARMAS );
    strcpy( Info->szPrompt, PROMPT );
    Info->nSingle = 1;
    strcpy( Info->szAuthorName, AUTHOR );
    strcpy( Info->szDescription, DESCRIPTION );
    Info->dwTimeOut = TIMEOUT;
    Info->nMark = 1;
    strcpy( Info->szImageFile, ICON );

    return TRUE;
}

BOOL __stdcall PluginFunc( VOID *Parm )
{
    int VulnNumber = 0;

    if( !PlugInitLib((struct arglist *)Parm) )
    {
        return FALSE;
    }

    PlugSetVulnNum( (struct arglist *)Parm, 0 );

    PlugSetCurrentSchedule( (struct arglist *)Parm, CHECKING_STRING );

    // 加入到线程池
    PlugAddThread( (struct arglist *)Parm, CrackMySQL, Parm, TIMEOUT );

    PlugWaitThread( (struct arglist *)Parm );

    VulnNumber = PlugGetVulnNum( (struct arglist *)Parm );

    return VulnNumber > 0 ? TRUE : FALSE;
}

DWORD WINAPI CrackMySQL( void * Parm )
{
    char    Host[256] = { 0 };
    char    LogType[8] = { 0 };
    int        Verbose = 0;
    char    Message[128] = { 0 };
    int        PortState = -1;

    FILE    *UserFile = NULL;
    FILE    *PassFile = NULL;
    char    TestUser[32] = { 0 };
    char    TestPass[32] = { 0 };

    MYSQL    Mysql;

    struct arglist    *MyArgList = (struct arglist *)Parm;

    // 获取扫描参数
    strncpy( Host, (char *)PlugGetParams(MyArgList, "HostName"), 255 );
    strncpy( LogType, (char *)PlugGetParams(MyArgList, "LogType"), 7 );
    Verbose = (int)PlugGetParams(MyArgList, "ShowVerbose");

    PlugSetCurrentSchedule( MyArgList, CHECKING_STRING );
 
    PortState = CheckPort( Host, MYSQL_PORT );

    // 端口没开放
    if( PortState <= 0 )
    {
        return 0;
    }

    if( !Verbose )
    {
        PlugAlertUser ( MyArgList, AT_NORMAL, CHECKING_STRING );
    }

    // 打开字典
    UserFile = fopen( "dat\mysql_user.dic", "r" );
    if( UserFile == NULL )
    {
        PlugAlertUser( MyArgList, AT_ERROR, "打开mysql_user.dic失败……" );
        return 0;
    }

    PassFile = fopen( "dat\mysql_pass.dic", "r" );
    if( PassFile == NULL )
    {
        PlugAlertUser( MyArgList, AT_ERROR, "打开mysql_pass.dic失败……" );
        return 0;
    }

    char    *p = NULL;

    while( !feof( UserFile ) )
    {
        fgets( TestUser, 31, UserFile );

        while( !feof( PassFile ) )
        {
            fgets( TestPass, 31, PassFile );

            if( 0 == strnicmp( TestPass, "%null%", 6 ) )
            {
                memset( TestPass, 0, sizeof(TestPass) );
            }
            else if( NULL != (p = strstr(TestPass, "%username%"))  )
            {
                // %username%123
                if( 0 == p - TestPass )
                {
                    char    TmpStr[32] = { 0 };
 
                    sprintf( TmpStr, "%s%s", TestUser, TestPass + strlen("%username%") );

                    memset( TestPass, 0 , sizeof(TestPass) );

                    strcpy( TestPass, TmpStr );
                }

                // 123%username%456 or 123%username%
                else if( 0 < p - TestPass )
                {
                    char    TmpStr[32] = { 0 };
 
                    // 这里有个溢出,懒得改了
                    strncpy( TmpStr, TestPass, p - TestPass );
                    strcat( TmpStr, TestUser );
                    strcat( TmpStr, p + strlen("%username%") );

                    memset( TestPass, 0 , sizeof(TestPass) );
                    strcpy( TestPass, TmpStr );
                }

            }

            if( TestUser[strlen(TestUser)-1] == '\n' )
            {
                TestUser[strlen(TestUser)-1] = '';
            }

            if( TestPass[strlen(TestPass)-1] == '\n' )
            {
                TestPass[strlen(TestPass)-1] = '';
            }

            if( Verbose )
            {
                if( 0 == strlen(TestPass) )
                {
                    sprintf( Message, "正在猜解MySQL数据库密码:%s/%s", TestUser, "空口令" );
                }
                else
                {
                    sprintf( Message, "正在猜解MySQL数据库密码:%s/%s", TestUser, TestPass );
                }

                PlugAlertUser( MyArgList, AT_NORMAL, Message );
            }

            mysql_init( &Mysql );

            if( mysql_real_connect( &Mysql, Host, TestUser, TestPass, DB_NAME, MYSQL_PORT, 0, NULL ) )
            {
                memset( Message, 0, sizeof(Message) );
                if( 0 == strlen(TestPass) )
                {
                    memset( TestPass, 0, sizeof(TestPass) );
                    strcpy( TestPass, "空口令" );
                }
                sprintf( Message, "MySQL弱口令:\n帐户:%s\n密码:%s", TestUser, TestPass );
                PlugLogToFile( MyArgList, "3306/TCP", "HOLE", Message );

                PlugAddVulnNum( MyArgList );

                memset( Message, 0, sizeof(Message) );
                sprintf ( Message, "%s\n%s\n%s/%s\n", Host, VULN_MEMBER_NAME, TestUser, TestPass );
                PlugAddToTV ( Message, ICON );
            }

            mysql_close( &Mysql );
        }
    }
    return 0;
}

DWORD WINAPI CheckPort ( char *Host, int Port)
{
    SOCKET        sock;
    SOCKADDR_IN    sin;

    memset( &sin, 0, sizeof(SOCKADDR_IN) );

    sin.sin_family = AF_INET;
    sin.sin_port = htons( Port );

    if( inet_addr( Host ) != INADDR_NONE )
    {
        sin.sin_addr.s_addr = inet_addr( Host );
    }        
    else
    {
        struct hostent    *phost = gethostbyname( Host );

        if( phost == NULL )
        {
            return -1;
        }
        memcpy( &sin.sin_addr , phost->h_addr_list[0] , phost->h_length );
    }

    // 建立socket失败则返回端口开放,等待mysql api直接连接,减少漏报
    sock = socket( AF_INET, SOCK_STREAM, 0 );
    if( sock == INVALID_SOCKET )
    {
        return 1;
    }

     int state = connect( sock , (struct sockaddr *)&sin , sizeof(sin) );
     if( state == SOCKET_ERROR )
     {
         return -1;
     }
     else
     {
         return 1;
     }
}