所谓不透明谓词,就是代码的编写者知道是真是假是什么,但是攻击者难以从字面获悉,最典型的就是导致IDA无法识别,因而出现一大堆垃圾代码,一连串分支
比如:
if ((x * x + x) % 2 == 0) { ... } else { ... }
对于公式x平方加x,等价于(x+1)*x,偶数乘奇数等于偶数,所以该判断必然成立,所以else分支永远不会走。
今天找了一个样本,简单记录一下去混淆的方法:
先IDA打开样本,发现没有JNI_Onload,猜测应该是在init_array中解密,去init_array中看看
进去后发现,所有的函数中都有一些分支在影响判断:
分析发现这些分支的判断条件都源于一些变量,这些变量的地址在bss段
bss段是在程序中用于存储未初始化的全局变量和静态变量的内存区域。它是静态内存分配的一部分,通常在程序开始执行之前会被自动清零,而通过查找引用发现这部分内存始终未被赋值,这意味着他将永远为0,((0 - 1)* 0&1)!= 0 && 0 > 9 结果为false, 所以这些分支的走向其实是固定的。
但是由于bss段是可读写的,要想让IDA将其识别为0,且能重新分析优化,要做两件事:1 修改这一段内存的属性为只读 2 修改内存值为0
通过脚本来修改:
看一下效果:
无用分支都被优化掉了