通过API代码修改的方式Hook了ZwQuerySystemInformation
但是不理解为啥呢么在删除进程链表之前要先脱钩执行一次ZwQuerySystemInformation
代码如下
NTSTATUS WINAPI NewZwQuerySystemInformation(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength)
{
NTSTATUS status;
FARPROC pFunc;
PSYSTEM_PROCESS_INFORMATION pCur, pPrev;
char szProcName[MAX_PATH] = { 0, };
//开始之前先脱钩
unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);
//通过GetProcAddress调用原始API
pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL), DEF_ZWQUERYSYSTEMINFORMATION);
status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
if (status != STATUS_SUCCESS)
goto __NTQUERYSYSTEMINFORMATION_END;
//仅针对SystemProcessInformation类型操作
if (SystemInformationClass == SystemProcessInformation)
{
//SYSTEM_PROCESS_INFORMATION类型转换
//pCur是单向链表的头
pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;
//开始遍历链表
while (TRUE)
{
if (pCur->Reserved2[1] != NULL)
{
//比较进程名字是否是我们的目的进程
if (!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName))
{
//如果是,判断是否位于链表尾部
//如果在链表尾部,就把前一个节点的Next设为0,直接丢弃掉目的进程的信息
//如果不是尾部,则需要跳过目的进程,方法是让前一个的Next指向目的进程的后一个进程,而不是指向目的进程
if (pCur->NextEntryOffset == 0)
pPrev->NextEntryOffset = 0;
else
pPrev->NextEntryOffset += pCur->NextEntryOffset;
}
else
//更新前一个节点
pPrev = pCur;
}
//如果遍历完链表,则退出
if (pCur->NextEntryOffset == 0)
break;
//更新当前节点,得到下一个节点的位置
pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONGLONG)pCur + pCur->NextEntryOffset);
}
}
__NTQUERYSYSTEMINFORMATION_END:
hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, (PROC)NewZwQuerySystemInformation, g_pOrgBytes);
return status;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!