0%
毅种循环

模块 46 - Payload 执行控制

恶意软件开发课程 - Payload 执行控制


模块 46 - Payload 执行控制#

[!IMPORTANT] 本知识库声明

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

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

Payload 执行控制#

简介#

在现实场景中,限制恶意软件执行的操作并专注于基本任务非常重要。恶意软件执行的操作越多,就越容易被监控系统发现。

Windows 同步对象 (Windows Synchronization Objects) 可以被用来控制 Payload 的执行。这些对象协调多个线程或进程对共享资源的访问,确保共享资源以受控方式被访问,并防止多个线程或进程尝试同时访问同一资源时出现冲突或竞态条件。通过使用同步对象,可以控制 Payload 在系统上执行的次数。

💡 初学者提示:为什么要控制执行次数?

想象一下,如果你不小心点开了两次病毒程序,它可能会启动两个相同的远控进程,这不仅会占用双倍系统资源,还会因为重复的网络连接、重复的注册表改动等行为,极大地增加被杀毒软件(AV/EDR)发现的风险。

此外,有些沙箱(Sandbox)在分析程序时,可能会尝试多次运行它。如果我们检测到已经有一个实例在运行,就可以优雅地退出,从而增加分析的难度。

同步对象有几种类型,包括 信号量 (Semaphores)互斥锁 (Mutexes)事件 (Events)。每种类型的同步对象工作方式略有不同,但最终目的都是为了协调共享资源的访问。

信号量 (Semaphores)#

信号量 是利用存储在内存中的值来控制对共享资源访问的同步工具。信号量有两种类型:二进制和计数。二进制信号量的值为 1 或 0,分别表示资源可用或不可用。而计数信号量的值大于 1,表示可用资源的数量或可以并发访问资源的进程数量。

要控制 Payload 的执行,可以在每次执行 Payload 时创建一个命名信号量对象。如果二进制文件被多次执行,第一次执行将创建命名信号量,Payload 将按预期执行。在随后的执行中,信号量创建将失败,因为同名的信号量已经在运行。这表示 Payload 正处在之前的运行中,因此不应再次运行以避免重复。

CreateSemaphoreA 将被用于创建信号量对象。将其创建为命名信号量对于防止初始运行后的后续执行非常重要。如果命名信号量已经在运行,CreateSemaphoreA 将返回现有对象的句柄,且 GetLastError 将返回 ERROR_ALREADY_EXISTS

// 创建一个名为 "ControlString" 的计数信号量
HANDLE hSemaphore = CreateSemaphoreA(NULL, 10, 10, "ControlString");

// 检查是否已经存在同名对象
if (hSemaphore != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
	// Payload 已经在运行
else
	// Payload 尚未运行
c

互斥锁 (Mutexes)#

互斥锁 (Mutex) 是“mutual exclusion”(互斥)的缩写,是一种用于管理进程和线程之间对共享资源访问的同步工具。实际上,尝试访问共享资源的线程会检查互斥锁的状态。如果它已被锁定,线程将等待直到互斥锁解锁后再继续。如果互斥锁未被锁定,线程将锁定它,对共享资源执行必要的操作,然后在完成后解锁互斥锁。这确保了同一时间只有一个线程可以访问共享资源,防止冲突和数据损坏。

CreateMutexA 用于创建命名互斥锁,如下所示:

// 创建一个名为 "ControlString" 的命名互斥锁
HANDLE hMutex = CreateMutexA(NULL, FALSE, "ControlString");

// 检查是否已存在
if (hMutex != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
	// Payload 已经在运行
else
	// Payload 尚未运行
c

事件 (Events)#

事件 (Events) 是另一种可用于协调线程或进程执行的同步工具。它们可以是手动的或自动的,手动事件需要显式的设置(Set)或重置(Reset)操作,而自动事件由外部条件触发,如定时器过期或任务完成。

要在程序中使用事件,可以采用 CreateEventA WinAPI。该函数用法演示如下:

// 创建一个名为 "ControlString" 的命名事件
HANDLE hEvent = CreateEventA(NULL, FALSE, FALSE, "ControlString");

// 检查是否已存在
if (hEvent != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
	// Payload 已经在运行
else
	// Payload 尚未运行
c

演示#

使用信号量:

图片
图片

使用互斥锁:

图片
图片

使用事件:

图片
图片


🎯 总结#

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

  1. 同步对象:了解了信号量、互斥锁和事件在进程间同步中的应用。
  2. 单实例运行:学习了如何利用“命名”对象和 ERROR_ALREADY_EXISTS 错误代码来防止 Payload 重复执行。
  3. 规避价值:控制执行次数可以减少系统痕迹,并可能规避某些重复性的自动分析环境。

💡 关键要点

  • 在红队开发中,使用一个足够独特的互斥锁名称(例如:{43067891-DE8C-4F9A-B03F-8C7987234BAC})是非常专业的做法。
  • 这种技术不仅用于防止重复运行,还能作为一种简单的“沙箱检测”指标——如果某些环境故意模拟已有的互斥锁来欺骗你的程序。

📚 下一步学习

下一个模块将介绍 Spoofing PPID。我们将学习如何修改进程的父进程 ID,让我们的攻击进程看起来像是从合法的系统进程(如 explorer.exe)启动的!