Windows 内核编程杂谈-内核摘链隐藏R3进程

原理

我们可以利用 _EPROCESS 结构体中的 ActiveProcessLinks 双向链表遍历进系统中的进程,并将特定进程从该双向链表中移除,以达到隐藏特定进程的目的。

_EPROCESS 结构体

kd> dt _EPROCESS
nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   /*
   	kd> dt _KPROCESS
    nt!_KPROCESS
       +0x000 Header           : _DISPATCHER_HEADER
       // 当结构体中含有 _DISPATCHER_HEADER 结构体的
       // 该结构体对象就可以使用WaitForSingleObject函数等待
       +0x010 ProfileListHead  : _LIST_ENTRY
       +0x018 DirectoryTableBase : [2] Uint4B	//Cr3
       +0x020 LdtDescriptor    : _KGDTENTRY		//历史遗留
       +0x028 Int21Descriptor  : _KIDTENTRY		//历史遗留
       +0x030 IopmOffset       : Uint2B
       +0x032 Iopl             : UChar
       +0x033 Unused           : UChar
       +0x034 ActiveProcessors : Uint4B
       +0x038 KernelTime       : Uint4B			//R0执行时间
       +0x03c UserTime         : Uint4B			//R3执行时间
       +0x040 ReadyListHead    : _LIST_ENTRY
       +0x048 SwapListEntry    : _SINGLE_LIST_ENTRY
       +0x04c VdmTrapcHandler  : Ptr32 Void
       +0x050 ThreadListHead   : _LIST_ENTRY
       +0x058 ProcessLock      : Uint4B
       +0x05c Affinity         : Uint4B			//规定进程中的所有线程能在哪个CPU上运行
       // 如果值为1,那这个进程的所以线程只能在0号CPU上跑(00000001)
	   // 如果值为3,那这个进程的所以线程能在0、1号CPU上跑(000000011)
	   // 4个字节共32位, 所以最多32核; Windows64位, 就64核
       +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   : UChar
   */
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER		// 进程的创建时间
   +0x078 ExitTime         : _LARGE_INTEGER		// 进程的退出时间
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +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		//虚拟内存相关的统计信息
   +0x0b4 SessionProcessLinks : _LIST_ENTRY
   +0x0bc DebugPort        : Ptr32 Void
       // 用于为调试器提供调试对象地址, 调试对象用于调试器与被调试进建立联系;
       // 当调试器附加进程时, 操作系统会在DebugPort处填充一个调试对象地址, 用于供调试器使用
       // 当该值为空时, 进程将会无法被调试
   +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		// 指向用户层下的_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

定位 ActiveProcessLinks

具体原理可以参考 基于 PEB 断链实现进程/模块隐藏

简单的隐藏进程的函数封装

注意:不同版本的 windows ActiveProcessLinks 偏移不同

一个简单的动态寻找 ActiveProcessLinks 偏移的函数:

static DWORD FindEprocessActiveProcessLinksOffset() // 获取ActiveProcessLinks偏移
{
	DWORD ofs = 0; // The offset we're looking for
	int idx = 0;                // Index
	DWORD pids[3];				// List of PIDs for our 3 processes
	PEPROCESS eprocs[3];		// Process list, will contain 3 processes

	//Select 3 process PIDs and get their EPROCESS Pointer
	for (int i = 16; idx < 3; i += 4)
	{
		if (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)i, &eprocs[idx])))
		{
			pids[idx] = i;
			idx++;
		}
	}

	/*
	Go through the EPROCESS structure and look for the PID
	we can start at 0x20 because UniqueProcessId should
	not be in the first 0x20 bytes,
	also we should stop after 0x600 bytes with no success
	*/

	for (int i = 0x20; i < 0x600; i += 4)
	{
		if ((*(DWORD*)((UCHAR*)eprocs[0] + i) == pids[0])
			&& (*(DWORD*)((UCHAR*)eprocs[1] + i) == pids[1])
			&& (*(DWORD*)((UCHAR*)eprocs[2] + i) == pids[2]))
		{
			//+ 0x440 UniqueProcessId  : Ptr64 Void
			//+ 0x448 ActiveProcessLinks : _LIST_ENTRY
			// UniqueProcessId next is ActiveProcessLinks
			ofs = i + sizeof(PVOID);
			break;
		}
	}

	ObDereferenceObject(eprocs[0]);
	ObDereferenceObject(eprocs[1]);
	ObDereferenceObject(eprocs[2]);
	DbgPrint("[ZfDriver] Activeprocesslinks Offset: 0x%x", ofs);
	return ofs;
}

隐藏进程函数:

BOOL Utils::ProcessHide(IN DWORD pid)
{
	PEPROCESS pEProcess = NULL;

	PsLookupProcessByProcessId((HANDLE)pid, &pEProcess);
	if (pEProcess == NULL)
	{
		return FALSE;
	}
	static DWORD offset = FindEprocessActiveProcessLinksOffset();
	PLIST_ENTRY listEntry = (PLIST_ENTRY)((DWORD64)pEProcess + offset);

	listEntry->Flink->Blink = listEntry->Blink;
	listEntry->Blink->Flink = listEntry->Flink;
	listEntry->Flink = listEntry;
	listEntry->Blink = listEntry;

	return TRUE;
}
(文章今日已有 1 人访问,总访问量 5 ::>_<::)
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇