挖掘注入线程

admin 2026-05-16 04:42:42 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文通过红蓝对抗实验详细演示了进程注入攻击技术:使用注入器将shellcode注入explorer.exe进程获取反向Shell,并利用PowerShell脚本Get-InjectedThreads检测异常线程。关键发现包括通过判断线程起始地址内存类型(MEMPRIVATE而非MEMIMAGE)识别注入行为,配合WinDBG验证内存属性形成可靠IoC。文档提供了完整的攻防实操流程与取证方法。 综合评分: 87 文章分类: 红队,内网渗透,恶意软件,应急响应,威胁情报


cover_image

挖掘注入线程

原创

Other Other

Ghost Wolf Lab

2026年5月9日 21:18 日本

在小说阅读器读本章

去阅读

简介

在红蓝对抗中,进程注入是攻击者维持访问、绕过防御的经典手段。本文通过一个完整的实验——从向 explorer.exe 注入 shellcode 获取反向 Shell,到使用 PowerShell 脚本与 WinDBG 进行交叉检测——逐层揭开线程注入的攻防细节,并深入解析检测工具背后的内存取证逻辑。

注入

首先,我们使用课程中编写的注入器程序,将一段用于反弹 Shell 的 shellcode 注入到 notepad.exe 或 exploer.exe 进程中。选择 explorer.exe 是因为它通常是用户态下长期运行且拥有合法网络连接权限的进程,注入后不易被察觉。

注入器内部会执行以下关键步骤:

  1. 打开目标进程:通过 OpenProcess 获取 notepad.exe 的句柄,申请必要的访问权限(如 PROCESS_VM_WRITEPROCESS_CREATE_THREAD)。
  2. 分配内存:在目标进程虚拟地址空间内调用VirtualAllocEx,申请一块可读、可写、可执行(RWX)的内存区域,大小与 shellcode 匹配。
  3. 写入 Shellcode:使用WriteProcessMemory将准备好的反弹 Shell 字节码拷贝到新分配的内存中。
  4. 启动远程线程:调用CreateRemoteThreadRtlCreateUserThread等 API,让目标进程执行这片内存中的代码。

执行注入器后,我们的受害者主机会立即显示弹窗信息,证明 shellcode 已在 notepad.exe 的上下文中成功运行。

注入检测

攻击发生后,我们切换到蓝队视角,使用开源 PowerShell 脚本 Get-InjectedThreads.ps1(来自 NetSPI)对系统内所有进程的线程进行扫描。

下载地址:

https://gist.github.com/jaredcatkinson/23905d34537ce4b5b1818c3e6405c1d2

$a = Get-InjectedThread; $a

脚本遍历当前系统中的每一个进程,并检查其内部的所有线程。很快,我们捕捉到一个异常项:

从输出可以明确看到,notepad 进程中存在一个线程 ID 为 5778 的活动线程,其起始地址指向一块私有、已提交的内存(MEM_PRIVATE | MEM_COMMIT),而正常线程通常从磁盘上加载的模块(MEM_IMAGE)开始执行。

这立刻触发了“已注入线程”的红旗。

为了进一步确认该异常线程是否确实携带了我们的恶意 shellcode,我们提取了线程内容字节。

在 PowerShell 中,$a.Bytes 字段存储了线程起始地址附近的内存数据,我们将其转换为熟悉的 \x 形式:

($a.Bytes | ForEach-Object ToString x2) -join "\x"

输出的十六进制字符串如下(示例):

与此同时,我们查看注入器源码中硬编码的原始 shellcode,两者进行严格比对。结果完全吻合——该线程正在执行我们的恶意负载,确认为注入后产生。

这种字节级的比对,在事件响应中可以形成可靠的技术证据,避免误报,也为后续的内存取证提供了精确的 IoC(入侵指标)。

WinDBG解剖

为了从调试器角度直观查看注入线程的细节,我们需要先定位具体是哪个线程。Process Explorer 等系统工具可以帮助我们快速找到 notepad.exe 下新增的线程。

如果存在注入,这里会变成一个孤零零的、很“突兀”的内存地址,比如 0x03730000,而不是像图中带有dll名称的符号(这里我们使用课程中讲解的进程注入编写,规避了显示)。

同时,Get-InjectedThread 的输出也直接给出了 ThreadId 和十进制形式的起始地址。

我们可以看到ThreadId为7548,也就是新建的线程,将其转为16进制为1d7c。

在WinDbg主界面,通过菜单或命令附加到目标进程。

点击 File → Attach to a Process,在弹出的列表中找到 explorer.exe,点击OK。

附加成功后,目标进程会被暂停,WinDbg的命令输入栏会显示调试提示符(例如 0:000>),等待指令。

使用~命令显示进程中的所有线程,确认可疑线程是否在列表中。

这个命令会列出所有线程的ID和状态。WinDbg使用~加上线程编号(如0, 1, 2…)来表示一个线程,注意这个编号是WinDbg内部的编号,并非系统线程ID。可以通过查看输出中的线程ID(十六进制显示)来定位我们之前发现的那个可疑注入线程。

接着,首先,使用~<线程编号> s命令切换到我们找到的可疑线程的上下文环境中。切换成功后,使用~.命令查看当前线程的详细信息。在输出中找到 StartAddressStart 字段,这个地址就是注入代码的入口点。

根据分析,Get-InjectedThreads.ps1 的检测核心在于判断线程起始地址的内存类型是否为 MEM_IMAGE。如果不是,则判定为可疑注入。我们可以通过以下命令在WinDbg中手动验证这一逻辑。

使用 !address 命令查询 StartAddressStart 所在内存区域的详细属性:

在输出结果中,查找 Type 和 State 字段:

  • 对于正常线程,Type 应为 MEM_IMAGE。
  • 对于我们分析的注入线程,Type 很可能为 MEM_PRIVATE(如果是通过 VirtualAllocEx 分配的内存)或 MEM_MAPPED。
  • 如果State是 MEM_COMMIT,且Type不是 MEM_IMAGE,则高度印证了注入行为。

对于正常创建的主线程或从 kernel32.dll 等模块启动的合法线程,其起始地址必然位于一个 MEM_IMAGE 类型的内存区域,因为代码是由系统加载器从 PE 文件映射而来。当攻击者使用 VirtualAllocEx 在目标进程中动态分配内存并直接写入 shellcode 时,这块内存就是 MEM_PRIVATE 类型。因此,只要线程的起始地址落在 MEM_PRIVATE 内存中,就几乎可以判定该线程正在执行未映射到磁盘的匿名代码——这正是注入的标志。

当然,更狡猾的注入技术(如通过映射合法 DLL 后再篡改其 .text 节)可能导致内存类型仍为 MEM_IMAGE,但 Get-InjectedThreads 同时配合其他启发式检查(例如模块加载列表比对、线程起始地址与已知模块导出函数的匹配)来增强检测率。尽管本文仅展示了最基础的“私有内存中的线程”检测,但它已经足以应对大多数入门级到中级的注入手法。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Ghost Wolf Lab Other Other《挖掘注入线程》

挖掘注入线程 网络安全文章

挖掘注入线程

文章总结: 本文通过红蓝对抗实验详细演示了进程注入攻击技术:使用注入器将shellcode注入explorer.exe进程获取反向Shell,并利用PowerS
评论:0   参与:  0