User32.dll,kernel32.dll,shell32.dll,gdi32.dll,rpcrt4.dll,comctl32.dll,advapi32.dll,version.dll等dll代表了Win32 API的基本提供者;
Win32 API中的所有調(diào)用最終都轉(zhuǎn)向了ntdll.dll,再由它轉(zhuǎn)發(fā)至ntoskrnl.exe。ntdll.dll是本機(jī) API用戶模式的終端。真正的接口在ntoskrnl.exe里完成。事實(shí)上,內(nèi)核模式的驅(qū)動(dòng)大部分時(shí)間調(diào)用這個(gè)模塊,如果它們請(qǐng)求系統(tǒng)服務(wù)。Ntdll.dll的主要作用就是讓內(nèi)核函數(shù)的特定子集可以被用戶模式下運(yùn)行的程序調(diào)用。Ntdll.dll通過(guò)軟件中斷int 2Eh進(jìn)入ntoskrnl.exe,就是通過(guò)中斷門切換CPU特權(quán)級(jí)。
Ntdll.dll 上面的相關(guān)API函數(shù)原型和參數(shù)都沒(méi)有文檔化(Undocumented ):
http://undocumented.ntinternals.net/ 這里提供了Ntdll.dll部分未公開函數(shù)的原型.
理解window API及函數(shù)原型對(duì)我們的調(diào)試將是非常重要的: 因?yàn)槟銜r(shí)常需要去察看一些函數(shù)的參數(shù),或者根據(jù)參數(shù)找到某些輸入指針.
例如:
17 Id: a84.cc4 Suspend: 1 Teb: 7ff3a000 Unfrozen
ChildEBP RetAddr Args to Child
187ffdb8 77845e6c 7782fc72 00001938 00000000 ntdll!KiFastSystemCallRet
187ffdbc 7782fc72 00001938 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
187ffe20 7782fb56 00000000 00000000 00000000 ntdll!RtlpWaitOnCriticalSection+0x13e
187ffe48 01b05d13 0x77c8ba60 81fa55ed 028766c8 ntdll!RtlEnterCriticalSection+0x150
從堆棧可以看出線程17 正在進(jìn)入某一個(gè)臨界區(qū). 0x77c8ba60 就是傳入的臨界值 參數(shù).
17> !cs 0x77c8ba60 --> !cs 是用來(lái)查看臨界區(qū)信息的命令
DebugInfo = 0x77fbde20
Critical section = 0x77c8ba60 (GDI32!semColorSpaceCache+0x0)
LOCKED
LockCount = 0x0
OwningThread = 0x00000dd8
RecursionCount = 0x1
LockSemaphore = 0x0
SpinCount = 0x00000000
可以看到 LOCKED 代表臨界區(qū)是鎖定狀態(tài). 即被占用.
OwningThread 即是占用線程.
臨界區(qū)信息結(jié)構(gòu)定義在ntdll, 可以使用如下指令進(jìn)行察看.
> dt ntdll!_RTL_CRITICAL_SECTION
+0x000 DebugInfo : Ptr32 _RTL_CRITICAL_SECTION_DEBUG
+0x004 LockCount : Int4B
+0x008 RecursionCount : Int4B
+0x00c OwningThread : Ptr32 Void
+0x010 LockSemaphore : Ptr32 Void
+0x014 SpinCount : Uint4B
察看某個(gè)動(dòng)態(tài)庫(kù)函數(shù)表的指令:
x ntdll!*
x kernal!*
察看結(jié)構(gòu)體定義:
dt ntdll!*
任何動(dòng)態(tài)庫(kù)包括window 32的用戶態(tài)dll 和用戶自定義動(dòng)態(tài)庫(kù)都是生長(zhǎng)在進(jìn)程內(nèi)存空間上的.
DLL 沒(méi)有自己的"私有"地址空間. 它們總是被影射到應(yīng)用程序的虛擬地址空間,在需要時(shí)才會(huì)被讀取到物理內(nèi)存中.
在本系列的其它章節(jié)我會(huì)談到虛擬地址空間的內(nèi)容.
通過(guò)指令可以看到ntdll 被映射到77800000 ~ 7793c000的內(nèi)存空間中.
> x *!
77800000 7793c000 ntdll (pdb symbols) c:\mylocalsymbols\ntdll.pdb\F0164DA71FAF4765B8F3DB4F2D7650EA2\ntdll.pdb
當(dāng)你的代碼(線程)棧中出現(xiàn)地址范圍在 77800000 ~7793c000 之間的函數(shù)調(diào)用都表示在call NTDLL.dll
比如:
7 Id: a84.c34 Suspend: 1 Teb: 7ff3f000 Unfrozen
ChildEBP RetAddr Args to Child
089bfe8c 77845e6c 75a0179c 00000d98 00000000 ntdll!KiFastSystemCallRet
089bfe90 75a0179c 00000d98 00000000 00000000 ntdll!NtWaitForSingleObject+0xc
089bfefc 75c9f003 00000d98 ffffffff 00000000 KERNELBASE!WaitForSingleObjectEx+0x98
089bff14 75c9efb2 00000d98 ffffffff 00000000 kernel32!WaitForSingleObjectExImplementation+0x75
089bff28 69434fea 00000d98 ffffffff 0780c178 kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
此線程中WARNING: Stack unwind information not available. Following frames may be wrong.表示windbg無(wú)法翻譯或者找到對(duì)應(yīng)symbols來(lái)顯示code stack. 這種錯(cuò)誤往往是保存dump file時(shí)出現(xiàn)的某種異常信息.window也沒(méi)有給出合理的解釋.
以下是MSDN的原話:
In some cases, the stack trace function will fail in the debugger. This can be caused by a call to an invalid address that caused the debugger to lose the location of the return address; or you may have come across a stack pointer for which you cannot directly get a stack trace; or there could be some other debugger problem. In any case, being able to manually walk a stack is often valuable.
這時(shí)候你需要手動(dòng)的進(jìn)行恢復(fù)棧調(diào)用. 如果你了解每個(gè)動(dòng)態(tài)庫(kù)的映射地址你就很容易進(jìn)行分析了.
察看動(dòng)態(tài)庫(kù)中每個(gè)函數(shù)映射的地址可以采用如下指令 :
x ntdll!
手動(dòng)恢復(fù)棧的大致原理如下:
1. 列出線程環(huán)境信息
0:000> !teb
TEB at 7fffe000
ExceptionList: 0012ff88
StackBase: 00130000
StackLimit: 00126000
……….
2. 打開整個(gè)線程棧.
0:000> dds 00126000 00130000
3. 察看內(nèi)存中所有可能是函數(shù)返回值.
>ln address
posted on 2009-08-24 11:20
Only Soft 閱讀(3102)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
Windbg