+0x01c EndStamp : 0xdcbabbbb
书中P681表23-7也列举了页堆堆块的填充模式:
占用堆块
空闲堆块
头结构的Start Magic
ABCDBBBB
ABCDBBBA
头结构的End Magic
DCBABBBB
DCBABBBA
用户区
C0或用户初始化00
F0
用户数据后的填充部分
D0
N/A
因此,为了满足Windows中8字节的分配粒度,该页堆虽然只申请了4字节,但尾部也填充了4字节的d0d0d0d0。这样也就解释了“为何该堆的大小只有4个字节,而已经写入了8个字节却没有出现异常”这个疑惑。
再看第二个疑惑:
为何memcpy明明从样本倒数第二个字节0x26e开始拷贝,而之前的8个字节已经被写入到堆的前8个字节?难不成在memcpy函数之前,就进行了堆的写入操作?
要想验证memcpy函数之前对该堆的写入操作,就要在堆创建后下内存写断点:
ba w4 eax
首先在在堆创建时下断点,得到堆的起始地址:
0:027> bp AviSplitter+0x0000303e
0:027> g
Breakpoint 1 hit
eax=31786469 ebx=00000000 ecx=00000004 edx=00000002 esi=21ed6f08 edi=00000270
eip=69e6303e esp=2516f338 ebp=2516f38c iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
AviSplitter+0x303e:
69e6303e e869480100 call AviSplitter!DllGetClassObject+0x337c (69e778ac)
0:027> p
eax=21510ff8 ebx=00000000 ecx=00000004 edx=00000000 esi=21ed6f08 edi=00000270
eip=69e63043 esp=2516f338 ebp=2516f38c iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
AviSplitter+0x3043:
69e63043 8986d4000000 mov dword ptr [esi+0D4h],eax ds:002b:21ed6fdc=00000000
上面申请的页堆起始地址eax=21510ff8,对之后8个字节下内存写断点:
0:027> ba w8 0x21510ff8
0:027> g
Breakpoint 2 hit
eax=21510ff8 ebx=00000000 ecx=00000004 edx=00000000 esi=21ed6f08 edi=00000270
eip=69e6304f esp=2516f338 ebp=2516f38c iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
AviSplitter+0x304f:
69e6304f 8b45ec mov eax,dword ptr [ebp-14h] ss:002b:2516f378=00000002
0:027> g
Breakpoint 2 hit
eax=00000002 ebx=00000000 ecx=00000004 edx=21510ff8 esi=21ed6f08 edi=00000270
eip=69e6305e esp=2516f33c ebp=2516f38c iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
AviSplitter+0x305e:
69e6305e 8b86d4000000 mov eax,dword ptr [esi+0D4h] ds:002b:21ed6fdc=21510ff8
细心对比相关指令发现,这些内存写操作就发生在call指令创建页堆之后:
69e6303e e869480100 call AviSplitter!DllGetClassObject+0x337c (69e778ac) --创建页堆
69e63043 8986d4000000 mov dword ptr [esi+0D4h],eax
69e63049 c70069647831 mov dword ptr [eax],31786469h --写第1-4字节
69e6304f 8b45ec mov eax,dword ptr [ebp-14h]
69e63052 8b96d4000000 mov edx,dword ptr [esi+0D4h]
69e63058 83c404 add esp,4
69e6305b 894204 mov dword ptr [edx+4],eax --写第5-8字节
69e6305e 8b86d4000000 mov eax,dword ptr [esi+0D4h]
69e63064 8b4dec mov ecx,dword ptr [ebp-14h]
69e63067 6a00 push 0
69e63069 51 push ecx
69e6306a 83c008 add eax,8
69e6306d e989010000 jmp AviSplitter+0x31fb (69e631fb)
由上可知,当页堆被创建后,无论申请的大小是多少,从页堆起始地址开始的8个字节就被赋予了下列内容:
|69 64 78 31 |02 00 00 00|
其中,前4个字节是以固定指令写入的,并不是样本文件中的内容,而后4个字节与样本最后两个字节之前的4字节内容相同:
◆◆1
发表评论