fmt格式化字符串漏洞总结

本文章适合写题时帮助快速回忆,不适合初学者

泄露数据

泄露栈上数据

直接用下面这种形式,n代表想要泄露的地址是printf的第几个参数。$后面代表输出的格式。

%n$x

泄露任意地址数据

64位的程序,printf的前六个参数是寄存器,第七个参数是下图中框起来的位置

那么由于我们可以控制该格式化字符串,我们首先要弄清楚格式化字符串是第几个参数。可以先用输入%p%p%p的方法。

由于地址中末尾肯定是有0,所以下面这种写法是不可取的(也就是ctfwiki上的写法)。因为解析到\x00,程序就会以为字符串结尾了,就不会向下解析了。

addr%k$s

比如如果格式化字符串是第八个参数,那么我们应该这么写:

%9$saaaa+p64(addr)   //四个a是用来占位的,让addr成为第九个参数

任意地址写

覆盖内存用到的是这个:

%n,不输出字符,但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量。

覆盖栈内存

要确定要覆盖的地址,并且这种方法只适合要修改成比较小的数字才管用。

.......addr%k$n

覆盖任意地址内存

直接用pwntools提供的fmstr_payload工具

fmtstr_payload(格式化字符串的偏移, {要覆盖的地址: 覆盖成的值})

pwnlib.fmtstr模块

#用FmtStr类获取`格式化字符串`在printf函数中的参数位置(偏移)

测试函数,用来获取`格式字符串`在printf函数里参数的顺序
'''
def exec_fmt(payload):
    p   = process("./overflow")
    p.recvuntil('\n',drop=True)
    p.sendline(payload)
    return p.recv()

if __name__ == '__main__':
    print("准备泄漏出(格式化字符串)在printf函数参数中的位置:")
    auto_fmtstr = FmtStr(exec_fmt)
    print("(格式化字符串)在printf函数中参数的位置是:{0}".format(auto_fmtstr.offset)

### 格式化字符串漏洞原理 格式化字符串漏洞源于C语言中的`printf`, `sprintf`, 和`sprintfn`等函数处理不当。这些函数用于将数据按照指定的格式转换为字符串并输出或存储。当程序员错误地直接传递用户可控的数据作为格式说明符而非实际参数时,攻击者可以控制程序的行为。 例如,在正常情况下应该这样调用`printf`: ```c char *pad = "Hello, world!"; printf("%s", pad); ``` 但如果简化为了: ```c printf(pad); // 这里假设pad是由外部输入控制的内容 ``` 那么如果`pad`包含了格式字符(如 `%x`, `%p`),这就会导致未预期的结果,可能泄露内存地址或其他敏感信息甚至执行任意代码[^2]。 ### 防御措施 针对上述风险,有几种有效的防御手段: #### 输入验证与过滤 对于任何来自用户的输入都应严格校验其合法性,并去除潜在危险字符。特别是要防止未经检查的数据被当作格式串的一部分传入标准库函数中去。 #### 使用更安全的API替代品 现代编程实践中推荐采用更为健壮的方法来进行字符串操作,比如使用带有固定数量参数版本的函数或是其他高级别的封装接口,它们能够更好地抵御此类攻击向量。 - C++ 中可以用 `std::format()` 或第三方库 fmtlib 来代替传统的 printf 家族成员; ```cpp #include <fmt/core.h> // ... auto message = fmt::format("{}", user_input); ``` - Python 用户则可以选择内置 f-string 表达式或者模板引擎来构建动态文本片段; #### 编译器选项加固 启用编译期警告以及运行时期检测机制可以帮助识别和阻止一些常见的编码失误。GCC/Clang 提供了 `-Wformat-security` 开关用来标记可疑语句,同时链接阶段也可以加入特定的安全增强特性 (SSP Stack Smashing Protector) 加强堆栈保护力度。 通过以上多方面努力,可以在很大程度上降低遭遇格式化字符串漏洞的风险,保障软件产品的稳定性和安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值