C++:实现DLL注入(附带源码)

一、项目背景详细介绍

在 Windows 平台下,DLL(Dynamic Link Library)注入是一项非常经典且重要的技术。它的本质是:

让目标进程在不知情或未主动加载的情况下,加载并执行我们指定的 DLL

DLL 注入在多个领域都有实际应用:


1. 常见应用场景

(1)调试与开发辅助

  • 给第三方程序注入日志模块
  • Hook API 以观察行为
  • 插桩统计函数调用情况

(2)自动化与工具开发

  • 游戏辅助工具
  • 自动化测试框架
  • GUI 注入扩展

(3)安全研究与逆向工程

  • API Hook 技术的基础
  • 恶意代码分析
  • 防注入 / 反调试技术研究

(4)系统级功能扩展

  • 无源码扩展已有程序功能
  • 动态替换实现逻辑

2. 为什么学习 DLL 注入?

DLL 注入几乎是 Windows 进程模型的“必修课”,它涉及:

  • 进程与线程
  • 虚拟内存
  • Windows API
  • 远程线程
  • PE / DLL 加载机制

不理解 DLL 注入,就无法真正理解 Windows 用户态程序是如何协作的。


3. 本项目目标

本项目将从:

  • 原理
  • API 调用流程
  • 安全边界
  • 完整 C++ 实现

四个层面,完整实现并讲透一个标准 DLL 注入器


二、项目需求详细介绍


1. 功能需求

实现一个 基于 LoadLibrary 的经典 DLL 注入器,要求:

  • 给定目标进程 PID
  • 将指定 DLL 注入目标进程
  • DLL 在目标进程中成功执行

2. 技术约束

  • 平台:Windows
  • 语言:C++
  • 注入方式:远程线程 + LoadLibrary
  • 架构:x86 注入 x86,x64 注入 x64(必须一致)

3. 工程要求

  • 完整代码
  • 清晰模块划分(通过注释)
  • 每个关键步骤有详细中文注释
  • 可直接编译运行(Visual Studio)

4. 教学要求

  • 解释 为什么这样做
  • 解释 Windows 背后的机制
  • 不仅“能用”,而且“看懂”

三、相关技术详细介绍


1. Windows 进程与地址空间

每个进程都有独立的虚拟地址空间

  • 进程 A 无法直接访问进程 B 的内存
  • DLL 注入的核心问题是:
    如何把数据 + 代码“送”进另一个进程

2. DLL 加载机制(LoadLibrary)

当进程调用:

LoadLibrary("xxx.dll");

Windows 会:

  1. 映射 DLL 到进程地址空间
  2. 解析 PE 结构
  3. 解析导入表
  4. 调用 DllMain(DLL_PROCESS_ATTACH)

DLL 注入的关键点:让目标进程执行 LoadLibrary


3. 远程线程(CreateRemoteThread)

Windows 提供了一个极其关键的 API:

CreateRemoteThread

它允许:

  • 其他进程中创建线程
  • 指定线程入口地址
  • 传入参数

这正是 DLL 注入的“突破口”。


4. 虚拟内存操作 API

为了把 DLL 路径传给目标进程,需要:

API作用
OpenProcess获取目标进程句柄
VirtualAllocEx在目标进程中分配内存
WriteProcessMemory向目标进程写数据
VirtualFreeEx释放远程内存

5. 注入完整流程概览

DLL 注入 ≠ 魔法,本质是 API 组合

流程如下:

  1. 打开目标进程
  2. 在目标进程中申请内存
  3. 写入 DLL 路径
  4. 获取 LoadLibrary 地址
  5. 创建远程线程
  6. 等待线程执行完成
  7. 清理资源

四、实现思路详细介绍


1. 核心设计思想

我们不直接“拷贝 DLL”,而是:

让目标进程自己加载 DLL

这是最稳定、最兼容、最经典的注入方式。


2. 为什么选择 LoadLibrary 注入?

优点:

  • 稳定
  • API 官方支持
  • DLL 生命周期完整
  • 易于教学与理解

缺点:

  • 容易被安全软件检测
  • 属于“老派注入方式”

3. 模块拆分

逻辑分为四个模块:

  1. 进程句柄获取
  2. 远程内存操作
  3. 远程线程创建
  4. 错误处理与清理

4. 架构注意事项

  • 注入器与目标进程 位数必须一致
  • DLL 路径必须是 绝对路径
  • DLL 必须导出 DllMain

五、完整实现代码

/************************************************************ * 文件:InjectDll.cpp * 描述:基于 LoadLibrary 的 DLL 注入器 ************************************************************/ #include <windows.h> #include <iostream> #include <string> /** * @brief 向指定进程注入 DLL * * @param pid 目标进程 ID * @param dllPath DLL 的完整路径 * @return true 注入成功 * @return false 注入失败 */ bool InjectDll(DWORD pid, const std::wstring& dllPath) { // 1. 打开目标进程 HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid ); if (!hProcess) { std::wcerr << L"OpenProcess failed!" << std::endl; return false; } // 2. 在目标进程中申请内存,用于存放 DLL 路径 size_t size = (dllPath.length() + 1) * sizeof(wchar_t); LPVOID remoteMemory = VirtualAllocEx( hProcess, nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); if (!remoteMemory) { CloseHandle(hProcess); return false; } // 3. 将 DLL 路径写入目标进程 BOOL writeResult = WriteProcessMemory( hProcess, remoteMemory, dllPath.c_str(), size, nullptr ); if (!writeResult) { VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); CloseHandle(hProcess); return false; } // 4. 获取 LoadLibraryW 的地址 HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll"); FARPROC loadLibraryAddr = GetProcAddress(hKernel32, "LoadLibraryW"); if (!loadLibraryAddr) { VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); CloseHandle(hProcess); return false; } // 5. 在目标进程中创建远程线程 HANDLE hThread = CreateRemoteThread( hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddr, remoteMemory, 0, nullptr ); if (!hThread) { VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); CloseHandle(hProcess); return false; } // 6. 等待远程线程执行完成 WaitForSingleObject(hThread, INFINITE); // 7. 清理资源 CloseHandle(hThread); VirtualFreeEx(hProcess, remoteMemory, 0, MEM_RELEASE); CloseHandle(hProcess); return true; } /************************************************************ * 文件:main.cpp * 描述:注入器入口 ************************************************************/ int main() { DWORD pid; std::wcout << L"请输入目标进程 PID:"; std::wcin >> pid; std::wstring dllPath = L"C:\\Test\\Inject.dll"; if (InjectDll(pid, dllPath)) { std::wcout << L"注入成功!" << std::endl; } else { std::wcout << L"注入失败!" << std::endl; } return 0; } /************************************************************ * 文件:InjectDll.dll(示例) ************************************************************/ #include <windows.h> BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { if (fdwReason == DLL_PROCESS_ATTACH) { MessageBoxW(nullptr, L"DLL 注入成功!", L"Inject", MB_OK); } return TRUE; } 

六、代码详细解读(仅解读方法作用)


1. InjectDll 函数

作用:

  • 封装完整 DLL 注入流程
  • 对外提供简单接口
  • 隐藏底层 Windows API 细节

2. OpenProcess

作用:

  • 获取目标进程的操作权限
  • 是所有远程操作的前提

3. VirtualAllocEx / WriteProcessMemory

作用:

  • 在目标进程中创建“参数区”
  • 用于传递 DLL 路径

4. GetProcAddress + CreateRemoteThread

作用:

  • 获取 LoadLibrary 地址
  • 让目标进程执行 DLL 加载

5. DllMain

作用:

  • DLL 的入口函数
  • 注入成功后自动执行

七、项目详细总结

本项目完整展示了:

  • Windows DLL 注入的本质原理
  • 注入器的工程实现方式
  • 远程线程 + LoadLibrary 的经典模型

这是:

✅ 逆向工程必学
✅ Windows API 深入理解
✅ Hook / 注入 / 安全研究基础


八、项目常见问题及解答


Q1:为什么 x86 不能注入 x64?

答:

  • 地址空间不同
  • 线程入口地址不兼容
  • Windows 强制架构一致

Q2:杀毒软件为什么能检测?

答:

  • CreateRemoteThread 行为特征明显
  • LoadLibrary 注入属于高风险行为

Q3:能否不使用 LoadLibrary?

答:

可以,例如:

  • Reflective DLL Injection
  • Manual Mapping
  • APC 注入

九、扩展方向与性能优化


1. APC 注入

  • 更隐蔽
  • 不直接创建线程

2. Manual Map 注入

  • 不调用 LoadLibrary
  • 绕过模块检测

3. 反注入与防护研究

  • Hook CreateRemoteThread
  • 检测远程内存写入

4. 64 位安全注入框架

  • 适配 Wow64
  • 支持跨架构注入

Read more

从下载到运行:MySQL 详细安装配置完整教程

从下载到运行:MySQL 详细安装配置完整教程

从下载到运行:MySQL 超详细安装配置完整教程 * 从下载到运行:MySQL 详细安装配置完整教程 * 一、MySQL下载步骤 * 二、MySQL安装流程 * 三、MySQL环境配置与验证 * 1. 配置环境变量 * 2. 验证MySQL是否安装成功 * 四、Navicat链接MySQL * 1. 安装Navicat 从下载到运行:MySQL 详细安装配置完整教程 一、MySQL下载步骤 首先访问MySQL官方下载地址,进入MySQL的官方下载页面。 下载完成后,在本地找到下载好的MySQL安装文件,双击文件启动安装程序。 二、MySQL安装流程 双击安装文件后,会进入MySQL安装类型选择界面,界面中提供5种安装模式,各自功能如下: Developer Default(开发者默认):包含MySQL开发所需的全套组件(如数据库服务、客户端工具、SDK等),适合开发人员使用。Server only(仅服务器):仅安装MySQL数据库服务,适合仅需搭建数据库服务器的场景。Client

By Ne0inhk
4nm移动SoC革命:三星高能效NPU架构解析

4nm移动SoC革命:三星高能效NPU架构解析

面向移动端SoC的高硬件效率神经网络处理单元 临近春节,围炉煮茶之余阅读了三星电子发表在固体电子学顶刊IEEE JSSC上的论文 《A Multi-Mode 8k-MAC HW-Utilization-Aware Neural Processing Unit With a Unified Multi-Precision Datapath in 4-nm Flagship Mobile SoC》 ,三星副总裁Inyup Kang博士 为本文的共同作者。三星电子的研究团队提出了一种应用于4nm移动SoC支持多模式的神经网络处理单元(NPU),专为猎户座移动SoC设计,通过统一多精度数据通路支持INT4/8及FP16运算,实现高能效与高面积效率的平衡。 原文链接 关键词 计算利用率、深度神经网络(DNN)、领域专用架构(DSA)、推理加速器、稀疏感知零跳过、统一乘加(MAC) 全文导图及摘要 针对深度卷积、浅层小通道层等端侧AI应用中的低硬件利用率场景,三星团队结合编译器提供的张量信息,通过重构计算流(包含基于特征图稀疏特性的零值跳过、Scatter-Gather等技术),硬件利用

By Ne0inhk
金仓数据库 MongoDB 兼容:多模融合下的架构之道与实战体验

金仓数据库 MongoDB 兼容:多模融合下的架构之道与实战体验

引言:从“平替”到“超越”的技术跨越 在国产化替代(信创)浪潮下,选择数据库不再只是考量“能否使用”,更多关注其“好用与否”,还要看是否能做到“无缝切换”。提到 MongoDB,想必大家都不生疏,作为 NoSQL 领域的佼佼者,凭借自身灵活的数据架构和飞快的读写效率,斩获诸多互联网及物联网项目,不过须要诚实地表明,一旦关乎到企业核心业务,譬如要确保数据完全一致,执行繁杂的关联查询或者实施统一运作管理时,MongoDB 就常常会有些力不从心。 电科金仓(Kingbase)所给出的多模融合数据库方案颇具趣味,该方案并非仅仅创建一层适配层来博取眼球,其实在架构层面上执行了“降维打击”,经由内核级别的 MongoDB 协议适配 并结合自主研发的 OSON 存储引擎,金仓把“关系型数据库稳定的基础”与“NoSQL 灵活的特性”融合起来,现在,让我们一起探究金仓数据库(KingbaseES,

By Ne0inhk
# Flutter三方库适配OpenHarmony【flutter_libphonenumber】——联合插件(Federated Plugin)架构解析

# Flutter三方库适配OpenHarmony【flutter_libphonenumber】——联合插件(Federated Plugin)架构解析

前言 欢迎来到 Flutter三方库适配OpenHarmony 系列文章!本系列围绕 flutter_libphonenumber 这个 电话号码处理库 的鸿蒙平台适配,进行全面深入的技术分享。 欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 上一篇我们从全局视角介绍了 flutter_libphonenumber 的功能定位和鸿蒙适配成果。本篇将深入解析该库采用的 联合插件(Federated Plugin)架构,这是理解整个适配工作的基础。我们将逐层拆解 platform_interface、MethodChannel、各平台实现包的协作关系,并详细分析鸿蒙平台是如何 无缝接入 这套架构的。 理解联合插件架构是进行任何 Flutter 三方库鸿蒙适配的 第一步,掌握了这套模式,你就能举一反三地适配其他库。 一、什么是联合插件(Federated Plugin) 1.1 传统插件的局限性 在 Flutter 早期,

By Ne0inhk