注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

且行且记录

点滴记录,行的更远!

 
 
 

日志

 
 

Off-by-one测试  

2013-05-02 11:01:24|  分类: 一些练习 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Off-by-one测试

Hcper @ 2013430星期二

 

用《软件剖析——代码攻防之道》上面的的一个简单代码,构造了个测试用例。

// off-by-one.c

#include <stdio.h>

 

void test(char *p)

{

       char t[12]; //总共可以容纳11个非空字符

       strcpy(t,"test"); //这里占用4个非空字符

       strncat(t,p,12-4); //这里剩下11-4个非空字符,但是计算错误,多一个!

       printf("t=%s\n",t);

}

 

int main(int argc, char *argv[])

{

       int i; // 这里加这个是为了该函数尾部出现mov esp,ebp

 

       if (argc !=2)

       {

              printf("help:\t%s string\n",argv[0]);

              return 0;

       }

 

       test(argv[1]);

       return 0;

}

 

编译后测试

d:\temp>off-by-one 111222

t=test111222

运行正常

 

d:\temp>off-by-one 111222333

t=test11122233

出现错误!

 

OD的代码如下:

 

00401000  /$ push    ebp

00401001  |. mov     ebp, esp

00401003  |. sub     esp, 0C

00401006  |. push    00409040  ;  ASCII "test"

0040100B  |. lea     eax, dword ptr [ebp-C]

0040100E  |. push    eax

0040100F  |. call    004011F0

00401014  |. add     esp, 8

00401017  |. push    8

00401019  |. mov     ecx, dword ptr [ebp+8]

0040101C  |. push    ecx

0040101D  |. lea     edx, dword ptr [ebp-C]

00401020  |. push    edx

00401021  |. call    004010B0 ?在这行下个断点,观察堆栈

00401026  |. add     esp, 0C

00401029  |. lea     eax, dword ptr [ebp-C]

0040102C  |. push    eax

0040102D  |. push    00409048  ;  ASCII "t=%s",LF

00401032  |. call    00401076

00401037  |. add     esp, 8

0040103A  |. mov     esp, ebp

0040103C  |. pop     ebp

0040103D  \. retn

 

00401040  /$ push    ebp

00401041  |. mov     ebp, esp

00401043  |. push    ecx

00401044  |. cmp     dword ptr [ebp+8], 2

00401048  |. je      short 00401061

0040104A  |. mov     eax, dword ptr [ebp+C]

0040104D  |. mov     ecx, dword ptr [eax]

0040104F  |. push    ecx

00401050  |. push    00409050  ;  ASCII "help:",TAB,"%s string",LF

00401055  |. call    00401076

0040105A  |. add     esp, 8

0040105D  |. xor     eax, eax

0040105F  |. jmp     short 00401072

00401061  |> mov     edx, dword ptr [ebp+C]

00401064  |. mov     eax, dword ptr [edx+4]

00401067  |. push    eax

00401068  |. call    00401000

0040106D  |. add     esp, 4

00401070  |. xor     eax, eax

00401072  |> mov     esp, ebp

00401074  |. pop     ebp

00401075  \. retn

 

 

以上的红色那行00401021  |. call    004010B0对应strncat函数,在该行下个断点。

 

正常输入为111222

断点处堆栈如下:

0012FEBC   0012FEC8  ASCII "test"

0012FEC0   00390F03  ASCII "111222"

0012FEC4   00000008

0012FEC8   74736574 ?这里内容就是test

0012FECC   00409000  off-by-o.00409000

0012FED0   94FD3895

0012FED4  /0012FEE4 ?之前的ebp

0012FED8  |0040106D  返回到 off-by-o.0040106D 来自 off-by-o.00401000

0012FEDC  |00390F03  ASCII "111222"

0012FEE0  |00000001

0012FEE4  ]0012FFC0

0012FEE8  |00401480  返回到 off-by-o.00401480 来自 off-by-o.00401040

0012FEEC  |00000002

0012FEF0  |00390EE0

 

单步过后如下:

0012FEBC   0012FEC8  ASCII "test111222"

0012FEC0   00390F03  ASCII "111222"

0012FEC4   00000008

0012FEC8   74736574 ?字符串从这开始

0012FECC   32313131

0012FED0   94003232 ?追加的字符串以零结尾

0012FED4  /0012FEE4 ?之前的ebp还没覆盖到

0012FED8  |0040106D  返回到 off-by-o.0040106D 来自 off-by-o.00401000

0012FEDC  |00390F03  ASCII "111222"

0012FEE0  |00000001

0012FEE4  ]0012FFC0

0012FEE8  |00401480  返回到 off-by-o.00401480 来自 off-by-o.00401040

0012FEEC  |00000002

0012FEF0  |00390EE0

 

现在输入111222333触发错误

还是上面的断点,单步过后的堆栈如下:

0012FEBC   0012FEC8  ASCII "test11122233"

0012FEC0   00390F03  ASCII "111222333"

0012FEC4   00000008

0012FEC8   74736574 ?字符串从这开始

0012FECC   32313131

0012FED0   33333232

0012FED4   0012FE00 ?之前的ebp最低一个字节被清零!

0012FED8   0040106D  返回到 off-by-o.0040106D 来自 off-by-o.00401000

0012FEDC   00390F03  ASCII "111222333"

0012FEE0   00000001

0012FEE4  /0012FFC0

0012FEE8  |00401480  返回到 off-by-o.00401480 来自 off-by-o.00401040

0012FEEC  |00000002

0012FEF0  |00390EE0

 

之后运行到如下:

0040103A  |. mov     esp, ebp ?这里的ebp还没有变

0040103C  |. pop     ebp ?这里从堆栈弹出被改过后的ebp=0012FE00

0040103D  \. retn

 

在运行到上层函数尾部如下:

00401070  |. xor     eax, eax

00401072  |> mov     esp, ebp ?这里把修改过后的ebp赋给esp扰乱了以前的堆栈

00401074  |. pop     ebp ?这里新的ebp来自0012FE00堆栈处的内容

00401075  \. Retn ?这里新的eip来自0012FE04堆栈处的内容

 

我这里的堆栈如下:

0012FE00   40000061

0012FE04   7C93005D  返回到 ntdll.7C93005D 来自 ntdll.7C92E906

0012FE08   00390FD8

0012FE0C   00390768

 

之后的执行就不可预测了,如果能够在溢出之前,提前布局0012FE04处的值,那就是可以控制了。

  评论这张
 
阅读(316)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017