Anti Rookit -- 检测隐藏进程

Anti Rookit 一:检测隐藏进程

引言

检测隐藏进程除了众所周知的枚举进程ID之外,还有枚举句柄表的方式。不过今天给大家带来的是第三种方法。

探究

应用层通过接口 C r e a t e P r o c e s s \textcolor{cornflowerblue}{CreateProcess} CreateProcess创建进程,在内部会调用到 K e r n e l b a s e ! C r e a t e P r o c e s s I n t e r n a l \textcolor{orange}{Kernelbase!CreateProcessInternal} Kernelbase!CreateProcessInternal函数,该函数会调用 n t d l l ! N t C r e a t e U s e r P r o c e s s \textcolor{orange}{ntdll!NtCreateUserProcess} ntdll!NtCreateUserProcess转到内核执行创建进程,成功后会向csrss进程发送进程创建的消息。

​ CreateProcessInternal内部

C s r C l i e n t C a l l S e r v e r \textcolor{cornflowerblue}{CsrClientCallServer} CsrClientCallServer在非csrss进程内是通过LPC 向csrss通讯的。在csrss进程内,由 C s r A p i R e q u e s t T h r e a d \textcolor{cornflowerblue}{CsrApiRequestThread} CsrApiRequestThread函数接收并处理,最终由 C s r p C r e a t e P r o c e s s \textcolor{cornflowerblue}{CsrpCreateProcess} CsrpCreateProcess函数负责处理新进程创建事件。

​ CsrpCreateProcess内部

函数会将进程信息链入一个符号为 C s r R o o t P r o c e s s \textcolor{red}{CsrRootProcess} CsrRootProcess的链表中。链表节点结构如下

c++ 复制代码
typedef struct _CSR_PROCESS
{
        struct _CLIENT_ID ClientId; 
        struct _LIST_ENTRY ListLink; // 指向下一个_CSR_PROCESS
        struct _LIST_ENTRY ThreadList; // 指向_CSR_THREAD
        struct _CSR_NT_SESSION NtSession; 
        VOID ClientPort; 
        CHAR ClientViewBase; 
        CHAR ClientViewBounds; 
        VOID ProcessHandle;
        ULONG SequenceNumber; 
        ULONG Flags;
        ULONG DebugFlags; 
        ULONG ReferenceCount; 
        ULONG ProcessGroupId; 
        ULONG ProcessGroupSequence;
        ULONG LastMessageSequence; 
        ULONG NumOutstandingMessages;
        ULONG ShutdownLevel;
        ULONG ShutdownFlags;
        struct _LUID Luid; 
        PVOID ServerDllPerProcessData[1];
} CSR_PROCESS, *PCSR_PROCESS;

对于检测隐藏的进程,我们只需要关注该结构的ClientIdListLink两个字段就可以了。于是事情就变得很明显了,我们只需要遍历这个双向链表就能得到系统创建的所有进程。

不过这个符号并未导出,我们需要通过特征码去定位。以win10 1909 x64为例

我采用的定位方式是先取得 c s r s r v ! C s r E x e c S e r v e r T h r e a d \textcolor{orange}{csrsrv!CsrExecServerThread} csrsrv!CsrExecServerThread函数地址,因为是导出函数,所以很容易获取地址。然后观察该函数的反汇编代码:

​ CsrExecServerThread内部

于是特征码为: 48 8 B 0 D C C C C C C C C \textcolor{orange}{48\ 8B\ 0D\ CC\ CC\ CC\ CC} 48 8B 0D CC CC CC CC。其他版本系统方法如是,这里不赘述了。

因为csrss是保护进程,应用层无法读取它的内存数据,所以需要放到内核去做。

关键代码

c++ 复制代码
VOID EnumCsrssProcessList(PCSR_PROCESS CsrProcessList)
{
	PEPROCESS pProcess = NULL;
	NTSTATUS ntStatus;
	PUNICODE_STRING uszProcName;
	PLIST_ENTRY pListHdr;
	PLIST_ENTRY pNext;

	__try
	{
		ProbeForRead(CsrProcessList, sizeof(CSR_PROCESS), 1);

		pListHdr = (PLIST_ENTRY)&CsrProcessList->ListLink;
		pNext = pListHdr->Blink;

		while (pListHdr != pNext)
		{
			PCSR_PROCESS pCsrProc = CONTAINING_RECORD(pNext, CSR_PROCESS, ListLink);
			ProbeForRead(pCsrProc, sizeof(CSR_PROCESS), 1);

			ntStatus = PsLookupProcessByProcessId(pCsrProc->ClientId.UniqueProcess, &pProcess);
			if (NT_SUCCESS(ntStatus))
			{
				ntStatus = SeLocateProcessImageName(pProcess, &uszProcName);
				if (NT_SUCCESS(ntStatus))
				{
					DbgPrint("Pid: %x -- %wZ\n",PsGetProcessId(pProcess) ,uszProcName);
					ExFreePool(uszProcName);
				}
				ObDereferenceObject(pProcess);
			}
			
			pNext = pNext->Blink;
		}
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		DbgPrint("[!] An exception occurred! Exception code = %I32x\n", GetExceptionCode());
	}

}

完整代码请到我的github仓库中查看:https://github.com/singlefreshBird/Rootkit/

演示

相关推荐
小职boy8 小时前
不忘初心Windows系统工具箱下载 - 系统优化与维护工具(v1.1)
windows·系统·电脑软件·工具箱
Mininglamp_271810 小时前
Claude Code 封禁中国开发者之后:本地 AI 编程工具的替代方案实测
开发语言·人工智能·windows·开源软件·ai-native
贾斯汀frank10 小时前
C# 15 类型系统改进:Union Types
开发语言·windows·c#
其实防守也摸鱼12 小时前
蓝队相关知识学习(1)---常用堡垒机和服务器
服务器·功能测试·学习·网络安全·网络攻击模型·攻防对抗·蓝队
YHHLAI12 小时前
Agent 智能体开发实战 · 第四课:完整工具集 —— 打造 AI 编程 Agent 的工具箱
人工智能·windows·microsoft
精神底层15 小时前
Skill——提示词的系统化封装
windows·.net
学逆向的16 小时前
汇编——数据存储模式
开发语言·汇编·网络安全
技术不好的崎鸣同学16 小时前
Windows 命令提示符(CMD)恶意脚本分析篇
网络·windows·安全·系统安全
阿米亚波18 小时前
【EVE-NG 实战】防火墙基础(VLAN · VRRP · NAT · ACL · 静态路由)
运维·网络·笔记·网络协议·计算机网络·网络安全·运维开发
2601_9623649719 小时前
告别明文密码:Windows Hello 抗钓鱼双因子认证安全体系科普
windows