16 Bytes Stack Alignment 的 MOVAPS 問題

by iok
4.4K 人次瀏覽

這篇是讀書筆記,不是教學文。

最近跟著台科大資安社的線上社課 PWN 學習。在 x64 CPU Linux 環境下,引用 pwntools 模組撰寫 Python exploit 程式,進行經典的緩衝區溢位( Stack Based Buffer Overflow )攻擊。

在 exploit 程式執行呼叫 interactive()函式,要拿 shell 的時候 ,出現下述的錯誤訊息。

[*] Got EOF while reading in interactive

雖然 exploit 程式最後仍有出現 $ 字符號,但是輸入任何 Linux 指令都無反應,表示攻擊失敗。

但 exploit 程式寫法沒有問題。使用 GDB 進行除錯,發現是 system() 函式所執行的一行組語,產生 segmentation fault 錯誤,進而程式執行錯誤。

 → 0x7fd8bd24ffbc <do_system+364>  movaps XMMWORD PTR [rsp+0x50], xmm0

查到這篇 ROP Emporium – Beginners’ guide ,在 The MOVAPS issue 章節說明到。這是 glibc 預設的 stack alignment 造成的問題,在 Return Oriented Programming 的攻擊常遇到,尤其是要呼叫 system() 函式的時候。

在 64 bits 環境下,有些 glibc 版本會預設 stack 位址 要對齊 16 bytes,意即 rsp 的值要能被 16 整除 ,rsp 最後一碼必須為 0。

在 gcc man page的 -mpreferred-stack-boundary 參數有說明預設的 stack boundary 是 16 bytes,資料如下:

-mpreferred-stack-boundary=num
Attempt to keep the stack boundary aligned to a 2 raised to num byte boundary. If -mpreferred-stack-boundary is not specified, the default is 4 (16 bytes or 128-bits).


Warning: If you use this switch, then you must build all modules with the same value, including any libraries. This includes the system libraries and startup modules.

程式一開始執行時,rsp 位址是在 0x00007ffd1c7f0f40,還有對齊 16 bytes 。

0x00007ffd1c7f0f40│+0x0000: 0x61617ffd1c7f1040   ← $rsp
0x00007ffd1c7f0f48│+0x0008: "aaaaaaaa"
0x00007ffd1c7f0f50│+0x0010: 0x0000000000000000   ← $rbp

進行 Stack Buffer Overflow成功控制 return 位址,呼叫到 do_system() 時,rsp 位址在 0x00007fffa0ac5468,已經沒有對齊 16 bytes了。

解法就是,設計溢位堆疊時,返回呼叫 backdoor() 函式前,多呼叫一次其他位址的ret ,讓 rsp 位址能減 8。

原本 payload 寫法:

payload = b'b' * 10
payload += p64(rbp)
payload += p64(backdoor) 

寫法改成:

payload = b'b' * 10
payload += p64(rbp)
payload += p64(ret_addr)
payload += p64(backdoor)

ret_addr 使用位址我是拿 init() + 70 的位址( 0x120f ),透過 objdump 指令得知。程式中其他的 ret 位址也都能使用。

00000000000011c9 <init>:
...
120e:  5d      pop    rbp
120f:  c3      ret    

安排 Stack 先返回 <init+70> 的位址,再返回 backdoor() 函式。返回前的 rsp 位址在 0x00007ffe5e388d58 (沒有對齊),Stack 與 Debug 視窗截圖如下:

自 <init+70> 準備返回 backdoor() 函式,rsp 位址是 0x00007ffe5e388d60,已對齊 16 bytes,並且成功獲得 /bin/sh。

參考資料

  • https://www.reddit.com/r/ExploitDev/comments/i5beqt/error_got_eof_while_reading_in_interactive_in/
  • https://ropemporium.com/guide.html
  • https://www.cameronwickes.com/stack-alignment-ubuntu-18-04-movaps/
  • https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40838
  • https://research.csiro.au/tsblog/debugging-stories-stack-alignment-matters/
  • man gcc

留言