移动APP测试中关键代码定位

百家 作者:OPPO安全应急响应中心 2019-07-25 10:34:59

1

1

以上文章由作者【小学生】投稿,也欢迎广大朋友继续投稿,详情可点击OSRC重金征集文稿!了解~~

在对移动APP分析测试过程中,经常需要寻找关键方法代码,比如通讯是加密的,则需要去定位加密方法的实现及调用,比如CS之间通讯的数据包请求,经常需要去定位网络框架及Java层的数据包请求方法,又比如想知道在触发某个业务的时候,都调用了哪些方法,方法与方法之间是如何调用的,谁调用了谁,谁又被谁调用了,这些都是在分析测试过程中经常需要考虑的,本文就结合自己实际项目测试经验,谈谈自己在实际项目中常用的关键代码查找的一些思路和方法。

1

利用Hook技术对特殊方法定位

Hook技术的发展,使得移动测试越来越有了新思路,android平台以前有xposed这种最负盛名的hook框架,通过xposed的插件,可去hook一些方法或修改系统参数,改变系统和程序的运行逻辑,从而达到自动、高效的测试目的,虽然xposed作为曾经的王者,优点众多,但依然有缺点,比如安装不是很方便,每次插件更新都需要重启等,现在项目中对xposed的依赖相对来说正在慢慢减少,取而代之的是frida,frida是最近2-3年才火起来的hook框架,frida由于其可动态的加载hook脚本,每次使用无需重启,使用安装方便,使用js编写脚本,版本迭代快等特点,快速的获得了开发者、逆向工程师、安全研究者的青睐,使用frida打印堆栈信息,能够对一些框架、库方法的调用情况进行快速定位。

比如,就加密通信而言,一般开发者在使用加解密库和随机数时,用的比较多的比如javax.crypto.Cipher,BouncyCastleProvider,java.security.SecureRandom,国密算法等等,那么就可以通过打印堆栈信息,来找出哪些应用层方法调用了这些加密库,有助于我们找出关键方法,当然这种方法也不是什么情况都适用,比如库被重命名打包了,或者在native层,或者开发者根本没使用这些库,不过在我实际使用过程中,效果还是基本满意的。

举个栗子:以通信加密算法为例

我们知道,javax.crypto.Cipher为开发者在加密时候常用的一个库,在开发中调用这个库,库中的方法到最后都会去调用一下getInstance这个方法,所以我们要做的就是打印getInstance这个方法的所有ovaload的堆栈,这里打印getInstance的重载方法。

拿某航空公司APP测试了一下,堆栈输出效果如下:

可以看到,输出的堆栈信息显示了代码经过了哪些方法最后调用到getInstance这个方法的,一眼望去,就发现了疑似我们的目标方法aesEncrypt,再经过单独hook这个方法进行确认,发现Java应用层中通信加密确实由这个方法来实现的。

举个栗子:以网络框架堆栈信息为例

根据我的经验,现在用的比较多的网络框架有Volley、okhttp、Retrofit、HttpUrlConnection,在数据请求中每个框架方法都有特定的方法最后被调用,所以我们打印这些特定方法的堆栈,以发现应用层的数据请求方法。

代码示例如下:

还是拿某航空公司APP测试输出如下:


根据结果,还是一眼望去,我们就发现了可疑方法doRequest,再去hook一下这个方法,就确定是它了。

同样的方式类推,可以去打印常用库的特定的构造器、特定的方法,这种方式还可以用到android系统中某些事件型的组件中,比如点击事件onClick,在一定条件下,可以比较快速的找出应用层数据请求方法。

frida除了hook方法之外,还可以通过frida-trace命令对方法和类进行跟踪,frida-trace是一个动态的跟踪方法调用的工具,该命令的最大方便就是可以使用一些正则表达式对不太确定的方法名进行模糊匹配,比如我们知道,开发者在加解密方法取方法名称的时候,一般会使用xxxencryptxxx、xxxdecryptxxx等方式,那就可以使用:

frida-trace  -U -i "*encryt*" APPNANE进行跟踪,可通过参数-i同时跟踪多个方法,还可以对特定的某个类中的特定方法进行跟踪,比如现在demo类中跟踪方法名称包含crypto的方法,则可使用frida-trace -m "-[demo *crypto*]" -U  APPNANE来实现,当你在操作某个业务时,如果该业务调用了该方法,就会输出相应的方法信息。

2

使用Method Profiling寻找关键代码

DDMS (Dalvik Debug Monitor Service)是安卓开发环境中的Dalvik虚拟机调试监控服务,在Android Studio 3.0之后就从面板中删除了打开DDMS的入口,但是可以从[SDK的安装目录]->Tools->monitor.bat打开,DDMS里面有一些动态调试的工具,Method Profiling就是其中之一,该工具最初的目的是为了对APP内部的具体方法进行性能分析,Method Profiling会根据方法的调用顺序来生成一个图表,每个方法也会通过Parents和Children来标识方法之间的调用关系。

通过在DDMS中选中目标应用程序,启用Method Profiling,再在手机上执行操作后停止Method Profiling,Method Profiling会自动去生成并分析一个trace文件。

可根据一些特殊方法进行搜索,比如按钮点击事件调用的是onClick方法,也可以根据经验,去搜索一些方法名称类似login、dologin、request、encrypt、decrypt的方法,这里直接搜索onClick方法,即可快速定位到目标方法,通过Parents和Children方法可快速的跟踪一个业务调用了哪些方法。

当然,如果APP能被反编译和重打包,还可以通过在代码中插入

startMethodTracing()、stopMethodTracing()来限制trace范围,对应的smali代码为:

invoke-static {}, Landroid/os/Debug;->startMethodTracing()Vinvoke-static {}, Landroid/os/Debug;->stopMethodTracing()V

通过这两个方法会在sdcard目录下生成后缀名为trace文件,使用adb pull将文件导出,通过DDMS即可打开分析。

下面以自己编写的demo测试代码为例,我们在代码中加入这两个方法,如果是smali,可插入smali代码,重签名打包,运行程序,点击按钮事件。

事件执行后,可去sdcard中查询trace文件,并导出;

通过DDMS打开,可以看到第一个方法就是目标方法,在实际项目中,我们可以扩大startMethodTracing()、stopMethodTracing()的标注范围,从而获取标注之间的代码方法调用关系。

3

通过运行日志定位代码

运行日志一般是开发者为了获取程序运行状态、调试应用程序而输出的,但当系统发布后,可能会忘记关闭所有应用程序日志或部分运行日志,或者应用程序通过某个Boolean参数控制日志开关,对于第一种情况,可直接通过logcat来获取日志信息,第二种方法可通过hook方法去修改日志控制参数的boolean值,从而让应用程序在运行时,输出日志信息,日志信息既然是方便开发者了解系统运行状态、方便调试程序而来,那对于移动安全测试者作用也是一样,比如日志信息打印的URL、字符串、请求方法等信息系统和调试信息,通过这些信息,可去逆向代码中进行搜索,进而分析代码上下文,完成关键代码查找。

下图就是某金融类APP的日志信息,大概的关键字段有hmacSha1Hex以及URL内容。

通过去代码中搜索关键字段,大概率会有收获,然后从关键方法开始跟踪代码逻辑,开启分析之路。

4

利用数据包定位关键代码

某些数据包在加密通信过程中,往往未对整个数据包进行加密,比如JSON格式请求包,类似(”EnryptText”,”密文”),或者在请求的URL中携带的请求文件名称,均可以作为一个着手点,通过去搜索相关的字段名和URL携带的文件名来定位关键方法。

5

应用程序提示信息

运行APP程序,在一些操作之下会出现提示信息,比如报错信息、toast弹框信息、某个业务操作成功、失败信息,根据程序反馈的信息作为突破口寻找关键代码,一般在开发阶段,字符提示信息会存储在string.xml中,也有可能被开发者硬编码在代码中,如果是string.xml中,则在被反编译后字符串以10进制的id形式访问,但在public.xml中是以16进制进行显示的,所以首先需要通过提示信息去反汇编的string.xml中找到对应的name字段,再通过name字段去public.xml中找到16进制id,最后将id转换成10进制在反编译代码中搜索,即可大概定位关键方法位置,如果是硬编码,则直接搜索字符串,关于相关的资源文件情况,笔者大概收集整理了一下这四个文件public.xml、R.java、resource.arsc、string.xml。

public.xml

源码和apk包中均无此文件,该文件是安卓资源打包工具aapt(Android Asset Packaging Tool )在编译过程中生成的,使用ApkTool反编译才会有此文件;

作用:把对象资源 ID 写死,格式是 

string.xml、resource.arsc

string.xml为源代码中和反汇编中存在的文件,打包好的apk中无此文件,apk在打包时,string.xml中的字符串被加密存储为resource.arsc文件并保存到apk包中,resource.arsc在apk反编译过程中解密。

R.java文件

R.java存在于源码中,apk包中无此文件,该文件是开发过程中自动生成和更新的,默认有attr、drawable、layout、string等四个静态内部类,每个静态内部类分别对应着一种类型资源,如layout静态内部类对应layout中的界面文件名称。

6

从应用主Activity开始分析

代码的入口Activity直接可以从AndroidManifest.xml中去找,主Activity的标识都非常明显,即

< action android:name="android.intent.action.MAIN"/>< category android:name="android.intent.category.LAUNCHER"/>

这里说的都是有UI界面的APP,服务式的APP不在讨论范围之内。

找到主Activity后可以直接从oncreate方法开始阅读,当分析多了之后会发现现在很多APP的主Activity基本上都是名称为SplashActivity、BaseActivity等等。

不过,这种方式平时用的相对来说比较少,这种情况只是适合代码量比较少,代码未混淆的情况,毕竟从入口去跟踪分析代码逻辑比较耗时,特别是对工程量比较大的APP来说,更加困难,再加上代码混淆机制,使得阅读代码、理清代码逻辑思路更是难上加难,想要找到关键方法就不是一件容易的事情了。

综上就是笔者用的比较多的方式来定位目标方法,当然也会有其他的方式,比如动态调试等,小小总结一下,关键的代码定位并不是某一种方式就可以完成的,而是需要多种方法的结合,因地制宜,根据实际情况采取合理的方式去寻找关键代码,且关键代码的定位还依赖于测试者其他方面的技能,比如需要测试者的有一定的代码开发经验,能较为熟练的阅读理解Java代码、C代码,甚至arm指令,能分析出来开发者的一些开发思路,又如能对代码进行逆向,甚至需要掌握一定的脱壳技术,又比如能掌握一些反混淆的技术。



关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接