脱掉“爱加密”家的壳

一、案例分析

第一步:反编译解压apk得到的classes.dex文件,得到java源码。
脱掉“爱加密”家的壳_第1张图片
看到,这里只有Application的壳,而且这个是爱加密加固之后的特点,都是这两个Application的。

第二步:使用apktool反编译apk,获取资源文件信息

脱掉“爱加密”家的壳_第2张图片
在application中加上这一句“android:name=’com.shell.SuperApplication’”原来就跑到自己加的类中去了,就变成“入口类了”!
分析一下加密流程:

爱加密把我们的源程序进行加密操作然后隐藏到了一个地方,在之前破解加固apk的那篇文章中也说过了,隐藏的地方就那么几个:assets目录、libs目录、自己的dex文件中。

我们在AndroidManifest.xml中看到了入口的Application类,先来看这个类
下面我们来分析一下这个SuperApplication类:

脱掉“爱加密”家的壳_第3张图片
注意:Application里面attachBaseContext和onCreate函数调用顺序

Application-> attachBaseContext ();

ContentProvider:onCreate()

Application:onCreate()

这里一般都是在attachBaseContext这个方法中进行操作的,这里的时机比较早,我们看到首先会调用loadLibs方法进行加载libs:
脱掉“爱加密”家的壳_第4张图片
这里区分不同的平台,然后进行拷贝不同的so文件,继续看copyLib方法:
脱掉“爱加密”家的壳_第5张图片
这里我们可以看到了,从assets目录下把爱加密增加的两个so文件:libexec.so和libexecmain.so拷贝到应用程序的files目录下。

到这里loadLibs方法就执行完了,下面就开始调用NativeApplication的load方法进行加载数据,继续看NativeApplication类:
脱掉“爱加密”家的壳_第6张图片
这里会开始从应用程序的files目录中加载这两个so文件,而且load方法也是一个native方法,我们继续看看这两个so文件内容:
我们首先用IDA打开libexecmain.so文件,但是发现,他里面并没有什么重要信息,连JNI_OnLoad函数都没有东东
脱掉“爱加密”家的壳_第7张图片
我们继续再查看libexec.so文件:
脱掉“爱加密”家的壳_第8张图片
提示格式错误,可能被加密了,ELF格式改了,那么我们yes强制打开,再使用ctrl+s查看so的各个段信息:
脱掉“爱加密”家的壳_第9张图片
现在可以百分百的确定,这个so文件被处理了,段格式被修改了。我们没办法分析so文件了,当然这里我们可以在dump出内存中的so文件,然后在分析的,但是这个不是今天讲解的重点。我们先分析到这里,也知道了爱加密的大体加密流程。
脱掉“爱加密”家的壳_第10张图片

注意:
理解:就是说application是用来保存全局变量的,并且是在package创建的时候就跟着存在了。所以当我们需要创建全局变量的时候,不需 要再像j2se那样需要创建public权限的static变量,而直接在application中去实现。只需要调用Context的getApplicationContext或者Activity的getApplication方法来获得一个application对象,再做出相应 的处理。创建自己的类时,继承即可。
android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application可以说是单例 (singleton)模式的一个类.且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。因为它是全局 的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。所以通过Application来进行一些,数据传递,数据共享 等,数据缓存等操作。
二、破解脱壳
那么还是开始说到的,脱壳的核心就一个:给dvmDexFileOpenPartial函数下断点,dump出内存的dex文件即可。
过程:
第一步,启动设备中的Android_server,然后进行端口转发。
第二步,debug模式启动程序
第三步,双开IDA,一个用于静态分析libdvm.so,一个用于动态调试。
第四步:使用jdb命令attach上调试器。
第五步:对dvmDexFileOpenPartial函数下断点。
第六步:设置Debugger Options选项。

再次点击任何一个按钮,都会退出了调试页面:

脱掉“爱加密”家的壳_第11张图片
三、反调试检测
当时我们也是遇到这个情况,在没有运行到我们下的断点处,就退出了调试页面,其实这个是现在加固平台必要选择的一种方式,其实反调试原理很简单,就是在程序运行最早的时机比如so加载的时候即:JNI_OnLoad方法中,读取本进程的status文件,查看TracerPid字段是否为0,如果不为0,那么就表示自己的进程被别人跟踪了,也就是attach了,那么这时候立马退出程序,下面我们使用IDA在attach进程成功之后,查看本进程的status信息。

首先我们上面分析了反调试的原理,一般在native代码去做检测的话,都是用fopen系统函数打开status文件,然后用fgets函数读取一行的内容,这个是国际惯例的,操作文件都是用的fopen函数的。

既然反调试肯定用到了fopen和fgets这两个函数,那么我们直接像给dvmDexFileOpenPartial下断点的方式一样,给这两个函数下断点,然后运行到fgets断点处的时候,发现如果是读取TracerPid这行内容的时候,就开始修改内存内容,把TracerPid字段的值改成0,或者修改R0寄存器的内容,跳过反调试检测。

四、还原应用apk
我们得到了内存中的dex数据之后,可以使用baksmali工具转化成smali源码,查看代码逻辑即可,这里不再演示了。

然后最后还有一步:还原apk

首先我们修改反编译之后的AndroidManifest.xml中:

android:name=”com.shell.SuperApplication”

把这段内容删除,如果有自己的Application的话,就改成自己的Application即可,同时删除assets目录下面的文件(入口activity不管吗?难道使用的是磨人的?!)。

然后使用apktool进行回编译,这时候,先不要着急签名apk,而是替换classes.dex:

我们把上面得到的dump.dex改成classes.dex然后直接用压缩软件,替换未签名的apk中的dex文件即可

最后在进行签名操作,完成还原apk工作。

你可能感兴趣的:(安卓逆向)