吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 42694|回复: 59
收起左侧

[Android 脱壳] Android脱壳圣战之---如何脱掉"爱加密"家的保护壳

  [复制链接]
crossroad 发表于 2016-6-12 08:57
本帖最后由 crossroad 于 2016-6-12 09:10 编辑

一、前言
今天我们来看一下在了解了破解三部曲之后,如何开始脱掉各个市场中的apk壳,关于破解三部曲在之前已经介绍了:
Android中使用Eclipse动态调试smali源码
Android中使用IDA动态调试so源码
Android中破解加固的apk

在看完这三篇文章之后,我们开始操作如何破解市场中的加壳方案,现在市场中比较流行的加壳平台就那么几个:爱加密,梆梆加固,360加固,腾讯加固等,所以后面会一一介绍如何脱掉这些平台的壳。之前也说过现在加固的方案大体思路都是:
把源apk进行加密拆分处理,然后在套一个外部的壳Application做一些初始化操作,比如解密apk,动态加载运行即可。但是我们已经知道了如何去破解那些加固的apk了,就是使用IDA给dvmDexFileOpenPartial函数下断点,然后dump出内存中的dex数据即可。因为内存中的dex肯定是解密之后的,所以大体思路知道了,但是这些加固平台也有对策,他们会把做一些反调试操作,对so文件进行混淆加密等,让我们的调试变得比较困难。这才是我们脱壳的阻碍地方。

二、案例分析
好了,说了这么多,下面我们就开始脱壳第一站:爱加密家的壳
为了脱掉他家的壳,我们得首先有一个案例程序,这个比较简单,我们自己弄一个demo程序,然后去他家的网站上加固一下,得到加固之后的apk,然后这时候我们开始破解了,按照惯例:
第一步:解压apk,看看大体的目录,得到classes.dex文件,然后用dex2jar+jd-gui得到[url=]Java[/url]源码
3.png
看到,这里只有Application的壳,而且这个是爱加密加固之后的特点,都是这两个Application的。
第二步:使用apktool来反编译apk,获取资源文件信息
4.png

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

这里我们直接看assets目录:
5.png
多了这个东东,猜想这个可能就是处理之后的源apk了。我们在AndroidManifest.xml中看到了入口的Application类,先来看这个类

下面我们来分析一下这个SuperApplication类:
6.png
这里一般都是在attachBaseContext这个方法中进行操作的,这里的时机比较早,我们看到首先会调用loadLibs方法进行加载libs:
7.png

这里区分不同的平台,然后进行拷贝不同的so文件,继续看copyLib方法:
8.png

这里我们可以看到了,从assets目录下把爱加密增加的两个so文件:libexec.so和libexecmain.so拷贝到应用程序的files目录下,我们可以去看看assets/ijm_lib目录下的so文件:
9.png

到这里loadLibs方法就执行完了,下面就开始调用NativeApplication的load方法进行加载数据,继续看NativeApplication类:
10.png
这里会开始从应用程序的files目录中加载这两个so文件,而且load方法也是一个native方法,我们继续看看这两个so文件内容:
我们首先用IDA打开libexecmain.so文件,但是发现,他里面并没有什么重要信息,连JNI_OnLoad函数都没有东东
11.png

我们继续在查看libexec.so文件:
12.png
擦,可惜的是,打开提示so文件格式错误,到这里,我们就猜到了,这个so可能被加密处理了,elf格式改了,关于so如何进行加密操作的,不了解的同学可以看这里:Android中如何对so文件进行加密 那么这里我们点击Yes继续强制打开之后,在使用Ctrl+S查看so的各个段信息:
14.png
现在可以百分百的确定,这个so文件被处理了,段格式被修改了。我们没办法分析so文件了,当然这里我们可以在dump出内存中的so文件,然后在分析的,但是这个不是今天讲解的重点。我们先分析到这里,也知道了爱加密的大体加密流程。

好了,到这里,我们差不多分析完了爱加密的加密流程了:
1、按照国际惯例把源apk进行加密处理存放在一个地方,通过分析猜想是assets目录下的ijiami.dat文件
2、添加壳Application:SuperApplication类,在这个壳的attachContext方法中,主要做了两件事:
1》第一件事是把assets/ijm_lib目录下的两个so文件copy到程序的files目录中;
2》第二件事是调用NativeApplication的load方法,在这个类中同时也把上面的两个so文件加载到内存中
3、对apk的加密操作都是放在底层的两个so文件中操作的,我们通过IDA去分析这两个so文件之后,发现核心功能的so文件被加密了,IDA打开是看不到具体信息了
到这里,我们知道爱加密加固之后的特点是:在程序的assets目录下多了一个ijiami.dat文件和两个so文件,同时这两个so文件被加密处理了,增加破解难度。

三、破解脱壳
上面就简单分析了爱加密的原理和流程,但是我们没有继续往下面分析了,因为这个不是我们今天讲解的重点,我们今天的重点是如何脱掉爱加密的壳,那么还是开始说到的,脱壳的核心就一个:给dvmDexFileOpenPartial函数下断点,dump出内存的dex文件即可,那么下面我们就是用IDA开始脱壳操作了:
第一步:启动设备中的android_server,然后进行端口转发
adb forward tcp:23946 tcp:23946
15.png

第二步:用debug模式启动程序
adb shell am start -D -n com.droider.crackme0201/.MainActivity
这里的包名和入口Activity都可以在上面反编译之后的AndroidManifest.xml中找到
16.png

第三步:双开IDA,一个用于静态分析libdvm.so,一个用于动态调试
17.png
记录dvmDexFileOpenPartial函数的相对地址:4777C
再次打开一个IDA,进行attach调试进程
18.png

第四步:使用jdb命令attach上调试器
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
19.png

第五步:对dvmDexFileOpenPartial函数下断点
进入调试页面之后,Ctrl+S查找libdvm.so的内存基地址:415BB000
20.png
在第三步得到相对地址:4777C+415BB000=4160277C 得到了dvmDexFileOpenPartial在内存中的绝对地址
注意:
当然这里还有一个更方便的办法:
就是直接打开Modules View:
21.png
在这里查找libdvm.so文件:
22.png
然后双击libdvm.so文件:
查找需要下断点的函数名称,看到这里的绝地地址也是:4160277C
这里有两种方式可以得到一个函数在内存中的绝对地址。
然后我们使用G键,直接跳转到函数处,下断点:
23.png

第六步:设置Debugger Options选项
能够让程序断在dvmDexFileOpenPartial函数处
24.png
注意:
上面的第四步,第五步,第六步,没有顺序的,只要在运行之前设置到就可以了。

第七步:运行程序
出现这个对话框,不要在意,一路点击Cancel即可
25.png
jdb也attach上了调试程序:
26.png

我们一路点击运行按钮,知道运行到dvmDexFileOpenPartial处的断点,但是可惜的是,这里我们遇到了错误:
27.png
我们点击OK之后,出现了下面对话框:
28.png
再次点击任何一个按钮,都会退出了调试页面:
29.png

我们在重新尝试一次上面的流程,开始调试,但是错误是一样的,好了,到这里我们就立马想到了,之前说的IDA调试so的那篇文章遇到的那个问题:反调试检测
当时我们也是遇到这个情况,在没有运行到我们下的断点处,就退出了调试页面,其实这个是现在加固平台必要选择的一种方式,其实反调试原理很简单,就是在程序运行最早的时机比如so加载的时候即:JNI_OnLoad方法中,读取本进程的status文件,查看TracerPid字段是否为0,如果不为0,那么就表示自己的进程被别人跟踪了,也就是attach了,那么这时候立马退出程序,下面我们使用IDA在attach进程成功之后,查看本进程的status信息:
30.png
看到这里的TracerPid为11340,不为0,表示被11340进程attach了,那么我们可以查看一下这个进程是谁:
31.png
其实这个进程就是我们在设备中安插的android_server,它用于和IDA进行通信。

好了到这里,我们可以看到爱加密做了反调试检测,但是按照之前的那篇文章中,我们可以给JNI_OnLoad函数下断点,然后找到检测代码,把对应的arm指令改成空指令,检测失效了,但是这里我们知道爱加密的两个so文件被处理了,IDA没法分析了,那么这里我们该怎么办呢?如何应对反调试呢?其实我们可以借助IDA可以修改寄存器和内存数据的特性来做到?
首先我们上面分析了反调试的原理,一般在native代码去做检测的话,都是用fopen系统函数打开status文件,然后用fgets函数读取一行的内容,这个是国际惯例的,操作文件都是用的fopen函数的

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

这两个函数是在libc.so文件中的,我们可以把设备的/system/lib/libc.so使用adb pull到本地即可,然后用IDA得到他的相对地址,在调试页面得到基地址,然后相加得到绝对地址,跳转即可,但是这里不用这种复杂的方式,有两种方式可以进行跳转:
第一种方式:在Modules界面,找到libc.so,然后在找到这两个函数,就可以得到他们的绝对地址了
32.png
然后使用G键,跳转下断点即可:
33.png

第二种方式:也是最简单的方式,就是G键,本身就有可以直接输入函数名进行跳转的功能
34.png
下断点:
35.png
看到了吧,这种方式是不是非常简单高效

好了到这里就给这两个函数下好了断点,当然这里还需要给dvmDexFileOpenPartial函数下断点,一切弄好了之后,这时候我们再次运行:
36.png
停在了fopen断点处,我们使用F8单步调试,看到R7寄存器中的内容是/proc/...,我们直接点击R7查看全部内容:
37.png
内容有点长,大致的内容是:/proc/self/cmdline.debug.atrace.app_cmdlines,这个是干什么的?
我们看看这个目录内容:
38.png
发现没有这个文件内容,只有cmdline文件,但是这里先不管他了,我们知道这个肯定不是读取status文件的,那我们直接略过这个断点,点击F9运行到下一个断点,中间过程先忽略,一路F9,直到运行到了fopen这个断点:
39.png
果然,这里使用了fopen来读取status文件了,点击R7寄存器查看全部内容:
40.png
这个16396就是我们本进程的id:
41.png
到这里,我们知道下一个断点肯定是fgets,所以点击F9进入到fgets断点处:
42.png
这里还看不到什么信息,我们继续点击F8单步调试:
44.png
途中,会看到有memchr和memcpy这两个重要函数,这个也是操作字符串的核心点,继续往下走:
45.png
到了fgets函数结束的地方,我们看到了R0寄存器的内容是Name...点击R0查看全部内容:
46.png
全部内容是:Name:   der.crackme0201;这个就是status文件的第一行内容:
47.png
到这里,我们知道了,开始读取status文件的每行内容了,但是到TracerPid那行还要继续执行5次fgets函数,所以还会进入5次断点,为了节省时间,这里点击5次F9,直接运行到读取TracerPid那行的内容的fgets断点处:
48.png
看到了关键的内容了TracerPid字段了,这时候,我们打开Hex View 查看16进制的内存数据:
49.png
但是我们看到,这个并没有和调试页面View位置相对应,我们可以这么操作:
在寄存器窗口查看到R0寄存器的内容:

50.png
这里就是TracerPid字段在内存的地址,记录一下,然后在Hex View页面中使用G键,进行跳转,这里一定要注意是在HexView,而不是调试页面,调试页面使用G键跳转到的是指令地址了。
51.png

好了,这里我们看到了TracerPid的内存内容了,这里我们就开始修改吧,选择我们要修改的内容:是11340那里:
52.png
选择内容开始处,右击,选择Edit,进入修改状态:
53.png
改了之后的内容是橘黄色的,修改完成之后,在点击右键,选择Apply changes:
54.png
完成修改,颜色变成灰土色了:
55.png
注意:
这里其实还可以直接修改寄存器R0的值:
56.png

这时候就表示修改成了,我们继续使用F8单步调试下去:
57.png
这里就开始把TracerPid字段的值和0作比较了,我们点击R0寄存器查看全部内容:
58.png
这里的值已经被改成了0,所以这里就骗过去了。继续运行,我们会发现,又进入了fopen函数的断点处,而且查看还是读取status文件,这个也不好奇,因为是反调试检测肯定是一个轮训机制的,所以肯定会反复的读取的这个文件,fopen走多次也是正常的,但是这个反调试肯定是在子线程的,所以只要到了主线程中解密dex文件就肯定到了dvmDexFileOpenPartial,所以这里会多次重复上面的操作,修改多次TracerPid的值,这里就不在演示了,我在操作的过程中修改了三次,当没有在走fopen函数的时候,遇到了这个错误,这里不关心,直接点击ok就可以了。
59.png
再次点击运行:
60.png
这里说明已经改开始解密dex文件了,应该离成功不远了,继续运行:
61.png
终于到了我们想要的地方了,到这里就好办了,直接点击Shirt+F2,打开脚本运行窗口,运行下面脚本:
62.png
static main(void)
{
    auto fp, dex_addr, end_addr;
    fp = fopen(“F:\\dump.dex”, “wb”);
    end_addr = r0 + r1;
    for ( dex_addr = r0; dex_addr < end_addr; dex_addr ++ )
        fputc(Byte(dex_addr), fp);
}

把内存中的dex保存到F:\dump.dex中,这里不再解释了,之前的一篇文章已经介绍过了,这里R0寄存器就是dex在内存中的起始地址,R1寄存器就是dex文件的大小:
63.png
我们使用G键,可以在HexView页面中查看R0寄存器中的地址内容:
64.png
看到了吧,这里就是dex的头文件格式。

四、还原应用apk
我们得到了内存中的dex数据之后,可以使用baksmali工具转化成smali源码,查看代码逻辑即可,这里不再演示了。
然后最后还有一步:还原apk
首先我们修改反编译之后的AndroidManifest.xml中:
65.png
把这段内容删除,如果有自己的Application的话,就改成自己的Application即可,同时删除assets目录下面的文件。
然后使用apktool进行回编译,这时候,先不要着急签名apk,而是替换classes.dex:
我们把上面得到的dump.dex改成classes.dex然后直接用压缩软件,替换未签名的apk中的dex文件即可
最后在进行签名操作,完成还原apk工作。

五、总结爱加密的破解流程
一个目标:
在脱壳的过程中,我们就一个目标:dump处内存中的dex文件

但是在上面分析了爱加密的加固流程之后,发现他做了这些事:
1、爱加密加固之后apk目录变化
把源程序apk加密处理放到了assets目录下的ijiami.dat,也同时在assets\ijm_lib目录下添加两个so文件:libexec.so和libexecmain.so,这里两个so文件用来处理整个apk解密,动态加载等逻辑,但是我们用IDA查看得知,这两个so文件被加密处理了
2、爱加密加上自己的壳Appliation
添加自己的壳Application:SuperApplication类,这个类中的attachContext方法中,首先把assets目录中的两个so文件copy到应用的files目录下,然后在使用System.load方法,加载这个files目录中的两个so文件

3、下断点调试遇到反调试检测
我们在给dvmDexFileOpenPartial下断点,进行调试的时候,发现有反调试检测,因为无法给JNI_OnLoad下断点来去除反调试功能的arm指令,所以只能去修改内存数据,把TracerPid的值变成0,骗过检测了。这里我们的思路就是给fopen和fgets这两个函数下断点,因为我们知道反调试的原理就是读取本进程的status文件,然后获取TracerPid那行内容即可,所以这里肯定用到了fopen和fgets函数,在使用fgets这个函数的时候,会读取每行内容,那么我们只要发现在读取到TracerPid那行内容的时候,去修改内存值,把TracerPid字段的值改成0即可。
4、给fopen和fgets函数下断点
有了上面的反调试思路之后,我们就开始进行操作了,但是在操作的过程中发现多次执行了fopen和fgets函数,而且我们需要修改多次TracerPid的值,原因很简单,因为是反调试检测,肯定是在子线程中轮训去检测这个值,所以会执行多次很正常,所以我们要修改多次TracerPid的值,骗过检测,直到当在主线程中,代码运行到了解密dex文件的时候,即到了dvmDexFileOpenPartial函数处的断点处为止
5、修改TracerPid内存数据骗过检测
最后修改多次TracerPid值,骗过检测,到了dvmDexFileOpenPartial这里,这时候,在执行dump脚本,把内存中的dex数据dump到本地即可。
通过上面的调试和破解流程其实不难发现,爱加密的流程是这样的:
1》调用fopen打开/proc/self/cmdline...
2》调用fgets读取com.droider.crackme0201
3》dvmLoadNativeCode–加载libexec.so
4》dvmLoadNativeCode–加载libexecmain.so
5》建立反调试线程(通过检查是否存在调试进程)
6》调用fopen打开/proc/pid/status
7》调用fgets读取调试进程pid
这里除了dvmDexFileOpenPartial函数,还有一个重要的函数dvmLoadNativeCode,它是加载和初始化so的函数,如果感兴趣的同学,可以去给这个函数下断点看看运行逻辑。
所以我们只要记住我们的目的只有一个:
到达dvmDexFileOpenPartial函数处,dump出内存中的dex文件,就算是完成脱壳工作

六、总结
到这里我们就分析完了如何去脱掉爱加密的壳,其实在之前说过,现在各个加固平台的原理都差不多,最后看到的就是各家的加固[url=]算法[/url]了,所以我们在脱壳的过程中目标也很明确,就是dump出内存中的dex文件即可。不管他上层再怎么牛逼的加密拆分操作,到了内存肯定是完整的dex文件了,所以现在加固平台也是一个思想就是不让你dump出来,就是让你给dvmDexFileOpenPartial函数下断点失败,调试失败。

43.png

免费评分

参与人数 19热心值 +19 收起 理由
派大星涛子 + 1 我很赞同! 虽然看不懂
lawlier + 1 我很赞同!
MistyRain + 1 我很赞同!
DNTTM + 1 学习了
Intro + 1 已答复!
lianaini + 1 谢谢@Thanks!
风间仁 + 1 我很赞同!
duke0323 + 1 谢谢@Thanks!
miracles + 1 谢谢@Thanks!
469164323 + 1 吊!
真的很疼 + 1 我很赞同!
xinluan + 1 用心讨论,共获提升!
h939030952 + 1 这个叼
hagcn + 1 谢谢@Thanks!
旱章鱼 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
州哥在江湖 + 1 用心讨论,共获提升!
cfcanying + 1 很不错的学习资源,收藏了
freedev100 + 1 谢谢@Thanks!
我的爱是你 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| crossroad 发表于 2016-6-12 09:16
有兴趣的童靴,去这里看吧,我的图片有些可能没配对,http://mp.weixin.qq.com/s?__biz=MzIzNDA3MDgwNA==&mid=2649229983&idx=1&sn=de2bd1a408d74e102ecd13a05512d1fa&scene=23&srcid=06121dFY4gXtdfE5MypJ2I0X#rd
【发这个链接要是违规了,请删帖,别扣分哦】
龙飞雪 发表于 2016-8-24 18:40
h_one 发表于 2016-6-23 10:34
楼主我一年多前分析的ijiami技术点和你分析的几乎一样。ijiami壳这一年多了技术还是这样?还是第一代的整体 ...

这位才是大神,多关注关注这位阿里的大牛的博客,哈哈
凉米饭 发表于 2016-6-12 09:03
 楼主| crossroad 发表于 2016-6-12 09:12
327001305 发表于 2016-6-12 09:03
宝宝  你的图片挂了

,转个贴正不容易啊,图已修
KevINBy 发表于 2016-6-12 09:34
学习学习 感谢分享
freedev100 发表于 2016-6-12 09:36
膜拜学习~~
头像被屏蔽
bm123 发表于 2016-6-12 09:59
提示: 作者被禁止或删除 内容自动屏蔽
shystartree 发表于 2016-6-12 10:32
能上个测试apk吗?
州哥在江湖 发表于 2016-6-12 10:37
此帖必看!!!
keeslient 发表于 2016-6-12 11:12
好东西 学习了 谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-1 01:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表