Android逆向实录

2019-12-16  本文已影响0人  dfqin

之前也做过一些关于Android安全相关的总结,但是如果不深入了解逆向技术,所有的安全都是纸上谈兵,知己知彼百战不殆,只有对常见逆向技术非常熟悉,才能更好的对自己APP做安全防护,这篇文章我们就尝试对APP做一些逆向工作。

筛选应用

对市面上的APP做个初步分析,会发现从逆向角度主要分三类:

通过上面分析我们知道,第一类没有任何挑战,第二类通常比较简单,采用成熟的虚拟机或者hook方案,如果没有没有找到合适的方案,自己去破解难度比较大,第三类上手简单,破解具体敏感点比较有挑战。这里我们选择第三类的APP进行研究学习,为了规避不必要的麻烦,这里我选择了一款国外的应用whatsapp。

逆向目的

我们为什么要逆向一个APP?因为现在都是轻客户端实现,所以通常客户端里面不会有什么重要的算法实现,目前常见的逆向目的,主要有网络协议破解、资源获取(字体、图片、秘钥)、源码修改(植入广告、游戏金币修改)等。目前最常见的还是协议破解,例如前一段火爆的微信群控外挂,就是需要破解微信协议才可以实现,这里我们把我们的目标定为协议破解。

抓包

既然我们想要破解协议,第一步肯定是要抓包,先看下抓到的请求是什么样的。我们打开charles和设置好手机上的代理,运行whatsapp,发现并没有抓到数据,而手机上的其他应用数据抓包都是好的,现在只能猜测它网络使用了tcp直连,或者网络请求禁用了代理,或者其他我们不知道的技术。抓包没能获得有效线索(暂不考虑tcp抓包),那么我们就暂时跳过这条路,看能不能从代码层面找到点突破。

静态分析

我们先找到一个静态分析的切入点,进入APP的验证码发送页面,在终端输入

adb shell dumpsys activity top

通过打印Activity栈,可以定位当前页面的类名为VerifySms,


image.png

下面我们就可以准备去翻逆向代码了。通过dex2jar直接把dex文件反汇编为java代码,或者直接使用jadx,直接反编译整个apk,代码、manifest和资源文件一起都能看到,如下图:


逆向后的工程
现在已经可以愉快地读代码了。很快就找到了请求相关的代码:
网络请求相关

通过源码分析,发现逻辑还挺复杂,代码又做过了混淆,阅读代码读起来挺困难,有些逻辑需要看下运行时的值才好理解,这时候就需要动态调试了。

动态调试

动态调试需要两步,首先要有一个debuggable的apk包,手机安装这个包并运行,第二步是要有这个包对应的源码。当然我们不可能有源码,我们只能使用由dex反汇编后的smali代码,不过关系不大,smali语法相对来说不是很复杂。我这里先做第一步,使用apktools反汇编apk包,可以看到反编译后的项目:

反编译项目
我们打开AndroidManifest.xml文件,修改debuggable为true,然后用apktools重新打包,生成的apk包是未签名的,重新签下名后就可以安装和调试了。需要注意的是重新打包时经常会报很多资源方面的错,根据报错删除或修改相关资源即可。下面我们需要将上面的反编译后的项目导入AndroidStudio,具体的操作细节可以参考这个文章https://www.jianshu.com/p/1a28e6439c6a。导入后我们输入如下指令查看whatsapp进程信息
adb shell ps | grep com.whatsapp
应用进程信息

我们可以看到whatsapp的PID为22512,我们通过如下命令做好端口映射

adb forward tcp:5007 jdwp:22512

映射成功后,跟平时调试程序一样,在AS上去附加应用就好:


image.png

附加后,在代码中打上断点,操作安装重编译后的whatsapp,就可以愉快的调试了:


调试代码
我们想研究发短信的接口,发现调用几次之后,下次调用的时间变得很长,严重影响调试,我们看能不能修改下代码,让发送按钮始终可用。
我们研究代码可以得知,每次点击发送短信,都会把按钮置为不可用,当倒计时结束时再置为可用。我们只需要把按钮职位不可用的代码修改掉,按钮就始终可用了,通过阅读和debug,我们找到了设置按钮状态的地方,我们修改一下代码,传的值永远为true即可,修改的代码如下:
按钮状态始终可用

我们重新打包安装,然后发现,这个按钮始终可用了,可以随时触发发送验证码的请求,方便不停的触发debug的场景。后面我们还发现接口参数用到了包签名,没关系,我们封装一个自己的类,返回原始包的签名,所有使用签名的地方都调用我们这个类,就可以绕过服务端的签名验证了。


修改签名

现在我们发现一个问题,每次修改一点代码,都要重新打包安装,才能继续调试,效率有些太低了。有没有办法可以避免频繁打包呢?下一节我们使用hook来解决这个问题。

hook 大法

这里的hook是指在使用高权限模式(设备需要root)运行的框架,改变运行时一些类的行为和实现,简单点说就是利用hook技术,可以在运行时改变你程序的行为,但并不需要改变你程序的代码。Android平台上用的比较多的是xposed框架,大家可以编写自己的模块,也可以去网上下载别人写好的模块,例如微信的防撤回、自动抢红包模块。下面是一张xposed图片

xposed模块
这里我们就不讲xposed的使用细节了,我们用xposed编写一个模块,去hook网络请求的参数和返回值:
hook请求数据
使用hook,就不需要每次都重新打包了(正常xposed插件每次编译更新后都需要重启手机才能生效,可以使用免重启的方法提高效率。有了hook,可以很方便的更改APP原来的实现逻辑,能够大大的提高逆向效率。我们也可以使用frida来进行hook,它使用起来更为方便,这里有一篇教程可以看一下。

小结

我们整理一下我们的逆向流程,为了分享网络协议,我们可以先抓包,通抓包数据分析协议,通常数据都是加密或者加过签名的,为了弄清楚加密规则,我们就要去静态分析源码,逻辑太复杂,我们可以通过动态调试帮助理解逻辑;为了方便调试或者验证自己的想法,我们需要对原APP修改Smali代码然后重新打包;为了解决修改代码重新打包低效的问题,我们使用hook技术,可以方便的修改APP原有逻辑。这套流程整下来,发现剩下的就是体力活了。

上一篇下一篇

猜你喜欢

热点阅读