代码混淆123

攻击者经常依赖混淆技术(一种故意使源代码变得混乱且不可读的技术)来隐藏恶意负载,使其躲过安全防御机制和代码审查人员的检查。对于致力于保护软件供应链的开发人员和安全团队来说,了解不同生态系统(npm、PyPI、Maven 和 Go 模块)中的混淆技术至关重要。

混淆到底是什么 ?

混淆技术会将原本可读、清晰的代码转化为令人困惑、复杂甚至看似毫无意义的指令。合法开发者可能会使用混淆技术来保护知识产权,或通过压缩文件来减小文件大小。然而,恶意行为者通常会滥用这种策略来逃避自动安全工具和人工审核流程的检测。

常见的混淆技术

让我们探索一下我们在各种生态系统中发现的一些广泛使用的混淆方法:

1. 编码字符串和字符操作

攻击者喜欢这种方法的原因: 编码允许攻击者隐藏关键的 URL、敏感令牌或命令,从而使自动扫描程序和人工审核人员难以快速检测到恶意意图。

它如何帮助攻击者: 可读字符串被转换成编码序列(十六进制、Unicode、Base64),将恶意代码与良性内容无缝混合。

// Encoded URL is harder to recognize immediately:
const url = '\x68\x74\x74\x70\x73\x3a\x2f\x2fexample[.]com'
fetch(url)

2. 动态代码生成和执行

攻击者喜欢这种方式的原因: 动态执行允许攻击者远程更新和传递有效载荷,而无需更改原始感染包,从而绕过静态分析检查。

它如何帮助攻击者: 使用 eval()exec() 运行远程获取的有效载荷会使静态分析无效,从而大大提高隐蔽性。

const cmd = ['al', 'ert', '("hacked!")'].join('')
eval(cmd)
// Dynamically constructs and executes alert("hacked!")

3. 基于数组的字符串混淆和移位

攻击者喜欢这种方法的原因: 将字符串存储在数组中并间接引用它们会使逆向工程尝试和人工代码审查变得复杂。

它如何帮助攻击者: 跨数组分割的敏感字符串具有复杂的索引,掩盖了真实意图,减慢了分析速度。

// Less recognizable directly:
let arr = ['.com', 'example', 'https://']
let url = arr[2] + arr[1] + arr[0] // "https://example.com"
fetch(url)

4. 控制流混淆

攻击者为什么喜欢它: 复杂的条件和循环使逻辑变得混乱,导致审阅者错过隐藏在看似无害的代码中的恶意意图。

它如何帮助攻击者: 混淆的流程会分散审阅者的注意力,从而降低检测的有效性。

// Complex yet straightforward malicious intent:
for (var i = 0; i < 1; i++) {
switch (i) {
case 0:
window['e' + 'val']("alert('malicious code')")
break
}
}

5. 死代码插入

攻击者为何喜欢这种方法: 不相关的代码会分散分析师的注意力,掩盖恶意负载并使自动检测变得复杂。
它如何帮助攻击者: 审阅者关注不相关的片段,无意中忽略了恶意指令。

// Distracting irrelevant logic:
public void harmlessMethod() {
int unused = 1234; // irrelevant and unused
if(false) {
System.out.println("This will never run.");
}
// Actual malicious logic follows
Runtime.getRuntime().exec("malicious command");
}

6. 基于环境的混淆

攻击者喜欢这种方法的原因: 在特定环境条件下(如生产服务器)激活恶意软件可以避免在受控的安全测试中被发现。
它如何帮助攻击者: 恶意代码仅在目标环境中执行,从而逃避早期检测。

import os
if os.getenv('PRODUCTION') == 'true':
exec("malicious payload")
# Only executes malicious code in specific environments