X麦APP逆向
听说演唱会一票难求,有人问我能不能写个抢票程序,仔细研究了半个月,解决处理一个一个难题,尤其是人机验证环节验证码处理一度让我有退却的想法,不过好在最后还是解决了,就是不知道离当黄牛还有多远距离^_^。
先睹为快
先来看看完成之后的效果
主要演示了购买流程和过验证码的环节,下面就来看看逆向学习的过程,这里借鉴了文章,但不会介绍具体实现过程,仅介绍学习当思路和流程。
工具准备
工欲善其事,必先利其器,在整个的分析流程需要用到如下工具
- jadx-gui,APK 静态代码解析
- frida,动态代码分析执行
- 已 root 的 Android 机,安装运行 frida-server
- adb,电脑 与 手机通讯
- wireshark,抓包分析
Roo Android 机
关于 root 手机的准备可以参考去年我折腾旧手机的文章。
frida
frida 作为动态工具类似 x64dbg,可以帮我们动态分析运行过程中的调用关系和变量数值,由于分析的是 App,所以需要在电脑端和手机端分别安装 frida
- 电脑端:frida-tools,作为分析端,发送操作指令分析返回信息
- 手机端:frida-server 作为电脑端指令接收方,对目标应用进行操作并反馈
电脑端安装比较容易,安装 Python 后直接 pip install frida-tools
即可,官方可能比较慢,可以借助国内源下载。
关于 frida-server 的安装,可以参考 frida android 篇教程,首先查看架构
1 | $ adb shell getprop ro.product.cpu.abi |
在发布页面,找到对应架构的 frida-server ,由于本例中是 arm64
所以选择 https://github.com/frida/frida/releases/download/16.1.9/frida-server-16.1.9-linux-arm64.xz
下载,解压得到 frida-server,然后丢到手机上按如下命令运行即可
1 | $ adb root # might be required |
其他
其他软件的安装相对简单,此处仅提供官方地址,安装过程就不再缀述。
手机抓包
根据本人粗浅的经验,逆向分析一般从两个方向进行
- 动态分析,通过界面操作触发观察记录数据
- 静态分析,根据可观测数据定位相关静态代码
分析静态代码模拟相关操作,达到相同效果。一般来说通过抓包可以获得一个不错的切入口,但是由于接口通讯基本都使用了 HTTPS,所以抓包需要一些小技巧才能分析。
这里沿用原文的方法,使用 tcpdump + frida + wireshark
的方式来进行数据包解密。主要原理可以类似之前博客 应用程序抓Https包 ,核心是通过记录会话密钥
来达到解密功能。
tcpdump 安装
首先准备 tcpdump 软件,下载架构匹配 tcpdump,由于本例中是 arm64,所以前往 64位下载地址下载,然后执行如下命令推送至手机里
1 | $ adb push tcpdump /data/local/tmp/ |
会话密钥监听
以上准备工作只是做了一半,还需要准备 frida 脚本来监听记录会话密钥
,大佬已经写好了直接拿来用即可,脚本内容如下:
1 | // sslkeyfilelog.js |
将上述内容保存为 sslkeyfilelog.js
之后,用 frida 命令 frida -U -l .sslkeyfilelog.js -f cn.damai
加载运行。运行后表明会话密钥记录开始。接着执行 ./tcpdump -i any -w tmp.pcap
,接着在App界面操作选票下单,跟随界面操作 frida 界面会滚动出现一些数据,这些数据就是会话密钥,操作结束后关闭 tcpdump 以及 frida,将 frida 界面里的数据保存为 sslkey.txt,其类似如下内容
1 | CLIENT_RANDOM 557e6dc49faec93dddd41d8c55d3a0084c44031f14d66f68e3b7fb53d3f9586d 886de4677511305bfeaee5ffb072652cbfba626af1465d09dc1f29103fd947c997f6f28962189ee809944887413d8a20 |
通过命令 adb pull /data/local/tmp/tmp.pacp .
将抓包数据下载到本地,接着在 wireshark 首选项 -> protocols -> TLS中,设置 (Pre)-Master-Secret log filename为上述sslkey.txt,然后用 wireshark 打开 tmp.pacp,分析操作请求。
接口解析
在 wireshark 窗口中显示一些请求,其中比较重要的是如下请求
- /gw/mtop.trade.order.build,订单构建
- /gw/mtop.trade.order.create,订单提交
关于请求内容解析可以参考原文,这里对原文的推理做一些其他方式的解析,从静态分析的角度来进行签名解析。
静态分析
需要说明的是静态分析更多的是需要耐心和合理的猜测。用 jadx-gui 打开 x 麦 apk 文件,加载完毕后,使用快捷键 ctrl + shift + f
搜索文本 mtop.trade.order.build
,可以定位到类 UltronBuildOrder
,里面的方法和环境配置有关,有getApiNameOnline
getApiNameTest
等方法,根据方法名推测是用于不同环境下,Online
作为在线的意思概率很高,对着 getApiNameOnline
右键查找用例
,可以追踪到 DMQueryKey
的方法 getBuildApiName
,接着右键查找用例
,可以定位到 UltronDataManager
,可以看到其方法名有 createBuildRequest
createSubmitRequest
基本对应 订单的构建 以及 提交,基本可以确定 UltronDataManager
类为订单基础类。
定位过程中可以借助 frida-trace
追踪函数的调用链,命令为 frida-trace -U -j '类名!方法名' 进程名
,这里就不做展示了。
frida 脚本编写
在实际编写功能离不开对 frida 脚本的熟悉,建议系统学习一遍官方文档,这里记录下编写过程中我遇到的问题
主线程
Andriod 系统中有些函数不能运行在工作线程中,这时我们就需要运行在主线程中,例如我们获取应用当上下文可以通过如下方式
1 | Java.scheduleOnMainThread(function () { |
同步通知
在编写中容易涉及多线程通知的问题,这里我用的是 CountDownLatch
方式可以有效解决
1 | let CountDownLatch = Java.use("java.util.concurrent.CountDownLatch"); |
写在最后
关于x 麦的逆向其实省略了很多没有写,包括订单构建中的场次信息如何获取,验证码如何处理等,都是花费了很多精力去处理的,精力有限,只做些简单的记录吧。对了,在这趟逆向之旅中,我深刻感受到知识融汇贯通的魅力,没有 Root 、 adb 和一些编程学习的能力,也许早就中途放弃了,希望各位在逆向的路上不要轻易放弃,坚持探索终会有成果的。