在线亚洲+欧美+日本专区,亚洲伦理一区,欧美日本精品一区二区三区http://www.shnenglu.com/ay19880703/category/8298.htmlzh-cnMon, 31 Oct 2011 11:46:27 GMTMon, 31 Oct 2011 11:46:27 GMT60WINDBG的堆調(diào)試--了解HEAP組織http://www.shnenglu.com/ay19880703/archive/2011/10/30/159364.html__ay__aySun, 30 Oct 2011 11:05:00 GMThttp://www.shnenglu.com/ay19880703/archive/2011/10/30/159364.htmlhttp://www.shnenglu.com/ay19880703/comments/159364.htmlhttp://www.shnenglu.com/ay19880703/archive/2011/10/30/159364.html#Feedback0http://www.shnenglu.com/ay19880703/comments/commentRss/159364.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/159364.html@作者: ay @文章出處: cnss-ay的博客@Notice: 轉(zhuǎn)載請(qǐng)注明出處!若文章顯示不完整,可以到文章出處閱讀。

HEAP的概念

堆棧堆棧,在操作系統(tǒng)內(nèi)存中有兩種存儲(chǔ)空間,一個(gè)是堆,一個(gè)是棧。堆主要用于存儲(chǔ)用戶動(dòng)態(tài)分配的變量,而棧呢,則是存儲(chǔ)我們程序過(guò)程中的臨時(shí)變量。當(dāng)然棧的作用遠(yuǎn)不止用作存儲(chǔ)變量,但這不是我們這篇文章的討論內(nèi)容。

?

堆(HEAP)的分配,使用,回收都是通過(guò)微軟的API來(lái)管理的,最常見的API是malloc和new。在往底層走一點(diǎn)呢,這兩個(gè)函數(shù)都會(huì)調(diào)用HeapAlloc(RtlAllocateHeap)。同樣的相關(guān)函數(shù)還有HeapFree用來(lái)釋放堆,HeapCreate用來(lái)創(chuàng)建自己的私有堆。下面是這些函數(shù)的調(diào)用鏈:

HeapCreate->RtlCreateHeap->ZwAllocateVirtualMemory? (這里會(huì)直接申請(qǐng)一大片內(nèi)存,至于申請(qǐng)多大內(nèi)存,由進(jìn)程PEB結(jié)構(gòu)中的字段覺得,HeapSegmentReserve字段指出要申請(qǐng)多大的虛擬內(nèi)存,HeapSegmentCommit指明要提交多大內(nèi)存,對(duì)虛擬內(nèi)存的申請(qǐng)和提交概念不清楚的童鞋,請(qǐng)參見windows核心編程相關(guān)內(nèi)容~)

HeapAlloc->RtlAllocateHeap(至于這里申請(qǐng)的內(nèi)存,由于HeapCreate已經(jīng)申請(qǐng)了一大片內(nèi)存,堆管理器這片內(nèi)存中劃分一塊出來(lái)以滿足申請(qǐng)的需要。這一步申請(qǐng)操作是堆管理器自己維護(hù)的,僅當(dāng)申請(qǐng)內(nèi)存不夠的時(shí)候才會(huì)再次調(diào)用ZwAllocateVirtualMemory

HeapFree->RtlFreeHeap (對(duì)于釋放的內(nèi)存,堆管理器只是簡(jiǎn)單的把這塊內(nèi)存標(biāo)志位已釋放讓后加入到空閑列表中,僅當(dāng)空閑的內(nèi)存達(dá)到一定閥值的時(shí)候會(huì)調(diào)用ZwFreeVirtualMeMory

HeapDestroy->RtlDestroyHeap->ZwFreeVirtualMeMory?? (銷毀我們申請(qǐng)的堆)

如何找到我們的HEAP信息?

WINDBG觀察堆

源碼:

#include "windows.h"

int main()
{
	HANDLE heap_handle = HeapCreate( NULL , 0x1000 , 0x2000 ) ;

	char *buffer = (char*)HeapAlloc(heap_handle , NULL , 128) ;

	char *buffer1 = (char*)HeapAlloc(heap_handle , NULL , 121) ;

	HeapFree(heap_handle, 0 , buffer ) ;
	HeapFree(heap_handle, 0 , buffer1 ) ;

	HeapDestroy( heap_handle) ;
	return 0 ;
}

該源碼生成編譯生成heap.exe,然后用windbg調(diào)試這個(gè)程序,在main函數(shù)下斷,緊接著執(zhí)行第五行語(yǔ)句,執(zhí)行結(jié)果如下

0:000> p
eax=002e1ca0 ebx=00000000 ecx=6d29b6f0 edx=00000000 esi=00000001 edi=01033374
eip=01031012 esp=0022fe8c ebp=0022feac iopl=0???????? nv up ei pl nz na po nc
cs=001b? ss=0023? ds=0023? es=0023? fs=003b? gs=0000???????????? efl=00000202
heap!main+0x12:
01031012 ff150c200301??? call??? dword ptr [heap!_imp__HeapCreate (0103200c)] ds:0023:0103200c={kernel32!HeapCreateStub (769a29d7)}

0:000> p
eax=002c0000 ebx=00000000 ecx=77429897 edx=77498500 esi=00000001 edi=01033374
eip=01031018 esp=0022fe98 ebp=0022feac iopl=0???????? nv up ei pl nz na pe nc
cs=001b? ss=0023? ds=0023? es=0023? fs=003b? gs=0000???????????? efl=00000206
heap!main+0x18:
01031018 8945fc????????? mov???? dword ptr [ebp-4],eax ss:0023:0022fea8=6d222201
0:000> !heap
Index?? Address? Name????? Debugging options enabled
? 1:?? 00300000???????????????
? 2:?? 00010000???????????????
? 3:?? 00020000???????????????
? 4:?? 002e0000???????????????
? 5:?? 002c0000??????

HeapCreate執(zhí)行的返回值存放在eax處,這個(gè)函數(shù)返回了一個(gè)堆句柄:0x002c0000。用!heap命令查看可以看到第五個(gè)堆就是我們創(chuàng)建的堆句柄了。

每個(gè)進(jìn)程都存在多個(gè)堆,我們也可以通過(guò)PEB結(jié)構(gòu)來(lái)得到進(jìn)程中存在的堆,結(jié)果和!heap命令顯示的內(nèi)容是一樣的。

heap!_PEB
?? +0x018 ProcessHeap????? : 0x00300000 Void???????? ; 進(jìn)程的默認(rèn)堆
?? +0x068 NtGlobalFlag???? : 0?????????????????????????????????????? ; 這個(gè)標(biāo)志位記錄了當(dāng)前堆調(diào)試模式,0為普通調(diào)試模式
?? +0x078 HeapSegmentReserve : 0x100000????????? ; 進(jìn)程在新建堆的時(shí)候默認(rèn)申請(qǐng)的虛擬內(nèi)存大小
?? +0x07c HeapSegmentCommit : 0x2000?????????????? ; 進(jìn)程在每次申請(qǐng)?zhí)峤坏奶摂M內(nèi)存大小,在提交的內(nèi)存用完后,進(jìn)程會(huì)又在一次提交HeapSegmentCommit中指定的內(nèi)存大小
?? +0x080 HeapDeCommitTotalFreeThreshold : 0x10000??? ; 當(dāng)釋放的內(nèi)存大小大于這個(gè)閥值,就進(jìn)行內(nèi)存解除提交操作
?? +0x084 HeapDeCommitFreeBlockThreshold : 0x1000???? ;? 當(dāng)一次性釋放的塊大小超過(guò)這個(gè)閥值,就進(jìn)行內(nèi)存解除提交操作,只有當(dāng)滿足這兩個(gè)條件時(shí)才會(huì)調(diào)用ZwFreeVirtualMeMory 釋放物理內(nèi)存
?? +0x088 NumberOfHeaps??? : 5?????????????????????????????????????????????? ; 當(dāng)前進(jìn)程的堆數(shù)目,這個(gè)數(shù)目對(duì)應(yīng)著!heap命令的堆顯示個(gè)數(shù)
?? +0x08c MaximumNumberOfHeaps : 0x10????????????????????????? ; 進(jìn)程所能運(yùn)行的最大堆數(shù)目,若堆數(shù)目超過(guò)這個(gè)值估計(jì)HeapCreate就失敗了吧
?? +0x090 ProcessHeaps???? : 0x77498500? -> 0x00300000 Void ;存儲(chǔ)堆句柄的數(shù)組,這里我們可以得到進(jìn)程的所有堆句柄

我們可以輸入如下命令來(lái)查看現(xiàn)有的堆句柄

0:000> dd 0x77498500?
77498500? 00300000 00010000 00020000 002e0000
77498510? 002c0000 00000000 00000000 00000000
77498520? 00000000 00000000 00000000 00000000
77498530? 00000000 00000000 00000000 00000000
77498540? 00000000 77498340 7749bb08 77498220
77498550? 00000000 00000000 00000000 00000000
77498560? 77498220 00317bd0 00000000 00000000
77498570? 00000000 00000000 00000000 00000000

可以看得到這里面的內(nèi)容和!heap命令的輸出結(jié)果是一樣的

而堆句柄的存放范圍,從MaximumNumberOfHeaps 上來(lái)看,就是77498500-77498540這0x40個(gè)字節(jié),因?yàn)槊總€(gè)堆句柄占4個(gè)字節(jié),0x10個(gè)堆句柄的存放空間就是0x40。

HEAP的組織結(jié)構(gòu)

堆的管理,我們可以理解為一個(gè)內(nèi)存池,它申請(qǐng)一大塊空間,然后負(fù)責(zé)接管應(yīng)用程序的申請(qǐng)釋放等請(qǐng)求。只有在創(chuàng)建堆,釋放堆(注意!是釋放堆,不是堆中的空間!)在這之前,我們需要對(duì)堆有關(guān)的數(shù)據(jù)結(jié)構(gòu)做一些解釋

我這里觀察到的HEAP結(jié)構(gòu),HEAP_SEGMENT結(jié)構(gòu)和HEAP_ENTRY結(jié)構(gòu)都和軟件調(diào)試?yán)锩婷枋龅牟灰粯樱?dāng)年奎哥寫軟件調(diào)試的時(shí)候估計(jì)還沒(méi)用上WIN7吧。。。我的演示系統(tǒng)是WIN7

HeapCreate函數(shù)返回的堆句柄其實(shí)就是一個(gè)指向堆管理結(jié)構(gòu)的指針,每個(gè)堆都會(huì)涉及到這樣三個(gè)結(jié)構(gòu):HEAP,HEAP_SEGMENT,HEAP_ENTRY

HEAP_ENTRY結(jié)構(gòu):

在堆管理中,每一塊申請(qǐng)下來(lái)的內(nèi)存都會(huì)有下面所示的固定模式:

HEAP_ENTRY(8 bytes)

我們new或malloc分配的空間

固定填充空間

這個(gè)結(jié)構(gòu)用來(lái)記錄所分配的空間的信息,包括用戶申請(qǐng)的空間,填充的空間,所在的段號(hào)等等信息。所以我們new或者malloc的地址減去8就指向該結(jié)構(gòu)。第三部分的固定填充空間是為了內(nèi)存對(duì)齊而生成的,當(dāng)然這部分空間還有一部分是用來(lái)額外記錄這塊內(nèi)存的其它信息,這里就不詳細(xì)做介紹了。

HEAP_SEGMENT結(jié)構(gòu):

我們可以這么認(rèn)為,堆申請(qǐng)內(nèi)存的大小是以段為單位的,當(dāng)新建一個(gè)堆的時(shí)候,系統(tǒng)會(huì)默認(rèn)為這個(gè)堆分配一個(gè)段叫0號(hào)段,通過(guò)剛開始的new和malloc分配的空間都是在這個(gè)段上分配的,當(dāng)這個(gè)段用完的時(shí)候,如果當(dāng)初創(chuàng)建堆的時(shí)候指明了HEAP_GROWABLE這個(gè)標(biāo)志,那么系統(tǒng)會(huì)為這個(gè)堆在再分配一個(gè)段,這個(gè)時(shí)候新分配的段就稱為1號(hào)段了,以下以此類推。每個(gè)段的開始初便是HEAP_SEGMENT結(jié)構(gòu)的首地址,由于這個(gè)結(jié)構(gòu)也是申請(qǐng)的一塊內(nèi)存,所以它前面也會(huì)有個(gè)HEAP_ENTRY結(jié)構(gòu):

HEAP_ENTRY(8 bytes)

HEAP_SEGMENT

HEAP_ENTRY(8 bytes)

我們new或malloc分配的空間

固定填充空間

HEAP_SEGMENT結(jié)構(gòu)會(huì)記錄段的一些基本信息,該段申請(qǐng)的大小,已經(jīng)提交內(nèi)存的大小,第一個(gè)HEAP_ENTRY結(jié)構(gòu)的入口點(diǎn)。(我觀察看貌似段申請(qǐng)的內(nèi)存并不會(huì)一次性全部提交,而是每次提交一個(gè)頁(yè)的大小,比如一個(gè)段大小2個(gè)頁(yè),那么它會(huì)先提交一個(gè)頁(yè)內(nèi)存,若用完了再提交一個(gè)頁(yè)的內(nèi)存,若內(nèi)存還用完了那就新建一個(gè)段,這個(gè)新建的段也會(huì)是先提交一個(gè)頁(yè)內(nèi)存。)但是0號(hào)段很特別,這個(gè)段的起始地址就是堆句柄指針指向的值,也就是說(shuō),HeapCreate返回的堆句柄總是指向0號(hào)段,為什么呢?因?yàn)镠EAP結(jié)構(gòu)是HEAP_ENTRY,HEAP_SEGMENT的合體加長(zhǎng)版~

HEAP結(jié)構(gòu):

HEAP結(jié)構(gòu)則是記錄了這個(gè)堆的信息,這個(gè)結(jié)構(gòu)可以找到HEAP_SEGMENT鏈表入口,空閑內(nèi)存鏈表的入口,內(nèi)存分配粒度等等信息。HEAP的首地址便是堆句柄的值,但是堆句柄的值又是0號(hào)段的首地址也是堆句柄,何解?其實(shí)很簡(jiǎn)單,0號(hào)段的HEAP_SEGMENT就在HEAP結(jié)構(gòu)里面,HEAP結(jié)構(gòu)類定義如這樣:

struct _HEAP

{

_HEAP_ENTRY Entry ; //HEAP_ENTRY結(jié)構(gòu),用來(lái)描述存儲(chǔ)HEAP內(nèi)存塊大小等信息的

_HEAP_SEGMENT Segment ;  //0號(hào)段的首地址

……  //對(duì)于該HEAP的描述信息

} ;

在我們看來(lái),內(nèi)存組織結(jié)構(gòu)應(yīng)該如下所示:

HEAP_ENTRY(8 bytes)

HEAP_SEGMENT

HEAP

更確切的說(shuō),HEAP結(jié)構(gòu)中本身就包含了HEAP_ENTRY和HEAP_SEGMENT,HEAP_ENTRY結(jié)構(gòu)是HEAP的第一個(gè)數(shù)據(jù)成員,HEAP_SEGMENT是它第二個(gè)數(shù)據(jù)成員。而對(duì)于HEAP_SEGMENT,它的第一個(gè)數(shù)據(jù)成員便是HEAP_ENTRY。這里為了方便理解,才在內(nèi)存組織結(jié)構(gòu)中把它們拆開展示。(注:這里是win7的情況,和軟件調(diào)試這本書中所描述的有一些差異,也屬正常現(xiàn)象,畢竟這部分結(jié)構(gòu)微軟并未公開)

用WINDBG觀察HEAP結(jié)構(gòu)

在之前已經(jīng)演示了如何從PEB結(jié)構(gòu)中找到所有的堆句柄,可以看到002c0000便是我們創(chuàng)建的句柄。然后我們執(zhí)示例程序的第7行代碼。執(zhí)行完后結(jié)果如下:

0:000> p
eax=002c0000 ebx=00000000 ecx=77429897 edx=77498500 esi=00000001 edi=01033374
eip=01031026 esp=0022fe8c ebp=0022feac iopl=0???????? nv up ei pl nz na pe nc
cs=001b? ss=0023? ds=0023? es=0023? fs=003b? gs=0000???????????? efl=00000206
heap!main+0x26:
01031026 ff1500200301??? call??? dword ptr [heap!_imp__HeapAlloc (01032000)] ds:0023:01032000={ntdll!RtlAllocateHeap (774120b5)}
0:000> p
eax=002c0590 ebx=00000000 ecx=774134b4 edx=002c0180 esi=00000001 edi=01033374
eip=0103102c esp=0022fe98 ebp=0022feac iopl=0???????? nv up ei pl zr na pe nc
cs=001b? ss=0023? ds=0023? es=0023? fs=003b? gs=0000???????????? efl=00000246
heap!main+0x2c:
0103102c 8945f0????????? mov???? dword ptr [ebp-10h],eax ss:0023:0022fe9c={heap!envp (0103301c)}

可以看到EAX保存的返回值為002c0590。我們通過(guò)兩種途徑來(lái)觀察我們申請(qǐng)的內(nèi)存,通過(guò)!heap命令觀察和通過(guò)dt命令觀察

通過(guò)!heap命令觀察

輸入命令!heap –a 2c0590得到的結(jié)果如下:

0:000> !heap -a 2c0000
Index?? Address? Name????? Debugging options enabled
? 5:?? 002c0000
??? Segment at 002c0000 to 002c2000 (00001000 bytes committed)
??? Flags:??????????????? 00001000
??? ForceFlags:?????????? 00000000
??? Granularity:????????? 8 bytes
??? Segment Reserve:????? 00100000
??? Segment Commit:?????? 00002000
??? DeCommit Block Thres: 00000200
??? DeCommit Total Thres: 00002000
??? Total Free Size:????? 0000013a
??? Max. Allocation Size: 7ffdefff
??? Lock Variable at:???? 002c0138
??? Next TagIndex:??????? 0000
??? Maximum TagIndex:???? 0000
??? Tag Entries:????????? 00000000
??? PsuedoTag Entries:??? 00000000
??? Virtual Alloc List:?? 002c00a0
??? Uncommitted ranges:?? 002c0090
??????????? 002c1000: 00001000? (4096 bytes)
??? FreeList[ 00 ] at 002c00c4: 002c0618 . 002c0618?
??????? 002c0610: 00088 . 009d0 [100] - free

??? Segment00 at 002c0000:
??????? Flags:?????????? 00000000
??????? Base:??????????? 002c0000
??????? First Entry:???? 002c0588
??????? Last Entry:????? 002c2000
??????? Total Pages:???? 00000002
??????? Total UnCommit:? 00000001
??????? Largest UnCommit:00000000
??????? UnCommitted Ranges: (1)

??? Heap entries for Segment00 in Heap 002c0000
??????? 002c0000: 00000 . 00588 [101] - busy (587)
??????? 002c0588: 00588 . 00088 [101] - busy (80)
??????? 002c0610: 00088 . 009d0 [100]
??????? 002c0fe0: 009d0 . 00020 [111] - busy (1d)
??????? 002c1000:????? 00001000????? - uncommitted bytes.

這個(gè)命令分別提煉出了HEAP(綠色區(qū)域),HEAP_SEGMENT(紅色區(qū)域)和HEAP_ENTRY(灰色區(qū)域)結(jié)構(gòu)中的信息。雖然在灰色區(qū)域中,我們找不到2c0590,但是找到了一個(gè)2c0588,這個(gè)正是2c0590-8的結(jié)果,也就是說(shuō)最右邊的地址是每個(gè)HEAP_ENTRY的首地址,接著00588這個(gè)字段表示了前面一個(gè)HEAP_ENTRY所占用的大小,后面的0088表示這個(gè)內(nèi)存塊的總大小,即我們申請(qǐng)的內(nèi)存+HEAP_ENTRY(128+8=0x80+0x8=0x88),[101]是這塊內(nèi)存的標(biāo)志位,最右邊一位為1表示該內(nèi)存塊被占用。然后busy(80)就是解釋說(shuō)這塊內(nèi)存是被占用的(非空閑的),它申請(qǐng)的內(nèi)存為0x80,轉(zhuǎn)化成十進(jìn)制正好就是我們申請(qǐng)的128字節(jié)大小。

但是這里用dt _HEAP_ENTRY 2c0588命令卻沒(méi)辦法查看對(duì)應(yīng)的結(jié)構(gòu)信息,真是怪哉,有篇博文也提到win2008中HEAP相關(guān)結(jié)構(gòu)也有變,看來(lái)到NT6后,HEAP結(jié)構(gòu)變得不小,起碼windbg中直接dt HEAP_ENTRY是無(wú)法原始數(shù)據(jù)的了,貌似對(duì)HEAP_ENTRY做了編碼。

通過(guò)dt命令觀察

同樣的,已知HEAP的首地址,那么先從HEAP下手好了,dt _HEAP 002c0000可以顯示HEAP的數(shù)據(jù)結(jié)構(gòu)

ntdll!_HEAP
?? +0x000 Entry??????????? : _HEAP_ENTRY
?? +0x008 SegmentSignature : 0xffeeffee??
?? +0x00c SegmentFlags???? : 0
?? +0x010 SegmentListEntry : _LIST_ENTRY [ 0x2c00a8 - 0x2c00a8 ]
?? +0x018 Heap???????????? : 0x002c0000 _HEAP
?? +0x01c BaseAddress????? : 0x002c0000 Void
?? +0x020 NumberOfPages??? : 2
?? +0x024 FirstEntry?????? : 0x002c0588 _HEAP_ENTRY
?? +0x028 LastValidEntry?? : 0x002c2000 _HEAP_ENTRY
?? +0x02c NumberOfUnCommittedPages : 1
?? +0x030 NumberOfUnCommittedRanges : 1
?? +0x034 SegmentAllocatorBackTraceIndex : 0
?? +0x036 Reserved???????? : 0
?? +0x038 UCRSegmentList?? : _LIST_ENTRY [ 0x2c0ff0 - 0x2c0ff0 ]

?? +0x040 Flags??????????? : 0x1000
?? +0x044 ForceFlags?????? : 0
?? +0x048 CompatibilityFlags : 0
?? +0x04c EncodeFlagMask?? : 0x100000
?? +0x050 Encoding???????? : _HEAP_ENTRY
?? +0x058 PointerKey?????? : 0x17c06e63
?? +0x05c Interceptor????? : 0
?? +0x060 VirtualMemoryThreshold : 0xfe00
?? +0x064 Signature??????? : 0xeeffeeff
?? +0x068 SegmentReserve?? : 0x100000
?? +0x06c SegmentCommit??? : 0x2000
?? +0x070 DeCommitFreeBlockThreshold : 0x200
?? +0x074 DeCommitTotalFreeThreshold : 0x2000
?? +0x078 TotalFreeSize??? : 0x13a
?? +0x07c MaximumAllocationSize : 0x7ffdefff
?? +0x080 ProcessHeapsListIndex : 5
?? +0x082 HeaderValidateLength : 0x138
?? +0x084 HeaderValidateCopy : (null)
?? +0x088 NextAvailableTagIndex : 0
?? +0x08a MaximumTagIndex? : 0
?? +0x08c TagEntries?????? : (null)
?? +0x090 UCRList????????? : _LIST_ENTRY [ 0x2c0fe8 - 0x2c0fe8 ]
?? +0x098 AlignRound?????? : 0xf
?? +0x09c AlignMask??????? : 0xfffffff8
?? +0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x2c00a0 - 0x2c00a0 ]
?? +0x0a8 SegmentList????? : _LIST_ENTRY [ 0x2c0010 - 0x2c0010 ]
?? +0x0b0 AllocatorBackTraceIndex : 0
?? +0x0b4 NonDedicatedListLength : 0
?? +0x0b8 BlocksIndex????? : 0x002c0150 Void
?? +0x0bc UCRIndex???????? : (null)
?? +0x0c0 PseudoTagEntries : (null)
?? +0x0c4 FreeLists??????? : _LIST_ENTRY [ 0x2c0618 - 0x2c0618 ]
?? +0x0cc LockVariable???? : 0x002c0138 _HEAP_LOCK
?? +0x0d0 CommitRoutine??? : 0x17c06e63???? long? +17c06e63
?? +0x0d4 FrontEndHeap???? : (null)
?? +0x0d8 FrontHeapLockCount : 0
?? +0x0da FrontEndHeapType : 0 ''
?? +0x0dc Counters???????? : _HEAP_COUNTERS
?? +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS
就如本文前面所述的,第一個(gè)字段是HEAP_ENTRY結(jié)構(gòu),接著應(yīng)該是HEAP_SEGMENT,這里只不過(guò)把HEAP_SEGMENT結(jié)構(gòu)的字段展開了,可以dt _HEAP_SEGMENT來(lái)觀察下這個(gè)結(jié)構(gòu)的字段

0:000> dt _heap_segment
ntdll!_HEAP_SEGMENT
?? +0x000 Entry??????????? : _HEAP_ENTRY
?? +0x008 SegmentSignature : Uint4B
?? +0x00c SegmentFlags???? : Uint4B
?? +0x010 SegmentListEntry : _LIST_ENTRY
?? +0x018 Heap???????????? : Ptr32 _HEAP
?? +0x01c BaseAddress????? : Ptr32 Void
?? +0x020 NumberOfPages??? : Uint4B
?? +0x024 FirstEntry?????? : Ptr32 _HEAP_ENTRY
?? +0x028 LastValidEntry?? : Ptr32 _HEAP_ENTRY
?? +0x02c NumberOfUnCommittedPages : Uint4B
?? +0x030 NumberOfUnCommittedRanges : Uint4B
?? +0x034 SegmentAllocatorBackTraceIndex : Uint2B
?? +0x036 Reserved???????? : Uint2B
?? +0x038 UCRSegmentList?? : _LIST_ENTRY

可以看到HEAP結(jié)構(gòu)中灰色部分是和HEAP_SEGMENT結(jié)構(gòu)中的字段是重復(fù)的,也就是說(shuō)灰色部分字段便是HEAP_SEGMENT結(jié)構(gòu)。在HEAP_SEGMENT結(jié)構(gòu)中,我們可以找到FirstEntry字段,這里指的便是我們的分配的內(nèi)存,不過(guò)HEAP_ENTRY結(jié)構(gòu)無(wú)法觀察,這里便沒(méi)辦法枚舉出所有的HEAP_ENTRY結(jié)構(gòu)了,但是說(shuō)一下思路:

每個(gè)HEAP_ENTRY和它對(duì)應(yīng)的內(nèi)存我們可以稱為一個(gè)內(nèi)存塊,計(jì)算下一個(gè)內(nèi)存塊需要用到現(xiàn)有內(nèi)存塊中的2個(gè)字段,Size和UnsedBytes,Size的值乘上粒度(就是0:000> !heap -a 2c0000命令顯示的信息中的Granularity: 8 bytes字段,這里是8字節(jié)),下一個(gè)內(nèi)存塊地址就是 本內(nèi)存塊地址+Size*8+UnsedBytes。當(dāng)然這里的粒度可以通過(guò)HEAP字段中的AlignMask 字段算出來(lái)。

HEAP的分配粒度

在HEAP結(jié)構(gòu)中指明了分配粒度,這個(gè)分配粒度是說(shuō)每次堆分配的時(shí)候,都以這個(gè)粒度為最小單位,這里看到粒度為8字節(jié)。所以這里就有了第二次分配內(nèi)存的實(shí)驗(yàn),我們讓程序執(zhí)行第9行,然后用!heap -a 002c0000觀察分配情況

Heap entries for Segment00 in Heap 002c0000
??? 002c0000: 00000 . 00588 [101] - busy (587)
??? 002c0588: 00588 . 00088 [101] - busy (80)
??? 002c0610: 00088 . 00088 [101] - busy (79)
??? 002c0698: 00088 . 00948 [100]
??? 002c0fe0: 00948 . 00020 [111] - busy (1d)
??? 002c1000:????? 00001000????? - uncommitted bytes.

這里可以看出多出了一個(gè)占用塊,大小是0x79(121) bytes,但是實(shí)際分配的大小還是0x 88 (128)bytes,這是因?yàn)橄到y(tǒng)是以8 bytes為粒度分配的,所以為這塊121 bytes的內(nèi)存自動(dòng)填充了7個(gè)字節(jié),可見申請(qǐng)121 bytes和申請(qǐng)128 bytes所使用的空間是一樣的。

HEAP的釋放和銷毀

執(zhí)行了11行和12行的代碼后,堆中的內(nèi)容分別如下:

執(zhí)行11行代碼的堆情況

FreeList[ 00 ] at 002c00c4: 002c06a0 . 002c0590?
??? 002c0588: 00588 . 00088 [100] – free?? ;空閑列表中多出了一塊內(nèi)存
??? 002c0698: 00088 . 00948 [100] – free?? ;空閑內(nèi)存,空閑空間為948

Heap entries for Segment00 in Heap 002c0000
002c0000: 00000 . 00588 [101] - busy (587)
002c0588: 00588 . 00088 [100]?? ;原先的這塊內(nèi)存釋放掉了
002c0610: 00088 . 00088 [101] - busy (79)
002c0698: 00088 . 00948 [100]??? ; 空閑內(nèi)存
002c0fe0: 00948 . 00020 [111] - busy (1d)
002c1000: 00001000 - uncommitted bytes.

執(zhí)行12行代碼的堆情況

FreeList[ 00 ] at 005c00c4: 005c0590 . 005c0590?
??? 005c0588: 00588 . 00a58 [100] – free ;回收了buffer1的內(nèi)存后,由于由于空閑內(nèi)存是連續(xù)的,所以直接合并成一塊內(nèi)存。可以看到之前內(nèi)存free空間是948,現(xiàn)在合并了以后便是948+88+88=a58,也就是當(dāng)前內(nèi)存大小

Heap entries for Segment00 in Heap 005c0000
??? 005c0000: 00000 . 00588 [101] - busy (587)
??? 005c0588: 00588 . 00a58 [100]
??? 005c0fe0: 00a58 . 00020 [111] - busy (1d)
??? 005c1000:????? 00001000????? - uncommitted bytes.

最后執(zhí)行14行代碼,對(duì)堆進(jìn)行釋放,釋放后我們通過(guò)!heap也可以看到只有4個(gè)堆了,我們申請(qǐng)的堆被釋放了.

0:000> !heap
Index Address Name Debugging options enabled
1: 00300000
2: 00010000
3: 00020000
4: 002e0000

?

至于HEAP_ENTRY結(jié)構(gòu)的問(wèn)題,有時(shí)間在調(diào)試看看是怎么回事吧~另外,這里說(shuō)明下,new和malloc內(nèi)部都會(huì)調(diào)用HeapAlloc來(lái)申請(qǐng)內(nèi)存,但是堆句柄從哪來(lái)呢?它會(huì)檢測(cè)_crtheap變量是否為空,若不為空則拿_crtheap變量來(lái)作為自己的堆句柄去調(diào)用HeapAlloc

參考:

軟件調(diào)試??? 張奎銀

MSDN???

React OS



]]>
內(nèi)核下進(jìn)行浮點(diǎn)運(yùn)算http://www.shnenglu.com/ay19880703/archive/2009/06/06/86940.html__ay__aySat, 06 Jun 2009 12:19:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/06/06/86940.htmlhttp://www.shnenglu.com/ay19880703/comments/86940.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/06/06/86940.html#Feedback0http://www.shnenglu.com/ay19880703/comments/commentRss/86940.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/86940.html
?1?????KFLOATING_SAVE?saveData?;
?2?????NTSTATUS?status;
?3?????int?i?=?0?;
?4?????double?tem?=?0?,?sum?=?0??;
?5?
?6?????//////////開啟浮點(diǎn)運(yùn)算環(huán)境
?7?????status?=?KeSaveFloatingPointState(&saveData);
?8?
?9?????if?(?!?NT_SUCCESS(status))
10?????????return?;
11?
12?????//浮點(diǎn)運(yùn)算操作
13?
14?????????//////////關(guān)閉浮點(diǎn)運(yùn)算環(huán)境
15?????KeRestoreFloatingPointState(&saveData);


內(nèi)核下進(jìn)行浮點(diǎn)運(yùn)算很特殊~~
正確操作應(yīng)該向上面代碼一樣

在貼個(gè)抄來(lái)的內(nèi)核sleep()函數(shù)

1?void?KeSleep(ULONG?uMiniseconds)
2?{
3?????KTIMER?ktimer;
4?????LARGE_INTEGER?liTimerout;
5?????liTimerout.QuadPart=-(LONG)(uMiniseconds*10000);
6?????KeInitializeTimer(&ktimer);
7?????KeWaitForSingleObject(&ktimer,Executive,KernelMode,FALSE,&liTimerout);
8?}

不過(guò)效率貌似有待改進(jìn)....有時(shí)間在說(shuō)吧~~那個(gè)xxxdelay函數(shù)也可以的


]]>
內(nèi)核部分筆記 --- 在內(nèi)核下把文件的內(nèi)容寫入內(nèi)存中 http://www.shnenglu.com/ay19880703/archive/2009/06/06/86938.html__ay__aySat, 06 Jun 2009 12:12:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/06/06/86938.htmlhttp://www.shnenglu.com/ay19880703/comments/86938.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/06/06/86938.html#Feedback0http://www.shnenglu.com/ay19880703/comments/commentRss/86938.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/86938.html
?1?????NTSTATUS?Status?;
?2?????HANDLE?fhandle?;
?3?????UNICODE_STRING?????ConfigFileName?;
?4?????OBJECT_ATTRIBUTES??objAttr??;
?5?????IO_STATUS_BLOCK????ioStatusBlock?;?
?6?????FILE_STANDARD_INFORMATION?FileInfo?;
?7?????LONG??BytesRead?;
?8?????UCHAR?*buf??=?NULL?;
?9?
10?????RtlInitUnicodeString(?&ConfigFileName,?FilePath?)?;??
11?????InitializeObjectAttributes(
12?????????&objAttr,
13?????????&ConfigFileName,
14?????????OBJ_CASE_INSENSITIVE?|?OBJ_KERNEL_HANDLE,
15?????????NULL,
16?????????NULL?)?;
17?
18?????Status?=?ZwCreateFile(
19?????????&fhandle?,
20?????????SYNCHRONIZE?|?FILE_READ_DATA,
21?????????&objAttr,
22?????????&ioStatusBlock,
23?????????NULL,
24?????????FILE_ATTRIBUTE_NORMAL,
25?????????0,
26?????????FILE_OPEN_IF,
27?????????FILE_SYNCHRONOUS_IO_NONALERT,
28?????????NULL,
29?????????0
30?????????)?;
31?
32?????if(?!NT_SUCCESS(Status)?)
33?????{
34?????????DbgPrint("Create?file?filed?\n")?;
35?????????*BufferAddress?=?NULL?;
36?????????*BufferSize?=?0?;
37?????????return?;
38?????}
39?
40?????Status?=?ZwQueryInformationFile(fhandle,
41?????????&ioStatusBlock,
42?????????&FileInfo,
43?????????sizeof(FILE_STANDARD_INFORMATION),
44?????????FileStandardInformation);
45?
46?????//注意??這里只取了低32位.一般文件大不過(guò)4G?
47?????BytesRead?=?FileInfo.EndOfFile.LowPart?;
48?????buf?=?ExAllocatePool(PagedPool??,?BytesRead)?;
49?????//NdisAllocateMemory(&buf,BytesRead,TAG);
50?
51?????ZwReadFile(
52?????????fhandle?,
53?????????NULL?,?
54?????????NULL?,
55?????????NULL?,
56?????????&ioStatusBlock?,
57?????????buf?,
58?????????BytesRead?,?
59?????????NULL?,
60?????????NULL?
61?????????)?;
62?
63?????*BufferAddress?=?buf?;
64?????*BufferSize?=?BytesRead?;
65?????ZwClose(fhandle)?;


這個(gè)功能只不過(guò)是在內(nèi)核下分配個(gè)內(nèi)存? 然后把文件內(nèi)容讀到內(nèi)存中
要記得釋放空間啊?? 我的代碼中沒(méi)釋放分配的內(nèi)存


]]>
關(guān)于jmp相對(duì)跳的一道程序分析http://www.shnenglu.com/ay19880703/archive/2009/02/13/73681.html__ay__ayThu, 12 Feb 2009 18:11:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/02/13/73681.htmlhttp://www.shnenglu.com/ay19880703/comments/73681.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/02/13/73681.html#Feedback2http://www.shnenglu.com/ay19880703/comments/commentRss/73681.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/73681.html

夜深人靜,嘿嘿 ? 只有這個(gè)時(shí)候才有時(shí)間靜下來(lái)看點(diǎn)東西

前幾天在看 16 位匯編語(yǔ)言程序設(shè)計(jì) ? 王爽 老師寫的 ? 寫得真的很好 ? 呵呵 ? 不是賣廣告哈 資源共享嘛

遇到一個(gè)問(wèn)題 ? 通過(guò)這個(gè)問(wèn)題發(fā)現(xiàn)能深刻理解到 jmp 指令很具內(nèi)涵的一些內(nèi)容

甚歡 乃著此文以記之

?

程序如下:

assume cs:codesg

codesg segment

?? mov ax,4c00h

?? int 21h

start :

?? mov ax,0

s:

?? nop

?? nop

?? mov di,offset s 這里應(yīng)該是計(jì)算 s 對(duì)于 segment 處的偏移量,賦值給 di

?? mov si,offset s2 計(jì)算 s2 對(duì)于 segment 處的偏移,保存到 si

?? mov ax , cs:[si]? s 處的 1 個(gè)字節(jié)指令內(nèi)容讀入 ax (注意,基址是 cs ~ 不是 ds

?? mov cs:[di],ax?? ax 內(nèi)容寫到 s 處,也就是填充上邊那 2 個(gè) nop

s0:

?? jmp short s ;跳到 s ,那么這個(gè)時(shí)候位于 s 處指令應(yīng)該是 jmp s1 ;接著執(zhí)行應(yīng)該是 mov ax 0 然后 int 21

s1:

?? mov ax,0

?? int 21h??

?? mov ax,0

s2:?

?? jmp short s1

?? nop

codesg ends

end start

?

?

結(jié)果發(fā)現(xiàn)我推測(cè)的跟執(zhí)行的內(nèi)容完全不一樣 …… 暈厥 ING~

又過(guò)了一天 一覺醒來(lái)想了想這個(gè)結(jié)果 哈哈 恍然大悟

?

書上的例子用的是 windows 自帶的 debug 調(diào)試 …… 我也只會(huì)用這個(gè)了 …… windbg 太麻煩 od 好像只能開 32 位的

只能截圖看了

ab.bmp

jmp 指令在被編譯器編譯的時(shí)候會(huì)自動(dòng)計(jì)算跳轉(zhuǎn)時(shí)指針與目的地址的偏移量 然后通過(guò)加減 ip 這個(gè)數(shù)值實(shí)現(xiàn)跳轉(zhuǎn)的

也就是說(shuō) jmp s 這指令實(shí)現(xiàn)的是相對(duì)位移跳轉(zhuǎn),跳到哪那是編譯器編譯的時(shí)候就計(jì)算好的了

我們來(lái)看看 1814 0016 這個(gè)地方的 jmp 指令 EBF0 這個(gè)指令對(duì)應(yīng)的匯編語(yǔ)句應(yīng)該是 jmp s

S 是在 1814 0008 所以反編譯的結(jié)果是 jmp 0008? 沒(méi)錯(cuò) 跟我們的語(yǔ)句沒(méi)出入

那么我們可以看看機(jī)器碼 BEF0? BE jmp 指令 F0 代表相對(duì)位移 以補(bǔ)碼形式保存

那么我們計(jì)算下發(fā)現(xiàn) F0 對(duì)應(yīng)的 10 進(jìn)制是 -16 也就是說(shuō)要往后跳 16 個(gè)字節(jié)(注意是字節(jié), 8bit 一個(gè)字節(jié)哦 ~

1814 0016 這個(gè)是我們執(zhí)行到 jmp 時(shí) cs ip 的地址,也就是取指令的地址

注意這個(gè)時(shí)候我們已經(jīng)取出 jmp s 這個(gè)指令了 那么 IP 指針應(yīng)該 +2 指向 1814 0018 這個(gè)位置了

往后跳 16 個(gè)字節(jié) 1814 0018 – 10 10 進(jìn)制就是 16 咯) = 1814 0008

應(yīng)該是跳到 0008 這個(gè)位置上了 正好就是 s 對(duì)應(yīng)的位置

那么我們看看 1814 0020 這個(gè)指令 EBF6? F6 是跳轉(zhuǎn)的相對(duì)位移 補(bǔ)碼形式存放 換算成 10 進(jìn)制就是 -10

想象下當(dāng)程序執(zhí)行到 s0 那個(gè)時(shí)候 s 處的那 2 個(gè) nop 指令已經(jīng)被填充成 EBF6 ? 根據(jù)相對(duì)位移的計(jì)算

? 這個(gè)時(shí)候程序運(yùn)行的步驟應(yīng)該是

通過(guò) jmp s 跳轉(zhuǎn)到 1814 0008 地址(這個(gè)時(shí)候下一個(gè)指令對(duì)應(yīng)的機(jī)器碼是 BEF0

取出下一個(gè)指令 IP+2? 這個(gè)時(shí)候 IP 指向 1814 000a

執(zhí)行 BEF6 這個(gè)指令(向后跳 10 個(gè)字節(jié))

也就是應(yīng)該跳到 1814 000a – a 10 16 進(jìn)制表示) = 1814 0000

也就是說(shuō)這個(gè)時(shí)候 jmp 指令應(yīng)該是 jmp 0000 跳到 segment 開始處而不是跳到 s1 處了

接著應(yīng)該是執(zhí)行

?? mov ax,4c00h

?? int 21h

實(shí)際調(diào)試的結(jié)果也是這樣的

如下圖示

?

sa.bmp

看到?jīng)] ? 執(zhí)行 jmp 0008 也就是 jmp s 以后然后就是跳到 1814 0000 而不是跳到 s1 對(duì)應(yīng)的那個(gè)偏移處

接著就是跟我們想的一樣 執(zhí)行了 mov ax 4c 00h 然后就 int 21h

aabb.bmp

?

也就是說(shuō)我們 jmp 的地址記錄的是相對(duì)偏移量 這個(gè)程序也說(shuō)明了 jmp 的地址是在運(yùn)行時(shí)計(jì)算出來(lái)的而不是編譯器一開始就硬編碼進(jìn)去的

不過(guò)當(dāng)然也有硬編碼進(jìn)去的跳轉(zhuǎn)指令啦 ~~ 好像是 jmp far 地址吧 忘了的說(shuō) 呵呵 ?

只不過(guò)小小闡明下 jmp 相對(duì)跳的執(zhí)行流程和細(xì)節(jié)部分

這樣也有個(gè)小小啟示就是以后用相對(duì)跳的時(shí)候小心咯 貌似 shellcode 編寫或者改內(nèi)核代碼的時(shí)候可以注意下 呵呵

跳轉(zhuǎn)的相對(duì)地址最好計(jì)算出來(lái)表直接就來(lái)個(gè)偏移 ? 一不小心機(jī)子就當(dāng)?shù)袅?/span> ? 哇咔咔 ~

?



]]>
windbg學(xué)習(xí)筆記 FOR 內(nèi)核調(diào)試(四) -- PspTerminateThreadByPointerhttp://www.shnenglu.com/ay19880703/archive/2009/02/03/72907.html__ay__ayTue, 03 Feb 2009 07:16:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/02/03/72907.htmlhttp://www.shnenglu.com/ay19880703/comments/72907.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/02/03/72907.html#Feedback2http://www.shnenglu.com/ay19880703/comments/commentRss/72907.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/72907.html????? 近日事情頗多 喝茶拉 吃好吃的還有看電影啊~磨去不少時(shí)間,甚歡.難得放假回家 一直被拉出去也沒(méi)看什么東西 前段時(shí)間剛跟鼠仙討論了下 我跑去看了下進(jìn)程保護(hù)的一些東東,但是膚淺的很 就研究了下WRK的一些代碼 發(fā)現(xiàn)關(guān)閉進(jìn)程都跟這個(gè)PspTerminateThreadByPointer函數(shù)有關(guān),NtProcess的代碼很簡(jiǎn)單,就是得到進(jìn)程的EPROCESS 然后遍歷它的線程鏈表 接著就一個(gè)個(gè)用 PspTerminateThreadByPointer 函數(shù)掛掉就OK? 也就是說(shuō)想要保護(hù)進(jìn)程 掛鉤個(gè) PspTerminateThreadByPointer 效果還是很理想的??? 反正拿這個(gè)去實(shí)現(xiàn)R3下進(jìn)程保護(hù)應(yīng)該綽綽有余了
為了練習(xí)下windbg的使用 準(zhǔn)備隨便跟下我們的
PspTerminateThreadByPointer 函數(shù) 冰刃剛下速度太慢了 我就用任務(wù)管理器試驗(yàn)的 呵呵

首先開虛擬機(jī),然后一陣啰嗦的操作后進(jìn)入正題

先給我們的函數(shù)下個(gè)斷
kd> bp nt!PspTerminateThreadByPointer

我們bl看看
kd> bl
?0 e 805c9b8e???? 0001 (0001) nt!PspTerminateThreadByPointer

OK 成功了 然后打開任務(wù)管理器 在隨便打開個(gè)程序? INSTDRV.exe? (平時(shí)加載驅(qū)動(dòng)用的,呵呵)

然后拿任務(wù)管理器做掉這個(gè)進(jìn)程 HOHO~~

Breakpoint 0 hit
nt!PspTerminateThreadByPointer:
805c9b8e 8bff??????????? mov???? edi,edi

斷下來(lái)了? 匯編顯示的是這個(gè)函數(shù)的第一條語(yǔ)句 不過(guò)這個(gè)命令無(wú)任何意義

拿k指令看看函數(shù)堆棧

kd> k
ChildEBP RetAddr?
f7932d28 805c9d8b nt!PspTerminateThreadByPointer
f7932d54 8053e648 nt!NtTerminateProcess+0xd5
f7932d54 7c92e4f4 nt!KiFastCallEntry+0xf8
0007f73c 7c92de5c ntdll!KiFastSystemCallRet
0007f740 7c801e3a ntdll!ZwTerminateProcess+0xc

喃~函數(shù)堆棧是個(gè)好東西? 呵呵? 那么我們結(jié)束進(jìn)程的過(guò)程就清楚了 由于后面的函數(shù)堆棧沒(méi)法顯示 不知道為什么 反正差不多的調(diào)用流程就是這樣
ZwTerminateProcess- NtTerminateProcess - PspTerminateThreadByPointer 中間那2個(gè)函數(shù)干嘛用的我就不太清楚了?? 反了下 ZwTerminateProcess
kd> uf nt!zwterminateprocess
nt!ZwTerminateProcess:
805001bc b801010000????? mov???? eax,101h
805001c1 8d542404??????? lea???? edx,[esp+4]
805001c5 9c????????????? pushfd
805001c6 6a08??????????? push??? 8
805001c8 e8c4e20300????? call??? nt!KiSystemService (8053e491)
805001cd c20800????????? ret???? 8


nt!KiSystemService這個(gè)函數(shù)好像是跟SSDT有關(guān) 估計(jì)就是跑去找NtProcess的地址的吧 那么中間那2個(gè)函數(shù)可以自己意淫一下應(yīng)該就是 進(jìn)行用戶態(tài)和內(nèi)核態(tài)之間的切換了~
不知道是不是這樣的? 希望哪位大牛可以解答下小弟的推測(cè)正確與否~ 在此謝過(guò)~!

然后單步調(diào)試開始了 嘿嘿 為了方便看 我重新斷了次(之前拿r指令開了顯示寄存器信息開關(guān)了 呵呵)
Breakpoint 0 hit
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b8e esp=f7932d2c ebp=f7932d54 iopl=0???????? nv up ei ng nz na pe cy
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000287
nt!PspTerminateThreadByPointer:
805c9b8e 8bff??????????? mov???? edi,edi
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b90 esp=f7932d2c ebp=f7932d54 iopl=0???????? nv up ei ng nz na pe cy
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000287
nt!PspTerminateThreadByPointer+0x2:
805c9b90 55????????????? push??? ebp
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b91 esp=f7932d28 ebp=f7932d54 iopl=0???????? nv up ei ng nz na pe cy
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000287
nt!PspTerminateThreadByPointer+0x3:
805c9b91 8bec??????????? mov???? ebp,esp
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b93 esp=f7932d28 ebp=f7932d28 iopl=0???????? nv up ei ng nz na pe cy
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000287
nt!PspTerminateThreadByPointer+0x5:
805c9b93 83ec0c????????? sub???? esp,0Ch ; 貌似是切換棧了~
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b96 esp=f7932d1c ebp=f7932d28 iopl=0???????? nv up ei ng nz ac po nc
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000292
nt!PspTerminateThreadByPointer+0x8:
805c9b96 834df8ff??????? or????? dword ptr [ebp-8],0FFFFFFFFh ss:0010:f7932d20=00000008
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b9a esp=f7932d1c ebp=f7932d28 iopl=0???????? nv up ei ng nz na pe nc
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000286
nt!PspTerminateThreadByPointer+0xc:
805c9b9a 56????????????? push??? esi
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b9b esp=f7932d18 ebp=f7932d28 iopl=0???????? nv up ei ng nz na pe nc
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000286
nt!PspTerminateThreadByPointer+0xd:
805c9b9b 57????????????? push??? edi ; 注意這里 原來(lái)的esi在ebp+8處
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=8130dda8
eip=805c9b9c esp=f7932d14 ebp=f7932d28 iopl=0???????? nv up ei ng nz na pe nc
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000286
nt!PspTerminateThreadByPointer+0xe:
805c9b9c 8b7d08????????? mov???? edi,dword ptr [ebp+8] ss:0010:f7932d30=81308da8
;喃~他把原來(lái)esi的值傳給edi了
kd> t
eax=81308da8 ebx=81299020 ecx=00000000 edx=00000000 esi=81308da8 edi=81308da8
eip=805c9b9f esp=f7932d14 ebp=f7932d28 iopl=0???????? nv up ei ng nz na pe nc
cs=0008? ss=0010? ds=0023? es=0023? fs=0030? gs=0000???????????? efl=00000286
nt!PspTerminateThreadByPointer+0x11:
805c9b9f 8db748020000??? lea???? esi,[edi+248h]
;wrk上有條語(yǔ)句如下
?if (Thread->CrossThreadFlags
??? & PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION)
然后根據(jù)這個(gè) lea???? esi,[edi+248h] 命令看來(lái) 貌似edi指向的是個(gè)ETHREAD結(jié)構(gòu) 應(yīng)為
ETHREAD偏移248處就是這個(gè)CrossThreadFlags成員變量
kd> dt _ethread
ntdll!_ETHREAD
?? +0x000 Tcb????????????? : _KTHREAD
?? [...]
?? +0x248 CrossThreadFlags : Uint4B
?? [...]
那么就是說(shuō)edi存放的是ethread的地址,上個(gè)命令
mov???? edi,dword ptr [ebp+8]就是把原esi的值傳給edi的
可見第一個(gè)參數(shù)是保存在esi中的?? 那我們來(lái)看看這個(gè)ethread的結(jié)構(gòu)
現(xiàn)在edi中存放的是ethread的地址
kd> r esi
esi=81308da8

然后
kd> dt _ethread 81308da8
ntdll!_ETHREAD
?? +0x000 Tcb????????????? : _KTHREAD
?? [...]
?? +0x1d0 ExitStatus?????? : 0
?? [...]
?? +0x220 ThreadsProcess?? : 0x81299020 _EPROCESS
?? [...]
找到 ThreadsProcess? 它的值是 0x81299020 這個(gè)就是線程對(duì)應(yīng)的進(jìn)程結(jié)構(gòu)地址
kd> dt _eprocess 0x81299020
ntdll!_EPROCESS
?? +0x000 Pcb????????????? : _KPROCESS
?? [...]
?? +0x174 ImageFileName??? : [16]? "INSTDRV.EXE"
?? [...]
看~"INSTDRV.EXE"是我們要結(jié)束的那個(gè)進(jìn)程吧~呵呵
PspTerminateThreadByPointer的函數(shù)原型是這樣的
NTSTATUS
PspTerminateThreadByPointer(
??? IN PETHREAD Thread,
??? IN NTSTATUS ExitStatus,
??? IN BOOLEAN DirectTerminate
??? )
第一個(gè)參數(shù)就是要做掉的線程結(jié)構(gòu) 要結(jié)束進(jìn)程得把這個(gè)進(jìn)程下所有線程掛掉 剛我們斷下PspTerminateThreadByPointer 拿第一個(gè)指向的結(jié)構(gòu)一路跟蹤過(guò)來(lái)就找到了這個(gè)"INSTDRV.EXE" eprocess
神奇吧~HOHO~

到這里我一度很是奇怪,咋個(gè)參數(shù)傳遞不都是通過(guò)棧傳遞的嗎?
我發(fā)現(xiàn)PspTerminateThreadByPointer的函數(shù)調(diào)用好像是第一個(gè)參數(shù)在esi里面
第二個(gè)參數(shù)不知道是不是在edi里面 那么~~第三個(gè)參數(shù)在哪....

我好像之前有略過(guò)一篇文章說(shuō)到這個(gè)windows堆棧傳遞忘了是那篇文章了...

一會(huì)要去T球了 暫時(shí)打住...
匯編好多指令不懂...先去修煉內(nèi)功先...再好好研究這個(gè)函數(shù)吧 呵呵
???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? __ay.字






]]>
修改setenv.bat,省的每次編譯驅(qū)動(dòng)的時(shí)候老要打文件夾名,在buildhttp://www.shnenglu.com/ay19880703/archive/2009/02/01/72768.html__ay__aySun, 01 Feb 2009 10:24:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/02/01/72768.htmlhttp://www.shnenglu.com/ay19880703/comments/72768.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/02/01/72768.html#Feedback0http://www.shnenglu.com/ay19880703/comments/commentRss/72768.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/72768.html做個(gè)備忘省的以后重裝了我好改回來(lái)

先是去那個(gè)什么Windows XP x86 Checked Build Environment快捷方式那看了下發(fā)現(xiàn)它的啟動(dòng)參數(shù)如下
/k D:\WinDDK\6001.18002\bin\setenv.bat D:\WinDDK\6001.18002\ chk x86 WXP

看到setenv.bat了吧 其實(shí)都是這個(gè)東西在處理編譯
略看了下執(zhí)行流程 然后把這個(gè)文件的倒數(shù)幾行處加點(diǎn)批處理語(yǔ)句就達(dá)到目的了 呵呵

[...]
:end
set _FreeBuild=
REM set _AMD64bit=
set _IA64bit=
set _HalBuild=
set _ddkspec=
set _title=
set _BscMake=
set _VersionedHeaders=
set _LatestOsTarget=
cd 你要的目錄
build

exit /b 0


這樣你直接點(diǎn)那個(gè)快捷方式就可以直接進(jìn)你的編譯目錄下了
省去了每次編譯要進(jìn)目錄 還有輸入build這些麻煩的動(dòng)作
舒服了不少


]]>
老把寄存器弄混~~特此記下這些 From 百度百科http://www.shnenglu.com/ay19880703/archive/2009/02/01/72765.html__ay__aySun, 01 Feb 2009 08:39:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/02/01/72765.htmlhttp://www.shnenglu.com/ay19880703/comments/72765.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/02/01/72765.html#Feedback0http://www.shnenglu.com/ay19880703/comments/commentRss/72765.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/72765.html   寄存器都是32-bits寬。
  A、通用寄存器
  下面介紹通用寄存器及其習(xí)慣用法。顧名思義,通用寄存器是那些你可以根據(jù)自己的意愿使用的寄存器,修改他們的值通常不會(huì)對(duì)計(jì)算機(jī)的運(yùn)行造成很大的影響。通用寄存器最多的用途是計(jì)算。
  EAX(accumulator):通用寄存器。相對(duì)其他寄存器,在進(jìn)行運(yùn)算方面比較常用。在保護(hù)模式中,也可以作為內(nèi)存偏移指針(此時(shí),DS作為段 寄存器或選擇器)
  EBX(base):通用寄存器。通常作為內(nèi)存偏移指針使用(相對(duì)于EAX、ECX、EDX),DS是默認(rèn)的段寄存器或選擇器。在保護(hù)模式中,同樣可以起這個(gè)作用。
  ECX(count):通用寄存器。通常用于特定指令的計(jì)數(shù)。在保護(hù)模式中,也可以作為內(nèi)存偏移指針(此時(shí),DS作為 寄存器或段選擇器)。
  EDX(data):通用寄存器。在某些運(yùn)算中作為EAX的溢出寄存器(例如乘、除)。在保護(hù)模式中,也可以作為內(nèi)存偏移指針(此時(shí),DS作為段 寄存器或選擇器)。
  同AX分為AH&AL一樣,上述寄存器包括對(duì)應(yīng)的16-bit分組和8-bit分組。
  B、用作內(nèi)存指針的特殊寄存器
  ESI(Source Index):通常在內(nèi)存操作指令中作為“源地址指針”使用。當(dāng)然,ESI可以被裝入任意的數(shù)值,但通常沒(méi)有人把它當(dāng)作通用寄存器來(lái)用。DS是默認(rèn)段寄存器或選擇器。
  EDI(Destination Index):通常在內(nèi)存操作指令中作為“目的地址指針”使用。當(dāng)然,EDI也可以被裝入任意的數(shù)值,但通常沒(méi)有人把它當(dāng)作通用寄存器來(lái)用。DS是默認(rèn)段寄存器或選擇器。
  EBP(Base Pointer):這也是一個(gè)作為指針的寄存器。通常,它被高級(jí)語(yǔ)言編譯器用以建造‘堆棧幀'來(lái)保存函數(shù)或過(guò)程的局部變量,不過(guò),還是那句話,你可以在其中保存你希望的任何數(shù)據(jù)。SS是它的默認(rèn)段寄存器或選擇器。
  注意,這三個(gè)寄存器沒(méi)有對(duì)應(yīng)的8-bit分組。換言之,你可以通過(guò)SI、DI、BP作為別名訪問(wèn)他們的低16位,卻沒(méi)有辦法直接訪問(wèn)他們的低8位。
  C、段選擇器:
  實(shí)模式下的段寄存器到保護(hù)模式下?lián)u身一變就成了選擇器。不同的是,實(shí)模式下的“段寄存器”是16-bit的,而保護(hù)模式下的選擇器是32-bit的。
  CS(Code Segment) 代碼段,或代碼選擇器。同IP寄存器(稍后介紹)一同指向當(dāng)前正在執(zhí)行的那個(gè)地址。處理器執(zhí)行時(shí)從這個(gè)寄存器指向的段(實(shí)模式)或內(nèi)存(保護(hù)模式)中獲取指令。除了跳轉(zhuǎn)或其他分支指令之外,你無(wú)法修改這個(gè)寄存器的內(nèi)容。
  DS(Data Segment) 數(shù)據(jù)段,或數(shù)據(jù)選擇器。這個(gè)寄存器的低16 bit連同ESI一同指向的指令將要處理的內(nèi)存。同時(shí),所有的內(nèi)存操作指令 默認(rèn)情況下都用它指定操作段(實(shí)模式)或內(nèi)存(作為選擇器,在保護(hù)模式。這個(gè)寄存器可以被裝入任意數(shù)值,然而在這么做的時(shí)候需要小心一些。方法是,首先把 數(shù)據(jù)送給AX,然后再把它從AX傳送給DS(當(dāng)然,也可以通過(guò)堆棧來(lái)做).
  ES(Extra Segment) 附加段,或附加選擇器。這個(gè)寄存器的低16 bit連同EDI一同指向的指令將要處理的內(nèi)存。同樣的,這個(gè)寄存器可以被裝入任意數(shù)值,方法和DS類似。
  FS F段或F選擇器(推測(cè)F可能是Free?)。可以用這個(gè)寄存器作為默認(rèn)段寄存器或選擇器的一個(gè)替代品。它可以被裝入任何數(shù)值,方法和DS類似。
  GS G段或G選擇器(G的意義和F一樣,沒(méi)有在Intel的文檔中解釋)。它和FS幾乎完全一樣。
  SS(Stack Segment) 堆棧段或堆棧選擇器。這個(gè)寄存器的低16 bit連同ESP一同指向下一次堆棧操作(push和pop)所要使用的堆棧地址。這個(gè)寄存器也可以被裝入任意數(shù)值,你可以通過(guò)入棧和出棧操作來(lái)給他賦 值,不過(guò)由于堆棧對(duì)于很多操作有很重要的意義,因此,不正確的修改有可能造成對(duì)堆棧的破壞。
  * 注意 一定不要在初學(xué)匯編的階段把這些寄存器弄混。他們非常重要,而一旦你掌握了他們,你就可以對(duì)他們做任意的操作了。段寄存器,或選擇器,在沒(méi)有指定的情況下都是使用默認(rèn)的那個(gè)。這句話在現(xiàn)在看來(lái)可能有點(diǎn)稀里糊涂,不過(guò)你很快就會(huì)在后面知道如何去做。
  指令指針寄存器:
  EIP(Instruction Pointer) 這個(gè)寄存器非常的重要。這是一個(gè)32位寬的寄存器 ,同CS一同指向即將執(zhí)行的那條指令的地址。不能夠直接修改這個(gè)寄存器的值,修改它的唯一方法是跳轉(zhuǎn)或分支指令。(CS是默認(rèn)的段或選擇器)

  

]]>
跟群內(nèi)某大牛聊天筆記...... FOR PspCidTablehttp://www.shnenglu.com/ay19880703/archive/2009/01/26/72607.html__ay__ayMon, 26 Jan 2009 13:04:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/01/26/72607.htmlhttp://www.shnenglu.com/ay19880703/comments/72607.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/01/26/72607.html#Feedback1http://www.shnenglu.com/ay19880703/comments/commentRss/72607.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/72607.html

問(wèn)題1.pspcidtable不是全局變量嗎?咋個(gè)不能聲明直接用?
結(jié)論:
因?yàn)樗鼪](méi)有導(dǎo)出...? 其實(shí)那個(gè)SSDT的結(jié)構(gòu)能用是因?yàn)樗鼘?dǎo)出了的...

問(wèn)題2.(在windbg調(diào)試第三篇的補(bǔ)充內(nèi)容那.....)

問(wèn)題3.咋個(gè),以及為什么那個(gè)HANDLE的值,TableCode的指針和對(duì)象體的指針低2位都要是0?
結(jié)論:
為了內(nèi)存對(duì)齊~ 這樣,內(nèi)存以4字節(jié)一單位劃分,指針的值是內(nèi)存地址 必須能被4整除,所以指針的開始2位必須為0(必須為4的倍數(shù)) 搜索內(nèi)存的時(shí)候就以4字節(jié)為單位搜索 減少搜索時(shí)間

感悟1:

? ?? ? if (*(PUSHORT)cPtr == 0x35FF && *(pOpcode + 6) == 0xE8)
? ?? ? {
? ?? ?? ?pPspCidTable = **(PVOID **)(pOpcode + 2);
? ?? ?? ?break;
? ?? ? }
這個(gè)代碼是在PsLookUpProcessByProcessId的函數(shù)內(nèi)定位pspcidtable
我反了下這個(gè)PsLookUpProcessByProcessId函數(shù)

kd> uf nt!PsLookUpProcessByProcessId
nt!PsLookupProcessByProcessId:
......
805ca42e ff35e0b25580??? push??? dword ptr [nt!PspCidTable (8055b2e0)]
805ca434 e84bb50300????? call??? nt!ExMapHandleToPointer (80605984)
......

大概就是內(nèi)存特征定位吧 哈哈 紅色標(biāo)注的地方就是pspcidtable的地址拉
也就是說(shuō)在整個(gè)函數(shù)中,pspcidtable的地址前面是0xff35 后面是 0xe8
通過(guò)這個(gè)特征找到0xff35和 0xe8之間的這8字節(jié)的數(shù)據(jù)就是pspcidtable的地址
當(dāng)然拉看起來(lái)不像是吧? 內(nèi)存存放順序跟我們看的不一樣 是以2字節(jié)為單位 壓棧壓進(jìn)去的
所以邏輯上的順序和內(nèi)存上的順序是正好相反的
所以紅色字體以2個(gè)字節(jié)倒著排過(guò)來(lái)就是 8055b2e0
我們拿windbg看看
kd> dd pspcidtable
8055b2e0? e1000860 00000002 00000000 00000000

看 果然是pspcidtable的地址 神奇阿~~

感悟2:
記得 <<基于pspCidTable的進(jìn)程檢測(cè)技術(shù)>>這篇牛文里面說(shuō)過(guò)獲取pspcidtable的方法還有一個(gè) 就是
KdEnableDebugger->KdInitSystem->KdDebuggerDataBlock
->KDDEBUGGER_DATA32->PspCidTable
這個(gè)流程 其實(shí)跟那個(gè)PsLookUpProcessByProcessId差不多 都是內(nèi)存定位
但是我們?nèi)旱呐8绺缯f(shuō)了個(gè)更加易用的方法~

#define GetVar( x )??? ??? (*(PULONG)((*(PULONG)0xffdff034) + (ULONG)(x)))
PspCidTable = GetVar(0x80);

就這么簡(jiǎn)單....? 原理很簡(jiǎn)單...? 0xffdff000是KPCR這個(gè)結(jié)構(gòu)變量的地址
那么0x34就是KdVersionBlock 成員變量在該結(jié)構(gòu)中的偏移
但是在0xffdff034指向的地方對(duì)應(yīng)有個(gè)結(jié)構(gòu)_DBGKD_GET_VERSION64
可惜的是這個(gè)結(jié)構(gòu)只有0x28字節(jié)大小 但是....嘿嘿? 這個(gè)結(jié)構(gòu)后面藏著N多超級(jí)重要的內(nèi)核變量
我們的pspcidtable這個(gè)變量其實(shí)就在這個(gè)結(jié)構(gòu)起始位置的0x80字節(jié)偏移處~
如此一來(lái) 我拿sp3的xp系統(tǒng)調(diào)試如下:
kd> dd 0xffdff034
ffdff034? 80546b38 8003f400 8003f000 80042000

kd> dd 80546b38+0x80
80546bb8? 8055b2e0 00000000 8055d708 00000000

kd> dd pspcidtable
8055b2e0? e1000860 00000002 00000000 00000000

其實(shí)0xffdff034指向的地方對(duì)應(yīng)的結(jié)構(gòu)體應(yīng)該就是傳說(shuō)中的KDDEBUGGER_DATA32這個(gè)結(jié)構(gòu)(windbg看了下說(shuō)沒(méi)這個(gè)符號(hào)...)?
typedef struct _KDDEBUGGER_DATA32 {
? ???DBGKD_DEBUG_DATA_HEADER32 Header;
? ???ULONG? ? KernBase;
? ???ULONG? ? BreakpointWithStatus;? ?? ?// address of breakpoint
? ???ULONG? ? SavedContext;
? ???USHORT? ? ThCallbackStack;? ?? ?? ?// offset in thread data
? ???USHORT? ? NextCallback;? ?? ?? ? // saved pointer to next callback frame
? ???USHORT? ? FramePointer;? ?? ?? ? // saved frame pointer
? ???USHORT? ? PaeEnabled:1;
? ???ULONG? ? KiCallUserMode;? ?? ?? ?// kernel routine
? ???ULONG? ? KeUserCallbackDispatcher;? ? // address in ntdll

? ???ULONG? ? PsLoadedModuleList;
? ???ULONG? ? PsActiveProcessHead;
? ???ULONG? ? PspCidTable;? ?? ?? ?// <--------- What we need!!
? ???//...
? ???ULONG? ? MmLoadedUserImageList;
} KDDEBUGGER_DATA32, *PKDDEBUGGER_DATA32;
大概就是這樣的 呵呵 里面保存著比較重要的變量比如pspcidtable PsActiveProcessHead
PsLoadedModuleList等等? 重要的是這個(gè)地址貌似是硬編碼進(jìn)去的 也就是說(shuō)好像只要是NT內(nèi)核的機(jī)器這個(gè)地址是不會(huì)變的,什么?根據(jù)?嘿嘿...
據(jù)某老外文獻(xiàn)記載:
;?Start?of?the?architecturally?defined?section?of?the?PCR.?This?section
;?may?be?directly?addressed?by?vendor/platform?specific?HAL?code?and?will
;?not?change?from?version?to?version?of?NT.
?
看沒(méi)看沒(méi) 反正我sp3上機(jī)器可以 的確是這個(gè)地址 沒(méi)錯(cuò)



??????????????????????????????????????????????????????????????????????????????????????????????????????????? ?? __ay.字
涉及到的學(xué)習(xí)資料
http://bbs.pediy.com/showthread.php?p=13746
http://www.0GiNr.com/
http://bbs.pediy.com/showthread.php?t=73028
futo 抹句柄表
Rootkits.com? opc0de





]]>
windbg學(xué)習(xí)筆記 FOR 內(nèi)核調(diào)試(三) --進(jìn)程句柄表HANDLE_TABLEhttp://www.shnenglu.com/ay19880703/archive/2009/01/25/72574.html__ay__aySun, 25 Jan 2009 09:43:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/01/25/72574.htmlhttp://www.shnenglu.com/ay19880703/comments/72574.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/01/25/72574.html#Feedback1http://www.shnenglu.com/ay19880703/comments/commentRss/72574.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/72574.html閱讀全文

]]>
windbg學(xué)習(xí)筆記 FOR 內(nèi)核調(diào)試(二)http://www.shnenglu.com/ay19880703/archive/2009/01/24/72527.html__ay__ayFri, 23 Jan 2009 16:51:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/01/24/72527.htmlhttp://www.shnenglu.com/ay19880703/comments/72527.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/01/24/72527.html#Feedback0http://www.shnenglu.com/ay19880703/comments/commentRss/72527.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/72527.html

最近終于把車考過(guò)去了 ,windbg 的學(xué)習(xí)耽擱了好多 前幾天每天都在練車 ~ 搞死我了 不過(guò)還好在海邊練 景色很宜人 ~ 舒服 ~HOHO

?

上次說(shuō)啥來(lái)著 ?

對(duì)了 就是這幾個(gè)命令 ~ 呵呵

堆棧顯示指令 kb , kp, kP , kv
反匯編指令 u,uf
跟蹤指令 T,TA,TB,TC
執(zhí)行相關(guān)指令 P,PA,PC
跟蹤查看指令 WT

?

這些差不多了 ? 到時(shí)候調(diào)試篇忘記了會(huì)把這些命令說(shuō)明插進(jìn)去 ~HOHO 這里僅做個(gè)整理

?

----------------------------------------------------------------------------

堆棧顯示指令

k [b|p|P|v]

在內(nèi)核調(diào)試的時(shí)候 ,k 命令用來(lái)顯示內(nèi)核棧的內(nèi)容

先說(shuō)說(shuō)內(nèi)核棧用來(lái)干嘛的 看了些資料個(gè)人理解是這樣的

比如我們的代碼運(yùn)行時(shí) , 肯定會(huì)有函數(shù) 函數(shù)然后還會(huì)調(diào)用函數(shù) 但是系統(tǒng)如何記錄是哪個(gè)父函數(shù)調(diào)用了這個(gè)子函數(shù) , 在子函數(shù)調(diào)用之前整個(gè)狀態(tài)又是怎樣的 , 其實(shí)系統(tǒng)是利用了堆棧記錄的 棧這個(gè)東西好阿 ? 先進(jìn)后出 ? 最近調(diào)用的函數(shù)記錄在最頂層 函數(shù)執(zhí)行完后就從棧內(nèi)彈出之前記錄的參數(shù) , 如果調(diào)用函數(shù) 一樣的把函數(shù)壓進(jìn)棧內(nèi)就好了 這樣一來(lái) 一旦子函數(shù)執(zhí)行完 , 從棧內(nèi)彈出的第一個(gè)函數(shù)肯定是該子函數(shù)的老爹 ? 我們可以看上層堆棧的狀態(tài)等等 功能大家慢慢去體會(huì)吧 我也沒(méi)用過(guò) ? 呵呵 ? 不好說(shuō)什么 下面說(shuō)些細(xì)節(jié)的東西

b

顯示傳給函數(shù)的前三個(gè)參數(shù)

p

顯示傳給函數(shù)的全部參數(shù)

P( 大寫 )

跟上面那個(gè)一樣 只不過(guò)是顯示形式不同而已

V

外加顯示一些額外的信息

----------------------------------------------------------------------------

u [f]

反匯編指令 , 嘿嘿 超級(jí)有用的指令喲 雖然說(shuō)內(nèi)核很多東西很復(fù)雜 認(rèn)識(shí)偶爾小小反下也是可以的

u

反匯編當(dāng)前寄存器指向的代碼

uf 函數(shù)名 ( 比如 nt!ZwCreateFile)

反匯編指定的函數(shù)

----------------------------------------------------------------------------

t [r]

單步跟蹤

r 打開指顯示寄存器的詳細(xì)信息 , 狀態(tài)的開關(guān) ( 下面指令一樣有效 , 在用 1 次就會(huì)關(guān)閉哦 ~)

ta 地址

讓程序執(zhí)行到指定地址

tb

讓程序運(yùn)行到分支語(yǔ)句時(shí)停止

tc

讓程序運(yùn)行到下一個(gè)函數(shù)調(diào)用停止

----------------------------------------------------------------------------

p [r]

單步執(zhí)行一跳指令

r 打開指顯示寄存器的詳細(xì)信息 , 狀態(tài)的開關(guān) ( 下面指令一樣有效 , 在用 1 次就會(huì)關(guān)閉哦 ~)

pa

讓程序執(zhí)行到指定地址

pc

讓程序執(zhí)行到函數(shù)調(diào)用就停止

?

----------------------------------------------------------------------------

wt

?

在想查看指定函數(shù)的信息而又不想單步通過(guò)該函數(shù)時(shí)很有用。可以到函數(shù)的起始地址并執(zhí)行 wt 命令。 ( 摘自翻譯文檔 )

?

這個(gè)感覺用處不是很大 . 不細(xì)細(xì)研究了



----------------------------------------------------------------------------

?

?

Ps: 很多人不清楚到底 p 指令和 t 指令有什么區(qū)別 其實(shí)很簡(jiǎn)單 p 指令執(zhí)行到函數(shù)時(shí)把這個(gè)當(dāng)做一個(gè)指令來(lái)執(zhí)行 也就是說(shuō)不會(huì)進(jìn)入函數(shù)執(zhí)行 , 但是 t 指令會(huì)進(jìn)入到函數(shù)里面執(zhí)行 ? 就這么簡(jiǎn)單 ~~ 呵呵

?

?

基礎(chǔ)指令就到這里了 ? 過(guò)段時(shí)間開始記點(diǎn)調(diào)試的東東了 呵呵

?

?

?



]]>
windbg學(xué)習(xí)筆記 FOR 內(nèi)核調(diào)試(一)http://www.shnenglu.com/ay19880703/archive/2009/01/16/72181.html__ay__ayFri, 16 Jan 2009 08:23:00 GMThttp://www.shnenglu.com/ay19880703/archive/2009/01/16/72181.htmlhttp://www.shnenglu.com/ay19880703/comments/72181.htmlhttp://www.shnenglu.com/ay19880703/archive/2009/01/16/72181.html#Feedback3http://www.shnenglu.com/ay19880703/comments/commentRss/72181.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/72181.html個(gè)人總結(jié)下

----------------------------------------------------------------------------
!drvobj 你的驅(qū)動(dòng)對(duì)象 [標(biāo)志位]
說(shuō)明:這個(gè)指令可以查看驅(qū)動(dòng)對(duì)象的具體信息 我們知道每個(gè)驅(qū)動(dòng)程序在內(nèi)核中都會(huì)對(duì)應(yīng)一個(gè)驅(qū)動(dòng)對(duì)象的結(jié)構(gòu),其實(shí)上面所說(shuō)的驅(qū)動(dòng)對(duì)象就是你的驅(qū)動(dòng)名字,比如我要找aynet.sys這個(gè)驅(qū)動(dòng)程序的驅(qū)動(dòng)對(duì)象結(jié)構(gòu),那么我就!drvobj aynet 就好啦~
標(biāo)志位是用來(lái)告訴windbg具體要顯示什么內(nèi)容的,標(biāo)志位可以組合使用
Bit 0 (0x1)
顯示所有跟這個(gè)驅(qū)動(dòng)對(duì)象相關(guān)聯(lián)的設(shè)備對(duì)象信息
Bit 1 (0x2)
顯示所有跟這個(gè)驅(qū)動(dòng)想關(guān)的派遣例程信息
Bit 2 (0x4)
顯示這個(gè)驅(qū)動(dòng)對(duì)象的詳細(xì)信息 (需要標(biāo)志位0)
ps: !object 可以查看對(duì)象的詳細(xì)信息 比如該內(nèi)核對(duì)象是什么內(nèi)核對(duì)象(文件,進(jìn)程等)
類似用法還有!handle(就是!后面跟結(jié)構(gòu)名)等等
----------------------------------------------------------------------------
dt name
說(shuō)明:dt用來(lái)查看本地|全局|結(jié)構(gòu)變量?jī)?nèi)容的 , name是指你的變量類型是什么,你要看_DEVICE_OBJECT這個(gè)結(jié)構(gòu)變量就直接打 dt _DEVICE_OBJECT? 查看變量就直接輸變量名
----------------------------------------------------------------------------
下面說(shuō)說(shuō)下斷點(diǎn)的指令
bp 地址
在地址處下斷點(diǎn) 也可以是函數(shù)名(其實(shí)函數(shù)名就對(duì)應(yīng)著地址)
打個(gè)比方bp aynet!DriverEntry 說(shuō)明在aynet這個(gè)驅(qū)動(dòng)程序的driverentry函數(shù)處下斷 也就是程序一執(zhí)行到這里windbg就自動(dòng)斷下來(lái)了
還有個(gè)bu指令 延遲下斷點(diǎn) 格式跟bp差不多

bm 匹配值
bm指令用于匹配模式下斷點(diǎn) 比如說(shuō)bm aynet!Driver* 可以把a(bǔ)ynet驅(qū)動(dòng)下所有跟Driver* 模式匹配的函數(shù)斷下 但是注意~需要符號(hào)表的支持

ba 變量名
可以對(duì)內(nèi)存訪問(wèn)下斷點(diǎn) 比如說(shuō)你程序里有個(gè)aynet驅(qū)動(dòng)程序a變量,總被莫名其妙的修改了,那么你可以設(shè)置 ba aynet!a ,當(dāng)這個(gè)a值被修改的時(shí)候就可以被windbg斷下來(lái)了

還有其他常用命令比如
BL(List)列舉斷點(diǎn),BC(Clear)清除斷點(diǎn),BE(Enable)啟用斷點(diǎn),BD(Disable)禁止斷點(diǎn)
這些很簡(jiǎn)單 就不累述了
----------------------------------------------------------------------------
注:一下指令區(qū)分大小
顯示內(nèi)存數(shù)據(jù)相關(guān)指令
格式:d[*] 變量名/地址
da--asc字符顯示
db--byte&asc字符顯示
dc--雙字節(jié)&asc字符顯示
dd--雙字節(jié)變量顯示
dD--雙精浮點(diǎn)數(shù)顯示
df--單精浮點(diǎn)數(shù)顯示
dp--四字節(jié)數(shù)值顯示
du--unicode字符顯示
dw--字符(2個(gè)字節(jié))顯示
dW--字符和asc字符顯示
dyb--二進(jìn)制顯示
dyd--二進(jìn)制和雙字節(jié)顯示
舉個(gè)例子:(注:xx是變量名 )
kd> dd xx????? //雙字節(jié)顯示(即16進(jìn)制)
8055b260? 610f0f64 00000002 00000000 00000000
8055b270? 00000000 00000000 00000000 00000000
8055b280? 00000000 00000000 00000000 00000000
8055b290? 00000000 00000000 00000000 00000000
8055b2a0? 00000000 00000000 00000000 00000000
8055b2b0? 00000000 00000000 00000000 00000000
8055b2c0? 00000000 00000000 00000000 00000000
8055b2d0? 00000000 00000000 00000000 00000000
kd> da xx? //asc字符顯示
8055b260? "`."
kd> du xx? //unicode字符顯示
8055b260? "..."

附加:
dv
查看本地變量用~

看內(nèi)存內(nèi)容的時(shí)候就會(huì)用到這個(gè)命令了~呵呵
----------------------------------------------------------------------------
今天就學(xué)了這么多
剩下的明天在看 呵呵
下次要說(shuō)的內(nèi)容是
堆棧顯示指令kb , kp, kP , kv
反匯編指令 u,uf
跟蹤指令 T,TA,TB,TC
執(zhí)行相關(guān)指令 P,PA,PC
跟蹤查看指令 WT
先記下來(lái)~省的我忘了~
要調(diào)試也就大概就用到這些命令了吧 以后就開始記我的調(diào)試過(guò)程了~




]]>
個(gè)人總結(jié)NDIS中NDIS_PACKET,NDIS_BUFFER的關(guān)系http://www.shnenglu.com/ay19880703/archive/2008/09/18/62233.html__ay__ayThu, 18 Sep 2008 15:25:00 GMThttp://www.shnenglu.com/ay19880703/archive/2008/09/18/62233.htmlhttp://www.shnenglu.com/ay19880703/comments/62233.htmlhttp://www.shnenglu.com/ay19880703/archive/2008/09/18/62233.html#Feedback13http://www.shnenglu.com/ay19880703/comments/commentRss/62233.htmlhttp://www.shnenglu.com/ay19880703/services/trackbacks/62233.html ?1?//???
?2?//?NDIS_PACKET結(jié)構(gòu)的定義??
?3?//???
?4?typedef?struct?_NDIS_PACKET??
?5?{??
?6?NDIS_PACKET_PRIVATE?Private;??
?7?//這個(gè)其實(shí)是一個(gè)鏈表結(jié)構(gòu),Private.Head指向第一個(gè)鏈表,Private.Tail指向最后一個(gè)??
?8?//以下有關(guān)于這個(gè)結(jié)構(gòu)的解釋??
?9?
10?union??
11?{??
12?struct?//?For?Connection-less?miniports???
13?{??
14?UCHAR?MiniportReserved[2*sizeof(PVOID)];??
15?UCHAR?WrapperReserved[2*sizeof(PVOID)];??
16?};??
17?
18?struct??
19?{??
20?//???
21?//?For?de-serialized?miniports.?And?by?implication?conn-oriented?miniports.???
22?//?This?is?for?the?send-path?only.?Packets?indicated?will?use?WrapperReserved???
23?//?instead?of?WrapperReservedEx???
24?//???
25?UCHAR?MiniportReservedEx[3*sizeof(PVOID)];??
26?UCHAR?WrapperReservedEx[sizeof(PVOID)];??
27?};??
28?
29?struct??
30?{??
31?UCHAR?MacReserved[4*sizeof(PVOID)];??
32?};??
33?};??
34?
35?ULONG_PTR?Reserved[2];?//?For?compatibility?with?Win95???
36?UCHAR?ProtocolReserved[1];??
37?
38?}?NDIS_PACKET,?*PNDIS_PACKET,?**PPNDIS_PACKET;??
39?
40?//?NDIS_PACKET_PRIVATE?的定義??
41?typedef?struct?_NDIS_PACKET_PRIVATE??
42?{??
43?UINT?PhysicalCount;?//?number?of?physical?pages?in?packet.???
44?UINT?TotalLength;?//?Total?amount?of?data?in?the?packet.???
45?PNDIS_BUFFER?Head;?//?鏈表指針,指向第一個(gè)?
46?PNDIS_BUFFER?Tail;?//?鏈表指針,指向最后一個(gè)??
47?
48?//?if?Head?is?NULL?the?chain?is?empty;?Tail?doesn\'t?have?to?be?NULL?also???
49?
50?PNDIS_PACKET_POOL?Pool;?//?so?we?know?where?to?free?it?back?to???
51?UINT?Count;??
52?ULONG?Flags;??
53?BOOLEAN?ValidCounts;??
54?UCHAR?NdisPacketFlags;?//?See?fPACKET_xxx?bits?below???
55?USHORT?NdisPacketOobOffset;??
56?}?NDIS_PACKET_PRIVATE,?*?PNDIS_PACKET_PRIVATE;??
57?
58?//NDIS_BUFFER定義?其實(shí)就是一個(gè)內(nèi)存描述符
59?
60?typedef?struct?_NDIS_BUFFER?{??
61?struct?_NDIS_BUFFER?*Next;?//指向下一個(gè)節(jié)點(diǎn)的指針
62?PVOID?VirtualAddress;??????//指向報(bào)文首地址
63?PNDIS_BUFFER_POOL?Pool;??
64?UINT?Length;???????????????//報(bào)文數(shù)據(jù)長(zhǎng)度
65?UINT?Signature;??
66?}?NDIS_BUFFER,?*?PNDIS_BUFFER;??
注釋寫的很清楚了??那么他們的關(guān)系還是不清楚的話看看附圖



? 好了??這樣一來(lái)我們的思路大概清楚了??NDIS_PACKET只不過(guò)是一個(gè)關(guān)于NDIS_BUFFER鏈表的結(jié)構(gòu)??在NDIS_PACKET中的成 員Private中有指向第一個(gè)NDIS_BUFFER的指針和指向最后一個(gè)NDIS_BUFFER的指針??分別是Private.Head 和Private.Tail? ???而NDIS_BUFFER中就記錄了我們數(shù)據(jù)包的地址和下一個(gè)NDIS_BUFFER的地址? ?操作有很多種方法? ?由于這些結(jié)構(gòu)體本來(lái)對(duì)我們是不透明的? ? 所以最安全的方法是用MS提供的一系列函數(shù)來(lái)操作NDIS_PACKET和NDIS_BUFFER??

? ? 還是拿個(gè)例子好說(shuō)話吧

?1?NDIS_STATUS?status?;
?2?????PNDIS_BUFFER?NdisBuffer?;
?3?????UINT?TotalPacketLength?=?0?,?copysize?=?0?,?DataOffset?=?0?,?PhysicalBufferCount??,??BufferCount???;
?4?????PUCHAR?mybuffer?=?NULL?,tembuffer?=?NULL?;??
?5?
?6?//假設(shè)這個(gè)是在PtReceive等函數(shù)中得到的PACKET
?7?NdisQueryPacket(packet?????????????????????//我們先得到第一個(gè)NDISBUFFER?的指針???
?8?????????,?&PhysicalBufferCount??????????????
?9?????????,?&BufferCount???????????????????????????
10?????????,&NdisBuffer???????????????????????????????//NdisBuffer就是指向鏈表頭
11?????????,?&TotalPacketLength
12?????????);
13?/*
14?其實(shí)也可以不用那么麻煩?直接??NdisBuffer?=?packet->Private.Head?;就可以取得第一個(gè)BUFFER了
15?*/
16?
17?????status?=?NdisAllocateMemory(?&mybuffer,?2048,?0,?HighestAcceptableMax?);??//分配我們自己的內(nèi)存塊
18?
19?????if(?status?!=?NDIS_STATUS_SUCCESS?)
20?????????return?NDIS_STATUS_FAILURE?;
21?
22?????NdisZeroMemory(?mybuffer,?2048?)?;
23?
24?????NdisQueryBufferSafe(??//取得NDIS_BUFFER描述符中數(shù)據(jù)的首地址和大小
25?????????????????????????????????NdisBuffer,
26?????????????????????????????????&tembuffer,
27?????????????????????????????????&copysize,
28?????????????????????????????????NormalPagePriority
29?????);??
30??????
31?????????//將數(shù)據(jù)復(fù)制到我們的內(nèi)存中
32?????NdisMoveMemory(mybuffer,?tembuffer,?copysize)?;
33?
34?????DataOffset?=?copysize?;
35?
36?????while(1)
37?????{
38?????????/*
39?????????????????也可以這樣操作而不用NdisGetNextBuffer
40?????????if(NdisBuffer->Next?==?packet->Private.Tail?)
41?????????????break?;
42?
43?????????NdisBuffer?=?NdisBuffer->Next?;
44?
45?????????if(pmdl?==?NULL?)
46????????????break?;
47????????????*/
48?????????//獲得下一個(gè)NDIS_BUFFER的的指針
49?????NdisGetNextBuffer(NdisBuffer?,?&NdisBuffer?)?;
50?????????如果指針是NULL??那么表示到鏈表尾了
51?????if(?NdisBuffer?==?NULL?)
52?????????break?;
53?
54?????NdisQueryBufferSafe(
55?????????????????????????????????NdisBuffer,
56?????????????????????????????????&tembuffer,
57?????????????????????????????????&copysize,
58?????????????????????????????????NormalPagePriority
59?????????????????????????????????)?;
60?
61?????NdisMoveMemory(?mybuffer?+?DataOffset?,?tembuffer,?copysize)?;
62?
63?????DataOffset?+=?copysize??;
64?
65?????}
66?
67?//OK??我們要的數(shù)據(jù)就全部都在我們申請(qǐng)的內(nèi)存mybuffer?數(shù)據(jù)大小為DataOffset

???
?



]]>
一级做a爱片久久毛片| 久久综合精品国产一区二区三区 | 午夜精品久久久久久影视777 | 色婷婷综合久久久久中文字幕| 久久亚洲中文字幕精品一区四| 国产精品99久久久精品无码| 奇米综合四色77777久久| 久久电影网一区| 久久伊人精品青青草原日本| 久久久久久精品免费看SSS| 精品国产VA久久久久久久冰| 国产午夜精品久久久久九九| 亚洲国产成人久久精品99 | 国产精品99久久久久久宅男小说| 国产精品久久成人影院| 欧美日韩成人精品久久久免费看| 日韩人妻无码精品久久久不卡| 久久精品二区| 伊人久久大香线蕉影院95| 成人午夜精品无码区久久| 精品欧美一区二区三区久久久 | 免费一级做a爰片久久毛片潮| 69久久精品无码一区二区| 久久精品免费全国观看国产| 97精品国产97久久久久久免费| 亚洲AV无码久久精品蜜桃| 亚洲国产精品一区二区三区久久| 久久96国产精品久久久| 亚洲AV日韩精品久久久久久| 久久无码人妻精品一区二区三区| 国内精品久久久久伊人av| 亚洲色婷婷综合久久| 久久精品亚洲AV久久久无码| 中文精品99久久国产| 香港aa三级久久三级老师2021国产三级精品三级在 | 无码乱码观看精品久久| 一级做a爰片久久毛片看看| 日本精品久久久久久久久免费| 精品一久久香蕉国产线看播放| 久久九九有精品国产23百花影院| 高清免费久久午夜精品|