仅供学习研究 。请勿用于非法用途,本人将不承担任何法律责任。
前言
环境
分析请求包
这是点击购买接口,大家都知道淘宝系的接口请求头都会包含
x-sign x-mini-wua
这两个参数,其他的都不是很重要,但是推荐还是带上比较好,可以自行测试
这个是下单的接口请求头都是一样的,请求体多了两个加密参数
wua params
,两个接口现在需要破解四个加密参数,下面来分析
分析加密参数
首先来看 x-sign
,具体的分析过程就不说了,没经验的话是非常掉头发的,知道应该都清楚这个参数最终是调用 so 层 JNICLibrary.doCommandNative
函数加密的,小弟不才没有能力去分析 so 文件,只能祭出强大的 hook 框架 frida
了,本次也是使用这个工具来主动调用函数获取加密结果的。
反编译之后找到 libsgmain.so
文件,把后缀改成 zip
在解压,使用 jadx-gui
或者其他工具打开解压后的 dex
文件就能看到 JNICLibrary.doCommandNative
函数的代码逻辑了
function getMapData(mapSet) {
try {
var result = {};
var key_set = mapSet.keySet();
var it = key_set.iterator();
while (it.hasNext()) {
var key_str = it.next().toString();
result[key_str] = mapSet.get(key_str).toString();
}
return result
} catch (error) {
return mapSet
}
}
function searchClassLoader(className) {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass(className)) {
console.log(loader);
Java.classFactory.loader = loader;
}
} catch (error) {
}
},
onComplete: function () {
}
})
}
function hookDoCommandNative() {
var JNICLibrary = Java.use('com.taobao.wireless.security.adapter.JNICLibrary');
JNICLibrary.doCommandNative.implementation = function (a, b) {
console.log('JNICLibrary.doCommandNative.a: ', a);
console.log('JNICLibrary.doCommandNative.b: ', b);
console.log('JNICLibrary.doCommandNative.b: ', b.length);
console.log('JNICLibrary.doCommandNative.b: ', JSON.stringify(b));
for (var i = 0; i < b.length; i++) {
try {
console.log('JNICLibrary.doCommandNative.b.i: ', i, ' data: ', b[i].toString())
} catch (error) {
console.log('JNICLibrary.doCommandNative.b.i: ', i, ' data: ', '空')
}
}
var res = this.doCommandNative(a, b);
console.log('JNICLibrary.doCommandNative.res: ', res);
try {
var result = getMapData(Java.cast(res, Java.use('java.util.HashMap')));
console.log('result: ', JSON.stringify(result));
} catch (error) {
} finally {
console.log('-------------------start stack-------------------');
console.log(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Throwable").$new()));
console.log('-------------------end stack-------------------');
}
return res;
}
}
function main() {
var className1 = 'com.taobao.wireless.security.adapter.JNICLibrary';
Java.perform(function () {
searchClassLoader(className1);
hookDoCommandNative();
})
}
setImmediate(main);
这里放一段 frida hook
代码,想要查看那个接口 x-sign x-mini-wua
加密参数的明文,直接运行这段代码就OK了
这张图片是运行后的log日志,可以看到 JNICLibrary.doCommandNative
函数的输入输出全部打印出来了,包括 object array
类型的数据也打印出来了。
根据log日志打印的明文信息,就可以自己去构建 frida hook
主动调用的代码了
function getXSign8110(signData) {
var result = '';
Java.perform(function () {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass('com.taobao.wireless.security.adapter.JNICLibrary')) {
Java.classFactory.loader = loader;
}
} catch (error) {
}
}, onComplete: function () {
}
});
var hashMap = Java.use('java.util.HashMap').$new();
var JNICLibrary = Java.use('com.taobao.wireless.security.adapter.JNICLibrary');
hashMap.put('INPUT', signData['input']);
var params = [
hashMap,
Java.use('java.lang.String').$new(signData['app_key']),
Java.use('java.lang.Integer').$new(7),
Java.use('java.lang.String').$new(''),
Java.use('java.lang.Boolean').$new(true),
];
var ps = Java.array('Ljava.lang.Object;', params);
result = JNICLibrary.doCommandNative(10401, ps).toString();
});
return result
}
function getMiniWua8110(wuaData) {
var result = '';
Java.perform(function () {
Java.enumerateClassLoaders({
onMatch: function (loader) {
try {
if (loader.findClass('com.taobao.wireless.security.adapter.JNICLibrary')) {
Java.classFactory.loader = loader;
}
} catch (error) {
}
}, onComplete: function () {
}
});
var JNICLibrary = Java.use('com.taobao.wireless.security.adapter.JNICLibrary');
var params = [
Java.use('java.lang.String').$new(wuaData['time_str']),
Java.use('java.lang.String').$new(wuaData['app_key']),
Java.use('java.lang.Integer').$new(8),
Java.use('java.lang.String').$new(''),
Java.use('java.lang.String').$new(wuaData['input']),
Java.use('java.lang.Integer').$new(0),
];
var ps = Java.array('Ljava.lang.Object;', params);
result = JNICLibrary.doCommandNative(20102, ps).toString();
});
return result
}
这里就是 x-sign x-mini-wua
的 hook 代码,大家可以自行测试,代码肯定是没问题的,如果又问题那就是你使用的姿势有问题
分析下单接口的 wua params
上面的图片有说到
params
参数还好,根据一些关键词可以搜索到,其实就是使用 gzip + base64
进行编码的 gzip.decompress(base64.b64decode(a)).decode()
这行代码可以成功解码出来,加密的话反过来就行了
wua
这个参数就比较蛋疼了,定位是比较好定位的,全部搜索就可以找到,最后也是调用了 JNICLibrary.doCommandNative
函数,进行加密的,但是这里有个很坑的地方就是,就是在构建参数的时候是个嵌套的 object array
使用 frida
一直报错,最后也是没有解决,索性就直接调用前面的函数
function bytes2String(arr) {
if (typeof arr === 'string') {
return arr;
}
var str = '',
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length === 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
try {
str += String.fromCharCode(parseInt(store, 2));
} catch (error) {
str += parseInt(store, 2).toString();
console.log(error);
}
i += bytesLength - 1;
} else {
try {
str += String.fromCharCode(_arr[i]);
} catch (error) {
str += parseInt(store, 2).toString();
console.log(error);
}
}
}
return str;
}
function getParamsWua8110(wuaData) {
// wuaData = {input: 'ab20540090ca99a9c1022c6f4d2e6feb17b9910bc42ac492b9'};
var result;
function initAvmp() {
var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
var context = currentApplication.getApplicationContext();
var SecurityGuardManager = Java.use('com.alibaba.wireless.security.open.SecurityGuardManager');
var IAVMPGenericComponent = Java.use('com.alibaba.wireless.security.open.avmp.IAVMPGenericComponent');
var IAVMPInstance = SecurityGuardManager.getInstance(context).getInterface(IAVMPGenericComponent.class);
IAVMPInstance = Java.cast(IAVMPInstance, IAVMPGenericComponent);
return IAVMPInstance.createAVMPInstance("mwua", "sgcipher");
}
Java.perform(function () {
var avmpInstance = initAvmp();
var params = [
Java.use('java.lang.Integer').$new(0),
Java.use('java.lang.String').$new(wuaData['input']).getBytes(),
Java.use('java.lang.Integer').$new(wuaData['input'].length),
Java.use('java.lang.String').$new(''),
Java.use('java.lang.String').$new('0000').getBytes(),
Java.use('java.lang.Integer').$new(0)
];
var aaaBytes = Java.use('java.lang.String').$new('').getBytes();
var aaaBytesClass = Java.cast(aaaBytes, Java.use('java.lang.Object')).getClass();
result = avmpInstance.invokeAVMP(
Java.use('java.lang.String').$new('sign'),
Java.cast(aaaBytesClass, Java.use('java.lang.Class')),
Java.array('Ljava.lang.Object;', params)
);
result = bytes2String(Java.array('byte', result));
});
return result
}
具体的分析流程就不说了,大家自行 hook JNICLibrary.doCommandNative
函数,跟一下调用栈就知道了
最后
所有的加密参数也是分析完了,自己简单整合一下就可以跑了,经过测试普通的商品是可以下单成功的,但是茅台这种预售的商品,后台的风控还是比较牛逼的,使用脚本去调用接口,就直接被 盾
了,后面在慢慢优化,哪位大佬如果感兴趣欢迎加博主一起讨论研究
版权声明
微信号: 2027762055
转载请注明出处
原创不易,请多点赞转发