65,210
社区成员
发帖
与我相关
我的任务
分享
[code=C/C++]
看lz那么认真,我给写下详细过程吧!!
以下全在vc6.0下测试
----------------------------------------------------------------
首先,得明白一点:
函数在调用的时候,都有什么东西在栈里,顺序是啥?
在栈上:函数首先入栈的,是函数参数(从右到左),然后是函数的return地址,然后是ebp,然后就是局部变量!
如下:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
|local var(局部变量) |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
|函数参数第1个 |
+-------------------------------+
|. |
|. |
|. |
+-------------------------------+
|函数参数第 n-1 个 |
+-------------------------------+
|函数参数 n 个 |
+-------------------------------+高地址
明白这个了,下面进行调试:
-----------------------------------------------------------------------------
先,看我们应该做些什么,我相信,lz应该能明白了,题目也写得很清楚,也就是对getbuf这个函数里定义的char buf[12]做手脚,可以看到
在getxs函数里的while循环,结束条件只是以回车或者是eof结束符为判断标准,所以,根本没对char输入的数量做判断!这样的话,我们可以输入
多于12个的数,从而缓冲区溢出!
其次:按照我上面说的函数栈的存放情况,在getbuf这个函数里,函数参数没有,我们不管,然后就是return返回地址,然后就是ebp指针,然后就是
char buf[12]
如下:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+高地址
所以:如果我们对buf溢出,能改写ebp和return地址!
下面看看,ebp是多少,return地址是多少??
----------------------------------------------------------------------------------------
那么我们要返回到哪儿:
看test函数的汇编代码(我只摘录重要的):
44: void test()
45: {
00416300 push ebp
46: int val;
48: val = getbuf();
00416325 call @ILT+20(getbuf) (00401019)
0041632A mov dword ptr [ebp-4],eax
49: printf("getbuf returned 0x%x\n", val);
0041632D mov eax,dword ptr [ebp-4]
00416330 push eax
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
00416336 call printf (00401280)
50: }
看以下两行:
00416300 push ebp
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
在函数返回的时候,pop ebp,得恢复断点的ebp,
+--------------------------------------------------+
|所以,我们知道,上面我们填充的ebp应该是这个ebp |
+--------------------------------------------------+
在pringf打印之前,push了eax,还有一个字串。
那么显然,我们不能通过这个eax来push进栈去,因为这样的话,eax怎么改掉呢?所以,在call完getbuf后,应该跳转到
第二句:也就是:
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
+---------------------------------------------------+
|所以,我们的返回地址应该是这里:00416331 |
+---------------------------------------------------+
然后,需要的输出字符咋办??
看堆栈,我刚说了,在printf前,有这个push eax,而我们没有push进去,那么打印什么呢?肯定一点,printf打印的是push进栈的东西
那么假如上面输入不出栈不就得了么?
所以:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
| 如果在这里 |
| 写上点儿啥 |
| 的话,不会出栈 |
| 不用push, |
| 从而能打印 |
+-------------------------------+高地址
所以,输入应该不仅要把返回地址覆盖掉,还要继续往下写,写入我们的返回地址!
综上,输入应该是:
前12个任意数+test函数中ebp的指针+return的地址(printf前面push那句)+需要显示的地址!
看lz那么认真,我给写下详细过程吧!!
以下全在vc6.0下测试
----------------------------------------------------------------
首先,得明白一点:
函数在调用的时候,都有什么东西在栈里,顺序是啥?
在栈上:函数首先入栈的,是函数参数(从右到左),然后是函数的return地址,然后是ebp,然后就是局部变量!
如下:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
|local var(局部变量) |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
|函数参数第1个 |
+-------------------------------+
|. |
|. |
|. |
+-------------------------------+
|函数参数第 n-1 个 |
+-------------------------------+
|函数参数 n 个 |
+-------------------------------+高地址
明白这个了,下面进行调试:
-----------------------------------------------------------------------------
先,看我们应该做些什么,我相信,lz应该能明白了,题目也写得很清楚,也就是对getbuf这个函数里定义的char buf[12]做手脚,可以看到
在getxs函数里的while循环,结束条件只是以回车或者是eof结束符为判断标准,所以,根本没对char输入的数量做判断!这样的话,我们可以输入
多于12个的数,从而缓冲区溢出!
其次:按照我上面说的函数栈的存放情况,在getbuf这个函数里,函数参数没有,我们不管,然后就是return返回地址,然后就是ebp指针,然后就是
char buf[12]
如下:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+高地址
所以:如果我们对buf溢出,能改写ebp和return地址!
下面看看,ebp是多少,return地址是多少??
----------------------------------------------------------------------------------------
那么我们要返回到哪儿:
看test函数的汇编代码(我只摘录重要的):
44: void test()
45: {
00416300 push ebp
46: int val;
48: val = getbuf();
00416325 call @ILT+20(getbuf) (00401019)
0041632A mov dword ptr [ebp-4],eax
49: printf("getbuf returned 0x%x\n", val);
0041632D mov eax,dword ptr [ebp-4]
00416330 push eax
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
00416336 call printf (00401280)
50: }
看以下两行:
00416300 push ebp
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
在函数返回的时候,pop ebp,得恢复断点的ebp,
+--------------------------------------------------+
|所以,我们知道,上面我们填充的ebp应该是这个ebp |
+--------------------------------------------------+
在pringf打印之前,push了eax,还有一个字串。
那么显然,我们不能通过这个eax来push进栈去,因为这样的话,eax怎么改掉呢?所以,在call完getbuf后,应该跳转到
第二句:也就是:
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
+---------------------------------------------------+
|所以,我们的返回地址应该是这里:00416331 |
+---------------------------------------------------+
然后,需要的输出字符咋办??
看堆栈,我刚说了,在printf前,有这个push eax,而我们没有push进去,那么打印什么呢?肯定一点,printf打印的是push进栈的东西
那么假如上面输入不出栈不就得了么?
所以:
+-------------------------------+低地址
|其他……(这不重要了,不用管) |
+-------------------------------+
| buf[0] |
+-------------------------------+
| . |
| . |
| . |
+-------------------------------+
| buf[10] |
+-------------------------------+
| buf[11] |
+-------------------------------+
|ebp指针入栈 |
+-------------------------------+
|return 返回地址 |
+-------------------------------+
| 如果在这里 |
| 写上点儿啥 |
| 的话,不会出栈 |
| 不用push, |
| 从而能打印 |
+-------------------------------+高地址
所以,输入应该不仅要把返回地址覆盖掉,还要继续往下写,写入我们的返回地址!
综上,输入应该是:
前12个任意数+test函数中ebp的指针+return的地址(printf前面push那句)+需要显示的地址!
test函数:
00416331 push offset string "getbuf returned 0x%x\n" (0042eb4c)
getbuf函数:
第一句:00401120 push ebp 这个ebp的值!(1240992 = 0x 0012EFA0)
输入:前面十二个数随便,后面接着是:ebp的值:a0 ef 12 00 然后是最上面那句的地址: 31 63 41 00
后面就是题目要求的东西:ef be ad de