根据网上资料和个人总结,进程隐藏主要有如下几种方法:
1、调用RegisterServiceProcess函数
2、HOOK ZwQuerySystemInformation(通过修改内核ntoskrnl的服务表结构体KeServiceDescriptorTable,计算机出ZwQuerySystemInformation的地址,
然后替换成自己的MyZwQuerySystemInformation,然后断掉过滤要隐藏的进程名.)
3、DKOM摘链(按照进程的ID找到进程的EPROCESS然后将样隐藏的进程的EPROCESS在链表中移除)
4、用Detour Patching来修改NtQuerySystemInformation函数
5、远程线程注入,提权注入到系统服务进程
6、无驱动进入ring0,再在ring0下修改内核对象实现隐藏
7、通过驱动加载.(通过用户空间程序获的进程ID,EPROCESS块 中FLINK和 PID的偏移量 ,传送给驱动程序,驱动程序修改链表隐藏进程。)
typedef struct _IMAGE_INFO {
union {
ULONG Properties;
struct {
ULONG ImageAddressingMode : 8;
ULONG SystemModeImage : 1;
ULONG ImageMappedToAllPids : 1;
ULONG ExtendedInfoPresent : 1;
ULONG MachineTypeMismatch : 1;
ULONG ImageSignatureLevel : 4;
ULONG ImageSignatureType : 3;
ULONG ImagePartialMap : 1;
ULONG Reserved : 12;
};
};
PVOID ImageBase;
ULONG ImageSelector;
SIZE_T ImageSize;
ULONG ImageSectionNumber;
} IMAGE_INFO, *PIMAGE_INFO;
由于隐藏进程需要操作系统级别的权限,因此需要编写驱动程序来实现。以下是一些编写驱动程序实现隐藏进程的C++代码:#include <ntifs.h>#include <ntimage.h>
#include <ntifs.h> #include <ntimage.h>
#define DRIVER_NAME L"TestDriver.sys" //要拦截的驱动名 #define DLL_NAME L"InjectDll.dll" //要拦截的DLL名
typedef struct _DLL_INFO { HANDLE ProcessId; PVOID pImageBase; }DLL_INFO, *PDLL_INFO; //Dll的信息,用来作为线程的参数传递
VOID DriverUnload(IN PDRIVER_OBJECT driverObject); VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo); //模块监控回调函数 BOOLEAN DenyLoadDriver(PVOID pLoadImageBase); //对驱动的加载进行拦截 BOOLEAN DenyLoadDll(HANDLE ProcessId, PVOID pImageBase); //对DLL的加载进行拦截 NTSTATUS MmUnmapViewOfSection(PEPROCESS Process, PVOID BaseAddr); //未导出函数声明 VOID ThreadProc(PVOID StartContext); //运行的线程函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath) { NTSTATUS status = STATUS_SUCCESS;
DbgPrint("驱动加载完成\r\n"); status = PsSetLoadImageNotifyRoutine(LoadImageNotifyRoutine); if (!NT_SUCCESS(status)) { DbgPrint("模块监控设置失败 0x%X\r\n", status); } else { DbgPrint("模块监控设置成功\r\n"); } exit: driverObject->DriverUnload = DriverUnload; return STATUS_SUCCESS; }
VOID LoadImageNotifyRoutine(PUNICODE_STRING FullImageName, HANDLE ProcessId, PIMAGE_INFO ImageInfo) { PDLL_INFO pDllInfo = NULL; HANDLE hThread = NULL;
/* DbgPrint("===========================================================================\r\n"); DbgPrint("检测到新加载的模块,模块信息如下:\r\n"); DbgPrint("加载该模块的进程ID:%d 模块完整名:%wZ 模块基址:0x%X 模块大小:0x%X", ProcessId, FullImageName, ImageInfo->ImageBase, ImageInfo->ImageSize); DbgPrint("===========================================================================\r\n"); */
// 是否是exe或者dll文件 if (ProcessId) { if (wcsstr(FullImageName->Buffer, DLL_NAME) != NULL) { pDllInfo = (PDLL_INFO)ExAllocatePool(NonPagedPool, sizeof(DLL_INFO)); if (!pDllInfo) { DbgPrint("ExAllocatePool Error"); } else { pDllInfo->ProcessId = ProcessId; pDllInfo->pImageBase = ImageInfo->ImageBase; PsCreateSystemThread(&hThread, 0, NULL, NtCurrentProcess(), NULL, ThreadProc, pDllInfo); if (hThread) ZwClose(hThread); } } } else { //加载的是驱动,判断是否是要拦截的驱动 if (wcsstr(FullImageName->Buffer, DRIVER_NAME) != NULL ) { if (DenyLoadDriver(ImageInfo->ImageBase)) { DbgPrint("成功拦截驱动%wZ的加载\r\n", FullImageName); } } } }
VOID ThreadProc(PVOID StartContext) { PDLL_INFO pDllInfo = (PDLL_INFO)StartContext; LARGE_INTEGER liTime = { 0 };
//延时5秒 liTime.QuadPart = -50 * 1000 * 1000; KeDelayExecutionThread(KernelMode, FALSE, &liTime); //卸载DLL if (DenyLoadDll(pDllInfo->ProcessId, pDllInfo->pImageBase)) { DbgPrint("Dll卸载完成\r\n"); }
if (pDllInfo) ExFreePool(pDllInfo); }
BOOLEAN DenyLoadDll(HANDLE ProcessId, PVOID pImageBase) { BOOLEAN bRet = TRUE; NTSTATUS status = STATUS_SUCCESS; PEPROCESS pEprocess = NULL; //保存加载DLL的进程的EPROCESS
//根据进程PID获取EPROCESS status = PsLookupProcessByProcessId(ProcessId, &pEprocess); if (!NT_SUCCESS(status)) { DbgPrint("PsLookupProcessByProcessId Error 0x%X", status); bRet = FALSE; goto exit; }
//卸载模块 status = MmUnmapViewOfSection(pEprocess, pImageBase); if (!NT_SUCCESS(status)) { DbgPrint("MmUnmapViewOfSection Error 0x%X\r\n", status); bRet = FALSE; goto exit; } exit: return bRet; }
BOOLEAN DenyLoadDriver(PVOID pLoadImageBase) { BOOLEAN bRet = TRUE; NTSTATUS status = STATUS_SUCCESS; PVOID pVoid = NULL; PIMAGE_DOS_HEADER pDosHead = NULL; PIMAGE_NT_HEADERS pNtHeader = NULL; PVOID pDriverEntry = NULL; PMDL pMdl = NULL; // 要写入的ShellCode,硬编码的意思是 // mov eax, 0xC0000022 // ret UCHAR szShellCode[6] = { 0xB8, 0x22, 0x00, 0x00, 0xC0, 0xC3}; ULONG uShellCodeLength = 6;
pDosHead = (PIMAGE_DOS_HEADER)pLoadImageBase; pNtHeader = (PIMAGE_NT_HEADERS)((ULONG)pLoadImageBase + pDosHead->e_lfanew); pDriverEntry = (PVOID)((ULONG)pDosHead + pNtHeader->OptionalHeader.AddressOfEntryPoint); //获取驱动入口点位置
//创建MDL并为内存属性添加可写属性 pMdl = MmCreateMdl(NULL, pDriverEntry, uShellCodeLength); if (pMdl == NULL) { bRet = FALSE; goto exit; }
//建立内存页的MDL描述 MmBuildMdlForNonPagedPool(pMdl); //改变MDL的标记为可写 pMdl->MdlFlags |= MDL_MAPPED_TO_SYSTEM_VA; //映射MDL空间 pVoid = MmMapLockedPages(pMdl, KernelMode); //将shellcode拷到目标地址 RtlCopyMemory(pVoid, szShellCode, uShellCodeLength); //释放MDL MmUnmapLockedPages(pVoid, pMdl); IoFreeMdl(pMdl); pMdl = NULL; exit: return bRet; }
VOID DriverUnload(IN PDRIVER_OBJECT driverObject) { NTSTATUS status = STATUS_SUCCESS;
status = PsRemoveLoadImageNotifyRoutine(LoadImageNotifyRoutine); if (!NT_SUCCESS(status)) { DbgPrint("模块监控删除失败 0x%X\r\n", status); } else { DbgPrint("模块监控删除成功\r\n"); } DbgPrint("驱动卸载完成\r\n"); } |