什么是混淆?
混淆是软件工程中的一个众所周知的术语。它是程序员有目的地隐藏编写的代码。它主要是出于安全目的,通过使其模糊以避免篡改、隐藏隐式值或隐藏所使用的逻辑来完成。人们可以借助特定于语言的反混淆器来混淆代码,这些反混淆器可以转换为有意义的代码。
例如:
- 下面是一个混淆的 C 代码:
int i;main(){for(i=0;i["]
- 这是人们可以理解的去混淆版本。
int i; void write_char(char ch) { printf("%c", ch); } int main() { for (i = 0; i < 15; i++) { write_char("hello, world!\n"[i]); } return 0; }
如何混淆应用程序中的代码?
要理解混淆,我们需要知道 Android 和Java是如何实现这种应用内形成的。有两种方法可以在应用程序中混淆代码:
- Shrinking:它有助于检测并安全地从应用程序的发布版本中删除未使用的类、字段、方法和属性。
- 优化:它有助于检查和重写代码以减小其大小。例如,如果优化器检测到从未使用 else {} 语句的 if-else 语句,则会删除 else 语句的代码。代码收缩器和优化器的示例包括适用于Java和 Android 的 ProGuard 以及适用于 Android 的 R8。
如何确定混淆方法的质量?
混淆方法的质量取决于其效力、弹性、隐秘性和成本的组合。
- 隐身:有必要隐藏程序的控制流。
- 成本:成本效益是必要的,以便混淆技术可以在多个类似应用程序中大规模应用。
- 效力:效力定义了转换后的代码比原始代码更模糊的程度。软件复杂度度量定义了软件的各种复杂度度量,例如它包含的谓词数量、继承树的深度、嵌套级别等。虽然好的软件设计的目标是根据这些参数最小化复杂度,但混淆的目标是最大化它。
- 弹性:弹性定义了转换后的代码抵抗自动反混淆攻击的能力。它是程序员创建反混淆器的努力以及反混淆器所需的时间和空间的组合。最高程度的弹性是一种无法被反混淆器撤消的单向转换。一个例子是当混淆删除诸如源代码格式之类的信息时。
混淆的优点:
- 用于混淆的一种著名方法是迭代代码混淆。在许多应用中,迭代代码混淆是一个过程,其中一个或多个混淆算法重复应用于代码,前一个混淆算法的输出为下一个混淆算法提供输入。这可以称为为代码添加安全层的一种方式。
- 如果一个人在他或她的直接控制之外的任何地方发布有价值的软件(尤其是Java、Android、.NET 和 iOS)并且源代码没有分发,那么混淆可能应该是应用程序开发过程的一部分。混淆使攻击者更难审查代码和分析应用程序。它还可能使黑客难以调试和篡改您的应用程序。最终目标是使从应用程序中提取或发现有用信息变得困难,例如商业秘密 (IP)、凭证或安全漏洞。
混淆的缺点:
网络犯罪分子也使用混淆技术。让我们看看如何保护自己免受他们的伤害。
- 恶意软件编写者广泛使用混淆来逃避防病毒扫描程序。分析这些混淆技术是如何在恶意软件中使用的至关重要。
- 死代码插入:这是一种简单的基本技术,它通过向程序添加无效指令来改变其外观,但不会改变其行为。为了对抗死代码插入,基于签名的防病毒扫描程序应该能够在分析之前删除无效的指令。
- 指令子程序:这种混淆技术通过将一些指令替换为原始指令的其他等效指令来确保原始代码的发展。
- 代码传输:代码转置对原始代码的指令序列进行重新排序,而不会对代码的行为产生任何明显的影响。本质上,有两种方法可以将此技术部署到行动中。第一种方法是随机打乱指令,通过插入无条件分支或跳转继续恢复原始执行顺序。对抗这种混淆的一种方法是通过删除无条件分支或跳转来恢复原始程序。相比之下,第二种方法通过选择和重新排序彼此没有影响的自由指令来创建新一代。寻找免费指令是一个复杂而复杂的问题。这种方法实施难度大,检测成本高。
- 代码集成:代码集成首先由 Win95/Zmist 恶意软件(也称为 Zmist)引入。 Zmist 恶意软件将自身绑定到其目标程序的代码。为了执行这种混淆技术,Zmist 必须首先将其目标程序反编译为可管理的小对象,并将自身插入它们之间,然后将集成代码重新组装成新一代。到目前为止,这是最复杂的混淆技术之一,它会使检测和恢复变得非常困难,而且成本很高。