cstar

eli's docs

   :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

修改邻接变量的方法对代码环境限制比较多,更通用、更强大的方法是修改 EBP、返回地址等状态值。

 

为了方便调试,修改之前的代码如下:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 
 5 #define PASSWORD "1234567"
 6 
 7 int verify_password(char *password)
 8 {
 9     int authenticated=0x03050709;
10     char buffer[8];     // add local buf to be overflowed
11     authenticated=strcmp(password,PASSWORD);
12     strcpy(buffer, password);  // overflow here
13     return authenticated;
14 }
15 
16 int main()
17 {
18     int valid_flag=0;
19     char password[1024];
20     if(!freopen("password.txt","r",stdin)) // 非打印字符不便于从console输入,故 redirect stdin
21     //FILE *fp;
22     //if(!(fp=fopen("password.txt","rw+")))
23     {
24         printf("file open error!\n");
25         exit(0);
26     }
27     scanf("%s",password);
28     //fscanf(fp,"%s",password);
29     printf("password input: %s\n",password);
30     valid_flag=verify_password(password);
31     if(valid_flag){
32         printf("Incorrect password!\n\n");
33     }
34     else
35     {
36         printf("Congratulation! You have passed the verification!\n\n");
37     }
38     //fclose(fp);
39     return 0;
40 }

 

在 password.txt 中存储内容为 abcdefg 时,OD 调试 exp_me.exe,执行完第 12 行 strcpy 后的栈帧如下图所示:

如上图,此时栈帧中 authenticated 的值(0x0012FAE8)为 1,表示验证未通过。EBP : 0x0012FAEC,前栈帧 EBP : 0x0012FF48,返回地址 : 0x0040ECD8。

 

 1 0040ECCC  |. 8D95 FCFBFFFF     LEA EDX,DWORD PTR SS:[EBP-404]
 2 0040ECD2  |. 52                PUSH EDX
 3 0040ECD3  |. E8 2D23FFFF       CALL exp_me.00401005
 4 0040ECD8  |. 83C4 04           ADD ESP,4
 5 0040ECDB  |. 8945 FC           MOV DWORD PTR SS:[EBP-4],EAX
 6 0040ECDE  |. 837D FC 00        CMP DWORD PTR SS:[EBP-4],0
 7 0040ECE2  |. 74 0F             JE SHORT exp_me.0040ECF3
 8 0040ECE4  |. 68 AC404200       PUSH OFFSET exp_me.??_C@_0BG@GFGB@Incorr>;  /format = "Incorrect password!
 9 
10 "
11 0040ECE9  |. E8 F225FFFF       CALL exp_me.printf                       ;  \printf
12 0040ECEE  |. 83C4 04           ADD ESP,4
13 0040ECF1  |. EB 0D             JMP SHORT exp_me.0040ED00
14 0040ECF3  |> 68 6C404200       PUSH OFFSET exp_me.??_C@_0DD@FPBB@Congra>;  /format = "Congratulation! You have passed the verification!
15 
16 "
17 0040ECF8  |. E8 E325FFFF       CALL exp_me.printf                       ;  \printf
18 0040ECFD  |. 83C4 04           ADD ESP,4
19 0040ED00  |> 33C0              XOR EAX,EAX
20 0040ED02  |. 5F                POP EDI
21 0040ED03  |. 5E                POP ESI

从上面的反汇编代码可以看到,0x0040ECD8 处的代码对应源码第 30 行后恢复栈帧处,如果能将此时的返回地址覆盖为 0x0040ECF3,就能跳过错误验证流程,直接执行源码中第 36 行的 else 分支,进入验证正确后的执行流程。

 

用 UltraEdit 将 password.txt 修改为如下内容:

注意,CPU 为 Little_Endian 模式,最后的四字节返回地址(0x0040ECF3)要反写成 E3 EC 40 00

在返回地址之前的前栈帧地址 0x0012FF48 不能写为 48 FF 12 00,因为这里的 00 会被 scanf 当作截断符中止读取,导致内容读取不够,覆盖返回地址失败(只能覆盖到 EBP)。

 

修改 password.txt 后,OD 调试结果如下:

 

紧接着出现如下错误,因为 EBP 覆盖成了错误的 0xAA12FF48 而不是 0x0012FF48,导致栈帧不平衡。

这个问题留着以后再学习吧,今天到此了,睡觉去(2014-3-31 23:31:55)。

posted on 2014-03-30 21:37  exclm  阅读(409)  评论(0编辑  收藏  举报