0%
毅种循环

模块 48 - 进程参数伪装 (1)

恶意软件开发课程 - 进程参数伪装 (1)


模块 48 - 进程参数伪装 (1)#

[!IMPORTANT] 本知识库声明

本知识库由本人整理自互联网 MalDev Academy 泄露资源,并由本人手动翻译为中文,过程中增加了大量关键技术提示实践心得

  1. 内容完整性:并未修改任何核心代码与技术逻辑,仅做汉化与注释加强。
  2. 版权归属:原始知识产权归原作者/官方所有。
  3. 支持正版:本仓库仅供内部学习交流,如果您有经济能力,请务必支持正版课程
  4. 权利申诉:如相关内容侵犯了您的权益,请联系我,我将立即核实并删除。

进程参数伪装 (1)#

简介#

进程参数伪装 (Process Argument Spoofing) 是一种用于隐藏新创建进程的命令行参数的技术。其目的是在不向日志服务(如 Procmon 或 Windows 事件日志)透露真实命令的情况下执行操作。

下图显示了 powershell.exe -c calc.exe 命令被 Procmon 捕获的情况。本模块的目标是在运行该命令的同时,让其在 Procmon 中显示为通过其他“无害”的参数启动。

图片
图片

💡 初学者提示:为什么要伪装参数?

很多监控软件(如 EDR)在进程启动的一瞬间,会记录下它的命令行参数。

比如你运行 powershell.exe -Enc QmFkQ29kZQ==(一段加密的恶意代码),监控系统会立刻报警。但如果你先用一个无害的命令启动(如 powershell.exe "Nothing suspicious here..."),然后在它还没正式开始工作前,偷偷修改它内存里的参数,那么监控系统记录下来的就是那个“无害”的字符串,而实际执行的却是你的恶意代码。

回顾 PEB#

执行参数伪装的第一步是理解参数在进程内部的存储位置。回顾课程开始时讲解的 PEB 结构,它保存了关于进程的信息。更具体地说,PEB 内部的 RTL_USER_PROCESS_PARAMETERS 结构包含 CommandLine 成员,该成员保存了命令行参数。

typedef struct _RTL_USER_PROCESS_PARAMETERS {
  BYTE           Reserved1[16];
  PVOID          Reserved2[10];
  UNICODE_STRING ImagePathName;
  UNICODE_STRING CommandLine; // 这里就是存储命令行的地方
} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
c

CommandLine 的类型是 UNICODE_STRING

UNICODE_STRING 结构#

typedef struct _UNICODE_STRING {
  USHORT Length;
  USHORT MaximumLength;
  PWSTR  Buffer; // 指向实际宽字符字符串的指针
} UNICODE_STRING, *PUNICODE_STRING;
c

Buffer 元素包含命令行参数的内容。因此,我们可以通过 PEB->ProcessParameters.CommandLine.Buffer 以宽字符字符串的形式访问命令行参数。

如何伪装进程参数#

伪装命令行参数的基本流程如下:

  1. 挂起启动:创建一个目标进程并处于挂起状态(CREATE_SUSPENDED),传入“假的”(无害的)哑元参数(Dummy arguments)。
  2. 获取 PEB:获取该远程进程的 PEB 地址。
  3. 读取内存:从远程进程中读取 PEB 及其中的 ProcessParameters
  4. 修补参数:使用 WriteProcessMemory 修改远程进程内存中 ProcessParameters.CommandLine.Buffer 所指向的字符串,将其改写为真正要执行的 Payload 字符串。
  5. 恢复运行:恢复进程运行。

⚠️ 重要限制:长度问题

写入 CommandLine.Buffer 的真实参数长度必须小于或等于启动时传入的哑元参数长度。

如果真实参数更长,它可能会覆盖掉哑元参数缓冲区之外的内存数据,导致进程奔溃。

口诀:假的要长,真的要短(或相等)。

获取远程 PEB 地址#

检索远程进程的 PEB 地址需要使用 NtQueryInformationProcessProcessBasicInformation 标志。

图片
图片

当使用 ProcessBasicInformation 时,该函数返回一个 PROCESS_BASIC_INFORMATION 结构,其中的 PebBaseAddress 成员即为我们需要的地址。

处理读取和写入#

读取远程 PEB 和参数结构体需要使用 ReadProcessMemory,而修改参数则需要使用 WriteProcessMemory

我们需要分步骤进行:

  • 第一次读取:根据 PEB 地址读取整个 PEB 结构。
  • 第二次读取:从 PEB 中找到 ProcessParameters 指针,读取该结构体。这里通常会多读取一些字节(如额外加 225 字节),以确保涵盖了由于参数长度变化可能导致的结构体差异。
  • 写入:找到 CommandLine.Buffer 指向的地址,覆盖写入真正的 Payload。

进程参数伪装函数实现#

CreateArgSpoofedProcess 函数封装了整个流程。

演示#

哑元参数:powershell.exe Totally Legit Argument (这将被记录在日志中)。 实际执行:powershell.exe -c calc.exe (这将被静默运行)。

图片
图片


🎯 总结#

在本模块中,我们学习了:

  1. 参数存储:理解了命令行参数存储在 PEB 的 ProcessParameters.CommandLine 中。
  2. 挂起修补法:利用 CREATE_SUSPENDED 启动机会,在进程开始工作前修改其内存。
  3. 规避原理:由于监控软件通常只在进程创建时抓取一次参数快照,我们的后期修补可以成功隐瞒真实意图。

💡 关键要点

  • 长度敏感:一定要确保启动时的哑元参数足够长,就像买大一码的鞋(容纳不同长度的脚)。
  • 底层操作:涉及 ReadProcessMemoryWriteProcessMemory 对远程 PEB 的直接修改。

📚 下一步学习

下一个模块将介绍 Process Argument Spoofing (2)。我们将探讨这种技术的一些局限性,以及如何通过更高级的手段进行改良。