0
点赞
收藏
分享

微信扫一扫

某猫超市 茅台抢购脚本 python

舍予兄 2021-09-19 阅读 76
日记本

仅供学习研究 。请勿用于非法用途,本人将不承担任何法律责任。

前言

环境

分析请求包


这是点击购买接口,大家都知道淘宝系的接口请求头都会包含 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
转载请注明出处
原创不易,请多点赞转发

举报

相关推荐

0 条评论