1 // stack_overflow.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include <string.h> //strcmp、strcpy 6 #include <STDIO.H> //printf 7 #include <conio.h> //getch 8 //全局变量保存真码 9 #define PASSWORD "1234567" 10 //密码验证函数 11 int verify_password(char *password) 12 { 13 int authenticated; //保存验证结果 14 char buffer[8]; 15 authenticated = strcmp(password,PASSWORD); //真码与假码的比较 16 strcpy(buffer,password); //将输入的假码放入缓冲区 17 return authenticated; //返回结果 18 } 19 20 int main(int argc, char* argv[]) 21 { 22 int valid_flag= 0; 23 char password[1024]; 24 while(1) 25 { 26 printf("please input password: "); 27 scanf("%s",password); 28 valid_flag = verify_password(password); 29 if (valid_flag) 30 { 31 printf("incorrect password!\n\n"); 32 } 33 else 34 { 35 printf("Congratulation!You have passed the verification!\n"); 36 break; 37 } 38 } 39 getch(); 40 return 0; 41 } 42
对应的反汇编程序:
1 00401070 >/$ 81EC 00040000 sub esp, 400 ; _main 2 00401076 |> 68 88804000 /push offset <InputInfo> ; ASCII "please input password: " 3 0040107B |. E8 67000000 |call <_printf> 4 00401080 |. 8D4424 04 |lea eax, dword ptr [esp+4] 5 00401084 |. 50 |push eax 6 00401085 |. 68 84804000 |push offset <InputFormat> ; ASCII "%s" 7 0040108A |. E8 41000000 |call <_scanf> 8 0040108F |. 8D4C24 0C |lea ecx, dword ptr [esp+C] 9 00401093 |. 51 |push ecx 10 00401094 |. E8 67FFFFFF |call <func_verify_password> 11 00401099 |. 83C4 10 |add esp, 10 12 0040109C |. 85C0 |test eax, eax 13 0040109E |. 74 0F |je short 004010AF 14 004010A0 |. 68 6C804000 |push offset <BadInfo> ; ASCII "incorrect password!",LF,LF 15 004010A5 |. E8 3D000000 |call <_printf> 16 004010AA |. 83C4 04 |add esp, 4 17 004010AD |.^ EB C7 \jmp short 00401076 18 004010AF |> 68 38804000 push offset <GoodInfo>
; ASCII "Congratulation!You have passed the verification!",LF 19 004010B4 |. E8 2E000000 call <_printf> 20 004010B9 |. E8 68580000 call <__getch> 21 004010BE |. 33C0 xor eax, eax 22 004010C0 |. 81C4 04040000 add esp, 404 23 004010C6 \. C3 retn 24 25
当输入异常时,就会出现:
然而,仅仅覆盖所需的结果不只是我们需要的,有时候我们更希望能覆盖返回地址。
这样,我们就可以跳转到程序的其它地方去执行我们希望的代码。
在这之前,我们先看看返回地址的位置和其中的数据是什么。
verify_password函数的下一行代码,就是这个。
我们的目标是淹没这个地址,使其指向我们希望的地址。
由于我们输入的字符,始终有一些缺憾,不能直接输入对应的数值使其指向我们希望的地方,所以下次我们构造一个使用文件类型的漏洞来进行
利用演示。