日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

基于内存搜索的进程检测方法

發(fā)布時(shí)間:2024/3/7 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于内存搜索的进程检测方法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

搜索內(nèi)存檢測(cè)進(jìn)程的原理
1) 問(wèn)題的提出——進(jìn)程檢測(cè)
Rootkit等后門(mén)為了在系統(tǒng)中長(zhǎng)期駐留,需要隱藏相應(yīng)的信息。這些信息包括自啟動(dòng)項(xiàng)、文件、進(jìn)程、模塊、端口、注冊(cè)表、服務(wù)等。其中,以進(jìn)程隱藏特別突出(因?yàn)橛脩艚?jīng)常會(huì)打開(kāi)任務(wù)管理器看看是不是有異常的進(jìn)程在自己的機(jī)器上運(yùn)行)。
隱藏進(jìn)程的方法有多種,例如掛鉤NtQuerySystemInformation函數(shù);從內(nèi)核EPROCESS結(jié)構(gòu)的ActiveProcessLinks等雙向鏈表上摘除自身;從csrss.exe進(jìn)程的句柄表上摘除自身;從PspCidTable上摘除自身等等。如果Rootkit用到了其中的某種方法,那么基于此的檢測(cè)將會(huì)失敗。比如,hxdef100(黑客守護(hù)者)掛鉤NtQuerySystemInformation實(shí)現(xiàn)隱藏,如果想通過(guò)NtQuerySystemInformation函數(shù)來(lái)獲取全部進(jìn)程信息就會(huì)失敗。再比如,FU_rootkit通過(guò)從內(nèi)核EPROCESS結(jié)構(gòu)的ActiveProcessLinks雙向鏈表上摘除自身實(shí)現(xiàn)隱藏,如果想通過(guò)遍歷該鏈表來(lái)檢測(cè)隱藏的FU_rootkit就會(huì)失敗。現(xiàn)在問(wèn)題來(lái)了,如果上面隱藏進(jìn)程的方法都用到了,該怎么檢測(cè)呢?
2)解決的思路之一——搜索內(nèi)存
在Windows系統(tǒng)中,進(jìn)程由內(nèi)存空間、進(jìn)程打開(kāi)的各種對(duì)象和進(jìn)程中運(yùn)行的線程所組成。線程僅僅是一個(gè)執(zhí)行上下文,系統(tǒng)調(diào)度的最基本單位,但每一個(gè)線程的運(yùn)行都必須依附(attach)一個(gè)進(jìn)程。
在Windbg中可以使用dt命令來(lái)查看線程ETHREAD的結(jié)構(gòu),命令格式為“dt _ETHREAD 線程地址”。例如:
kd> dt _ETHREAD 8238F3B8
nt!_ETHREAD
+0x000 Tcb????????????? : _KTHREAD
+0x1c0 CreateTime?????? : _LARGE_INTEGER 0xe4d5cd5`36b71830
……
+0x21c DeviceToVerify?? : (null)
+0x220 ThreadsProcess?? : 0x8234f718 _EPROCESS
+0x224 StartAddress???? : 0x7c810867
+0x228 Win32StartAddress : 0x010027f2
……
+0x254 ForwardClusterOnly : 0 ''
+0x255 DisablePageFaultClustering : 0 ''
在線程控制塊的偏移0x220處是一個(gè)ThreadsProcess指針,指向一個(gè)EPROCESS結(jié)構(gòu),即一個(gè)進(jìn)程EPROCESS。
在Windbg中可以使用“!process”命令來(lái)查看進(jìn)程的線程摘要,命令格式為“!process 進(jìn)程地址
3”。我們看看上面顯示的地址0x8234f718對(duì)應(yīng)進(jìn)程的線程摘要信息。
kd> !process 0x8234f718 3
PROCESS 8234f718? SessionId: 0? Cid: 05bc??? Peb: 7ffd6000? ParentCid: 0424
DirBase: 07a00280? ObjectTable: e1975848? HandleCount:? 38.
Image: wscntfy.exe
……
BasePriority?????? 8
CommitCharge???? 164
THREAD 8238f3b8? Cid 05bc.05c4? Teb: 7ffdf000 Win32Thread: e1d88da8 WAIT:
(UserRequest) UserMode Non-Alertable
8258cef8? SynchronizationEvent
8259b7b8? SynchronizationEvent
從命令輸出可以看出該進(jìn)程名為wscntfy.exe,有一個(gè)線程地址為8238f3b8,這個(gè)地址就是最開(kāi)始的那個(gè)線程控制塊的地址。
現(xiàn)在思路有了,既然每一個(gè)線程都要依附一個(gè)進(jìn)程,每一個(gè)線程控制塊中有一個(gè)指向該進(jìn)程的進(jìn)程控制塊的指針,那么,我們就可以通過(guò)搜索系統(tǒng)中所有線程得到所有進(jìn)程。
搜索內(nèi)存檢測(cè)進(jìn)程的具體實(shí)現(xiàn)
1) 問(wèn)題
問(wèn)題1,如何判斷一個(gè)內(nèi)存塊是線程的ETHREAD結(jié)構(gòu)?
Windows系統(tǒng)中存在兩個(gè)系統(tǒng)描述符表,一個(gè)是KeServiceDescriptorTable,一個(gè)是KeServiceDescriptorTableShadow。兩個(gè)系統(tǒng)描述符表中的KeServiceDescriptorTable描述系統(tǒng)基本服務(wù),我們稱(chēng)之為主表;KeServiceDescriptorTableShadow除了描述系統(tǒng)基本服務(wù)之外,還描述GUI和USER服務(wù),我們稱(chēng)之為副表。每個(gè)線程都有自己指向系統(tǒng)服務(wù)描述符表的指針,這個(gè)指針指向兩個(gè)系統(tǒng)描述符表中的任意一個(gè)。線程ETHREAD偏移為0的位置是一個(gè)KTHREAD結(jié)構(gòu),這個(gè)結(jié)構(gòu)的偏移0x0e0處就是這樣一個(gè)指向系統(tǒng)描述符表的32位指針ServiceTable。
kd> dt _KTHREAD
nt!_KTHREAD
+0x000 Header?????????? : _DISPATCHER_HEADER
+0x010 MutantListHead?? : _LIST_ENTRY
……
+0x0df InitialNode????? : UChar
+0x0e0 ServiceTable???? : Ptr32 Void
+0x0e4 Queue??????????? : Ptr32 _KQUEUE
……
+0x1bb DisableBoost???? : Uchar
假定我們讀取地址Addr的信息,如果Addr偏移0x0e0處的內(nèi)容是系統(tǒng)服務(wù)調(diào)度表的地址,就可以初步判定這個(gè)Addr很有可能就是一個(gè)線程ETHREAD的入口。
問(wèn)題2,如何獲得系統(tǒng)服務(wù)調(diào)度表的地址?
任何一個(gè)系統(tǒng)的系統(tǒng)服務(wù)描述符表在系統(tǒng)運(yùn)行時(shí)是不會(huì)改變的,而且從前面的分析可以看出,這個(gè)表的位置線程是知道的,這樣線程在運(yùn)行時(shí)才能成功找到自己要調(diào)用的服務(wù)。
可是不同版本的Windows系統(tǒng)的描述符表地址并不一樣,同一版本的各個(gè)系統(tǒng)上描述符表的地址也不一樣,因此最好能夠有一種動(dòng)態(tài)獲得系統(tǒng)描述符表地址的方法。
基于前面對(duì)于主表和副表的分析,找到一個(gè)需要系統(tǒng)基本服務(wù)和GUI/USER服務(wù)的進(jìn)程,獲取其所有線程中的ServiceTable內(nèi)容,就可以得到系統(tǒng)描述符表的地址。而通過(guò)這種方法得到的地址是在程序運(yùn)行過(guò)程中動(dòng)態(tài)獲取的,可以滿足我們的需求。
我們通過(guò)遍歷EPROCESS中偏移0x088
處的ActiveProcessLinks來(lái)找到擬采用的進(jìn)程,比如explorer.exe(偏移0x174處為ImageFileName,映像名稱(chēng))。
kd> dt _EPROCESS 81405560
nt!_EPROCESS
+0x000 Pcb????????????? : _KPROCESS
……
+0x084 UniqueProcessId? : 0x000005fc
+0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x815c0c98 - 0x815a6b00 ]
……
+0x170 Session????????? : 0xf9ebc000
+0x174 ImageFileName??? : [16]? "explorer.exe"
+0x184 JobLinks???????? : _LIST_ENTRY [ 0x0 - 0x0 ]
+0x18c LockedPagesList? : (null)
+0x190 ThreadListHead?? : _LIST_ENTRY [ 0x81405424 - 0x813adadc ]
+0x198 SecurityPort???? : (null)
……
+0x255 WorkingSetAcquiredUnsafe : 0 ''
+0x258 Cookie?????????? : 0x70f74bdb
在找到這個(gè)進(jìn)程之后,我們接著要遍歷它所有的線程,以獲取我們需要的系統(tǒng)服務(wù)描述符表的地址。EPROCESS結(jié)構(gòu)偏移0x190
處的ThreadListHead是一個(gè)類(lèi)型為_(kāi)LIST_ENTRY的雙向鏈表,通過(guò)它可以得到線程鏈表的頭。
kd> dt _ETHREAD
nt!_ETHREAD
+0x000 Tcb????????????? : _KTHREAD
……
+0x220 ThreadsProcess?? : Ptr32 _EPROCESS
+0x224 StartAddress???? : Ptr32 Void
+0x228 Win32StartAddress : Ptr32 Void
+0x228 LpcReceivedMessageId : Uint4B
+0x22c ThreadListEntry? : _LIST_ENTRY
+0x234 RundownProtect?? : _EX_RUNDOWN_REF
……
+0x254 ForwardClusterOnly : UChar
+0x255 DisablePageFaultClustering : UChar
而線程ETHREAD結(jié)構(gòu)的偏移0x22c處也是這樣一個(gè)雙向鏈表,通過(guò)它可以遍歷所有線程。問(wèn)題好像已經(jīng)解決了,地址“EPROCESS+0x190-0x22c+0x0e0”中的內(nèi)容即是ServiceTable,亦即系統(tǒng)描述符表的地址,其中0x190是ThreadListHead相對(duì)EPROCESS的偏移,0x22c是ThreadListEntry相對(duì)ETHREAD的偏移,0x0e0是ServiceTable相對(duì)ETHREAD的偏移。
圖1給出了系統(tǒng)中EPROCESS和ETHREAD結(jié)構(gòu)的關(guān)系,我們可以從這個(gè)圖中看出上面所描述的過(guò)程(注:ServiceTable在Tcb結(jié)構(gòu)中,為了使結(jié)構(gòu)清晰明了,圖1沒(méi)有給出)。
?
圖1 EPROCESS結(jié)構(gòu)與ETHREAD結(jié)構(gòu)的關(guān)系
問(wèn)題3,如何獲取系統(tǒng)中所有進(jìn)程的EPROCESS結(jié)構(gòu)?
通過(guò)圖1我們可以看出,在內(nèi)存中搜索線程之后,通過(guò)EPROCESS與ETHREAD的關(guān)系,可以得到線程依附的進(jìn)程。“ETHREAD+
ThreadsProcess”中即是EPROCESS的地址,其中“ETHREAD”為線程ETHREAD結(jié)構(gòu)的地址,“ThreadsProcess”為T(mén)hreadsProcess指針相對(duì)ETHREAD的偏移量。獲得EPROCESS地址,便對(duì)應(yīng)上了進(jìn)程。一個(gè)線程會(huì)依附一個(gè)進(jìn)程,而一個(gè)進(jìn)程則可以對(duì)應(yīng)多個(gè)線程。用這個(gè)方法會(huì)得到很多重復(fù)的進(jìn)程地址,我們只需要把重復(fù)部分刪除即可。
2)實(shí)現(xiàn)
獲取系統(tǒng)服務(wù)描述符表的部分代碼如下,通過(guò)遍歷,能夠獲得兩個(gè)描述符表的地址。
currlist=currlist->Flink;
ssdt=*(PULONG)((ULONG)currlist-ThreadListEntry+ServiceTable);
if(s[0]==0)
s[0]=ssdt;
else
{
if((s[1]==0)&&(s[0]!=ssdt))
s[1]=ssdt;
}
if((s[0]!=0)&&(s[1]!=0))
break;
count++;
采用鏈表的形式記錄所有進(jìn)程EPROCESS結(jié)構(gòu)地址的部分代碼如下,需要在內(nèi)核中申請(qǐng)非分頁(yè)的地址空間。
{
if((r=(process *)ExAllocatePool(NonPagedPool,sizeof(process)))==NULL)
{
return;
}
p->next=r;
r->addr=EPROCaddr;
r->next=NULL;
p=r;
}
具體細(xì)節(jié)的補(bǔ)充說(shuō)明
我所給出的基本結(jié)構(gòu)和原理是Windows NT架構(gòu)下所有系統(tǒng)都采用的,因而在其他系統(tǒng)下這個(gè)方法依然可以實(shí)現(xiàn)進(jìn)程檢測(cè)。但由于在Winodws
2000/XP/2003下相關(guān)數(shù)據(jù)結(jié)構(gòu)有一定的差別,所以在其他系統(tǒng)下需要對(duì)相應(yīng)系統(tǒng)數(shù)據(jù)偏移量等值進(jìn)行修改。我所給出的驅(qū)動(dòng)程序在Windows XP
SP2下由Windows DDK編譯,可以使用rootkit.com提供的InstDrv進(jìn)行加載,使用Dbgview查看運(yùn)行結(jié)果,在Windows XP
SP2下測(cè)試通過(guò),可以成功檢測(cè)FU_rootkit、hxdef100(黑客守護(hù)者)和FUTo_enhanced隱藏的進(jìn)程。
目前給出的方法具有一定的不準(zhǔn)確性。比如內(nèi)核空間地址范圍,線程、進(jìn)程的判定,系統(tǒng)服務(wù)描述符表的獲取等都具有一定的局限性,這些都會(huì)影響檢測(cè)的準(zhǔn)確性。雖然目前的測(cè)試結(jié)果都是準(zhǔn)確的,但是一種從方法上能夠確保準(zhǔn)確的思路是以后努力的方向。

?

總結(jié)

以上是生活随笔為你收集整理的基于内存搜索的进程检测方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。