63

PWN中格式化字符串漏洞

 3 years ago
source link: https://fl4g.cn/2020/09/03/PWN中格式化字符串漏洞/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

哈哈哈,太懒了,时隔一年半又来更新博客了。

by22Qrz.jpg!mobile

0x01 漏洞原理

最近做pwn的练习,发现格式化字符串漏洞会经常遇到,不太理解,只能抽出时间来研究一下这古老的漏洞。

首先,我们来看一下常见的样式,(题目为“攻防世界”的string)ida反编译后在某个函数中看到如下的代码:

Jry2Y3n.png!mobile

通常使用printf函数,根据cdcel调用约定,从右到左逐个压栈,如果传入字符串,则压入该字符串指针。由于printf无法知道被调用之前有多少参数被压入栈中,所以需要使用format参数用以指定到底有多少参数。

format类型

参数 表示 %d 表示输出十进制整数 %n 输出所有打印的字符数 %x 输出十六进制数 %s 从内存中读取字符串 %p 显示一个指针

# 特性一: printf()函数的参数个数不固定

当我们写作printf(str)时,此时参数可控,我们在控制了format参数之后结合printf()函数的特性就可以进行相应的攻击。

当我们输入format参数大于存在参数时,printf会读取内存内的数据,如图

e2A7Bn.jpg!mobile

此时我们只有3个参数,而我们使用printf(“%s %d %d %d %x\n”,buf,a,b,c)读取时,需要读取4个数据,此时便会读取到下一个地址的内容。

以下例进行分析

#include <stdio.h>
int main(int argc, char *argv[])
{
    char str[200];
    fgets(str,200,stdin);
    printf(str);
    return 0;
}

当我们在fgets时输入AAAA%08x%08x%08x%08x%08x%08x(%08x为格式化为8位16进制数,左对齐,空位补0),调用printf时输出数值时便会读取到内存中的0x41414141(A的16进制为0x41),输出结果为AAAA000000c8b7fc1c20b7e25438080482100000000141414141。

如果我们将AAAA修改为某一敏感地址,使用%s读取地址里面的数据,如读取0x41414141地址的数据 \x41\x41\x41\x41%08x%08x%08x%08x%08x%s

# 特性二:利用%n格式符写入数据

%n的作用是把前面已经打印的长度写入某个内存地址,(同一个printf中的输出长度)

如下代码

#include <stdio.h>
main()
{
  int num=66666666;

  printf("Before: num = %d\n", num);
  printf("%d%n\n", num, #);
  printf("After: num = %d\n", num);

}

此时%n成功修改了num的值,输出结果为:

Before: num = 66666666
66666666
After: num = 8

# 特性三:自定义打印字符串宽度

此时我们修改 printf("%d%n\n", num, &num);printf("%100d%n\n", num, &num); 时,最终num输出为100。若改为%.100d或%0100d,则会在6之前输出92个0。

当我们要把0x8048000地址写入内存时,此时,我们可以使用如下方式

printf("%.134512640d%n\n", num, #);
printf("After: num = %x\n", num);

此外还需要$的配合,如下的代码

printf("7th: %7$d, 4th: %4$05d\n", 10, 20, 30, 40, 50, 60, 70, 80);

会打印输出

7th: 70, 4th: 00040

即%7$d 获取的将是参数列表中第7个元素的值,%4$05d 获取的是第四个参数的值,且有效位长度是5。

0x02 其他相关

在Stack中Canary found绕过问题:

系统产生一个随机数,在程序开始和结尾时会进行检查,如果发生改变就会抛出异常。

MnY7NfA.jpg!mobile

某些题目需要将其先泄漏出来,再填充到结束的位置


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK