整理那些见过的非平坦化、非 bcf 混淆,以后见到新的再添加进来。

函数名称混淆


利用 deinfe 宏对函数名做重命名,编译时编译器会用后面那串玩意替代函数名

效果如下,其实意义不大,还是能够通过分析函数逻辑知晓其功能

利用ida递归下降算法的缺陷


ida 反汇编算法知识参考下面两篇文章:

反汇编算法介绍和应用——线性扫描算法分析
反汇编算法介绍和应用——递归下降算法分析

在BL指令后面塞入垃圾数据,像下图这种,ida会错误地将其识别为指令,而在BL调用的函数中修改返回值跳过混淆数据。

函数中计算出一个值放到 R0 寄存器,倒数第二句指令用 R0 覆盖掉栈上的 LR ,最后一句指令 pop pc 跳转过去,这就是美团 libmtguard 中的混淆

还有一种修改执行流的方式,往 PC 寄存器 mov 一个地址

插入破坏栈平衡的指令


下图中的指令 ADD SP,SP, #0x40 修改了栈指针 SP ,导致栈不平衡

F5 后能看到 ida 提示了 “positive sp value has been detected, the output may be wrong!”

解决办法参考:https://bbs.pediy.com/thread-140002.htm和https://bbs.pediy.com/thread-158896.htm

首先勾选 Stack pointer

然后是检查整个函数有哪些指令操作了 SP ,这些指令后的指令栈指针值是负数的,找出来然后 nop 掉

实现可以参考这篇文章:【技术分享】漫谈几种反编译对抗技术

栈展开函数stack_check_fail识别失败


这种会导致 make function 失败,如下图,loc_2404 就是 stack_check_fail 函数,它的上面的 pop 指令就是函数末尾处,再往上 0x23FE 处会跳过函数末尾到达 loc_2404 ,这其实是检查有没有栈溢出,所以跳转 stack_check_fail 函数,这个函数应该会使程序退出

进入 sub_47FC 看看,编辑该函数可以看到 ida 识别它是返回的,那就不对了,把 Does not return 勾选了,然后在函数开头按 p 键创建函数

无条件跳转JUMPOUT


利用 ida 无法计算动态值,构造地址无条件跳转,使得 ida 识别的函数提前结束,如下图所示,实际上 BX R5 只是跳到下面不远处,而中间塞了一些垃圾数据。

对这种只能根据指令特征写脚本 patch

修改elf文件的dynamic段


这种姑且算是混淆吧,毕竟是利用了 ida 解析 elf 的缺陷。
ida 加载 so 报错,这种基本是修改了 elf 导致的

dynamic 的 p_offsetp_vaddr 不同,而且 p_offset 指向的位置全是 0

一般来说,p_offset 和 p_vaddr 不相同出现在第二个 load 段,因为第一个段与第二个段加载地址之间有间隔,而在文件中没有偏移,但这个 so 只有一个 load 段,不可能出现 dynamic 段的 p_offset 和 p_vaddr 不相同的情况

再看源码,linker 加载 so 时以 p_vaddr 为参考加载 dynamic 段,得出结论是 p_offset 被修改了,只要把 p_offset 改成 p_vaddr 就修复好了