顶象企业版加固逆向分析

首先看一下顶象对于这种自身的虚拟源码保护是怎么说明的?

 

结合免费版分析可以猜测是这样的加固流程:

1.   首先进行免费版转换把dex中对应的方法通过JNI反射转换为cpp文件(当然这里企业版比免费版转换的方法要多,免费版中的内部类MainActivity$1就没有进行转换);

2.   然后就是独有工具链的编译,猜测很有可能是基于LLVM的自定义编译;

3.   进行虚拟化保护,生成相对的VMdata和对应的Handler解释器,最后每次通过dispatcher来读取VMdata完成解释。

 

一、分析篇:

1.So脱壳:

根据上一次的免费版分析知道顶象中so的保护采用的变形的UPX加壳。

在linker执行完第一个init函数,也就是upx的loader函数后开始dump.

在偏移值为274E处下断点:

 

 

 

根据base和Size dump出来

dump下来接着修复。

通过对Load和dynamic进行简单修复后基本上所有的函数,静态都可以看到了,

如图所示:

 

2.直接分析:

静态分析:

这里面要抓住几个核心的问题,一是核心代码的虚拟指令,二是虚拟安全运行环境.

OK,开始吧!在IDA中打开分析看到JNI_Onload、oncreate、wanwan01、wanwan02、wanwan0、Testloop等这些函数基本上是遵从一个规则那就是:

 

 

 

所以可以猜想的是这几个函数是构成那个虚拟运行环境的重点函数,也是我们分析的重点。

进入sub_43B0这个函数以后发现如下:

经过简单分析以后发现

 

 

 

在F5看伪代码以后发现:是一个控制流平展图,里面的case总共有250个左右,但是只有50多个,200个左右没有显示,大致猜测加固原理如下:

在加固处理的时候对dex native化形成的cpp文件进行语法分析,或者就是上面所说的形成了中间二进制文件,然后根据这些二进制文件的特征来形成了50个左右“Handler”。(总共是253个“Handler”,这里只用到50个),每次解释的时候读取这个虚拟指令集合。然后调用相应的Handler来进一步的进行解释完成。

动态调试分析:

 

 

 

如上图所示为去虚拟指令的一个过程。下图是每次调用执行完返回的一个过程。

 

下面感觉是维护一个地址表:

 

并且在调试过程中发现case94、case 249、case107、case222、case197这些Handler的内容是一样的,或许是一些无用的垃圾指令。

 

在调试中如下图所示会发现有大量的重复的虚拟指令,并且对应的Handler也没有具体的语义。如下图所示:

 

 

 

因此转换思路,从JNI一些系统函数入手:

3.间接分析:

转换思路,HOOK 这些JNI 接口函数,比如Findclass,GetMethodID函数,或者是找到这些函数地址然后进行向上引用来发现其中的Handler和对应的虚拟指令。

通过对之前免费版的加固分析,我们这里只重点关注两个重点函数Findclass,GetMethodID;

发现FindClass的地址为:41520778 ;GetMethodID的地址为:4151FC58并且在手机不重启的情况下这个地址是不变的。

因此接着分析:

 

 

 

同样的继续F9执行发现每次都是停留在116这个case中,这个时候才明白真正的扮演dispatcher的角色是这条分支。

 

-..$..$-.$--.$-..-$..$.-$-.$--. 这个偏移里面保存就是各个类和方法名的一些字符串

同样的继续F9执行可以看出:又是执行ExceptionCheck这个系统函数。

 

 

 

可以看出这个过程执行的不就是在上一次免费版中sub_2170函数,如下图所示:

 

 

 

对于反射执行中只要理清了这些系统函数的一个调用过程基本就可以搞清楚基本逻辑了,接下来就不用分析了,基本上case 116这条分支执行的就是类似把如下的这些sub_XX函数走完一遍:

 

 

 

上面拿onCreate含有Android SDK的函数作为重点分析例子,接下来一个JAVA SDK的也就是Testloop这个方法:

 

 

 

通过上面的分析发现也是case 116这条Handler,基本可以逆推出反射执行的所有流程和框架,这里不再进行演示。

因为在上一个so没保护的APP中核心分支是210,并且所对应的“虚拟指令”也是不同的,这可能就是顶象所说的每台设备的虚拟指令均不相同。

从以上可以说明在同一个APP中核心的分支是一样的,不同的APP的“虚拟指令”是不同的并且核心分支也是不一样的。

对于含有Android SDK 或者java SDK的反射分析基本就到这了,其实可以借助于HOOK JNI接口函数,然后进行log输出,根据log的输出以及结合以上的分析更好的理解整个反射执行的基本流程,从而尝试着手动进行还原。

二、总结篇

优点:

1.首先这种编译虚拟方法可以完美的解决平台兼容性问题,不像基于指令虚拟,需要很多的适配。

2.真正的做到了逻辑的隐藏并且确实每个加固的APP的“虚拟指令”和对应重要case分支不一样。

3.通过对生成的cpp进行控制流混淆,并且在里面加入垃圾分支,增加了正面分析的难度。

Dex保护方面:

java层先做了一层java2cpp的翻译,之后才走虚机机保护。即cpp2vmp的过程。由于java2cpp的过程中需要借助于JNI的一些接口,因此间接去找核心的关键点。

Cpp保护方面:

Cpp层直接就是DX单独提供的私有的NDK编译工具,直接在编译过程中进行虚拟加固保护,很强。就不能借助上面的逻辑了,需要正面分析。

三、最后

本身年前分析的,还没有完全分析清楚,年后有许多别的事情,没时间,分享给大家,希望大家一起交流学习。

DX加固做的真的很强大,在每一个步骤上的处理要想做到完善完美难度都很大!

 

至于样本如果想研究分析的可以发邮件:xueyimengqu@163.com

 

 

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值