背景
-
寄存器 -
正则表达式和捕获组 -
通过分叉和合并进行数据流控制 -
聚合 -
数据扣除 -
AES 解密
在近期的恶意软件对抗中,山石情报中心对于某钓鱼高度混淆的文件进行了深度去混淆,示例结果如下:
为此,我们将深入介绍该工具,在后面分别演示这些功能之后,我们会把它们全部组合起来,为一个多阶段恶意软件开发配置提取器。该篇文章参考自matthew的《Advanced CyberChef Techniques for Configuration Extraction – Detailed Walkthrough and Examples》。
获取样品:
寄存器
寄存器允许我们在 CyberChef 会话中创建变量,并在需要时引用它们。
寄存器是通过正则表达式捕获组定义的,并允许我们创建一个具有未知值的变量,该变量根据代码中的已知模式进行拟合。
1
案例一
下面我们有一个使用 AES 解密的 powershell 脚本。传统上,使用 CyberChef 可以轻松解码,只需手动复制密钥值并将其粘贴到“AES 解密”操作中即可。
在这里,我们可以看到复制到 AES 解密操作中的密钥。
这种手动复制密钥的方法有效,但这意味着密钥是“硬编码”的,并且配方不适用于使用相同技术的类似样品。如果另一个示例使用不同的密钥,则需要手动更新此新密钥才能使 CyberChef 配方正常工作。
2
案例二
通过使用“寄存器”操作,我们可以开发一个正则表达式来匹配 AES 密钥的结构,然后通过寄存器变量(如“$R0”)访问它。在这种情况下,AES 密钥是一个 44 个字符的 base64 字符串,因此我们可以使用 44-46 个字符的 base64 正则表达式来提取 AES 密钥。我们稍后可以通过 AES Decrypt 操作中的 $R0 变量访问它。
3
案例三
在同一示例的上一阶段中,恶意软件使用基本的减法操作从大整数数组创建 ASCII 字符代码。
正则表达式
1
正则表达式 – 用例 1(寄存器)
正则表达式的首次使用是在初始寄存器操作中。在这里,我们应用了一个正则表达式来提取一个键值,稍后在反混淆过程中使用。正则表达式在这里的主要用途是能够通常捕获与解码过程相关的密钥。避免对值进行硬编码,并允许配方在多个样本中工作。
2
正则表达式 – 用例 2(隔离文本)
3
正则表达式 – 用例 3(追加值)
有时,您需要将值追加到各个输出行。在这些情况下,可以使用正则表达式来捕获整行 (.*) ,然后将其替换为相同的值(通过 $1 中引用的捕获组),然后替换另一个值(我们的初始寄存器)。关键用例是能够轻松捕获和追加数据,这对于稍后将在此配方中使用的减法运算符等操作至关重要。
4
正则表达式 – 用例 4(提取加密密钥)
5
正则表达式 – 用例 5(提取 Base64 文本)
正则表达式可用于隔离包含感兴趣内容的 base64 文本。此特定示例将最终恶意软件阶段存储在大型 AES 加密和 Base64 编码的 blob 中。由于我们已经通过寄存器提取了 AES 密钥,因此我们可以应用正则表达式来隔离主 base64 blob,然后执行 AES 解密。
6
正则表达式 – 用例 6(提取初始字符)
此示例利用 base64 解码内容的前 16 个字节为 AES 解密创建 IV。我们可以利用正则表达式和寄存器来提取解码内容的前 16 个字节 .{16} 。这使我们能够捕获 IV,然后通过寄存器引用它以执行 AES 解密。
7
正则表达式 – 用例 7(删除尾随空字节)
正则表达式可用于从数据末尾删除尾随的空字节。这特别有用,因为有时我们只想删除数据“末尾”的空字节。而传统的“删除空字节”将删除代码中所有位置的空字节。在此示例中,有一些尾随的 nullbytes 正在破坏解密过程的一部分。
通过应用空字节搜索, +$ 我们可以使用查找/替换来删除这些尾随的空字节。在这种情况下, + 查找一个或多个 null 字节, $ 指定这必须位于数据的末尾。
应用此操作后,现在将从数据末尾删除尾随的空字节。
数据流“分叉”
分叉允许我们分离值并独立地对每个值执行操作,就好像它们是一个单独的配方一样。在下面的用例中,我们有一个很大的十进制值数组,我们需要从每个值中减去 787。这里的一个大问题是,为了减去 787,我们需要在下面屏幕截图中的每个十进制值之后附加 787。这将是一场手工完成的噩梦。
由于数据是结构化的,并用逗号分隔,我们可以应用带有逗号拆分分隔符和换行符合并分隔符的分叉操作。拆分分隔符是分隔数据中值的任何内容,但合并分隔符是您希望新数据的结构。此时,每个换行符都表示一个新的输入数据,所有未来的操作都将独立地作用于每一行。
如果我们现在继续应用查找替换,我们可以看到该操作已经单独影响了每一行。
如果我们在没有分叉的情况下应用相同的概念,那么整个十进制数据块的末尾只会添加一个 787。
数据流“聚合”
合并本质上是分叉操作的“撤消”。使用分支成功解码内容后,需要确保应用合并,以确保可以适当地分析新内容。如果没有合并,所有将来的操作将只影响单个字符,而不会影响整个脚本。
AES 解密
Cyberchef 能够通过 AES 解密操作进行 AES 解密。要利用 AES 解密,请在恶意软件代码中查找 AES 的关键指标,并将所有变量与 AES 操作对齐。例如,确保对齐密钥、模式和 IV。然后,只需将这些值插入 CyberChef 即可。
最终,您可以使用正则表达式和寄存器有效地自动执行此操作,如前所述。
配置提取案例(22 个操作)
利用所有这些技术,我们可以为NetSupport Loader开发一个配置提取器,其中包含3个独立的脚本,这些脚本都可以在同一配方中解码。这总共需要 22 个操作,下面将演示这些操作。
1
第 1 阶段 – 解码(7 次操作)
初始脚本使用大量十进制整数数组进行混淆。对于这些十进制值中的每一个,都会减去数字 787,然后将结果用作 ASCII 字符码。
-
使用寄存器提取减法值 -
使用正则表达式提取十进制数组 -
使用分叉分隔每个十进制值 -
使用正则表达式追加存储在寄存器中的 787 值。 -
应用减法操作以生成 ASCII 字符码 -
应用“从小数点开始”以生成第 2 阶段 -
使用合并操作启用对第二阶段脚本的分析。
操作 1 – 提取减法值
初始减法值可以通过寄存器操作和正则表达式提取。
这必须在进行额外的分析和解码之前完成,以确保减法值存储在寄存器内。
第二步是使用正则表达式和捕获组提取主十进制数组。
捕获组确保我们隔离十进制值并忽略它周围的任何脚本内容。
此正则表达式查找长度为 1000 或更大的 {1000,} 小数或逗号 [d,] 。用圆括号 ( 和 ) .
没有转义的内括号形成捕获组。
第三个操作利用 Fork 来分离十进制值并独立地对每个十进制值执行操作。
Fork 在原始代码中存在的逗号处定义了一个分隔符,并指定了一个 Merge Delimiter n 以提高可读性。
第四个操作使用正则表达式查找/替换将 787 值追加到分叉操作创建的每行的末尾。
请注意,我们曾经 (.*) 捕获原始十进制值,然后 $1 再次访问它。用于 $R0 访问可在操作 1 中创建的寄存器。
我们现在可以在操作 4 中附加 787 值后执行减法运算。
这将生成构成第二阶段脚本的原始 ASCII 字符码。
请注意,我们指定了一个空格分隔符,因为这是操作 4 中十进制值和减法值之间的分隔符。
我们现在可以使用“从十进制”运算解码 ASCII 代码。
这将生成原始脚本。尽管由于我们之前的 Fork 操作,这些值通过换行符分隔。
2
第 2 阶段 – 使用 AES 加密的 Powershell 脚本(8 个操作)
经过 7 次操作,我们现在发现了一个第二阶段的 Powershell 脚本,该脚本利用 AES 加密来解开另一个阶段。下面突出显示了此脚本中解密所需的关键点。
-
使用寄存器提取 AES 密钥 -
使用正则表达式提取 Base64 blob -
解码 Base64 blob -
使用寄存器提取初始化向量 -
从输出中删除 IV -
执行AES解密,引用我们的寄存器 -
使用正则表达式删除尾随 NullBytes -
执行 GZIP 解压缩以解锁第 3 阶段
我们知道是这种情况,因为脚本从数据的偏移量 16 开始解密。
这可以通过 TransformFinalBlock 的官方文档来确认。
操作 13 – AES 解密
我们还可以注意到选择了 ECB 模式,因为这是脚本中指定的模式。
操作 14 – 删除尾随空字节
请注意,我们知道使用了 Gzip,因为它在 AES 解密过程之后的第 2 阶段被引用。
3
第 3 阶段 – Powershell 脚本(7 个操作)
要解码第 3 阶段,我们必须执行以下操作
-
使用寄存器提取减法值 -
使用正则表达式提取十进制数组 -
使用分叉分隔数组 -
使用另一个 Fork 分隔各个十进制值 -
使用查找/替换附加减法值 -
执行减法 -
从生成的 ASCII 代码中恢复文本
我们现在可以通过应用分叉运算来分隔十进制数组。
当前的数组由换行符分隔,因此我们可以将其指定为拆分分隔符。
为了便于阅读,我们可以将合并分隔符指定为双换行符。双换行符除了使输出更易于阅读外,什么都不做。
现在我们已经隔离了数组,我们需要隔离各个整数值,以便我们可以附加减法值。
我们可以使用另一个 Fork 操作来做到这一点,指定一个逗号分隔符(因为这是分隔我们的十进制值)和一个换行符的合并分隔符。同样,这个换行符除了提高可读性之外什么也没做。
隔离十进制值后,我们可以继续使用以前的 techniquq 来捕获每一行并附加当前存储在 $R3 中的减法值。
在这里,我们可以看到附加到包含十进制值的每行的减法值。
现在,我们可以应用减法运算来减去上一步中附加的值。
这将恢复原始的 ASCII 字符码,以便我们可以在下一步中解码它们。
将 ASCII 代码恢复为原始十进制形式后,我们可以应用 from decimal 运算来恢复原始文本。
在这里,我们可以看到 Net.Webclient 字符串,尽管由于我们的分叉操作,它被隔在换行符上。
删除合并分隔符后,现在将显示四个十进制数组的输出。
关于山石网科情报中心
山石网科情报中心,涵盖威胁情报狩猎运维和入侵检测与防御团队。 山石网科情报中心专注于保护数字世界的安全。以情报狩猎、攻击溯源和威胁分析为核心,团队致力于预防潜在攻击、应对安全事件。山石网科情报中心汇集网络安全、计算机科学、数据分析等专家,多学科融合确保全面的威胁分析。我们积极创新,采用新工具和技术提升分析效率。团队协同合作,分享信息与见解,追求卓越,为客户保驾护航。无论是防范未来威胁还是应对当下攻击,我们努力确保数字世界安全稳定。其中山石网科网络入侵检测防御系统,是山石网科公司结合多年应用安全的攻防理论和应急响应实践经验积累的基础上自主研发完成,满足各类法律法规如 PCI、等级保护、企业内部控制规范等要求。
原文始发于微信公众号(山石网科安全技术研究院):你真的会用CyberChef吗?