pwn初识格式化字符串漏洞

格式化字符串漏洞通常情况下是由printf函数产生的;

正常情况下我们用printf函数输出字符串时是这样的:

char a[100]="fmtstr";
int b=12,c=666;
printf("%s %d %x",a,b,c);

但是有时是出于方便会直接输出字符串:

char str[12]="fmtstr";
printf(str);

这时,如果这个str是我们用户输入可控的,那么这就存在了一个格式化字符串漏洞,这时攻击者将有机会对任意内存地址进行读写操作;

printf的读写操作:

 

我们都知道printf函数可以打印出一段内容,比如:

printf("%d",a); //打印一个整型a
printf("%s",b); //打印一个字符串b
printf("%c",c); //打印一个字符c
printf("%x",d); //以十六进制数的格式打印d

但是printf里面还有一个%n的格式可以用来对一段地址写值;

#include
int main()
{
        int a,b,c;
        printf("ABC%nEFG%n\n",&a,&b);
        printf("%123c%n\n",'a',&c);
        printf("a=%d b=%d c=%d\n",a,b,c);
        return 0;
}

输出结果:a=3 b=6 c=123

我们并没有对a,b,c进行初始化和赋值,但我们通过%n来写入了一个值,这就是printf写的操作,具体的还可以往某一个字节写值(%hnn);

危害:

用一个简单的列子来说明:

#include     
int main()            
{                     
        char str[100];  
        scanf("%s",str); //用户可控的字符串
        printf(str);    //格式化字符串漏洞
        printf("\n"); 
        return 0;     
}                     

如果我们将我们输入一些特殊的字符串比如%x会怎么样呢;

我们发现,它将栈中的数据打印出来了,而我们输入的第一个数据在第6个;

如果我们将我们输入是‘aaaa'换成某一个地址,然后找到它在栈中的位置,我们是不是就可以获得一些敏感信息了呢,

比如我们可以打印出开了canary的cookie,某一个函数在got表中的地址然后找到函数的真实的地址,然后减去偏移获得基地址;

具体的方法我们在另外一篇中,用一个具体的列子来讲。。。。。

# 格式参数详解

%a             浮点数、十六进制数字和p-记数法(C99)
%A    浮点数、十六进制数字和p-记法(C99)
%c     一个字符(char)

%C           一个ISO宽字符

%d    有符号十进制整数(int)(%e    浮点数、e-记数法
%E    浮点数、E-记数法
%f     单精度浮点数(默认float)、十进制记数法(%.nf  这里n表示精确到小数位后n位.十进制计数)

%g    根据数值不同自动选择%f或%e.
%G    根据数值不同自动选择%f或%e.
%i              有符号十进制数(与%d相同)
%o    无符号八进制整数
%p      指针
%s     对应字符串char*(%S             对应宽字符串WCAHR*(%u      无符号十进制整数(unsigned int)
%x    使用十六进制数字0f的无符号十六进制整数 
%X      使用十六进制数字0f的无符号十六进制整数
%%     打印一个百分号

你可能感兴趣的:(Pwn,CTF)