本篇帖子是在我爬虫笔记里的的记录
只是操作记录,代码量少
主要记录了脱壳、调试、objection hook、frIDA hook注入,最后调用注入的方法获取加密参数
一、环境准备:
1、某药品监管apk:v5.3.2
2、安卓端脱壳工具——BlackDex:无版本要求,最新的即可
github :
[color=]https://github.com/CodingGay/BlackDex/releases
脱壳环境要求
截图.png (45.75 KB, 下载次数: 1)
下载附件
安卓端脱壳工具——BlackDex
2023-8-18 14:55 上传
3、Frida
frida 15.2.2
frida-tools 11.0.0
4、objection
objection github:
[color=]https://github.com/sensepost/objection
pip install objection
pip安装最新的即可,无版本要求
5、jadx
6、安卓真机或模拟器
安卓 7
逍遥模拟器
7、Android Studio
8、python 3.7
二、开始
1、抓包分析
通过对app的抓包可知app端就一个加密参数 tzRgz52a签名
[color=]
headers:
[JavaScript] 纯文本查看 复制代码 Accept-Language: zh-CN,zh;q=0.8
User-Agent: Mozilla/5.0 (Linux; U; Android 7.1.2; zh-cn; HD1910 Build/N2G48H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Connection: close
Host: mobile.nmpa.gov.cn
Accept-Encoding: gzip
tzRgz52a: BlRnN9IbxigK7nqPZitab6KNJ5oaPyiKKmPOSV-k_6JsT7bS0ywp0DhUwx7pDVsvshj5S5Mj26SqTg6YK_jc81sahiH4oH86rAotrTjoK8I3NYzEGP_wDWlJtGolNxD8XgDZr0z3hoyGzTI7dCuL2RI5e_uNwyIuD-yUEWz9TrTEKVO9Po1iWTPGbgfns9xN7bgjDYfbmHxiXi0IRWmBNZY2uNZ6I7b2iI2GeR2lLN_Zj42B2UP_oClQv5jdPxENikZ8GOa8UoJM4Slja0hY2k-FT6RWtjDoL6IvXIYy40WdnM0pYvMWxE2kkczs_WuN7nuFPKjZplGDwJYABG5R4qSchFSoIt_95rLa3N9OtgRvWMur9qQM3rHVZa16WqRKcYJqHwIrxiOncUS-udOLYfFtQlCLsxe0RlFpVxn0ykiw1O0ualP2_2r-mY7VoOKS0wDCM6aaWynDAfVdNQJonnRv1SjS9MjgJ0BgAMGdPwENNTUn_cAkwFK-HVZpw35H7PGqAk0DoMhNfQ9vR0XQ7p3eUkyc1Lp3bdDXL94AHZb3lVSEUicex9BumrwnkNGM3F3s4B1zjdetUk3tZZlj8u3v_Fj48wDC7zsR8-KOBkrGMBj-t2rOahfGk1PXqK8_epWVIysgbLlXInHP35587M0
Connection: close
Cache-Control: no-cache
2、frida-server
下载与frida版本对应的 frida-server,模拟器就下载 x86版本的(红框),安卓真机就下载arm版本的(蓝框),也可以adb shell 进入手机终端,执行以下命令查看内核版本,再下载相应的frida-server
[Shell] 纯文本查看 复制代码adb shell
getprop ro.product.cpu.abi
截图2.png (6.41 KB, 下载次数: 0)
下载附件
2023-8-18 14:59 上传
截图3.png (97.48 KB, 下载次数: 0)
下载附件
2023-8-18 14:59 上传
将下载的frida-server-15.2.2-android-x86_64.xz解压,将文件夹中的 frida-server-15.2.2-android-x86_64 push到安卓目录 /data/local/tmp/ 下,并给该文件添加权限,然后并启动
[Shell] 纯文本查看 复制代码adb shell
cd /data/local/tmp
su
#添加权限
chmod 777 frida-server-15.2.2-android-x86_64
#启动frida-server
./frida-server-15.2.2-android-x86_64
新建cmd窗口开启端口转发
[Shell] 纯文本查看 复制代码adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
在cmd窗口中输入 frida-ps -U命令后输出模拟器进程,说明frida安装成功
[Shell] 纯文本查看 复制代码frida-ps -U
截图4.png (16.37 KB, 下载次数: 0)
下载附件
2023-8-22 14:07 上传
3、app脱壳
在手机上安装 药监局app 和 BlackDex app
对于BlackDex 64位的和32位的都要安装,如果一个脱壳失败,就换另一个版本
截图5.png (140.07 KB, 下载次数: 0)
下载附件
2023-8-18 15:02 上传
根据提示将脱壳后的dex文件提取出来
截图6.png (12.75 KB, 下载次数: 0)
下载附件
2023-8-18 15:02 上传
截图7.png (78.32 KB, 下载次数: 1)
下载附件
2023-8-18 15:02 上传
4、调试
使用jadx打开dex文件
截图8.png (16.53 KB, 下载次数: 1)
下载附件
2023-8-18 15:05 上传
先在jadx中全局搜索tzRgz52a 结果是搜不到的
如果经验多的话 这时候就应该知道,先搜索与header有关的
搜索 getheader 结果如下
截图9.png (75.83 KB, 下载次数: 0)
下载附件
2023-8-18 15:05 上传
可以发现,搜索到了很多,重点观察com开头的节点,发现两个可以的方法com.msec.MSecClient 的 _ts_getHeaderKey, _ts_getRequestHeader
截图10.png (67.21 KB, 下载次数: 0)
下载附件
2023-8-18 15:05 上传
下一步就可以根据上面的结果进一步调试hook看能否拿到我们想要的数据
调试方法有很多
1、objection hook
2、python 写脚本 hook
3、fridamanager 注入 js hook
4、xposed 插件注入 js hook
5、aosp 内置 frida hook
都可进行尝试,这里用的是objection
三、objection hook
1、查找app及其包名
cmd窗口执行
[Shell] 纯文本查看 复制代码frida-ps -Uai
结果如下
截图16.png (15.69 KB, 下载次数: 0)
下载附件
2023-8-22 14:07 上传
com.hxzk.android.hxzksyjg_xj 即是包名
2、objection hook
cmd执行 ,进入objection
[Shell] 纯文本查看 复制代码objection -g com.hxzk.android.hxzksyjg_xj explore
截图12.png (13.33 KB, 下载次数: 0)
下载附件
2023-8-22 14:07 上传
根据二、4的结果 搜索msec相关的类
[Shell] 纯文本查看 复制代码android hooking search classes msec
截图13.png (17.11 KB, 下载次数: 0)
下载附件
2023-8-18 15:07 上传
hook com.msec.MSecClient 类,查看类中的方法,找到要hook的方法
[Shell] 纯文本查看 复制代码android hooking watch class com.msec.MSecClient
截图14.png (36.14 KB, 下载次数: 0)
下载附件
2023-8-18 15:09 上传
hook以上两个方法
[Shell] 纯文本查看 复制代码android hooking watch class_method com.msec.MSecClient._ts_getH
eaderKey --dump-args --dump-backtrace --dump-return
android hooking watch class_method com.msec.MSecClient._ts_getRequestHeader --dump-args --dump-backtrace --dump-return
去app中请求接口,即可看到hook结果
截图15.png (49.41 KB, 下载次数: 2)
下载附件
2023-8-18 15:09 上传
根据hook结果可知 _ts_getRequestHeader()方法的返回值 即是 tzRgz52a签名
[color=]
3、使用frida hook并注入,hookjs如下:
[JavaScript] 纯文本查看 复制代码function get_yjj_tzRgz52a() {
console.log('script 加载成功')
Java.perform(function () {
console.log('hook test')
var MainActivity = Java.use('com.msec.MSecClient');
MainActivity._ts_getRequestHeader.implementation = function (x, y, z) {
// 这里开始是原函数的逻辑
console.log(x)
console.log(y)
console.log(z)
// 这里对原函数的参数重新赋值
var vaule = this._ts_getRequestHeader(x, y, z);
// 返回原函数的结果
console.log(vaule);
return vaule
}
})
}
setTimeout(get_yjj_tzRgz52a)
使用 以下命令注入:
[Shell] 纯文本查看 复制代码frida -U -l 1.js 中国药品监管
注意:这里注入后面写的是name 而并非包名
如图所示,注入成功
截图17.png (17.26 KB, 下载次数: 1)
下载附件
2023-8-18 15:11 上传
在app中重新请求 接口,hook结果如下
截图18.png (44.84 KB, 下载次数: 1)
下载附件
2023-8-18 15:11 上传
0 0 http://mobile.nmpa.gov.cn/datasearch/QueryList?tableId=25&searchF=Quick%20SearchK&pageIndex=4&pageSize=15
分别对应方法的参数 x y z,多次请求后发现 0 0是固定的,即只有参数z是变量,z就是 请求的数据接口链接
4、RPC主动调用
确定方法的参数后即可使用RPC将被动调用 改为主动调用
稍微改动下hook的js
[JavaScript] 纯文本查看 复制代码function getYjjTzRgz52a(x, y, z) {
var vaule;
Java.perform(function () {
Java.choose('com.msec.MSecClient', {
onMatch: function (instance) {
vaule = instance._ts_getRequestHeader(x, y, z);
},
onComplete: function () {
console.log('_ts_getRequestHeader()调用完成')
}
})
})
return vaule
}
rpc.exports = {
getyjjtzrgz52a: getYjjTzRgz52a
}
RPC使用python实现,代码如下:
[Python] 纯文本查看 复制代码#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2022 LouShimin, Inc. All Rights Reserved
#
# @version : 1.0
# @AuThor : LouShimin
# @Time :
# @FileName: yjj.py
# @desc :
import frida
def on_message(message, data):
if message['type'] == 'send':
print(message['payload'])
elif message['type'] == 'error':
print(message['stack'])
device = frida.get_usb_device()
process = device.attach('中国药品监管')
with open('./yjj_end_rpc.js', encoding='utf-8') as f:
jscode = f.read()
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
def get_yjj_rpc():
rpc = script.exports
return rpc
def get_yjj_tzRgz52a(page):
rpc = get_yjj_rpc()
a1 = rpc.getyjjtzrgz52a(0, 0,
'http://mobile.nmpa.gov.cn/datasearch/QueryList?tableId=25&searchF=Quick%20SearchK&pageIndex={}&pageSize=15'.format(
page))
print(a1)
if __name__ == '__main__':
while True:
page = input('请输入页码:')
print(page)
get_yjj_tzRgz52a(page)
运行程序后输入页码,返回值即为tzRgz52a 签名
截图19.png (25.02 KB, 下载次数: 1)
下载附件
2023-8-18 15:14 上传
5、Sanic+RPC远程调用
接口文件如下:
[Python] 纯文本查看 复制代码#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2022 LouShimin, Inc. All Rights Reserved
#
# @Version : 1.0
# @Author : LouShimin
# @Time :
# @FileName: sanic_app.py
# @Desc :
from sanic import Sanic
from sanic.response import json as response_json
from commons.frida_rpc.yjj_rpc import get_yjj_rpc
app = Sanic(__name__)
yjj_rpc = get_yjj_rpc()
@app.route("/getSignFromJni", methods=['POST'])
async def req_proxy_data(request):
res = request.json
yjj_url = res['yjj_url']
tzRgz52a = yjj_rpc.getyjjtzrgz52a(0, 0, yjj_url)
print(tzRgz52a)
res_data = {
'msg': 'success',
'code': 200,
'tzRgz52a': tzRgz52a,
'yjj_url': yjj_url
}
return response_json(res_data)
if __name__ == '__main__':
app.run("0.0.0.0", port=16383, debug=True, workers=30)
改造并引入三、4中的 getyjjtzrgz52a()方法接口通过接口形式调用:
截图20.png (85.59 KB, 下载次数: 0)
下载附件
2023-8-18 15:14 上传