2017-01-30 34 views
1

我在Windows內部讀取創建線程時,默認情況下1 MB的虛擬內存被保留以供用戶堆棧。在這1 MB中,只有第一頁(0x1000)將被提交。!地址命令顯示給用戶模式堆棧初始不同的值提交大小

我可以看到這個當我轉儲使用DUMPBIN.EXE圖像頭。以下是dumpbin顯示的內容: enter image description here

但是,當我使用!address命令在Windbg中轉儲此exe文件的地址空間時,我看到了不同。 WinDbg中讓我發現,最初承諾的大小等於3頁即0x3000處

有誰知道爲什麼會出現提交初始堆棧之間的差異大小,圖像頭和調試器顯示?

+0

如何(尤其是當?)你連接到進程?你能描述完整的程序嗎?問題是:你真的得到了初始狀態,還是你太晚嘗試了? –

+0

我使用Windbg中的「Open Executable」選項並打開了可執行文件。然後,我嘗試使用address命令查看包括堆棧在內的地址區域。 – Neena

+0

好的,所以你停在最初的斷點處。那很好。 –

回答

2

這是一個很好的問題,關鍵答案是理解初始斷點是什麼。對於初學者來說,它的初始狀態如何?

TLDR:最初的斷點太晚了。該堆棧已經增長。

您還沒有共享您正在處理的二進制,所以我選擇表現出相同的行爲二進制 - cacls.exe在64位Windows 10(文件版本:10.0.14393.0)。

在最初的斷點我們觀察到:

CommandLine: "c:\Windows\System32\cacls.exe" 
Symbol search path is: srv* 
Executable search path is: 
ModLoad: 00007ff6`83bd0000 00007ff6`83bdc000 cacls.exe 
ModLoad: 00007ff8`29ce0000 00007ff8`29eb1000 ntdll.dll 
ModLoad: 00007ff8`27500000 00007ff8`275ab000 C:\Windows\System32\KERNEL32.DLL 
ModLoad: 00007ff8`26f30000 00007ff8`2714d000 C:\Windows\System32\KERNELBASE.dll 
ModLoad: 00007ff8`280b0000 00007ff8`2814e000 C:\Windows\System32\msvcrt.dll 
ModLoad: 00007ff8`29b10000 00007ff8`29bb2000 C:\Windows\System32\advapi32.dll 
ModLoad: 00007ff8`273d0000 00007ff8`27429000 C:\Windows\System32\sechost.dll 
ModLoad: 00007ff8`254f0000 00007ff8`25522000 c:\Windows\System32\NTMARTA.dll 
ModLoad: 00007ff8`27150000 00007ff8`27245000 C:\Windows\System32\ucrtbase.dll 
ModLoad: 00007ff8`277c0000 00007ff8`278e1000 C:\Windows\System32\RPCRT4.dll 
(1310.17b0): Break instruction exception - code 80000003 (first chance) 
ntdll!LdrpDoDebuggerBreak+0x30: 
00007ff8`29db34e0 cc    int  3 
0:000> !dh -f cacls 

File Type: EXECUTABLE IMAGE 
FILE HEADER VALUES 
    8664 machine (X64) 
     6 number of sections 
57899A04 time date stamp Sat Jul 16 05:20:52 2016 

     0 file pointer to symbol table 
     0 number of symbols 
     F0 size of optional header 
     22 characteristics 
      Executable 
      App can handle >2gb addresses 

OPTIONAL HEADER VALUES 
    20B magiC# 
    14.00 linker version 
    4C00 size of code 
    3600 size of initialized data 
     0 size of uninitialized data 
    52F0 address of entry point 
    1000 base of code 
     ----- new ----- 
00007ff683bd0000 image base 
    1000 section alignment 
    200 file alignment 
     3 subsystem (Windows CUI) 
    10.00 operating system version 
    10.00 image version 
    10.00 subsystem version 
    C000 size of image 
    400 size of headers 
    AF10 checksum 
0000000000080000 size of stack reserve 
0000000000002000 size of stack commit 
0000000000100000 size of heap reserve 
0000000000001000 size of heap commit 
    C160 DLL characteristics 
      High entropy VA supported 
      Dynamic base 
      NX compatible 
      Guard 
      Terminal server aware 
     0 [  0] address [size] of Export Directory 
    7010 [  1CC] address [size] of Import Directory 
    A000 [  7F0] address [size] of Resource Directory 
    9000 [  2DC] address [size] of Exception Directory 
     0 [  0] address [size] of Security Directory 
    B000 [  54] address [size] of Base Relocation Directory 
    6A10 [  38] address [size] of Debug Directory 
     0 [  0] address [size] of Description Directory 
     0 [  0] address [size] of Special Directory 
     0 [  0] address [size] of Thread Storage Directory 
    60E0 [  D0] address [size] of Load Configuration Directory 
     0 [  0] address [size] of Bound Import Directory 
    61B0 [  3B8] address [size] of Import Address Table Directory 
     0 [  0] address [size] of Delay Import Directory 
     0 [  0] address [size] of COR20 Header Directory 
     0 [  0] address [size] of Reserved Directory 

0:000> !address @rsp 


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:     Stack 
Base Address:   00000049`8fbbc000 
End Address:   00000049`8fbc0000 
Region Size:   00000000`00004000 ( 16.000 kB) 
State:     00001000   MEM_COMMIT 
Protect:    00000004   PAGE_READWRITE 
Type:     00020000   MEM_PRIVATE 
Allocation Base:  00000049`8fb40000 
Allocation Protect:  00000004   PAGE_READWRITE 
More info:    ~0k 


Content source: 1 (target), length: 180 

我們看到初始堆棧提交大小是爲0x2000,而是0x4000的實際提交。

但是,這已經在進程初始化過程中(沒有雙關語意)很晚。例如,所有導入DLL都已加載。

所謂的「初始斷點」只是一個(或多或少的)硬編碼的int 3指令,由NTDLL中的進程初始化代碼調用。如果你看一下堆在這一點上,你會看到恰當地命名爲LdrpDoDebuggerBreak功能是由LdrpInitializeProcess稱爲:

0:000> k 
# Child-SP   RetAddr   Call Site 
00 00000049`8fbbee80 00007ff8`29d72e22 ntdll!LdrpDoDebuggerBreak+0x30 
01 00000049`8fbbeec0 00007ff8`29da8986 ntdll!LdrpInitializeProcess+0x1962 
02 00000049`8fbbf2c0 00007ff8`29d59fae ntdll!_LdrpInitialize+0x4e982 
03 00000049`8fbbf340 00000000`00000000 ntdll!LdrInitializeThunk+0xe 

通過所發生堆棧已經被使用的時間(例如,加載靜態鏈接DLLs並執行它們的初始化代碼),所以堆棧已經增長不應該感到驚訝。

爲了檢查剛剛創建的進程,我們需要在進程創建事件而不是初始斷點(這不是我們現在理解的最初的斷點)上斷開。

我們可以使用sxe cpr.restart像我這樣做或運行WinDbg/NTSD與-xe cpr。這樣做,揭示了一些有趣的事情:

0:000> .restart 
CommandLine: C:\Windows\System32\cacls.exe 

************* Symbol Path validation summary ************** 
Response       Time (ms)  Location 
Deferred          srv* 
Symbol search path is: srv* 
Executable search path is: 
ModLoad: 00007ff6`83bd0000 00007ff6`83bdc000 cacls.exe 
00007ff8`29d470b0 4883ec48  sub  rsp,48h 

0:000> .imgscan /l 
MZ at 00007ff6`83bd0000, prot 00000002, type 01000000 - size c000 
    Name: cacls.exe 
    Loaded cacls.exe module 
MZ at 00007ff8`29ce0000, prot 00000002, type 01000000 - size 1d1000 
    Name: ntdll.dll 
    Loaded ntdll.dll module 

0:000> !address @rsp 


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:     Stack 
Base Address:   0000004a`5428e000 
End Address:   0000004a`54290000 
Region Size:   00000000`00002000 ( 8.000 kB) 
State:     00001000   MEM_COMMIT 
Protect:    00000004   PAGE_READWRITE 
Type:     00020000   MEM_PRIVATE 
Allocation Base:  0000004a`54210000 
Allocation Protect:  00000004   PAGE_READWRITE 
More info:    ~0k 


Content source: 1 (target), length: 478 

承諾區域大小爲0x2000 - 像頭說!

如果我們讓它繼續,我們最終會得到初始斷點與comitted更多的堆棧。


我說的或多或少的硬編碼,因爲該函數的實際代碼是

0:000> uf ntdll!LdrpDoDebuggerBreak 
ntdll!LdrpDoDebuggerBreak: 
00007ff8`29db34b0 4883ec38  sub  rsp,38h 
00007ff8`29db34b4 488364242000 and  qword ptr [rsp+20h],0 
00007ff8`29db34ba 41b901000000 mov  r9d,1 
00007ff8`29db34c0 4c8d442440  lea  r8,[rsp+40h] 
00007ff8`29db34c5 418d5110  lea  edx,[r9+10h] 
00007ff8`29db34c9 48c7c1feffffff mov  rcx,0FFFFFFFFFFFFFFFEh 
00007ff8`29db34d0 e88b30fdff  call ntdll!NtQueryInformationThread (00007ff8`29d86560) 
00007ff8`29db34d5 85c0   test eax,eax 
00007ff8`29db34d7 780a   js  ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch 

ntdll!LdrpDoDebuggerBreak+0x29: 
00007ff8`29db34d9 807c244000  cmp  byte ptr [rsp+40h],0 
00007ff8`29db34de 7503   jne  ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch 

ntdll!LdrpDoDebuggerBreak+0x30: 
00007ff8`29db34e0 cc    int  3 
00007ff8`29db34e1 eb00   jmp  ntdll!LdrpDoDebuggerBreak+0x33 (00007ff8`29db34e3) Branch 

ntdll!LdrpDoDebuggerBreak+0x33: 
00007ff8`29db34e3 4883c438  add  rsp,38h 
00007ff8`29db34e7 c3    ret 

它做的東西像檢查該線程是否是要「從調試器隱藏」 ,但基本上它只是闖入調試器。

.imgscan /l需要的,因爲沒有它,我們得到:

0:000> !address @rsp 

No symbols for ntdll. Cannot continue. 
+0

太棒了,現在有道理。我嘗試着像你解釋的那樣打破進程創建,並且能夠看到初始堆棧的大小與我們在圖像頭中看到的大小相同。感謝您的幫助。 – Neena