免杀专题
37、隐藏模块
1. 课程目标
学习如何隐藏已加载的DLL模块,避免被检测工具发现。
2. 隐藏方法
2.1 从PEB.Ldr链表中摘除
#include <windows.h>
#include <winternl.h>
typedef struct _LDR_DATA_TABLE_ENTRY_FULL {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
// ... 更多字段
} LDR_DATA_TABLE_ENTRY_FULL, *PLDR_DATA_TABLE_ENTRY_FULL;
BOOL UnlinkModule(HMODULE hModule) {
// 获取PEB
PPEB pPeb = (PPEB)__readgsqword(0x60); // x64
// 获取Ldr
PPEB_LDR_DATA pLdr = pPeb->Ldr;
// 遍历InLoadOrderModuleList
PLIST_ENTRY pHead = &pLdr->InLoadOrderModuleList;
PLIST_ENTRY pEntry = pHead->Flink;
while (pEntry != pHead) {
PLDR_DATA_TABLE_ENTRY_FULL pLdrEntry =
CONTAINING_RECORD(pEntry, LDR_DATA_TABLE_ENTRY_FULL, InLoadOrderLinks);
if (pLdrEntry->DllBase == hModule) {
// 从三个链表中移除
// InLoadOrderLinks
pLdrEntry->InLoadOrderLinks.Flink->Blink = pLdrEntry->InLoadOrderLinks.Blink;
pLdrEntry->InLoadOrderLinks.Blink->Flink = pLdrEntry->InLoadOrderLinks.Flink;
// InMemoryOrderLinks
pLdrEntry->InMemoryOrderLinks.Flink->Blink = pLdrEntry->InMemoryOrderLinks.Blink;
pLdrEntry->InMemoryOrderLinks.Blink->Flink = pLdrEntry->InMemoryOrderLinks.Flink;
// InInitializationOrderLinks
pLdrEntry->InInitializationOrderLinks.Flink->Blink = pLdrEntry->InInitializationOrderLinks.Blink;
pLdrEntry->InInitializationOrderLinks.Blink->Flink = pLdrEntry->InInitializationOrderLinks.Flink;
return TRUE;
}
pEntry = pEntry->Flink;
}
return FALSE;
}
2.2 修改模块名称
BOOL RenameModule(HMODULE hModule, LPCWSTR szNewName) {
// 找到模块的LDR_DATA_TABLE_ENTRY
// 修改FullDllName和BaseDllName
// ...
return TRUE;
}
3. 检测隐藏模块
// 遍历内存查找PE头
void ScanForHiddenModules() {
MEMORY_BASIC_INFORMATION mbi;
LPVOID pAddr = NULL;
while (VirtualQuery(pAddr, &mbi, sizeof(mbi))) {
if (mbi.State == MEM_COMMIT &&
mbi.Type == MEM_IMAGE) {
// 检查是否是PE头
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)mbi.BaseAddress;
if (pDos->e_magic == IMAGE_DOS_SIGNATURE) {
// 检查是否在Ldr链表中
if (!IsInLdrList(mbi.BaseAddress)) {
printf("[!] 发现隐藏模块: %p\n", mbi.BaseAddress);
}
}
}
pAddr = (LPBYTE)mbi.BaseAddress + mbi.RegionSize;
}
}
4. 课后作业
4.1、作业1:隐藏模块(必做)
- 实现从PEB链表中摘除模块
- 使用Process Hacker验证效果
4.2、作业2:检测隐藏(进阶)
- 实现扫描隐藏模块的工具
- 测试检测效果
5. 下一课预告
下一课我们将学习更多异常ShellCode加载方式。