• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2026-06-09 16:17 Aet 隐藏边栏 |   抢沙发  1 
文章评分 1 次,平均分 5.0

概述

注入方法

  1. CreateRemoteThread + LoadLibraryA/W (最经典)
  2. SetWindowsHookEx (钩子注入)
  3. QueueUserAPC + LoadLibraryA (APC 注入)
  4. 注册表/配置文件 + AppInit_DLLs (系统级)
  5. 内存补丁 + 改执行流 (Inline Hook/代码补丁,高级)

CreateRemoteThread + LoadLibraryA/W(线程)

原理

  1. 在目标进程里创建一个新线程,让这个线程的入口点指向 LoadLibraryA(dllpath),DLL 一加载就自动执行 DllMain

理解

  1. 为什么可以让新创建的线程的入口点指向 LoadLibraryA(dllpath)
    1. 因为 LoadLibraryA 的函数签名恰好符合线程入口函数的约定

  1. 新线程什么时机执行?
    1. CreateRemoteThread 返回时,线程已创建但不一定已运行(取决于内核调度)
    2. WaitForSingleObject 主动等待线程结束,期间当前线程会释放 CPU

实现

  1. OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid) 拿目标进程句柄
  2. VirtualAllocEx(hProcess, nullptr, dllpath_len, MEM_COMMIT, PAGE_READWRITE) 在目标进程分配内存放 DLL 路径
  3. WriteProcessMemory(hProcess, lpRemote, dllpath, dllpath_len, nullptr)DLL 路径字符串写进去
  4. CreateRemoteThread(hProcess, nullptr, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, lpRemote, 0, nullptr) 创建线程,入口是 LoadLibraryA,参数是 DLL 路径地址
  5. WaitForSingleObject(hThread, INFINITE) 等线程完成

特点

  1. 优点
    1. 最直白、最兼容,Win2000+ 都能用
    2. 不需要知道目标进程内存布局
    3. 代码短,容易理解
  2. 缺点
    1. 创建一个新的可见线程,有 PID、有栈,痕迹明显(调试器一眼能看到)
    2. 如果目标进程做了线程白名单限制(某些反 cheat),这条线程可能被识别为异常

示例代码

  1. app,目标进程
    1. 先启动目标进程,然后启动注入器,传入piddll全路径

  1. 要注入的dll

  1. 注入器

SetWindowsHookEx (钩子)

原理

  1. 给目标进程的线程挂一个系统钩子(比如消息钩子),钩子回调函数在 DLL 里,DLL 一被加载就执行 DllMain,回调函数可以自己卸钩

理解

  1. 比如注册了消息钩子,什么时机会触发这个消息?
    1. 不同的钩子类型,触发时机完全不同
    2. 比如WH_GETMESSAGE 钩子在目标线程调用 GetMessage()PeekMessage() API 时触发

  1. 触发消息钩子时,由于回调函数在DLL里面,如果此时DLL还没加载,会自动加载这个DLL吗?
    1. 是的,系统会自动加载

实现

  1. 把要注入的 DLL 编译成包含钩子回调函数
  2. SetWindowsHookEx(WH_GETMESSAGE, DllCallbackFunc, hDllModule, targetThreadId) 给目标线程挂钩子
  3. 目标线程一旦处理消息,系统自动加载那个 DLL、调钩子
  4. 钩子函数里自己 UnhookWindowsHookEx 卸钩,函数返回
  5. DLL 留在目标进程地址空间(或自己 FreeLibrary)

特点

  1. 优点
    1. 不显式创建线程,更隐蔽
    2. 利用系统消息循环,不用 WaitForSingleObject
  2. 缺点
    1. 只能钩线程级钩子,需要知道目标线程 ID
    2. 依赖消息循环,如果目标线程没有消息循环就无效
    3. Win10+ 加强了钩子的安全检查,某些钩子类型被限制

QueueUserAPC + LoadLibraryA (APC )

原理

  1. QueueUserAPC 往目标线程的异步过程调用(APC)队列里塞一个调用,指向 LoadLibraryA
  2. 线程进入可警告状态(alertable wait)时这个 APC 会被执行

理解

  1. 什么是线程的异步过程调用(APC)队列?
    1. 数据结构层面:每个线程都有一个私有的 APC 队列,存放待执行的异步过程调用

  1. 什么是线程的可警告状态?
    1. 线程的可警告状态是指线程处于等待状态,且设置了允许 APC 中断这个等待
    2. 关键的四个字:中断等待

  1. 什么时机线程会进入可警告状态?
    1. 取决于应用代码调用的 API
    2. 线程不是自动进入可警告状态的。只有当线程调用某些特定的 API,并且传入"允许警告"的参数,线程才会进入可警告状态

API 如何使用 说明
SleepEx SleepEx(1000, TRUE) Sleep 的可警告版本
WaitForSingleObjectEx WaitForSingleObjectEx(h, INFINITE, TRUE) 第三个参数 TRUE
WaitForMultipleObjectsEx WaitForMultipleObjectsEx(n, h, FALSE, INFINITE, TRUE) 第五个参数 TRUE
MsgWaitForMultipleObjectsEx MsgWaitForMultipleObjectsEx(...) 消息队列的可警告等待
GetQueuedCompletionStatus 默认可警告 异步 I/O 完成端口
ReadFileEx 配合回调 异步读文件
WriteFileEx 配合回调 异步写文件
SignalObjectAndWait SignalObjectAndWait(h1, h2, INFINITE, TRUE) 第四个参数 TRUE
I/O 完成端口相关 API 多个 通常都可警告

不可警告 可警告版本
Sleep SleepEx(..., TRUE)
WaitForSingleObject WaitForSingleObjectEx(..., TRUE)
WaitForMultipleObjects WaitForMultipleObjectsEx(..., TRUE)
  1. 为什么线程进入可警告状态时这个APC会被执行?
    1. Windows 内核的设计里,APC 机制是用来实现异步操作和系统级回调的
    2. 当线程显式进入可警告状态时,内核默认:"这个线程现在愿意处理异步请求"。所以内核会:

实现

  1. OpenProcess/OpenThread 拿目标线程
  2. 在目标进程分配内存放 DLL 路径(VirtualAllocEx + WriteProcessMemory)
  3. QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)lpDllPath)APC
  4. 触发目标线程进入可警告状态(比如它在 WaitForSingleObject/Sleep 会自动进入)
  5. APC 被执行,DLL 加载

特点

  1. 优点
    1. 没有创建新线程的痕迹(没有新 TID)
    2. 相对隐蔽
  2. 缺点
    1. 依赖目标线程进入可警告状态,无法强制
    2. 如果线程在执行用户代码、没有系统调用,APC 队列里的请求会堆积,什么时候执行不确定
    3. 某些反 cheat 专门检测 APC 队列异常

注册表/配置文件 + AppInit_DLLs (系统级)

原理

  1. DLL 路径写进 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs,操作系统在加载任何用户模式进程时会自动加载这些 DLL(通过 user32.dll 的初始化)

理解

  1. 是注入到了user32.dll里面了吗
    1. 不是注入到 user32.dll 里面

实现

  1. 以管理员权限修改注册表:AppInit_DLLs = "your.dll" 或多个用分号分隔
  2. 重启系统或新启动的进程会自动加载
  3. 注意:LoadAppInit_DLLs 值要设为 1

特点

  1. 优点
    1. 一次配置、全局生效(之后启动的所有用户进程都加载)
    2. 无需逐个注入,省事
  2. 缺点
    1. 需要管理员权限
    2. 很明显的注册表痕迹,任何清理工具都能找到
    3. 现代 Windows(Win10 1607+)默认禁用,需要特定条件才work
      Windows 10 version 1607 开始,AppInit_DLLs 的功能被大幅限制
    4. 本质是持久化手段,不是动态注入

示例代码

内存补丁 + 改执行流 (Inline Hook/代码补丁,高级)

原理

  1. 扫描目标进程内存,定位某个已加载模块,解析其 PE 头,对其代码段做 inline patch(改几个字节跳转到你的代码),后续执行流就被劫持了

理解

  1. pe相关

实现

  1. VirtualQueryEx 扫目标进程内存,找 MZ
  2. 解析 PE 头,找到想要 hook 的函数地址
  3. VirtualProtectEx 改页保护为可写
  4. WriteProcessMemory 改那个函数前几字节为 jmp your_codecall your_code
  5. VirtualProtectEx 改回原保护
  6. 你的代码执行后再跳回,原函数继续

特点

  1. 优点
    1. 非常隐蔽,没有新线程、没有钩子、没有 APC
    2. 对已有线程立刻生效,不需要等可警告状态
  2. 缺点
    1. 非常脆弱,依赖目标模块的内存布局和版本,版本一变、函数地址变、patch 的位置就错了
    2. 如果 patch 的位置碰巧在某个指令中间,会破坏指令,目标崩溃
    3. 需要知道目标进程的内存映像(PE 结构、导入表、IAT),工作量大
    4. 改完代码后要保证原指令流完整性(call 了要 push return address,改了栈要恢复),极容易出 bug

注入原理

概述

  1. 前面五种方法,底层原理其实分两大类
  2. 第一类:加载 DLL 让系统自动执行 DllMain
    1. CreateRemoteThread + LoadLibraryA/W (最经典)
    2. SetWindowsHookEx (钩子注入)
    3. QueueUserAPC + LoadLibraryA (APC 注入)
  3. 第二类:绕过系统,自己接管
    1. 注册表/配置文件 + AppInit_DLLs (系统级)
    2. 内存补丁 + 改执行流 (Inline Hook/代码补丁,高级)

声明:本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享