0%

pwn系列之三

格式化字符串漏洞

常见的字符串函数

  • scanf:从stdin读入
  • printf:输出到stdout
  • fprintf:输出到指定FILE流
  • vprintf:根据参数列表格式化输出到stdout
  • vfprintf:根据参数列表格式化输出到指定FILE流
  • sprintf:输出到字符串
  • snprintf:输出指定字节数到字符串
  • syslog:输出日志

格式化字符串格式

%[parameter][flags][field width][.precision][length]type 具体各参数可见ctfwiki

原理

问题出在格式化字符上,只给函数提供字符串,而不提供其他参数,程序依然会成功运行,函数会将字符串后面的内存当做参数进行输出。若能够写入格式化字符串或者其后的内存,则可泄露、修改相应的内存空间,完成攻击。

利用

  • 程序崩溃:输入若干个%s即可,但这样仅能造成程序不可用而无法达到攻击的目的。
  • 泄露内存:利用%n$x来获取栈中被视为第n+1个参数的值(或用%p);利用%n$s来获取指定参数对应地址的内容
  • 覆盖内存

小提示

可使用pwntools自带的FmtStr以及fmtstr_payload函数,示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- coding: utf-8 -*-

from pwn import *

# context.log_level = 'debug'

def exec_fmt(payload):
p = process("./format")
p.sendline(payload)
info = p.recv()
p.close()
return info

autofmt = FmtStr(exec_fmt)
print autofmt.offset

以及
payload = fmtstr_payload(autofmt.offset, {printf_got: system_add}),其中第一个参数为offset偏移,第二个参数是一个字典,意义是往printf函数的地址,写入system的地址。

https://paper.seebug.org/246/