0day安全:軟體漏洞分析技術 第二章 棧溢位原理及實踐
_stdcall呼叫約定下,函式呼叫時用到的指令序列大致如下:
push 引數3
push 引數2
push 引數1
call 函式地址;a)向棧中壓入當前指令在記憶體中的位置,即儲存儲存返回地址。
b)跳轉到所呼叫函式的入口
push ebp 儲存舊棧幀的底部
mov ebp,esp 設定新棧幀的底部(棧幀切換)
sub esp,xxx 設定新棧幀的頂部(擡高棧頂,為新棧幀開闢空間)
函式呼叫時系統棧的變化過程
2.2修改臨近變數
#include <stdio.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
int authenticated;
char buffer[8];// add local buff
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);//over flowed here!
return authenticated;
}
main()
{
int valid_flag=0;
char password[1024];
while(1)
{
printf("please input password: ");
scanf("%s",password); valid_flag = verify_password(password); if(valid_flag) { printf("incorrect password!\n\n"); } else { printf("Congratulation! You have passed the verification!\n"); break; } }
}
動態除錯分析:
進入該函式verify_password前:
此時的棧截圖:
步入
進入strcmp前
進入strcpy前
步過strcpy之後
win32記憶體
記憶體資料與數值資料
記憶體中由低位到高位儲存,但是作為數值應用時,按照高位到低位進行解釋
輸入8個字元且ASCII值比1234567就可過掉驗證
2.3修改函式返回地址
#include <stdio.h>
#define PASSWORD "1234567"
int verify_password (char password)
{
int authenticated;
char buffer[8];
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);//over flowed here!
return authenticated;
}
main()
{
int valid_flag=0;
char password[1024];
FILE
if(!(fp=fopen("password.txt","rw+")))
{
exit(0);
}
fscanf(fp,"%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("incorrect password!\n");
}
else
{
printf("Congratulation! You have passed the verification!\n");
}
fclose(fp);
}
最後四位元組是修改的返回地址,這個地址就是成功初地址
程式碼植入
彈個MessageBoxA
兩個地址需要從本機上查出來修改