学习之前应该先搞清楚如何调试进程当前的内存信息
艰难的起步(No symbols for ntdll. Cannot continue.)
之前在公司win7 电脑上调试内存泄漏信息,用了其中的一个命令!address 查看进程地址空间的大概的分布状态。在自己的电脑上简单的使用!address 命令的时候发现如下错误:
Microsoft (R) Windows Debugger Version 10.0.18362.1 X86
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: F:\program\MemoryList\Release\ExeTestDllHeapTest.exe
************* Path validation summary **************
Response Time (ms) Location
Deferred srv*c:\symbols*https://msdl.microsoft.com/download/symbols
Symbol search path is: srv*c:\symbols*https://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00660000 00697000 ExeTestDllHeapTest.exe
ModLoad: 77090000 7722a000 ntdll.dll
ModLoad: 75500000 755e0000 C:\WINDOWS\SysWOW64\KERNEL32.DLL
ModLoad: 750d0000 752cc000 C:\WINDOWS\SysWOW64\KERNELBASE.dll
(688.13bc): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=002bc000 ecx=8aab0000 edx=00000000 esi=009a1ed8 edi=7709688c
eip=7713e9d2 esp=0056f948 ebp=0056f974 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2b:
7713e9d2 cc int 3
0:000> !address
No symbols for ntdll. Cannot continue.
注意到输入!addrses 之后的提示:No symbols for ntdll. Cannot continue
无脑的参考之间的经验,删除了ntdll.dll 的有关符号,并重新加载,发现并没有解决问题,之后搜索引擎 ,发现并相关的方法可以没有解决自己的问题。
解决之路:
细节决定成败吧,windbg 提示我们没有ntdll 的符号,而我们看windbg 的启动信息,发现它显然是有一个ntdll.dll 的符号的,之后我们用process hacker 查看初始状态时一个进程的模块加载信息:
我们发现这里加载了很多符号,而windbg 只是列出了一部分,wow 相关的模块一个都没有,而我通常习惯于启动32位windbg 调试32位exe,这可能是一个问题的原因,wow 相关,后来尝试用64bit 的windbg 启动并调试32位的exe 时,可以正常的使用!address 命令了。这可能是windbg 的问题,因为我在工作机器win7上,32-bit windbg.exe 调试32-bit exe ,查看其模块信息是没有问题的,但这不是我们学习的重点,有机会可以继续探索一下
进程初始时的地址空间信息的查看
Response Time (ms) Location
Deferred srv*c:\symbols*https://msdl.microsoft.com/download/symbols
Symbol search path is: srv*c:\symbols*https://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 00000000`00660000 00000000`00697000 ExeTestDllHeapTest.exe
ModLoad: 00007ffc`65ee0000 00007ffc`660d0000 ntdll.dll
ModLoad: 00000000`77090000 00000000`7722a000 ntdll.dll
ModLoad: 00007ffc`64eb0000 00007ffc`64f05000 C:\WINDOWS\System32\wow64.dll
ModLoad: 00007ffc`64b10000 00007ffc`64b8d000 C:\WINDOWS\System32\wow64win.dll
(3524.23cc): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00007ffc`65fb11dc cc int 3
0:000> !address -summary
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 Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 15 0`7fa62000 ( 1.995 GB) 99.73%
<unknown> 13 0`00314000 ( 3.078 MB) 55.41% 0.15%
Image 13 0`001d1000 ( 1.816 MB) 32.70% 0.09%
Other 5 0`00054000 ( 336.000 kB) 5.91% 0.02%
Stack64 3 0`00040000 ( 256.000 kB) 4.50% 0.01%
Heap64 2 0`0000f000 ( 60.000 kB) 1.05% 0.00%
TEB64 1 0`00003000 ( 12.000 kB) 0.21% 0.00%
PEB64 1 0`00002000 ( 8.000 kB) 0.14% 0.00%
MappedFile 1 0`00001000 ( 4.000 kB) 0.07% 0.00%
--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE 21 0`00369000 ( 3.410 MB) 61.39% 0.17%
MEM_IMAGE 13 0`001d1000 ( 1.816 MB) 32.70% 0.09%
MEM_MAPPED 5 0`00054000 ( 336.000 kB) 5.91% 0.02%
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE 15 0`7fa62000 ( 1.995 GB) 99.73%
MEM_RESERVE 8 0`0034a000 ( 3.289 MB) 59.21% 0.16%
MEM_COMMIT 31 0`00244000 ( 2.266 MB) 40.79% 0.11%
--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_EXECUTE_READ 2 0`0013b000 ( 1.230 MB) 22.15% 0.06%
PAGE_READONLY 12 0`000e1000 ( 900.000 kB) 15.82% 0.04%
PAGE_READWRITE 11 0`0001a000 ( 104.000 kB) 1.83% 0.00%
PAGE_WRITECOPY 4 0`00009000 ( 36.000 kB) 0.63% 0.00%
PAGE_READWRITE|PAGE_GUARD 2 0`00005000 ( 20.000 kB) 0.35% 0.00%
--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
Free 0`01580000 0`75b10000 ( 1.839 GB)
<unknown> 0`0109a000 0`00166000 ( 1.398 MB)
Image 0`77091000 0`0011a000 ( 1.102 MB)
Other 0`7f550000 0`00033000 ( 204.000 kB)
Stack64 0`01220000 0`00035000 ( 212.000 kB)
Heap64 0`01574000 0`0000b000 ( 44.000 kB)
TEB64 0`01097000 0`00003000 ( 12.000 kB)
PEB64 0`01095000 0`00002000 ( 8.000 kB)
MappedFile 0`7f540000 0`00001000 ( 4.000 kB)
使用winddbg 加载exe 之后第一次查看调试信息会发现上面的地址空间分布,由于我们猜测进程模块会有进程模块堆的构建,这里只看到了64-bit 的堆,有点难以理解。
定制的dll 和 exe ,用于研究dll 模块的堆的使用和释放
- exe
int main()
{
printf("print to alloc local memory\n");
getchar();
char* pszLocal = (char*)malloc(0x2000);
strcpy_s(pszLocal, 0x2000, "hello local");
printf("[%p]\t[%s]\n", pszLocal, pszLocal);
printf("print to local free\n");
getchar();
free(pszLocal);
pszLocal = NULL;
typedef void(__stdcall * ptr_func)(void);
HMODULE hDll = LoadLibrary(_T("DllHeapTest.dll"));
printf("print to load library \n");
getchar();
ptr_func Func = (ptr_func)GetProcAddress(hDll, "AllocMemoryAndNoFree");
printf("print to call alloc memory");
getchar();
Func();
printf("before FreeLibrary click to free");
getchar();
FreeLibrary(hDll);
std::cout << "after free memory!\n";
getchar();
system("pause");
- dll
void __stdcall AllocMemoryAndNoFree()
{
void* temp = malloc(0x1000);
char flag[] = "hello world";
memcpy_s(temp, 0x1000,flag, sizeof(flag));
printf("[%p]\n", temp);
}
f5 键,查看进程的crt 执行之后再下断点,查看进程的地址信息
0:000> g
ModLoad: 00000000`77080000 00000000`77089000 C:\WINDOWS\System32\wow64cpu.dll
ModLoad: 00000000`75500000 00000000`755e0000 C:\WINDOWS\SysWOW64\KERNEL32.DLL
ModLoad: 00000000`750d0000 00000000`752cc000 C:\WINDOWS\SysWOW64\KERNELBASE.dll
(3524.23cc): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll_77090000!LdrpDoDebuggerBreak+0x2b:
7713e9d2 cc int 3
我们之后f5 键,发现又有模块加载,并被断了下来,是之前在process hacker 中显示,却没有在windbg 中显示的模块。此时我们再次尝试使用!address 命令,看看有没有我们想要的进程默认堆结构
0:000:x86> !address -summary
No symbols for ntdll. Cannot continue.
再次出现了这个可怕的指令,可怕,但由于之前我们是有机会能使用!address 命令的,这里猜测是wow64系统上,刚开始的初始化是初始化了一个64-bit 进程 ,并被windbg 断了下来,此时被断,进程已经被转换成了wow64 模式,平时也经常遇见这种wow 无法正常调试的状况,需要使用转换命令,将环境转换为32-bit 环境,再继续调试
0:000:x86> .load wow64exts
0:000:x86> !address -summary
No symbols for ntdll. Cannot continue.
0:000:x86> !sw
Switched to Host mode
0:000> !address -summary
注意上面的操作,连续执行 .load wow64exts !sm才可以转换过来,还是要熟悉这个 操作
。。。。等等,和上面刚开始的地址空间来说,是有区别的,但不是我们此次关注的重点,暂时忽略
经历了这里的环境转换,恍然大悟,是不是32-bit windbg.exe在 win10 上,调试32-bit .exe 的时候,也需要 转换wow 环境的?-------反人类的是,我们已经用32-bit windbg.exe调试 32-bit 程序了,为啥还需要这一个转换的步骤,验证之后发现无法通过类似办法转换模式解决!address 指令执行失败的问题,老老实实用64-bit windbg.exe 转换模式后调试 wow64 进程
继续我们的程序,此次f5 之后,应该走完了进程crt 的初始化,然后我们再下断点一定可以得到一个相关熟悉的进程的地址空间
0:001> !address -summary
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
Free 23 0`7f35d000 ( 1.988 GB) 99.39%
<unknown> 21 0`0051a000 ( 5.102 MB) 40.57% 0.25%
Image 33 0`004b6000 ( 4.711 MB) 37.47% 0.23%
MappedFile 3 0`001c3000 ( 1.762 MB) 14.01% 0.09%
Stack64 6 0`00080000 ( 512.000 kB) 3.98% 0.02%
Other 6 0`00059000 ( 356.000 kB) 2.76% 0.02%
Heap64 3 0`0001f000 ( 124.000 kB) 0.96% 0.01%
TEB64 2 0`00006000 ( 24.000 kB) 0.19% 0.00%
PEB64 1 0`00002000 ( 8.000 kB) 0.06% 0.00%
--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_PRIVATE 33 0`005b2000 ( 5.695 MB) 45.29% 0.28%
MEM_IMAGE 33 0`004b6000 ( 4.711 MB) 37.47% 0.23%
MEM_MAPPED 9 0`0022b000 ( 2.168 MB) 17.24% 0.11%
--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
MEM_FREE 23 0`7f35d000 ( 1.988 GB) 99.39%
MEM_RESERVE 20 0`006b2000 ( 6.695 MB) 53.25% 0.33%
MEM_COMMIT 55 0`005e1000 ( 5.879 MB) 46.75% 0.29%
--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal
PAGE_EXECUTE_READ 6 0`00365000 ( 3.395 MB) 27.00% 0.17%
PAGE_READONLY 24 0`0021b000 ( 2.105 MB) 16.74% 0.10%
PAGE_READWRITE 20 0`00056000 ( 344.000 kB) 2.67% 0.02%
PAGE_READWRITE|PAGE_GUARD 4 0`0000a000 ( 40.000 kB) 0.31% 0.00%
PAGE_WRITECOPY 1 0`00001000 ( 4.000 kB) 0.03% 0.00%
--- Largest Region by Usage ----------- Base Address -------- Region Size ----------
Free 0`01850000 0`73880000 ( 1.805 GB)
<unknown> 0`0109d000 0`00163000 ( 1.387 MB)
Image 0`750d1000 0`001c3000 ( 1.762 MB)
MappedFile 0`7f3f5000 0`000fb000 (1004.000 kB)
Stack64 0`01220000 0`00035000 ( 212.000 kB)
Other 0`7f550000 0`00033000 ( 204.000 kB)
Heap64 0`00fc0000 0`00010000 ( 64.000 kB)
TEB64 0`01097000 0`00003000 ( 12.000 kB)
PEB64 0`01095000 0`00002000 ( 8.000 kB)
发现了地址空间的heap 还是用heap64标识的时候,我已经知道了自己的假设错误了,64-bit上,或者说64-bit windbg中标识heap 的方法,应该就是heap64吧,此时我们观察heap结构不太合理,因为之前没有观察初始的时候的heap 的结构
从头开始,对比heap 进程crt 初始化前后,heap的状态:
00007ffc`65fb11dc cc int 3
0:000> !heap -p -all
_HEAP @ b80000
No FrontEnd
_HEAP_SEGMENT @ b80000
CommittedRange @ b80740
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
* 0000000000b80740 0013 0000 [00] 0000000000b80750 0012f - (busy)
0000000000b80870 0013 0013 [00] 0000000000b80880 00100 - (busy)
0000000000b809a0 0021 0013 [00] 0000000000b809b0 001d8 - (busy)
0000000000b80bb0 0021 0021 [00] 0000000000b80bc0 001d8 - (busy)
0000000000b80dc0 0008 0021 [00] 0000000000b80dd0 00048 - (busy)
0000000000b80e40 0004 0008 [00] 0000000000b80e50 00004 - (busy)
0000000000b80e80 0004 0004 [00] 0000000000b80e90 00010 - (busy)
0000000000b80ec0 0013 0004 [00] 0000000000b80ed0 00100 - (busy)
0000000000b80ff0 0013 0013 [00] 0000000000b81000 00100 - (busy)
0000000000b81120 0133 0013 [00] 0000000000b81130 012f2 - (busy)
unknown!printable
0000000000b82450 007e 0133 [00] 0000000000b82460 007a8 - (busy)
0000000000b82c30 0007 007e [00] 0000000000b82c40 0003c - (busy)
unknown!noop
0000000000b82ca0 0006 0007 [00] 0000000000b82cb0 00030 - (busy)
unknown!noop
0000000000b82d00 000a 0006 [00] 0000000000b82d10 00062 - (busy)
unknown!noop
0000000000b82da0 0015 000a [00] 0000000000b82db0 00120 - (busy)
0000000000b82ef0 0008 0015 [00] 0000000000b82f00 00050 - (busy)
0000000000b82f70 0015 0008 [00] 0000000000b82f80 00120 - (busy)
0000000000b830c0 0008 0015 [00] 0000000000b830d0 00050 - (busy)
0000000000b83140 0027 0008 [00] 0000000000b83150 00238 - (busy)
0000000000b833b0 0013 0027 [00] 0000000000b833c0 00120 - (free)
0000000000b834e0 0015 0013 [00] 0000000000b834f0 00120 - (busy)
0000000000b83630 0008 0015 [00] 0000000000b83640 00050 - (busy)
unknown!noop
0000000000b836b0 0007 0008 [00] 0000000000b836c0 0003c - (busy)
unknown!noop
0000000000b83720 001a 0007 [00] 0000000000b83730 00190 - (free)
0000000000b838c0 0015 001a [00] 0000000000b838d0 00120 - (busy)
? ntdll!PebLdr+10
0000000000b83a10 0008 0015 [00] 0000000000b83a20 00070 - (free)
0000000000b83a90 0008 0008 [00] 0000000000b83aa0 00042 - (busy)
unknown!noop
0000000000b83b10 004b 0008 [00] 0000000000b83b20 004a0 - (free)
* 0000000000b83fc0 0004 004b [00] 0000000000b83fd0 00030 - (busy)
VirtualAllocdBlocks @ b80110
第一次被断的情况 下两次如下:
0:000> g
ModLoad: 00000000`77080000 00000000`77089000 C:\WINDOWS\System32\wow64cpu.dll
ModLoad: 00000000`75500000 00000000`755e0000 C:\WINDOWS\SysWOW64\KERNEL32.DLL
ModLoad: 00000000`750d0000 00000000`752cc000 C:\WINDOWS\SysWOW64\KERNELBASE.dll
(3fc8.13e0): WOW64 breakpoint - code 4000001f (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
ntdll_77090000!LdrpDoDebuggerBreak+0x2b:
7713e9d2 cc int 3
0:000:x86> .load wow64exts
0:000:x86> !sw
Switched to Host mode
0:000> !heap -p -all
_HEAP @ b80000
No FrontEnd
_HEAP_SEGMENT @ b80000
CommittedRange @ b80740
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
* 0000000000b80740 0013 0000 [00] 0000000000b80750 0012f - (busy)
0000000000b80870 0013 0013 [00] 0000000000b80880 00100 - (busy)
0000000000b809a0 0021 0013 [00] 0000000000b809b0 001d8 - (busy)
0000000000b80bb0 0021 0021 [00] 0000000000b80bc0 001d8 - (busy)
0000000000b80dc0 0008 0021 [00] 0000000000b80dd0 00048 - (busy)
0000000000b80e40 0004 0008 [00] 0000000000b80e50 00004 - (busy)
0000000000b80e80 0004 0004 [00] 0000000000b80e90 00010 - (busy)
0000000000b80ec0 0013 0004 [00] 0000000000b80ed0 00100 - (busy)
0000000000b80ff0 0013 0013 [00] 0000000000b81000 00100 - (busy)
0000000000b81120 0133 0013 [00] 0000000000b81130 012f2 - (busy)
unknown!printable
0000000000b82450 007e 0133 [00] 0000000000b82460 007a8 - (busy)
0000000000b82c30 0007 007e [00] 0000000000b82c40 0003c - (busy)
unknown!noop
0000000000b82ca0 0006 0007 [00] 0000000000b82cb0 00030 - (busy)
unknown!noop
0000000000b82d00 000a 0006 [00] 0000000000b82d10 00062 - (busy)
unknown!noop
0000000000b82da0 0015 000a [00] 0000000000b82db0 00120 - (busy)
0000000000b82ef0 0008 0015 [00] 0000000000b82f00 00050 - (busy)
0000000000b82f70 0015 0008 [00] 0000000000b82f80 00120 - (busy)
0000000000b830c0 0008 0015 [00] 0000000000b830d0 00050 - (busy)
0000000000b83140 0027 0008 [00] 0000000000b83150 00238 - (busy)
0000000000b833b0 0006 0027 [00] 0000000000b833c0 00050 - (free)
0000000000b83410 0008 0006 [00] 0000000000b83420 00050 - (busy)
0000000000b83490 0005 0008 [00] 0000000000b834a0 00040 - (free)
0000000000b834e0 0015 0005 [00] 0000000000b834f0 00120 - (busy)
0000000000b83630 0008 0015 [00] 0000000000b83640 00050 - (busy)
unknown!noop
0000000000b836b0 0007 0008 [00] 0000000000b836c0 0003c - (busy)
unknown!noop
0000000000b83720 0008 0007 [00] 0000000000b83730 00042 - (busy)
unknown!printable
0000000000b837a0 0012 0008 [00] 0000000000b837b0 00110 - (free)
0000000000b838c0 0015 0012 [00] 0000000000b838d0 00120 - (busy)
0000000000b83a10 0006 0015 [00] 0000000000b83a20 00028 - (busy)
0000000000b83a70 0002 0006 [00] 0000000000b83a80 00010 - (free)
0000000000b83a90 0008 0002 [00] 0000000000b83aa0 00042 - (busy)
unknown!noop
0000000000b83b10 0083 0008 [00] 0000000000b83b20 00800 - (busy)
0000000000b84340 0015 0083 [00] 0000000000b84350 00120 - (busy)
? ntdll!PebLdr+10
0000000000b84490 0008 0015 [00] 0000000000b844a0 00042 - (busy)
unknown!noop
0000000000b84510 02ab 0008 [00] 0000000000b84520 02aa0 - (free)
* 0000000000b86fc0 0004 02ab [00] 0000000000b86fd0 00030 - (busy)
VirtualAllocdBlocks @ b80110
_HEAP @ aa0000
No FrontEnd
_HEAP_SEGMENT @ aa0000
CommittedRange @ aa0740
0000000000aa0740 0088 0004 [00] 0000000000aa0750 00870 - (free)
* 0000000000aa0fc0 0004 0088 [00] 0000000000aa0fd0 00030 - (busy)
VirtualAllocdBlocks @ aa0110
0:000> g
(3fc8.26c4): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00007ffc`65f7fad0 cc int 3
0:001> !heap -p -all
_HEAP @ b80000
No FrontEnd
_HEAP_SEGMENT @ b80000
CommittedRange @ b80740
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
* 0000000000b80740 0013 0000 [00] 0000000000b80750 0012f - (busy)
0000000000b80870 0013 0013 [00] 0000000000b80880 00100 - (busy)
0000000000b809a0 0021 0013 [00] 0000000000b809b0 001d8 - (busy)
0000000000b80bb0 0021 0021 [00] 0000000000b80bc0 001d8 - (busy)
0000000000b80dc0 0008 0021 [00] 0000000000b80dd0 00048 - (busy)
0000000000b80e40 0004 0008 [00] 0000000000b80e50 00004 - (busy)
0000000000b80e80 0004 0004 [00] 0000000000b80e90 00010 - (busy)
0000000000b80ec0 0013 0004 [00] 0000000000b80ed0 00100 - (busy)
0000000000b80ff0 0013 0013 [00] 0000000000b81000 00100 - (busy)
0000000000b81120 0133 0013 [00] 0000000000b81130 012f2 - (busy)
unknown!printable
0000000000b82450 007e 0133 [00] 0000000000b82460 007a8 - (busy)
0000000000b82c30 0007 007e [00] 0000000000b82c40 0003c - (busy)
unknown!noop
0000000000b82ca0 0006 0007 [00] 0000000000b82cb0 00030 - (busy)
unknown!noop
0000000000b82d00 000a 0006 [00] 0000000000b82d10 00062 - (busy)
unknown!noop
0000000000b82da0 0015 000a [00] 0000000000b82db0 00120 - (busy)
0000000000b82ef0 0008 0015 [00] 0000000000b82f00 00050 - (busy)
0000000000b82f70 0015 0008 [00] 0000000000b82f80 00120 - (busy)
0000000000b830c0 0008 0015 [00] 0000000000b830d0 00050 - (busy)
0000000000b83140 0027 0008 [00] 0000000000b83150 00238 - (busy)
0000000000b833b0 0006 0027 [00] 0000000000b833c0 00050 - (free)
0000000000b83410 0008 0006 [00] 0000000000b83420 00050 - (busy)
0000000000b83490 0005 0008 [00] 0000000000b834a0 00040 - (free)
0000000000b834e0 0015 0005 [00] 0000000000b834f0 00120 - (busy)
0000000000b83630 0008 0015 [00] 0000000000b83640 00050 - (busy)
unknown!noop
0000000000b836b0 0007 0008 [00] 0000000000b836c0 0003c - (busy)
unknown!noop
0000000000b83720 0008 0007 [00] 0000000000b83730 00042 - (busy)
unknown!printable
0000000000b837a0 0012 0008 [00] 0000000000b837b0 00110 - (free)
0000000000b838c0 0015 0012 [00] 0000000000b838d0 00120 - (busy)
0000000000b83a10 0006 0015 [00] 0000000000b83a20 00028 - (busy)
0000000000b83a70 0002 0006 [00] 0000000000b83a80 00010 - (free)
0000000000b83a90 0008 0002 [00] 0000000000b83aa0 00042 - (busy)
unknown!noop
0000000000b83b10 0083 0008 [00] 0000000000b83b20 00800 - (busy)
0000000000b84340 0015 0083 [00] 0000000000b84350 00120 - (busy)
? ntdll!PebLdr+10
0000000000b84490 0008 0015 [00] 0000000000b844a0 00042 - (busy)
unknown!noop
0000000000b84510 02ab 0008 [00] 0000000000b84520 02aa0 - (free)
* 0000000000b86fc0 0004 02ab [00] 0000000000b86fd0 00030 - (busy)
VirtualAllocdBlocks @ b80110
_HEAP @ aa0000
No FrontEnd
_HEAP_SEGMENT @ aa0000
CommittedRange @ aa0740
0000000000aa0740 0088 0004 [00] 0000000000aa0750 00870 - (free)
* 0000000000aa0fc0 0004 0088 [00] 0000000000aa0fd0 00030 - (busy)
VirtualAllocdBlocks @ aa0110
里面微小的差距,我们大可不必纠结,下面可以看一下概览的信息,用于有个大概的了解:
0:001> !address -f:Heap(过滤只查看Heap 相关的信息)
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
--------------------------------------------------------------------------------------------------------------------------
0`00aa0000 0`00ab0000 0`00010000 MEM_MAPPED MEM_COMMIT PAGE_READWRITE Heap64 [ID: 1; Handle: 0000000000aa0000; Type: Segment]
0`00b80000 0`00b87000 0`00007000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Heap64 [ID: 0; Handle: 0000000000b80000; Type: Segment]
0`00b87000 0`00b8f000 0`00008000 MEM_PRIVATE MEM_RESERVE Heap64 [ID: 0; Handle: 0000000000b80000; Type: Segment]
** 进程初始化的时候,只有两个堆**
进程的第一次malloc 操作之后的地址状态:
尝试获取其所在的堆的信息:
0:001> !heap -p -a c67330
发现没有输出任何信息,查看对列表及地址空间的详细信息:
0:001> !address -f:Heap
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
--------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------
0`00a40000 0`00a50000 0`00010000 MEM_MAPPED MEM_COMMIT PAGE_READWRITE Heap64 0`00a40000 0`00a50000 0`00010000 MEM_MAPPED MEM_COMMIT PAGE_READWRITE Heap64 [ID: 1; Handle: 0000000000a40000; Type: Segment][ID: 1; Handle: 0000000000a40000; Type: Segment]
0`011e0000 0`011e7000 0`00007000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Heap64 0`011e0000 0`011e7000 0`00007000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Heap64 [ID: 0; Handle: 00000000011e0000; Type: Segment][ID: 0; Handle: 00000000011e0000; Type: Segment]
0`011e7000 0`011ef000 0`00008000 MEM_PRIVATE MEM_RESERVE Heap64 0`011e7000 0`011ef000 0`00008000 MEM_PRIVATE MEM_RESERVE Heap64 [ID: 0; Handle: 00000000011e0000; Type: Segment][ID: 0; Handle: 00000000011e0000; Type: Segment]
堆的地址空间不包含我们申请的内存的起始地址。
检查地址空间:
0:001> !address
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...
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
BaseAddress EndAddress+1 RegionSize Type State Protect Usage
--------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------
无用信息
+ + 0`00c00000 0`00c35000 0`00035000 MEM_PRIVATE MEM_RESERVE Stack64 0`00c00000 0`00c35000 0`00035000 MEM_PRIVATE MEM_RESERVE Stack64 [~1; 42bc.2ed8][~1; 42bc.2ed8]
0`00c35000 0`00c38000 0`00003000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE|PAGE_GUARD Stack64 0`00c35000 0`00c38000 0`00003000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE|PAGE_GUARD Stack64 [~1; 42bc.2ed8][~1; 42bc.2ed8]
0`00c38000 0`00c40000 0`00008000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Stack64 0`00c38000 0`00c40000 0`00008000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Stack64 [~1; 42bc.2ed8][~1; 42bc.2ed8]
+ + 0`00c40000 0`00c60000 0`00020000 MEM_FREE PAGE_NOACCESS Free 0`00c40000 0`00c60000 0`00020000 MEM_FREE PAGE_NOACCESS Free
+ + 0`00c60000 0`00c6d000 0`0000d000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE <unknown> 0`00c60000 0`00c6d000 0`0000d000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE <unknown> [mb..............][mb..............]
0`00c6d000 0`00d60000 0`000f3000 MEM_PRIVATE MEM_RESERVE <unknown> 0`00c6d000 0`00d60000 0`000f3000 MEM_PRIVATE MEM_RESERVE <unknown>
+ + 0`00d60000 0`00d61000 0`00001000 MEM_IMAGE MEM_COMMIT PAGE_READONLY Image 0`00d60000 0`00d61000 0`00001000 MEM_IMAGE MEM_COMMIT PAGE_READONLY Image [ExeTestDllHeapTest; "ExeTestDllHeapTest.exe"][ExeTestDllHeapTest; "ExeTestDllHeapTest.exe"]
0`00d61000 0`00d82000 0`00021000 MEM_IMAGE MEM_COMMIT PAGE_EXECUTE_READ Image 0`00d61000 0`00d82000 0`00021000 MEM_IMAGE MEM_COMMIT PAGE_EXECUTE_READ Image [ExeTestDllHeapTest; "ExeTestDllHeapTest.exe"][ExeTestDllHeapTest; "ExeTestDllHeapTest.exe"]
无用信息
这个地址在windbg 中没有关联其他的heap信息,和通常我们理解的,new delete,malloc,free 都操作的是进程堆,是违背的。
通过ida查看申请操作的详细逻辑:
void *__cdecl _malloc_base(unsigned int size)
.text:00411285 __malloc_base proc near ; CODE XREF: __crt_stdio_output::formatting_buffer::ensure_buffer_is_big_enough<char>(uint)+46↑p
.text:00411285 ; _malloc+6↑j ...
.text:00411285
.text:00411285 size = dword ptr 8
.text:00411285
.text:00411285 mov edi, edi
.text:00411287 push ebp
.text:00411288 mov ebp, esp
.text:0041128A push esi
.text:0041128B mov esi, [ebp+size]
.text:0041128E cmp esi, 0FFFFFFE0h
.text:00411291 ja short loc_4112C3
.text:00411293 test esi, esi
.text:00411295 jnz short loc_4112AE
.text:00411297 inc esi
.text:00411298 jmp short loc_4112AE
.text:0041129A ; ---------------------------------------------------------------------------
.text:0041129A
.text:0041129A loc_41129A: ; CODE XREF: __malloc_base+3A↓j
.text:0041129A call __query_new_mode
.text:0041129F test eax, eax
.text:004112A1 jz short loc_4112C3
.text:004112A3 push esi ; size
.text:004112A4 call __callnewh
.text:004112A9 pop ecx
.text:004112AA test eax, eax
.text:004112AC jz short loc_4112C3
.text:004112AE
.text:004112AE loc_4112AE: ; CODE XREF: __malloc_base+10↑j
.text:004112AE ; __malloc_base+13↑j
.text:004112AE push esi ; dwBytes
.text:004112AF push 0 ; dwFlags
.text:004112B1 push ___acrt_heap ; hHeap//这里我们明显看到了crt 中使用了堆内存,但是windbg 中显然没有堆这部分内存的支持
.text:004112B7 call ds:__imp__HeapAlloc@12 ; HeapAlloc(x,x,x)
.text:004112BD test eax, eax
.text:004112BF jz short loc_41129A
.text:004112C1 jmp short loc_4112D0
.text:004112C3 ; ---------------------------------------------------------------------------
.text:004112C3
.text:004112C3 loc_4112C3: ; CODE XREF: __malloc_base+C↑j
.text:004112C3 ; __malloc_base+1C↑j ...
.text:004112C3 call __errno
.text:004112C8 mov dword ptr [eax], 0Ch
.text:004112CE xor eax, eax
.text:004112D0
.text:004112D0 loc_4112D0: ; CODE XREF: __malloc_base+3C↑j
.text:004112D0 pop esi
.text:004112D1 pop ebp
.text:004112D2 retn
.text:004112D2 __malloc_base endp
确实用的是堆内存,而且是peb 中的系统默认堆,但是windbg 中没有显示这部分的堆内存
使用!peb 检查当前peb,手动查看进程默认堆的细节
0:001> !peb
Wow64 PEB32 at edf000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: Yes
ImageBaseAddress: 0000000000d60000
NtGlobalFlag: 70
NtGlobalFlag2: 0
Ldr 00000000771adca0
*** _PEB_LDR_DATA type was not found...
*** unable to read Ldr table at 00000000771adca0
SubSystemData: 0000000000000000
ProcessHeap: 0000000000c60000
ProcessParameters: 0000000000c61ed8
*** _CURDIR type was not found...
*** _CURDIR type was not found...
WindowTitle: '< Name not readable >'
ImageFile: '< Name not readable >'
CommandLine: '< Name not readable >'
DllPath: '< Name not readable >'
Environment: 0000000000000000
Unable to read Environment string.
查看进程默认堆 0000000000c60000的信息
失败的原因还是,wow 64调试的问题,这块我不是那么熟悉,导致了这么艰难的行进
先跳过这个疑问,在32-bit win7 虚拟机中,用相关指令研究堆的分配情况
- 打开虚拟机的时候发现虚拟机无法执行,相关解决方案见:
- https://bbs.csdn.net/topics/394603510?page=1#post-409297329
####重开一个博客收拾鸡毛