我最近看到了以下代码混淆方法:

...
jump loc_1234
;-------------------------
         Bunch of junk
;-------------------------

loc_1234:
code continued...


混淆机制背后的逻辑看起来很简单。将一堆垃圾插入具有跳转指令的代码中以使其越过。我想,这样做的目的通常是混淆线性扫描反汇编程序和混淆文件。我想了解更多。有人知道它叫什么吗?这种方法对现代杀毒软件的效果如何?

评论

我称之为“破坏与时间相关的指令的顺序局部性”。

我将其称为“死代码插入”。对我来说,这是一种避免线性扫描和递归遍历的技术。但是,一旦您在拆卸时遵循了指令的语义,这种混淆就完全没有用了。

如果从其他地方执行,@ perror不会死。

@ cb88:我以为是一堆垃圾...

@perror我认为它不应混淆递归遍历,因为它遵循二叉树并且只会跟随跳转。我说得对吗?

#1 楼

这种反拆卸技术在《实用恶意软件分析》一书(第1版第336页,第16章)中被描述为具有恒定条件的跳转指令。正如您所描述的,这种想法是要有一个条件,使得始终执行跳转,并在跳转之后添加代码,这将在跳转的位置生成错误的反汇编。由于反汇编程序假定两个分支是连贯的,因此它将仅反汇编其中的一个分支。

关于反病毒软件的有效性,大多数都使用模拟器。由于条件始终存在,因此仿真器将在那里继续并查看正确的说明。

#2 楼

对此的一种变化是使用“分支函数”。基本思想如下:


将跳转指令“ jmp L”转换为“ call branch_fn”,并在该调用指令后插入N字节的垃圾;被调用者branch_fn将N添加到其返回地址然后返回。

可以用多种方式来详细说明此基本方案,例如:相同的分支函数,它们可以具有不同的N值(返回地址所需的调整量)。分支函数使用返回地址标识调用站点,从而标识所考虑的特定跳转指令,从中可以确定所需的调整量N(例如,使用基于返回地址的表查找)。
应用于返回地址的调整量N无需“明文”存储,而是可以通过表达式的计算来动态计算。例如,使用完美的哈希函数将返回地址映射到调整值N会产生难以理解的代码。
分支函数不必调整自己的返回地址,因为这相对容易发现。相反,它可以使用一系列调用branch_fn0-> branch_fn1-> ...-> branch_fnK,其中序列中的最后一个“到达”调用堆栈以进行返回地址调整。

但是,如上所述,这主要是为了消除静态拆卸;它并没有对动态分析做很多事情。

#3 楼

另一种解决方法是,您正在查看手工编码的汇编,实际上并没有欺骗欺骗反汇编程序的方法。代码我经常会设置数据选择器以匹配代码选择器,然后将我的数据直接嵌入代码段中。例如,如果我正在编写实模式引导加载程序或其他一些短暂的代码段,则尤其要这样做。在一段漏洞利用代码中。这使我拥有可以可靠引用的变量,并且仍然拥有非常紧凑的Shell代码。