利用C++ R3层断链实现模块隐藏功能可以通过操作Windows系统内核模块,使得应用程序在加载模块的时候不出现在模块列表中,从而实现模块的隐藏。 下面是具体的操作步骤:
第一步:获取模块基址
获取需要隐藏的模块的基址。可以使用工具如Process Hacker或Task Manager等查看正在运行的进程,并获取该进程中需要隐藏的模块的基址。可以使用函数GetModuleHandleEx
获取基址,该函数可以比较快速地获取多个内核地址。
第二步:破坏PEB或LDR数据结构
通过操作这两个数据结构,可以阻止模块出现在模块列表中。具体来说,可以使用类似下面的代码破坏PEB数据结构:
PPEB peb = NtCurrentPeb();
PLDR_DATA_TABLE_ENTRY pEntry = peb->Ldr->InLoadOrderModuleList.Flink;
while (pEntry->DllBase != NULL)
{
if (pEntry->DllBase == (HMODULE) baseAddr)
{
RemoveEntryList(&(pEntry->InLoadOrderLinks));
RemoveEntryList(&(pEntry->InMemoryOrderLinks));
RemoveEntryList(&(pEntry->HashLinks));
break;
}
pEntry = pEntry->InLoadOrderLinks.Flink;
}
这段代码会遍历PPEB_LDR_DATA->InLoadOrderModuleList
链表,然后在链表中找到指定的模块,从而从链表中移除该模块。
第三步:破坏SSDT表
可以使用内核钩子函数来破坏SSDT表,使得系统调用的时候不会调用被隐藏的模块中的函数。下面是一个破坏SSDT表的例子:
#define SYSCALL_INDEXZZZ SystemCallIndexFromWin32Index
#define ZZZ32_SYSCALL_INDEX 100
DWORD Index = SYSCALL_INDEXZZZ(ZZZ32_SYSCALL_INDEX);
DWORD * ServiceTable = (DWORD *) KeServiceDescriptorTable; // SSDT表
DWORD * FunctionAddress = (DWORD *) ServiceTable[Index];
DWORD originalFunc = 0;
LOCKED_PAGE * page = GetPage((PVOID)FunctionAddress); // SSDT页的锁定
originalFunc = InterlockedCompareExchange(&page->byte0,
NewFunctionAddress.LowPart,
(ULONG) FunctionAddress);
if (FunctionAddress != originalFunc)
Restore(&page->byte0, FunctionAddress);
上面代码中的ZZZ32_SYSCALL_INDEX
是需要破坏的系统调用号,函数KeServiceDescriptorTable
可用于获取SSDT表的地址。该代码中主要利用了GetPage
函数锁定该函数所在的内存页,修改其中的地址为新地址,从而替代原始的系统调用函数,从而实现破坏SSDT表的效果。
示例说明
- 隐藏“xhook”模块
假设需要隐藏的模块是名为“xhook”的动态链接库,可以使用下面代码进行隐藏:
HMODULE hModule = LoadLibraryW(L"xhook.dll");
DWORD baseAddr = (DWORD) hModule;
PPEB peb = NtCurrentPeb();
PLDR_DATA_TABLE_ENTRY pEntry = peb->Ldr->InLoadOrderModuleList.Flink;
while (pEntry->DllBase != NULL)
{
if (pEntry->DllBase == (HMODULE) baseAddr)
{
RemoveEntryList(&(pEntry->InLoadOrderLinks));
RemoveEntryList(&(pEntry->InMemoryOrderLinks));
RemoveEntryList(&(pEntry->HashLinks));
break;
}
pEntry = pEntry->InLoadOrderLinks.Flink;
}
该代码将从PEB数据结构中查找名为“xhook”的模块,然后将其从链表中移除,从而隐藏该模块。
- 破坏SSDT表
假设需要破坏的函数是NtCreateProcess
,可以使用下面的代码破坏SSDT表:
#define SYSTEMSERVICE_INDEX_NtCreateProcess 0x00000036
// 记录原始函数指针地址
PVOID OriginalFunctionEntry = KeServiceDescriptorTable->ServiceTable[SYSTEMSERVICE_INDEX_NtCreateProcess];
// 将函数指针地址替换为自定义函数地址
InterlockedExchangePointer(&(KeServiceDescriptorTable->ServiceTable[SYSTEMSERVICE_INDEX_NtCreateProcess]),
NewFunctionAddress);
该代码将系统调用NtCreateProcess
所在的SSDT表项的函数指针地址替换为自定义函数指针地址,从而实现了破坏SSDT表的效果。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:利用C++ R3层断链实现模块隐藏功能 - Python技术站