1. 程式人生 > >ROP_chains demo code No.1

ROP_chains demo code No.1

    gadgets 為小裝置它代表著鏈上所需要的各個組成部分,ROP_chains 是利用棧與 RETN 的特性工作的,但有一點就是說用於攻擊目的 rop_chains 裡面的各個小裝置,攻擊者會想辦法的從各個版本的作業系統已知公共的DLL庫中提出來(指向程式碼的公共基址幾乎是等同的),這個東西你可以稱呼它為 “返回導向”

refer-originl:https://blog.csdn.net/liulilittle/article/details/80959798

    下面的 demo 程式碼演示了具體的過程,但顯然這個與真實應用到攻擊上是不完全的,同時由於是自定義的程式程式碼它主要是用於表明 ROP_chinas 攻擊是如何進行工作的,但它並不起到實際的攻擊目的。

注執行以下的程式碼,最好是除錯環境下會比較直觀另一點就是說,DEP(執行資料保護)的開關是可以忽略的,ROP_chains 最大的優點就是繞過 DEP,顯然你關閉了 DEP 那麼測試以下程式碼的意義就不存在了。

同時這個 ROP_chains 比較簡單,它僅僅只是呼叫一個 MessageBoxA 的函式列印一個 “bac” 的字串,當客戶關閉了資訊框時呼叫 exit 函式,退出當前的程序(當然在真實攻擊的情況下都會想辦法的讓受攻擊程式不被中止,呼叫 ShellExecuteA 這一類函式執行 net user xxx 的類似命名改掉目標主機的登陸使用者密碼,或者編寫重量級的 shellcode 在目標的程式中偵聽埠或者注入木馬後門)當然本人不是在教你搞壞事,因為我只是一名菜鳥,我們瞭解這些東西僅僅只是為了讓我們在設計系統的時候儘可能兼顧考量這些問題。

#include <stdio.h>
#include <windows.h>

void def_gadgets_1(void) 
{
    _asm
    {
        pop esi
        ret
    }
}

void def_gadgets_2(void)
{
    _asm
    {
        mov eax,esp
        add eax,4
        ret
    }
}

void def_gadgets_3(void)
{
    _asm
    {
        push '\0'
        push eax
        push eax
        push '\0'
        call esi
        pop esi
        ret
    }
}

char* get_gadgets_ptr(void* f)
{
    unsigned char* p = f;
    if (*p == 0xE9)
    {
        p += (5 + *(int*)(p + 1));
    }
    while (1)
    {
        if (*p++ == 0xC3) return p;
    }
}

int main(int argc, char* argv[])
{
    void* gadgets[] = 
    {
        get_gadgets_ptr(&def_gadgets_1) - 0x02,
        get_gadgets_ptr(&def_gadgets_2) - 0x06,
        get_gadgets_ptr(&def_gadgets_3) - 0x0A,
    };
    void* ebpplus4addr = NULL;
    _asm
    {
        lea eax,dword ptr[ebp+4]
        mov dword ptr[ebpplus4addr],eax
    }
    UINT32 shellcode[5];
    shellcode[0] = gadgets[0];
    shellcode[1] = &MessageBoxA;
    shellcode[2] = gadgets[1];
    shellcode[3] = gadgets[2];
    shellcode[4] = '\0' << 0x18 | 'c' << 0x10 | 'a' << 0x08 | 'b';
    shellcode[5] = &exit;

    memcpy(ebpplus4addr, shellcode, sizeof(shellcode));
}