(53)进程结构体EPROCESS,擦除 DebugPort 实现反调试,ActiveProcessLinks 断链实现进程隐藏
一、進程的作用
進程最重要的作用是提供了CR3,10-10-12分頁下CR3指向頁目錄表,2-9-9-12分頁下CR3指向頁目錄指針表。
每個進程有一個或多個線程。本質上,沒有進程切換,只有線程切換。我們過去說進程切換是切換了CR3的值,實際上是切換線程時切換了CR3,只不過同一進程內的線程切換不會改變CR3。
我們說進程是空間概念,進程為它的線程提供了CR3,那么它的線程訪問同一個線性地址時,就能訪問到同一個物理頁。
attach 和 .process 本質就是切換CR3。
二、0環如何找到當前進程的 EPROCESS
不使用API的其中一種做法是通過 KPCR 找當前線程,然后+0x220找當前進程,示例代碼如下:
3環驅動加載程序:
int _tmain(int argc, _TCHAR* argv[]) {printf("我是驅動加載程序,PID: %x\n", GetCurrentProcessId());LoadDriver(DRIVER_NAME, DRIVER_PATH);UnLoadDriver(DRIVER_NAME);getchar();return 0; }驅動程序:
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) {PEPROCESS pEprocess = NULL;PCHAR ImageFileName;ULONG pid;__asm{mov eax, fs:[0x124];mov eax, [eax + 0x220];mov pEprocess, eax;mov eax, [eax + 0x84];mov pid, eax;}ImageFileName = (PCHAR)pEprocess + 0x174;DbgPrint("pid: %x, ImageFileName:%s\n",pid, ImageFileName);driver->DriverUnload = DriverUnload;return STATUS_SUCCESS; }上述程序說明,驅動加載后,執行驅動入口代碼時,所屬進程是系統進程。這和 DeviceIoControl 時情況又有所不同,DeviceIoControl 通信時,所屬進程是發起通信的3環程序。
三、KPROCESS 屬性
KPROCESS 是 EPROCESS 的起始部分 0x6c 字節。
KPROCESS 結構
ntdll!_KPROCESS+0x000 Header : _DISPATCHER_HEADER+0x010 ProfileListHead : _LIST_ENTRY+0x018 DirectoryTableBase : [2] Uint4B+0x020 LdtDescriptor : _KGDTENTRY+0x028 Int21Descriptor : _KIDTENTRY+0x030 IopmOffset : Uint2B+0x032 Iopl : UChar+0x033 Unused : UChar+0x034 ActiveProcessors : Uint4B+0x038 KernelTime : Uint4B+0x03c UserTime : Uint4B+0x040 ReadyListHead : _LIST_ENTRY+0x048 SwapListEntry : _SINGLE_LIST_ENTRY+0x04c VdmTrapcHandler : Ptr32 Void+0x050 ThreadListHead : _LIST_ENTRY+0x058 ProcessLock : Uint4B+0x05c Affinity : Uint4B+0x060 StackCount : Uint2B+0x062 BasePriority : Char+0x063 ThreadQuantum : Char+0x064 AutoAlignment : UChar+0x065 State : UChar+0x066 ThreadSeed : UChar+0x067 DisableBoost : UChar+0x068 PowerState : UChar+0x069 DisableQuantum : UChar+0x06a IdealNode : UChar+0x06b Flags : _KEXECUTE_OPTIONS+0x06b ExecuteOptions : UCharKPROCESS主要成員介紹:
+0x000 Header : _DISPATCHER_HEADER
“可等待”對象,比如Mutex互斥體、Event事件等(WaitForSingleObject)
+0x018 DirectoryTableBase : [2] Uint4B
頁目錄表的基址(為啥是8字節?)
+0x020 LdtDescriptor : _KGDTENTRY
+0x028 Int21Descriptor : _KIDTENTRY
歷史遺留,16位Windows 段選擇子不夠 每個進程都有一個LDT表
Int21Descriptor 是 DOS下要用的
+0x038 KernelTime : Uint4B
+0x03c UserTime : Uint4B
統計信息 記錄了一個進程在內核模式/用戶模式下所花的時間
+0x05c Affinity : Uint4B
規定進程里面的所有線程能在哪個CPU上跑,如果值為1,那這個進程的所以線程只能在0號CPU上跑(00000001)
如果值為3,那這個進程的所以線程能在0、1號CPU上跑(000000011)
如果值為4,那這個進程的所以線程能在2號CPU上跑(000000100)
如果值為5,那這個進程的所以線程能在0,2號CPU上跑(000000101)
4個字節共32位 所以最多32核 Windows64位 就64核
如果只有一個CPU 把這個設置為4 那么這個進程就死了
+0x062 BasePriority : Char
基礎優先級或最低優先級 該進程中的所有線程最起碼的優先級.
四、EPROCESS 屬性
EPROCESS 結構
nt!_EPROCESS+0x000 Pcb : _KPROCESS+0x06c ProcessLock : _EX_PUSH_LOCK+0x070 CreateTime : _LARGE_INTEGER+0x078 ExitTime : _LARGE_INTEGER+0x080 RundownProtect : _EX_RUNDOWN_REF+0x084 UniqueProcessId : Ptr32 Void+0x088 ActiveProcessLinks : _LIST_ENTRY+0x090 QuotaUsage : [3] Uint4B+0x09c QuotaPeak : [3] Uint4B+0x0a8 CommitCharge : Uint4B+0x0ac PeakVirtualSize : Uint4B+0x0b0 VirtualSize : Uint4B+0x0b4 SessionProcessLinks : _LIST_ENTRY+0x0bc DebugPort : Ptr32 Void+0x0c0 ExceptionPort : Ptr32 Void+0x0c4 ObjectTable : Ptr32 _HANDLE_TABLE+0x0c8 Token : _EX_FAST_REF+0x0cc WorkingSetLock : _FAST_MUTEX+0x0ec WorkingSetPage : Uint4B+0x0f0 AddressCreationLock : _FAST_MUTEX+0x110 HyperSpaceLock : Uint4B+0x114 ForkInProgress : Ptr32 _ETHREAD+0x118 HardwareTrigger : Uint4B+0x11c VadRoot : Ptr32 Void+0x120 VadHint : Ptr32 Void+0x124 CloneRoot : Ptr32 Void+0x128 NumberOfPrivatePages : Uint4B+0x12c NumberOfLockedPages : Uint4B+0x130 Win32Process : Ptr32 Void+0x134 Job : Ptr32 _EJOB+0x138 SectionObject : Ptr32 Void+0x13c SectionBaseAddress : Ptr32 Void+0x140 QuotaBlock : Ptr32 _EPROCESS_QUOTA_BLOCK+0x144 WorkingSetWatch : Ptr32 _PAGEFAULT_HISTORY+0x148 Win32WindowStation : Ptr32 Void+0x14c InheritedFromUniqueProcessId : Ptr32 Void+0x150 LdtInformation : Ptr32 Void+0x154 VadFreeHint : Ptr32 Void+0x158 VdmObjects : Ptr32 Void+0x15c DeviceMap : Ptr32 Void+0x160 PhysicalVadList : _LIST_ENTRY+0x168 PageDirectoryPte : _HARDWARE_PTE+0x168 Filler : Uint8B+0x170 Session : Ptr32 Void+0x174 ImageFileName : [16] UChar+0x184 JobLinks : _LIST_ENTRY+0x18c LockedPagesList : Ptr32 Void+0x190 ThreadListHead : _LIST_ENTRY+0x198 SecurityPort : Ptr32 Void+0x19c PaeTop : Ptr32 Void+0x1a0 ActiveThreads : Uint4B+0x1a4 GrantedAccess : Uint4B+0x1a8 DefaultHardErrorProcessing : Uint4B+0x1ac LastThreadExitStatus : Int4B+0x1b0 Peb : Ptr32 _PEB+0x1b4 PrefetchTrace : _EX_FAST_REF+0x1b8 ReadOperationCount : _LARGE_INTEGER+0x1c0 WriteOperationCount : _LARGE_INTEGER+0x1c8 OtherOperationCount : _LARGE_INTEGER+0x1d0 ReadTransferCount : _LARGE_INTEGER+0x1d8 WriteTransferCount : _LARGE_INTEGER+0x1e0 OtherTransferCount : _LARGE_INTEGER+0x1e8 CommitChargeLimit : Uint4B+0x1ec CommitChargePeak : Uint4B+0x1f0 AweInfo : Ptr32 Void+0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO+0x1f8 Vm : _MMSUPPORT+0x238 LastFaultCount : Uint4B+0x23c ModifiedPageCount : Uint4B+0x240 NumberOfVads : Uint4B+0x244 JobStatus : Uint4B+0x248 Flags : Uint4B+0x248 CreateReported : Pos 0, 1 Bit+0x248 NoDebugInherit : Pos 1, 1 Bit+0x248 ProcessExiting : Pos 2, 1 Bit+0x248 ProcessDelete : Pos 3, 1 Bit+0x248 Wow64SplitPages : Pos 4, 1 Bit+0x248 VmDeleted : Pos 5, 1 Bit+0x248 OutswapEnabled : Pos 6, 1 Bit+0x248 Outswapped : Pos 7, 1 Bit+0x248 ForkFailed : Pos 8, 1 Bit+0x248 HasPhysicalVad : Pos 9, 1 Bit+0x248 AddressSpaceInitialized : Pos 10, 2 Bits+0x248 SetTimerResolution : Pos 12, 1 Bit+0x248 BreakOnTermination : Pos 13, 1 Bit+0x248 SessionCreationUnderway : Pos 14, 1 Bit+0x248 WriteWatch : Pos 15, 1 Bit+0x248 ProcessInSession : Pos 16, 1 Bit+0x248 OverrideAddressSpace : Pos 17, 1 Bit+0x248 HasAddressSpace : Pos 18, 1 Bit+0x248 LaunchPrefetched : Pos 19, 1 Bit+0x248 InjectInpageErrors : Pos 20, 1 Bit+0x248 VmTopDown : Pos 21, 1 Bit+0x248 Unused3 : Pos 22, 1 Bit+0x248 Unused4 : Pos 23, 1 Bit+0x248 VdmAllowed : Pos 24, 1 Bit+0x248 Unused : Pos 25, 5 Bits+0x248 Unused1 : Pos 30, 1 Bit+0x248 Unused2 : Pos 31, 1 Bit+0x24c ExitStatus : Int4B+0x250 NextPageColor : Uint2B+0x252 SubSystemMinorVersion : UChar+0x253 SubSystemMajorVersion : UChar+0x252 SubSystemVersion : Uint2B+0x254 PriorityClass : UChar+0x255 WorkingSetAcquiredUnsafe : UChar+0x258 Cookie : Uint4B+0x070 CreateTime : _LARGE_INTEGER
+0x078 ExitTime : _LARGE_INTEGER
進程的創建/退出時間
+0x084 UniqueProcessId : Ptr32 Void
進程的編號 任務管理器中的PID
+0x088 ActiveProcessLinks : _LIST_ENTRY
雙向鏈表 所有的活動進程都連接在一起,構成了一個鏈表
PsActiveProcessHead指向全局鏈表頭,該變量未導出。
+0x090 QuotaUsage : [3] Uint4B +0x09c QuotaPeak : [3] Uint4B
物理頁相關的統計信息
+0x0a8 CommitCharge : Uint4B
+0x0ac PeakVirtualSize : Uint4B
+0x0b0 VirtualSize : Uint4B
虛擬內存相關的統計信息
+0x11c VadRoot : Ptr32 Void
標識0-2G哪些地址沒占用了
+0x0bc DebugPort : Ptr32 Void
+0x0c0 ExceptionPort : Ptr32 Void
調試相關
+0x0c4 ObjectTable : Ptr32 _HANDLE_TABLE
句柄表
+0x174 ImageFileName : [16] UChar
進程鏡像文件名 最多16個字節
+0x1a0 ActiveThreads : Uint4B
活動線程的數量
+0x1b0 Peb : Ptr32 _PEB
PEB((Process Environment Block 進程環境塊):進程在3環的一個結構體,里面包含了進程的模塊列表、是否處于調試狀態等信息。
五、體會 DebugPort 的作用
用OD附加記事本,下斷點,然后在windbg中清空EPROCESS中的DebugPort中的值,然后單步調試,觀察結果(注意:OD不要使用插件 下載一個原版OD)。
調試notepad
擦除 DebugPort
調試崩啦
六、ActiveProcessLinks 斷鏈實現進程隱藏
使用windbg將某個進程斷鏈(從EPROCESS中的ActiveProcessLinks摘除),然后在任務管理器中查找該進程。
之前在3環做過PEB斷鏈的實驗,和這次的要求沒什么區別的。
3環PEB斷鏈
我這里就實現這樣的效果:隱藏所有記事本進程。加載驅動用KMD工具。
#include <ntddk.h>NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path); VOID DriverUnload(PDRIVER_OBJECT driver);NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path) {PEPROCESS pEprocess, pCurProcess;PCHAR ImageFileName;// 獲取 EPROCESS__asm{mov eax, fs:[0x124];mov eax, [eax + 0x220];mov pEprocess, eax;}pCurProcess = pEprocess;// 遍歷 ActiveProcessLinksdo {ImageFileName = (PCHAR)pCurProcess + 0x174;if (strcmp(ImageFileName, "notepad.exe") == 0){PLIST_ENTRY preNode, curNode, nextNode;// 初始化節點curNode = (PLIST_ENTRY)((ULONG)pCurProcess + 0x88);nextNode = curNode->Flink;preNode = curNode->Blink;// 上一個節點的下一個節點指向我的下一個節點preNode->Flink = curNode->Flink;// 下一個節點的上一個節點指向我的上一個節點nextNode->Blink = curNode->Blink; }//DbgPrint("%s\n", ImageFileName);pCurProcess = (PEPROCESS)(*(PULONG)((ULONG)pCurProcess + 0x88) - 0x88);} while (pEprocess != pCurProcess);driver->DriverUnload = DriverUnload;return STATUS_SUCCESS; }VOID DriverUnload(PDRIVER_OBJECT driver) {DbgPrint("驅動卸載成功\n"); }驅動執行前,任務管理器中可以看到記事本進程
驅動執行后,ActiveProcessLinks 斷鏈完成,notepad進程被隱藏了
總結
以上是生活随笔為你收集整理的(53)进程结构体EPROCESS,擦除 DebugPort 实现反调试,ActiveProcessLinks 断链实现进程隐藏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (52)系统调用阶段测试——基于 SSD
- 下一篇: (54)线程结构体 ETHREAD,线程