最近开始接触android客户端安全相关技术,以前对移动客户端的测试主要集中在数据传输层面,现在开始学习基于软件层面的安全测试。其实,很多东西和windows平台的软件安全还是有些相似的。
APP相关安全测试或者破解,基本思路大概就是,先对apk进行反编译,然后通过分析反编译的文件(smali文件或这jar文件)来寻找程序突破口,进行程序的修改,完成修改后,重新打包成apk文件并签名。下面主要是各步的常用操作流程。
首先,对于反编译apk文件,相对来说比较简单。因为安卓应用是基于java进行开发的,相对来说,java还是比较容易被反编译的。可以利用apktool将apk文件反编译成smali文件,如下图:
但smali文件相对来说不是特别直观,对smali语法掌握不好的人来说(比如我),直接看smali文件并不友好。第二种是使用dex2-jar直接反编译成jar文件,随后可以使用jd-gui打开成类似java源码的代码,,当然有时候jd-gui也不好使,源码反编译不出来。不过最近找到一个叫luyten的软件,功能类似jd-gui,有些类jd-gui没法反编译成java源码的,lutyen可以反编译出来。后面简单分析jd-gui和luyten优缺点。总体来说,smali文件和java源码两者结合使用可以加快分析速度。
完成反编译之后,现在就有smali文件和能被反编译成类似源码的jar文件了。通过这两类文件分析程序运行原理,一般主要看jar文件,毕竟近似源码的代码更友好,找到需要修改的地方,然后去相应的smali文件进行修改。但实际使用时,发现jd-gui有些地方反编译没有luyten好。例如一个APP,启动页面中的一个方法addDuStatistics,两个软件的反编译结果如下:
jd-gui反编译结果:(打码。。避免泄漏是什么APP)
luyten反编译结果:
smali文件中该函数的代码如下:
通过分析smali文件可以看出来,其实jd-gui的反编译结果是错误的,luyten是正确的。用了一段时间,个人总结了一下jd-gui和luyten的优缺点:
1.在反编译效果方面,各有优缺点,总体来说luyten正确性要高点。
2.有些类jd-gui是无法反编译出来的,一般luyten都可以反编译。
3.jd-gui操作方便,主要是可以直接点击被下划线标识的类,跳转到该类的反编译文件中。这个还是很方便的,luyten就没有这个功能,所以你得自己去找,而且在一堆类中,一个人还真不一定那么容易找到这个类的。
4.jd-gui还有个有点就是,可以通过中键列出该类的所有属性和方法。便于遍历了解该类以及跳转到需要查看的方法。
总体来说luyten在反编译方面还是较强的,但易用性方面不如jd-gui。所以一般都是两者结合使用,效果还不错。
至于具体的分析过程,每个APP可能都不一样。一般第一步是查看反编译后的AndroidManifest.xml文件,可以了解到很多信息。最主要是找到软件运行时候第一个启动的activity,这样就知道从哪里开始下手。如下图,android:name中就是开始运行第一个启动的activity(打码。。)。然后就顺着该activity进行分析。当然一般先大致浏览一下整体的包结构,类等,在未做混淆处理的情况下,包名和类名的含义还是很容易理解的,并且能给出不少有价值的信息。
至于如何定位到关键代码,《Android软件安全与逆向分析》中提到了六种方法:
1.信息反馈法。主要是大多数软件会有一些正常或错误的信息提示字符串,通过res中的public.xml和string.xml得到相应的id,这些id值都会在程序中进行引用的,找到引用的地方,就可以正推或反推,从而找到关键代码。
2.特征函数反馈法。类似第一种方法,通过一些特定的sdk去找,因为一般提示信息都是弹窗方式显示的,通过定位弹框sdk去找。
3.顺序查看法。也就是从上面的第一个activity开始,按程序流程分析下去。。。。这个方法应该说很好,但是太耗时耗力,完整的分析APP的运行流程大多数情况下是不需要的。
4.代码注入法。主要通过修改apk代码,加入log输出,随后使用logcat捕获到输出的信息。比如捕获注册码等信息。目前还没用过,其实和windows平台的类似。。。
5.栈跟踪法。动态调试方法,类似上面的,输出栈信息。
6.method profiling。也是动态调试的手段,据说比栈跟踪更强大,,,没用过
其实怎么分析APP,每个人可能都有自己的玩法。而且有时候还需要点运气。。。。
分析完APP,定位到需要修改的代码,直接到smali文件中修改即可,修改完成后,就可以直接用apktool进行重打包,生成apk文件。这步也有很多坑,有时候打包会各种报错,导致重打包不成功。
遇到的一种报错如下:
就是报资源文件中的png文件不是png格式的。。。一开始也比较奇怪,为什么格式不对。使用file测试了一下
结果显示这个png文件,真实格式是jpeg的,,,然后把这些png后缀改成jpg就可以了。有人说这个是一种防护手段,没做过app开发,不清楚是作为防护手段还是因为开发中的其他原因导致的。如果不修改资源文件,直接在反编译的时候使用-r参数,不反编译资源文件即可避免这个问题。
重打包完成后,就是签名了。理论上除非你能搞到这个APP的正式发布证书,一般都是使用测试证书进行签名,所以这样签名后的app肯定和发布版不一样的。如果这个APP做了签名校验的话,自己修改的app肯定也无法运行的。签名校验模块一比对签名发现APP被修改了,就会报错自动退出运行的。这也是一种APP加固方法。
通常,如果APP没做加固,上面的一套下来,就可以实现自己想要的功能,,比如破解注册,去除广告等。。。不过目前大部分APP都或多或少的做了一些加固。目前了解到的一些主流加固方法有:
1.混淆技术。最简单,用的最多的加固方法,效果还可以,至少可以增加写分析难度。目前主要是proguard
2.签名对比。上面也说了,做了签名对比的话,除非你能拿到正式的证书,不然测试证书是过不了的。签名对比模块如果是通过Java程序实现的话,,,其实也很容易破解。并且也有人分享了些绕过思路。不要用java做签名模块,可以使用ndk
3.NDK技术。可以把一些重要核心的模块,使用c/c++编写成so库,随后使用jni去调用。相对来说c/c++破解难度会大一点。。。不过有人说很熟悉ARM反编译。。就喜欢直接看ARM反编译的。。只能说增加难度。。高手还是很难挡住的
4.加壳技术。类似windows上的各种加壳,换成android平台。也有很多加壳方法等等。。。
5.其他技术。。。。。还有很多吧,没了解过,或者不是很主流。