实验程序:
#include <stdio.h>
void Func()
{
printf("MyFunction
");
}
void Hack()
{
printf("I am a Hacker!
");
}
int main()
{
Func();
return 0;
}
编译环境VC++ 6.0
打开项目设置
在Release版本中勾选上生成调试信息
编译、链接、执行
在资源管理器中可看到如下文件结构
打开Windbg
打开刚刚编译好的程序
添加符号文件路径
在main()函数处,设置断点
0:000> bp StackTest!main
*** WARNING: Unable to verify checksum for StackTest.exe
0:000> bl
0 e 00401020 0001 (0001) 0:**** StackTest!main
输入g,程序中断于断点处
查看当前eip和esp的值
0:000> r eip,esp
eip=00401020 esp=0012ff4c
查看程序的反汇编代码
StackTest!Func:
00401000 6830804000 push offset StackTest!`string' (00408030)
00401005 e826000000 call StackTest!printf (00401030)
0040100a 59 pop ecx
0040100b c3 ret
0040100c 90 nop
0040100d 90 nop
0040100e 90 nop
0040100f 90 nop
StackTest!Hack:
00401010 683c804000 push offset StackTest!`string' (0040803c)
00401015 e816000000 call StackTest!printf (00401030)
0040101a 59 pop ecx
0040101b c3 ret
0040101c 90 nop
0040101d 90 nop
0040101e 90 nop
0040101f 90 nop
StackTest!main:
00401020 e8dbffffff call StackTest!Func (00401000)
00401025 33c0 xor eax,eax
00401027 c3 ret
单步执行,进入Func函数调用
dd esp
查看堆栈信息
0:000> r eip,esp
eip=00401000 esp=0012ff48
0:000> dd esp
0012ff48 00401025 00401115 00000001 00380b78
0012ff58 00380bf0 00000000 00000000 7ffdf000
0012ff68 00000000 00000000 0012ff5c 00000000
0012ff78 0012ffc4 00402790 004070e0 00000000
0012ff88 0012ff94 765e3c45 7ffdf000 0012ffd4
0012ff98 76fd37f5 7ffdf000 76166a17 00000000
0012ffa8 00000000 7ffdf000 00000000 00000000
0012ffb8 00000000 0012ffa0 00000000 ffffffff
此时栈顶存放的是main函数中调用Func后的下一条命令的地址,也就是Func返回的地址
00401025
单步执行至Func的ret语句
0040100b c3 ret
0:000> dd esp
0012ff48 00401025 00401115 00000001 003d0b78
0012ff58 003d0bf0 00000000 00000000 7ffd5000
0012ff68 00000000 00000000 0012ff5c 00000000
0012ff78 0012ffc4 00402790 004070e0 00000000
0012ff88 0012ff94 765e3c45 7ffd5000 0012ffd4
0012ff98 76fd37f5 7ffd5000 763f4c17 00000000
0012ffa8 00000000 7ffd5000 00000000 00000000
0012ffb8 00000000 0012ffa0 00000000 ffffffff
0:000> ed esp
0012ff48 00401025 00401010
更改栈顶返回地址的值,使其跳转到Hack函数的位置
记录真正要返回的地址00401025
运行至Hack函数的ret语句,此时修好栈顶的值为
0:000> ed esp 00401025
0:000> dd esp
0012ff4c 00401025 00000001 003d0b78 003d0bf0
0012ff5c 00000000 00000000 7ffd5000 00000000
接着单步运行