格式化字符串漏洞学习汇总笔记
久仰”系统实战篇”,最近终于拜读了这本神作,在格式化串漏洞部分令我受益良多
前言
格式化字符串的格式如下:
%[parameter][flags][field width][.precision][length]type
知道漏洞怎么利用的第一步当然是知道漏洞是怎么发生的:
- 使用格式化字符串的函数有:
1 |
|
格式化符:
整数:
%d,%i,%u,%o,%x
浮点数:
%e,%f,%g,%a
字符:
%c
特殊字符:
%s: 视为指向字符串的指针,以字符串的形式输出参数 %n: 视为指向整数的指针,于参数前输出的字符数量将存于所指向的地址
小技巧:
1. 使用%p获取对应栈内存 2. 使用%s获取变量所对应的地址内容(有00截断) 3. %order$x(s)来直接读取对应参数
利用所需满足的条件:
- 可控制参数,并可以将输出字符写入任意区域
- 宽度格式字符允许用任意长度填充输出,因此可以修改单字节
一些有意思的地址:
- 保存的返回地址
- 全局偏移表GOT
- 析构函数表
- C函数库钩子(malloc_hook,realloc_hook,free_hook)
- atexit结构
- 函数指针 : c++ vtables,回调函数
利用姿势
- 改写保存的返回地址
- 改写其他函数指针
- 改写指向异常处理的指针,然后引起异常
- 改写GOT条目
- 改写atexit处理程序
- 改写DTORS区段的条目
- 用非i空数据改写空值终止符,将其转化为堆/栈溢出
- 改写特殊数据,如(uid或gid)
- 修改字符串中包含的命令反映所选命令
- 泄露内存
- 栈内存:
- 某变量对应内存
- 某个变量对应地址的内存
- 泄露任意地址内存:
- 利用GOT表得到libc基地址
- 栈内存:
如果程序开启了NX保护,可以先利用%n类格式符,将shellcode写至内存地址;
也可以先写一个小的shellcode来寻找一大片可以写入的shellcode然后利用
辅助利用模块(pwntools)
pwntools的pwnlib.fmtstr模块提供了一些格式化字符串漏洞的相关利用工具:1
class pwnlib.fmtstr.FmtStr(execute_fmt, offset=None, padlen=0, n umbwritten=0)
各参数意义如下:
- execute_fmt (function):与漏洞进程进行交互的函数
- offset (int):所控制的第一个格式化程序的偏移量
- padlen (int):在 paylod 之前添加的 pad 的大小
- numbwritten (int):已经写入的字节数
还有自动生成payload的fmtstr_payload
1 |
|
其中各参数意义如下:
- offset (int):所控制的第一个格式化程序的偏移量
- writes (dict):格式为 {addr: value, addr2: value2},用于往 addr 里写入 value的值
- numbwritten(int): 已经由 printf 函数写入的字节数
- write_size (str):必须是 byte,short 或 int。告诉你是要逐 byte 写,逐 short 写还是逐 int 写(hhn,hn或n)
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!