前言:
本文仅供学习交流,只提供关键思路不会给出完整代码,严禁用于非法用途,若有侵权请联系我删除!技术交流合作请私信!
用到工具如下:
之所以要选择android 6 手机,原理如下:
Android 系统将 CA 证书又分为两种:用户 CA 证书和系统 CA 证书。
系统 CA 证书存放在 /etc/security/cacerts/ 目录下,名称是 CA 证书 subjectDN 的 Md5 值前四位移位取或,后缀名是 .0,比如 00673b5b.0。考虑到安全原因,系统 CA 证书需要有 Root 权限才能进行添加和删除。
对于非 Root 的 Android 设备,用户只能安装用户 CA 证书。
无论是系统 CA 证书还是用户 CA 证书,都可以在设置 → 系统安全 → 加密与凭据 → 信任的凭据中查看:
(图1CA证书的位置 用户凭据)
Android 从 7.0 开始,系统不再信任用户 CA 证书(应用 targetSdkVersion >= 24 时生效,如果 targetSdkVersion <24 即使系统是 7.0 + 依然会信任)。也就是说即使安装了用户 CA 证书,在 Android 7.0 + 的机器上,targetSdkVersion>= 24 的应用的 HTTPS 包就抓不到了。
https://www.charlesproxy.com/download/latest-release/
(图2 charles下载位置)
按照默认next即可,然后选择路径。
https://www.zzzmode.com/mytools/charles/
(图3 charles 在线破解)
在Charles的菜单栏上选择”Proxy”->“Proxy Settings”,填入代理端口8888并且勾上”Enable transparent HTTP proxying”,这样就完成了在Charles上的设置
在”Help”->”Local IP Address”中可以查看本机的ip地址,当然也可以在cmd中通过ipconfig查看。
(图3 charles 配置与使用)
(图3 charles 配置与使用2)
设置保存完成后,charles界面会弹出一个连接请求框,点击“Allow”。
(3.charles抓包配置1)
(3.charles抓包配置2)
(3.charles抓包配置3手机设置代理)
https://www.wandoujia.com/apps/279987
之所以不选用最新版APP,是因为最新版APP不走系统代理(Proxy.NO_PROXY)抓不到包;
https://github.com/skylot/jadx
(图4 jadx下载)
https://hex-rays.com/IDA-pro/
https://frida.re/
https://github.com/zhkl0228/unidbg
打开手机app,然后再点击某个商品,可以看到已经抓到明文数据了:
参数分析
https://api.m.jd.com/client.action?functionId=wareBusiness&clientVersion=10.1.4&build=90060&client=android&d_brand=Xiaomi&d_model=MI4LTE&osVersion=6.0.1&screen=1920*1080&partner=ks006&oaid=&eid=eidA0c138122bas4uo1qCosmRnqrZBkTZ+zEF7qNa5UCxrzSE5IyVBHJw4jzuBKyNz0TPXE0oY0j0H/viRPJy5RUE1KWCJuMWV52ufEtPyZiLpXsetVD&sdkVersion=23&lang=zh_CN&eu=8363533373230323933313336333&fv=93D2634303938303363663032626&uuid=d5aada6c69ce7237&aid=d5aada6c69ce7237&area=25_2258_2259_57314&networkType=wifi&wifiBssid=d9077de60f51d1d1d6f228a96f318e0c&uemps=0-2&harmonyOs=0&scval=7929459&st=1695609462872&sign=e684ce9273978b1b9fc14382508e25ca&sv=121
https://api.m.jd.com | api服务器 |
---|---|
functionId=wareBusiness | 表示请求商品信息 |
clientVersion=10.1.4 | 表示app版本号 |
build=90060 | 固定值 |
client=android&d_brand=Xiaomi&d_model=MI4LTE& osVersion=6.0.1&screen=1920*1080 |
手机基本信息 |
partner=ks006 | 固定值 |
oaid=&eid= | 并未参与服务器校验,不用管 |
sdkVersion=23 | android 版本号 |
eu=&fv= | 并未参与服务器校验,不用管 |
uuid= | 设备标识,参与签名校验 |
aid=&area= | 固定值 |
networkType=wifi | 网络类型 |
wifiBssid= | 固定值 |
uemps=0-2&harmonyOs=0&scval=7929459 | 固定值 |
st=1695609462872& sign=e684ce9273978b1b9fc14382508e25ca& sv=121 |
经过多次抓包查看,发现这三个值是变化的。 st,sign,sv为签名字符串,必须,否则采集不到数据。 |
发送post请求,携带body数据如下:
body=%7B%22abTest800%22%3Atrue%2C%22avoidLive%22%3Afalse%2C%22brand%22%3A%22Xiaomi%22%2C%22cityId%22%3A2258%2C%22cpsNoTuan%22%3Anull%2C%22darkModelEnum%22%3A3%2C%22districtId%22%3A2259%2C%22eventId%22%3A%22Productdetail_AutoTextViewInitTime%22%2C%22fromType%22%3A0%2C%22isDesCbc%22%3Atrue%2C%22latitude%22%3A%2224.343482%22%2C%22lego%22%3Atrue%2C%22longitude%22%3A%22102.548063%22%2C%22model%22%3A%22MI+4LTE%22%2C%22ocrFlag%22%3Afalse%2C%22pluginVersion%22%3A101040%2C%22plusClickCount%22%3A0%2C%22plusLandedFatigue%22%3A0%2C%22provinceId%22%3A%2225%22%2C%22skuId%22%3A%227929459%22%2C%22source_type%22%3A%22indexMiaoShaArea%22%2C%22source_value%22%3A%2234_1_7929459_0_4_0_0_0%22%2C%22townId%22%3A57314%2C%22uAddrId%22%3A%220%22%2C%22utmMedium%22%3Anull%7D&
body数据为url编码的字符串,解码后如下:
{"abTest800":true,"avoidLive":false,"brand":"Xiaomi","cityId":2258,"cpsNoTuan":null,"darkModelEnum":3,"districtId":2259,"eventId":"Productdetail_AutoTextViewInitTime","fromType":0,"isDesCbc":true,"latitude":"24.343482","lego":true,"longitude":"102.548063","model":"MI 4LTE","ocrFlag":false,"pluginVersion":101040,"plusClickCount":0,"plusLandedFatigue":0,"provinceId":"25","skuId":"7929459","source_type":"indexMiaoShaArea","source_value":"34_1_7929459_0_4_0_0_0","townId":57314,"uAddrId":"0","utmMedium":null}
其中:"skuId":"7929459"为商品ID,其它值可以固定。
:method POST
:path /client.action?functionId=wareBusiness&clientVersion=10.1.4&build=90060&client=android&d_brand=Xiaomi&d_model=MI4LTE&osVersion=6.0.1&screen=1920*1080&partner=ks006&oaid=&eid=eidA0c138122bas4uo1qCosmRnqrZBkTZ+zEF7qNa5UCxrzSE5IyVBHJw4jzuBKyNz0TPXE0oY0j0H/viRPJy5RUE1KWCJuMWV52ufEtPyZiLpXsetVD&sdkVersion=23&lang=zh_CN&eu=8363533373230323933313336333&fv=93D2634303938303363663032626&uuid=d5aada6c69ce7237&aid=d5aada6c69ce7237&area=25_2258_2259_57314&networkType=wifi&wifiBssid=d9077de60f51d1d1d6f228a96f318e0c&uemps=0-2&harmonyOs=0&scval=7929459&st=1695609462872&sign=e684ce9273978b1b9fc14382508e25ca&sv=121
:authority api.m.jd.com
:scheme https
cookie whwswswws=AAgsrKcqKECi7HFAHqcQGCPELbQtKWubWUX3axAAAAAA;unionwsws={"devicefinger":"eidA0c138122bas4uo1qCosmRnqrZBkTZ+zEF7qNa5UCxrzSE5IyVBHJw4jzuBKyNz0TPXE0oY0j0H\/viRPJy5RUE1KWCJuMWV52ufEtPyZiLpXsetVD","jmafinger":"AAgsrKcqKECi7HFAHqcQGCPELbQtKWubWUX3axAAAAAA"};
charset UTF-8
user-agent okhttp/3.12.1;jdmall;android;version/10.1.4;build/90060;screen/1080x1920;os/6.0.1;network/wifi;
jdc-backup whwswswws=AAgsrKcqKECi7HFAHqcQGCPELbQtKWubWUX3axAAAAAA;unionwsws={"devicefinger":"eidA0c138122bas4uo1qCosmRnqrZBkTZ+zEF7qNa5UCxrzSE5IyVBHJw4jzuBKyNz0TPXE0oY0j0H\/viRPJy5RUE1KWCJuMWV52ufEtPyZiLpXsetVD","jmafinger":"AAgsrKcqKECi7HFAHqcQGCPELbQtKWubWUX3axAAAAAA"};
accept-encoding br,gzip,deflate
cache-control no-cache
content-type application/x-www-form-urlencoded; charset=UTF-8
content-length 757
{
"code": 0,
"floors": [{
"bId": "eCustom_flo_299",
"cf": {
"bgc": "#ffffff",
"spl": "empty"
},
"data": {
"isShowAR": false,
"threeDSwitch": false,
"hasNew3d": true,
"maxSales": {
"head": "https://m.360buyimg.com/umm/jfs/t1/129759/16/40027/1248/64ca1744Fa4fa92fb/d7e880a19b60e3fd.png"
},
"videoControl": {
"autoPlay": false,
"masterVideo": {
"duration": 30,
"imageUrl": "https://img10.360buyimg.com/videocover/jfs/t1/172698/25/26029/144332/61e12e9dEed51eb34/7491df6c1a6e32ae.jpg",
"playBackFlag": false,
"playUrl": "https://jvod.300hu.com/vod/product/4aadfd4b-5cdc-4c8e-9f33-624def0cf178/225dab7defb0493cb062fba090286249.mp4?source=2&h265=h265/18799/902cee167a96463b93fbe4f6fbc5443e.mp4",
"useCoverPicture": false,
"videoDuration": "00'30\"",
"videoId": "687650717",
"videoShare": {
"des": "我发现了一个精彩的视频,快来看看吧",
"microBlog": "我发现了一个精彩的视频,快来看看吧https://h5.m.jd.com/dev/3UmozpxSyHxMaXRXndHbUhwC4iuN/index.html?skuId=7929459",
"title": "这个小视频不错哦~",
"url": "https://h5.m.jd.com/dev/3UmozpxSyHxMaXRXndHbUhwC4iuN/index.html?skuId=7929459"
}
},
"optimize": true
}
},
把app导入到jadx,我们要追踪st,sign,sv这三个参数的来源,那么我们搜索一下,先搜索sign的位置,然后一步步查找,最终找到:
sgin签名 计算涉及到了接口的这几个参数
functionId,body,uuid,client,clientVersion
签名函数
String signature = a.XL().XT().signature(a.XL().getApplicationContext(), queryParameter, str, deviceUUID, property, versionName);
(图6sign签名位置2)
签名函数的位置,可见签名函数位于jdbitmapkit.so文件中。
关键代码:
BitmapkitUtils.getSignFromJni(context, str, str2, str3, str4, str5);
getSignFromJni 这个加密方法 是调用了jdbitmapkit.so里面的代码:
ReLinker.loadLibrary(JdSdk.getInstance().getApplication(), "jdbitmapkit");
注意新版京东有检测frida的,需要改个进程名跟端口。
用frida注入如下函数 BitmapkitUtils.getSignFromJni(context, str, str2, str3, str4, str5);
function HookHandle(clazz) {
clazz.getSignFromJni.implementation = function (a, b, c, d, e, f) {
console.log("=======================================")
var r = this.getSignFromJni(a, b, c, d, e, f);
console.log("param1: ", a)
console.log("param2: ", b)
console.log("param3: ", c)
console.log("param4: ", d)
console.log("param5: ", e)
console.log("param6: ", f)
console.log("result: ", r)
return r;
}
console.log("HookHandle ok")
}
Java.perform(function () {
Java.choose("dalvik.system.PathClassLoader", {
onMatch: function (instance) {
try {
var clazz = Java.use('com.jingdong.common.utils.BitmapkitUtils');
HookHandle(clazz)
return "stop"
} catch (e) {
console.log("next")
console.log(e)
}
},
onComplete: function () {
console.log("success")
}
})
})
(图7.Frida注入验证)
如上,我们可以看出,st sign sv都是从so来的。
至此,sign的来源已理清。
直接压缩软件打开app,搜索,找出文件jdbitmapkit.so
.直接上IDA,把文件拖进去
在方法sub_127E4 找到关键词sign=
方法里面也刚好有uuid,body,st等关键词,确认是这个没错了。
查看ida的代码分析一下算法,并且用java还原,再翻译成python代码。
继续搜索”cipher“字段,找到cipher加解密位置如下:
cipher这个直接复制d这个类就包含了加解密。
技术交流 5b6u5L+h77yaYnljNjM1MiAgUVE6Mzk4NDg4NzI=(base64解码)