【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 介绍 聚合管道由一个或多个处理文档的阶段组成: 每个阶段对输入文档执行一个操作。例如,某个阶段可以过滤文档、对文档进行分组并计算值。 从一个阶段输出的文档将传递到下一阶段。 一个聚合管道可以返回针对文档…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
