本文案例是对美图秀秀app的sig参数和client_session参数生成分析。
案例环境:美图版本9.3.5 、工具Jadx、夜神安卓7、Frida
APP包名: com.mt.mtxx.mtxx
接口分析
抓包,搜索接口和参数如下:
url = "https://api.xiuxiu.meitu.com/v2/search/feeds.json"
params = {
"client_timestamp": "1639113315051",
"client_timezone": "GMT+8",
"is_gdpr": "0",
"client_channel_id": "baidu",
"client_model": "MI 9",
"cpuModel": "shamu",
"client_brand": "Android",
"resolution": "900*1600",
"client_id": "1089867602",
"sigVersion": "1.3",
"runtimeMaxMemory": "192",
"ad_sdk_version": "5.7.20",
"feed_sort": "normal",
"is_test": "0",
"keyword": "韩国证件照",
"client_network": "wifi",
"ram": "3482",
"cpuVendor": "Other",
"count": "12",
"version": "9.3.5.0",
"search_type": "0",
"is_basic": "0",
"country_code": "CN",
"app_hot_start_times": "1",
"attachFlag": "409",
"client_session": "8b5f0ef740d6d22fd3a5c5e7cd069e45",
"is64Bit": "0",
"client_is_root": "2",
"client_operator": "CHINA MOBILE",
"gid": "2638425610",
"mac": "08:00:27:97:F2:76",
"client_language": "zh_CN",
"cn_switch_on": "0",
"sig": "50a300ed42c1202deb5439a77c3dcc70",
"sigTime": "1639113315054",
"client_os": "5.1.1",
"lang": "1",
"is_privacy": "0",
"user_agent": "mtxx-9350-Xiaomi-MI 9-android-5.1.1-9d212252",
"is_ohos": "0",
"sigEnv": "0",
"appAreaType": "3",
"personality_not_recommend": "0",
"community_version": "2.0.0",
"android_sdk_int": "22",
"ad_personality_not_recommend": "0",
"imei": "863254944222826",
"is_device_support_64": "0",
"android_id": "e3be29a75f28a5c2"
}
经过分析, 动态参数有 client_timestamp、client_session、sig、sigTime。
client_timestamp,sigTime是时间戳,client_session、sig 应该是加密参数。
接口分析完成,接下来进行源码分析。
源码分析
查壳,尬住,查出来是阿里聚安全。
这个壳没啥好脱法,所以不脱了,直接丢jadx中反编译。
8G内存吃满了,没办法我修改成了12G,如果你没这么多内存就换其他工具,Apktools或者JEB反编译。
内存加载完成之后,占了8.2G。
开始静态搜索加密参数,和sig相关的搜索词有很多,"sig"、sig;、"sig、=sig 等等。
经过多次查看,最后找到了比较符合的位置。
进去之后,观察文件内容,有很多SigEntity重载方法。
那如何知道生成sig的是哪一个方法呢,这里最好是hook查看。
Frida hook
启动frida
不知道参数名该怎么写的话,就随便写两个,然后看frida的报错提示就可以。
{
'type': 'error', 'description': "Error: generatorSig(): specified argument types do not match any of:
overload('java.lang.String', '[Ljava.lang.String;', 'java.lang.String')
overload('java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.Object')",
}
这是报错中给出的参数类型,直接拿来用。每个都测一下就知道哪个是生成sig的方法了。
Frida HOOK代码如下:
import frida, sys
def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)
jscode_hook = """
Java.perform(
function(){
console.log("1. start hook");
var ba = Java.use("com.meitu.secret.SigEntity");
if (ba != undefined) {
console.log("2. find class");
ba.generatorSig.overload('java.lang.String', '[Ljava.lang.String;', 'java.lang.String', 'java.lang.Object').implementation = function (a1,a2,a3,a4) {
console.log("3. find function");
console.log(a1);
console.log(a2);
console.log(a3);
console.log(a4);
var res = ba.generatorSig(a1,a2,a3,a4);
console.log("计算result:" + res);
return res;
}
}
}
)
"""
process = frida.get_usb_device().attach('com.mt.mtxx.mtxx')
script = process.create_script(jscode_hook)
script.on('message', on_message)
print('[*] Hook Start Running')
script.load()
sys.stdin.read()
触发请求,查看frida打印内容。
- 第一个参数是:search/feeds.json
- 第二个参数是:提交的参数、包括设备环境
- 第三个参数是:6184556633574670337
- 第四个参数是:com.meitu.remote.hotfix.app.RemoteHotfixApplication@3fbe8c4
经过多次测试,除了提交的参数,比如搜索词之外,其他都是定值。 需要注意的是第四个参数是Object对象。
根据代码逻辑判断,只有 obj符合Context类型时,才会生成sig,所以可以笃定obj是一个Context对象。
攒够了参数之后,就可以根据方法去编写加密算法了,但是查看了一下加密函数的逻辑,调用了native中的方法。
秉承着不分析so文件的思路,此时有两种解决方法。通过unidbg去模拟调用so中的方法;或者依旧通过frida来RPC导出函数生成sig。
sig生成
【温馨提示:此处隐藏内容需要付费订阅后才能查看!】
执行结果:
Frida Flask PRC
正常的RPC导出代码:
【温馨提示:此处隐藏内容需要付费订阅后才能查看!】
通过Flask配合Frida实现RPC远程调用。
【温馨提示:此处隐藏内容需要付费订阅后才能查看!】
示例:
client_session分析
接着再看一下 client_session
点进去
m77880a方法
m74573a 和 m74574a ,这是一个md5算法。
所以 client_session的生成很简单。