软件调试纵横谈-18-页堆
18.页堆_哔哩哔哩_bilibili
周日继续看录像学习,页堆。
书接上回,FreCheck程序在free时才检测到堆块被破坏,需要启动页堆,提前到堆块被破坏时就出异常。
设置gflag标记
打开一个管理员权限的命令行窗口。
PS C:\cpp\vc2022\FreCheck\Debug> gflags.exe -i .\FreCheck.exe
No Registry Settings for FreCheck.exe executable
说明注册表原来没有,增加了一项。
PS C:\cpp\vc2022\FreCheck\Debug> gflags.exe -i .\FreCheck.exe +hpa
Current Registry Settings for FreCheck.exe executable are: 02000000
hpa - Enable page heap
页堆已启用。
gflags支持哪些选项?windbg的help中有:
重新运行FreCheck
.restart
初始断点处检查gflag
0:000> !gflag
Current NtGlobalFlag contents: 0x02000000
hpa - Place heap allocations at ends of pages
0:000> bp main
Bp expression 'main' could not be resolved, adding deferred bp
*** Bp expression 'main' contains symbols not qualified with module name.
0:000> bl
0 e Disable Clear u 0001 (0001) (main)
0:000> g
然后从main开始单步执行。
HeapCreate后看一下当前堆:
0:000> !heap
Heap Address NT/Segment Heap
5d40000 NT Heap
6000000 NT Heap
5fc0000 NT Heap
8680000 NT Heap
8650000 NT Heap
9760000 NT Heap
a550000 NT Heap
96e0000 NT Heap
a4e0000 NT Heap
9730000 NT Heap
10fd0000 NT Heap
0:000> dv
argc = 0n1
argv = 0x0db5cfc8
hHeap = 0x17bd0000 --启用页堆后和上面有差异了
继续HeapAlloc,观察是不是在页边界
0:000> dv
i = 0n-858993460
argc = 0n1
argv = 0x0db5cfc8
hHeap = 0x17bd0000
p = 0x17bd5ff0 "???"
0:000> !heap -x 0x17bd5ff0 --竟然没有堆块,奇怪了。
0:000> db 0x17bd5ff0
17bd5ff0 c0 c0 c0 c0 c0 c0 c0 c0-c0 d0 d0 d0 d0 d0 d0 d0 ................
17bd6000 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
17bd6010 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
17bd6020 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
17bd6030 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
17bd6040 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
17bd6050 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ????????????????
17bd6060 ?? ?? ?? ?? ?? ?? ?? ??-?? ?? ?? ?? ?? ?? ?? ?? ?????
9个c0是分配的9个字节,7个d0是末尾填充,后面的??是栅栏。
0:000> !address 17bd6000 仔细看一下栅栏,发现是reserved
Mapping file section regions...
Mapping module regions...
Mapping PEB regions...
Mapping TEB and stack regions...
Mapping heap regions...
Mapping page heap regions...
Mapping other regions...
Mapping stack trace database regions...
Mapping activation context regions...
Usage: PageHeap
Base Address: 17bd6000
End Address: 17cd0000
Region Size: 000fa000 (1000.000 kB)
State: 00002000 MEM_RESERVE --不可访问
Protect: <info not present at the target>
Type: 00020000 MEM_PRIVATE
Allocation Base: 17bd0000
Allocation Protect: 00000001 PAGE_NOACCESS
More info: !heap -p 0x17bd1000
More info: !heap -p -a 0x17bd6000
Content source: 0 (invalid), length: fa000
碰到异常
继续执行循环,就会碰到异常了。
0:000> p
(3c68.c98): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=17bd6000 ebx=00ec7000 ecx=01001010 edx=00000000 esi=010ffc64 edi=010ffd54
eip=00b518fc esp=010ffc64 ebp=010ffd54 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
FreCheck!main+0x7c:
00b518fc 8808 mov byte ptr [eax],cl ds:002b:17bd6000=??
cl=10,就是循环到16的时候出错了,写完16字节,写第17个字节到了下一页,不可写。
0:000> k
# ChildEBP RetAddr
00 010ffd54 00b52183 FreCheck!main+0x7c [C:\cpp\vc2022\FreCheck\FreCheck.cpp @ 10]
01 010ffd74 00b51fca FreCheck!invoke_main+0x33 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 78]
02 010ffdd0 00b51e5d FreCheck!__scrt_common_main_seh+0x15a [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288]
03 010ffdd8 00b52208 FreCheck!__scrt_common_main+0xd [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331]
04 010ffde0 76907ba9 FreCheck!mainCRTStartup+0x8 [D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17]
05 010ffdf0 77d1c10b KERNEL32!BaseThreadInitThunk+0x19
06 010ffe48 77d1c08f ntdll!__RtlUserThreadStart+0x2b
07 010ffe58 00000000 ntdll!_RtlUserThreadStart+0x1b
可以看到是写的时候就出异常了。
!heap -x 。。。这个命令录像中和我的环境一样,不成功。说明页堆后有些命令失效了。