美文网首页
摩托x的逆向分析

摩托x的逆向分析

作者: 布丁和尚 | 来源:发表于2021-12-08 11:05 被阅读0次

    篇幅有限

    完整内容及源码关注公众号:ReverseCode,发送

    apk放入jadx-1.2.0中很明显被奇虎360加固了

    image-20210727192532494

    使用PKiD再次确认

    image-20210727192630567

    脱壳

    环境

    安卓8.1+fs128arm64+pyenv local 3.8.2

    adb install 摩托邦4.8.0.2021070601.apk

    FRIDA-DEXDump

    对于完整的 dex,采用暴力搜索 DEX.035 即可找到。而对于抹头的 dex,通过匹配一些特征来找到。FRIDA-DEXDump纯粹的利用特征从内存中检索已经加载的 DEX 文件,而不需要拦截任何的函数得到一些结构体,并从中获取 DEX 的内存地址或其他相关信息。

    git clone https://github.com/hluwa/FRIDA-DEXDump.git  支持搜索没有文件头的 DEX 文件
    python main.py  前台运行需要脱壳的app,将dump下的dex放到jadx-1.2.0中反编译
    
    image-20210727192238333

    FART

    在设置中找到需要脱壳的应用配置sdcard存储空间权限,否则只能存到var savepath = "/data/data/com.motoband";首先拷贝fart.so和fart64.so到/data/app目录下(权限不足就先放到/data/local/tmp再转移目录),并使用chmod 777 设置好权限

    frida_fart_reflection.js

    用反射的方式实现的函数粒度的脱壳,与使用hook方式实现的方法不同,可以使用spawn和attach两种方式使用

    调用dump(classname),传入要处理的类名,只完成对某一个类下的所有函数的CodeItem完成dump,效率更高,dump下来的类函数的所有CodeItem在含有类名的bin文件中

    frida_fart_hook.js

    使用hook的方式实现的函数粒度的脱壳,仅仅是对类中的所有函数进行了加载,但依然可以解决绝大多数的抽取保护,需要以spawn方式启动app,等待app进入Activity界面后,执行fart()函数即可

    如果发现某个类中的函数的CodeItem没有dump下来,可以调用dump(classname),传入要处理的类名,完成对该类下的所有函数体的dump,dump下来的函数体会追加到bin文件当中

    git clone https://github.com/hanbinglengyue/FART.git
    frida -UF -l frida_fart_reflection.js
    frida -U -f com.motoband -l frida_fart_reflection.js --no-pause
    frida -U -f com.motoband -l frida_fart_hook.js --no-pause
    mv dex /sdcard/com.motoband/   在使用爱莫助手下载
    
    image-20210727195632734

    Youpk

    仅限机型pixel 1代,效果最好,脱的裤衩都没了

    7z x Youpk_sailfish.zip 
    adb reboot bootloader
    cd sailfish-nzh54d && sh flash-all.sh
    

    安装apk后在Settings-Apps-摩托邦-Permissions启动存储权限

    adb shell "echo com.motoband >> /data/local/tmp/unpacker.config"  启动apk等待脱壳,每隔10秒将自动重新脱壳(已完全dump的dex将被忽略), 当日志打印unpack end时脱壳完成
    adb pull /data/data/com.motoband/unpacker  pull出dump文件, dump文件路径为 /data/data/包名/unpacker
    java -jar dexfixer.jar /data/data/com.motoband/unpacker /data/data/com.motoband/output   调用修复工具 dexfixer.jar, 两个参数, 第一个为dump文件目录(必须为有效路径), 第二个为重组后的DEX目录(不存在将会创建)
    
    adb install wifiadb.apk
    adb tcpip 5555   免root执行tcpip调试模式
    adb connect 172.20.103.254:5555
    

    适用场景

    1. 整体加固
    2. 抽取:
      • nop占坑型(类似某加密)
      • naitve化, 在<clinit>中解密(类似早期阿里)
      • goto解密型(类似新版某加密?najia)

    AUPK

    抓包

    charles+postern

    image-20210728113500752

    SSL handshake with client failed: An unknown issue occurred processing the certificate (certificate_unknown)看起来做了证书绑定,使用r0capture开启dump证书也未dump下来,无法正常抓包

    ./fs1280arm64 启动frida,netstat -tnlp|grep 27042 查看占用端口

    frida_ssl_logger

    核心原理就是对SSL_readSSL_write进行hook,得到其收发包的明文数据

    python ssl_logger.py -U -f com.motoband
    python ssl_logger.py -U -f com.motoband -p motoband.pcap  生成的pcap通过wireshark打开
    
    image-20210728101147025

    OkHttpLogger-Frida

    由于所有使用的okhttp框架的App发出的请求都是通过RealCall.java发出的,那么我们可以hook此类拿到request和response,也可以缓存下来每一个请求的call对象,进行再次请求,所以选择了此处进行hook

    adb push okhttpfind.dex /data/local/tmp
    frida -U -l okhttp_poker.js -f com.motoband --no-pause  可追加 -o [output filepath]保存到文件
    

    判断是否混淆,如果混淆需要修改okhttp_poker.js中的混淆后的变量

    image-20210728102421848

    开启抓包

    image-20210728102752197

    r0capture

    ./fs14216arm64
    pyenv local 3.9.0

    adb shell dumpsys activity activities  查看前台app包名
    python r0capture.py -U -f  com.motoband -v
    python r0capture.py -U -f  com.motoband -v -p motoband.pcap
    python r0capture.py -U -f com.motoband -v >>motoband.txt
    frida -U -f com.motoband -l script.js --no-pause -o motoband.txt
    

    ctrl+shift+o获取请求与请求头

    image-20210728111350099

    ctrl+shift+o获取请求参数

    image-20210728111453906

    拼装到postman中

    image-20210728111914921 image-20210728111831220

    分析

    通过Youpk脱下的dex一起放到jdax-1.2.0中,搜索seriesinfo

    @POST("car/seriesinfo")
    Observable<ResponseBody> motoInfo(@Body RequestBody requestBody);
    

    查找用例位于com.motoband.core.manager.ChooseCarManager

    public Observable<MotorbikeSeriesModel> requestMotorInfo(String str, int i) {
        HashMap hashMap = new HashMap();
        hashMap.put(IntentConstants.MODELID, str);
        hashMap.put("source", Integer.valueOf(i));
        return RetrofitHelper.getObjectObservable(((ChooseCarService) RetrofitHelper.getRetrofit().create(ChooseCarService.class)).motoInfo(RetrofitHelper.getRequestBody(hashMap)), MotorbikeSeriesModel.class).observeOn(AndroidSchedulers.mainThread()).doOnNext($$Lambda$ChooseCarManager$XcbjKQVeNSK4TPlk0mzi1vIv6Z0.INSTANCE);
    }
    

    显然getRequestBody就是生成众多加密参数的方法,位于com.motoband.core.http.RetrofitHelper

    public static RequestBody getRequestBody(Map<String, Object> map) {
        if (map == null) {
            map = new HashMap<>();
        }
        long currentTimeMillis = System.currentTimeMillis();
        map.put("token", UserInfo.getInstance().getToken());
        map.put(MBRequestConstants.REQUEST_REQUESTID, CommonUtil.getRequestId(currentTimeMillis));
        map.put(MBRequestConstants.REQUEST_CTYPE, "2");
        map.put(MBRequestConstants.REQUEST_CVERSION, AppUtils.getAppVersionName());
        map.put("citycode", UserInfo.getInstance().getCitycode());
        if (!map.containsKey("userid")) {
            map.put("userid", UserInfo.getInstance().getUserid());
        }
        if (!map.containsKey(MBRequestConstants.REQUEST_LONLAT)) {
            map.put(MBRequestConstants.REQUEST_LONLAT, UserInfo.getInstance().getLonlatStr());
        }
        map.put(MBRequestConstants.REQUEST_PUSH_ID, JPushInterface.getRegistrationID(MBUtil.getContext()));
        ArrayList<String> arrayList = new ArrayList();
        for (String str : map.keySet()) {
            if (map.get(str) == null) {
                arrayList.add(str);
            }
        }
        for (String str2 : arrayList) {
            map.remove(str2);
        }
        String str3 = null;
        try {
            str3 = RSAUtil.rsaSign(EncryptUtils.encryptMD5ToString(RSAUtil.getSignContent(map)).toLowerCase(), Constants.CLIENT_PRIVATE_KEY);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(MBResponseCode.RSA_SIGN_ERROR);
        }
        map.put("sign", str3);
        return RequestBody.create(MediaType.parse(HttpConstants.MediaType_Json), JSON.toJSONString(map));
    }
    

    多进程保护

    由于摩托邦存在多进程保护,基于信号的发送和接收,实现相互的保护防止被动态攻击。简单的双进程保护就是从原进程再fork一个空进程出来,让逆向分析的时候附加到空进程中导致hook不上。

    双进程进程保护主要功能: 1、保护父进程,ptrace所有线程,防止被附加、调试、暂停; 2、保护子进程,防止被暂停、异常退出;

    objection附加双进程保护的app的时候报错,一般双进程保护,先把app关掉直接用spwan模式就能附加上。

    查看frida源码和objection源码:

    frida附加的顺序:spawn->resume->attach
    objection附加的顺序:spawn->attach->resume

    vim /root/.pyenv/versions/3.8.2/lib/python3.8/site-packages/objection/utils/agent.py   添加如下代码
            debug_print('Resuming PID test `{pid}`'.format(pid=self.spawned_pid))
            self.device.resume(self.spawned_pid)
    
    image-20210728160806491
    注释如下代码
            #if not self.exports().ping():
            #    click.secho('Failed to ping the agent', fg='red')
            #    raise Exception('Failed to communicate with agent')
    
    image-20210728160856891

    实际就是把resume放到步骤的中间,如果不行的话适当加个sleep就能附加上了

    内存漫游

    objection -g com.motoband explore -P ~/.objection/plugins
    android hooking search classes com.motoband.core.manager.ChooseCarManager  搜索类
    android hooking list class_methods com.motoband.core.manager.ChooseCarManager  列出类方法
    
    image-20210728150824474
    plugin wallbreaker classdump com.motoband.core.http.RetrofitHelper  根据指定类dump类结构
    plugin wallbreaker objectdump --fullname 0x3576  查看类的值
    
    image-20210728165336743
    plugin wallbreaker classsearch com.motoband.core.http.RetrofitHelper   搜索所有相关类
    plugin wallbreaker objectsearch com.motoband.core.http.RetrofitHelper$1$1  搜索内存中指定类返回地址
    plugin wallbreaker objectdump --fullname 0x2d9a   根据地址dump类所有方法
    
    image-20210728164831881
    android hooking watch class_method com.motoband.core.manager.ChooseCarManager.requestMotorInfo --dump-backtrace --dump-args --dump-return   hook指定方法requestMotorInfo,打印参数返回值调用栈
    
    image-20210728152259851

    以上hook说明在requestMotorInfo中传入品牌型号3334后进入getRequestBody函数

    jobs list  查看进程中的任务
    jobs kill id  杀死hook任务
    
    image-20210728152113382

    参数分析

    根据以上Jadx中的分析,App在请求car/seriesinfo时调用了RetrofitHelper.getRequestBody(hashMap)),在函数getRequestBody中对不同参数包括token,sign等进行了加密,并RequestBody.create(MediaType.parse(HttpConstants.MediaType_Json), JSON.toJSONString(map));最终将请求参数的HashMap转成JSONString作为create传递参数。

    那么即可通过主动调用getRequestBody的同时hook函数RequestBody.create拿到第二个参数作为请求参数,由于headers中数据一致,加上请求url即可完成数据抓取。

    function hook_RequestBody_create(){
        Java.perform(function(){
            Java.use("okhttp3.RequestBody").create.overload('okhttp3.MediaType', 'java.lang.String').implementation = function(mediaType,str){
                var result = this.create(mediaType,str)
                console.log("params====",str)
                return result;
            }
        })
    }
    function Initiative_getRequestBody(){
        Java.perform(function(){
            var map = Java.use('java.util.HashMap').$new();
            var StringClass = Java.use("java.lang.String");
            map.put("modelid", StringClass.$new("3334"));
            var RetrofitHelper = Java.use("com.motoband.core.http.RetrofitHelper");
            RetrofitHelper.getRequestBody(map);
        })
    }
    function main(){
        console.log("Main")
        hook_RequestBody_create(); 
    }
    setImmediate(main)
    
    image-20210728175304412

    以上完成绕过so层通过主动调用和hook的方式获取请求参数,接下来就是完成爬虫的具体逻辑。

    抓包

    通过python r0capture.py -U com.motoband -v -p moto.pcap抓包分析各个页面请求并使用python实现,headers可以通过请求头加引号.py自动生成

    选车列表

    headers = {
        'Source': 'source',
        'Date': 'Wed, 28 Jul 2021 10:42:37 GMT',
        'Authorization': 'hmac id="AKIDKpo6me25b14nzcNefQeoqR95syh2ayx97s0g", algorithm="hmac-sha1", headers="date source", signature="LueIYYQhihnHza8ZIzzH3X1J6xM="',
        'Content-Type': 'application/json; charset=utf-8',
        'Content-Length': '396',
        'Host': 'api.motuobang.com',
        'Connection': 'Keep-Alive',
        'Accept-Encoding': 'gzip',
        'User-Agent': 'okhttp/3.14.9'
    }
    param_str = '{"jpushregistrationid":"18071adc03d4364a59f","ctype":"2","citycode":"0512","requestid":"10120210728184237309B6FABE44946F25C3","brandid":0,"sign":"Un9ld6EYErQmE2ab0CgGP4pbqGKz8taTYlT2d4vgJlR1e6N3vp2Ld/YHpZVHLAYQgdYxmHDPDmdPiapY/Irewg==","type":0,"cversion":"4.8.0.2021070601","userid":"53AEB07289854E91A74DA4718D86617F","token":"6A057F7AB0654DEBA3A9BAFE51A17D62","lonlat":"[120.670592,31.295319]"}'
    
    data = requests.post('http://api.motuobang.com/release/car/brandinfo', data=param_str,
                         headers=headers).json()["data"]
    brandlist = json.loads(data)["brandlist"]
    

    品牌列表

    headers = {
        'Source': 'source',
        'Date': 'Wed, 28 Jul 2021 11:02:48 GMT',
        'Authorization': 'hmac id="AKIDKpo6me25b14nzcNefQeoqR95syh2ayx97s0g", algorithm="hmac-sha1", headers="date source", signature="xUe79aim7V1Nur4J8DfN9KSDU0Q="',
        'Content-Type': 'application/json; charset=utf-8',
        'Content-Length': '396',
        'Host': 'api.motuobang.com',
        'Connection': 'Keep-Alive',
        'Accept-Encoding': 'gzip',
        'User-Agent': 'okhttp/3.14.9'
    }
    param_str = '{"jpushregistrationid":"18071adc03d4364a59f","searchcar":"{\\"brandids\\":[28],\\"haveabs\\":0,\\"maxcc\\":0.0,\\"maxmaxpower\\":0.0,\\"maxprice\\":0,\\"maxsitheight\\":0,\\"maxxuhanglicheng\\":0,\\"maxzuigaochesu\\":0,\\"mincc\\":0.0,\\"minmaxpower\\":0.0,\\"minprice\\":0,\\"minsitheight\\":0,\\"minxuhanglicheng\\":0,\\"minzuigaochesu\\":0,\\"modelid\\":-1,\\"month\\":0,\\"pagenum\\":0,\\"pagesize\\":200,\\"searchtype\\":0,\\"source\\":0,\\"store\\":0,\\"year\\":0}","ctype":"2","citycode":"0512","requestid":"10120210728190247800B530F6E7211E0724","sign":"BeHwJ+uZ0BK7bR9z6Q4XifFqp0crBtwDouA3BxYYU7br2XQvwehJPrkfnn9MV/PezYqMawUZI6zEDiplwJ49ug==","cversion":"4.8.0.2021070601","userid":"53AEB07289854E91A74DA4718D86617F","token":"5100BF109300497C83A51614C58314FD","lonlat":"[120.67073,31.295348]"}'
    
    data = requests.post('http://api.motuobang.com/release/car/searchv2', data=param_str,
                         headers=headers).json()["data"]
    print(json.loads(data)["serieslist"])
    

    品牌详情

    headers = {
        'Source': 'source',
        'Date': 'Mon, 26 Jul 2021 05:47:06 GMT',
        'Authorization': 'hmac id="AKIDKpo6me25b14nzcNefQeoqR95syh2ayx97s0g", algorithm="hmac-sha1", headers="date source", signature="jmwgtLvjj06A/M/TNcCqL72GRsk="',
        'Content-Type': 'application/json; charset=utf-8 ',
        'Content-Length': '403',
        'Host': 'api.motuobang.com',
        'Connection': 'Keep-Alive',
        'Accept-Encoding': 'gzip',
        'User-Agent': 'okhttp/3.14.'
    }
    param_str = '{"jpushregistrationid":"1104a89792736fd015f","lonlat":"[120.670593,31.295318]","ctype":"2","sign":"SJxFIJSEi7BwlnPLC/6j3RfyxsR2EEEC2uWGpfC3/MQl/8gSCS5GcqSbre/S3Jrrws+/LYQzGE08T+Gv+tIIAg==","source":0,"token":"89DFF7721007455D806E282F8195B0EF","requestid":"10120210726134706717A11599A619EBCF39","citycode":"0512","cversion":"4.8.0.2021070601","userid":"53AEB07289854E91A74DA4718D86617F","modelid":"3387"}'
    
    data = requests.post('http://api.motuobang.com/release/car/seriesinfo', data=param_str,
                         headers=headers).json()["data"]
    print(json.loads(data)["seriesinfo"])
    

    frida rpc 数据传递

    hook RequestBody.create

    由于RequestBody.create(MediaType.parse(HttpConstants.MediaType_Json), JSON.toJSONString(map));,hook create即可拿到入参=请求头加密参数。

    function hook_body_create(){
        Java.perform(function(){
            Java.use("okhttp3.RequestBody").create.overload('okhttp3.MediaType', 'java.lang.String').implementation = function(mediaType,str){
                var result = this.create(mediaType,str)
                send(str)
                return result;
            }
        })
    }
    function main(){
        console.log("Main")
        hook_body_create(); 
    }
    setImmediate(main)
    

    主动调用searchv2

    查看选车列表时,搜索brandinfo

    @POST("car/brandinfo")
    Observable<ResponseBody> refreshBrandInfo(@Body RequestBody requestBody);
    

    查找用例com.motoband.core.manager.MotoBrandManager

    android hooking watch class com.motoband.core.manager.MotoBrandManager --dump-args --dump-backtrace --dump-return   将整个类hook,点击触发类实现
    android hooking watch class_method com.motoband.core.manager.MotoBrandManager.requestBrandDetail --dump-args --dump-backtrace --dump-return  hook触发的类方法并拿到参数为brandid
    
    image-20210728211005543

    查看品牌列表时,搜索searchv2

    @POST("car/searchv2")
    Observable<ResponseBody> searchNewMotoModelsV2(@Body RequestBody requestBody);
    
    image-20210729084834395

    查找用例时有多个方法中调用,不过只有两个类,接下来通过objection hook上这两个类中的所有方法,点击指定品牌,触发car/searchv2

    android hooking watch class com.motoband.core.manager.ChooseCarManager --dump-args --dump-backtrace --dump-return
    android hooking watch class_method com.motoband.core.manager.ChooseCarManager.brandSeries --dump-args --dump-backtrace --dump-return
    
    image-20210729085320595

    以上分析得知触发了com.motoband.core.manager.ChooseCarManager.brandSeries方法,传递第一个参数为brandid,结合jadx分析

    public Observable<CarFilterSearchModel> brandSeries(String str, boolean z) {
        HashMap hashMap = new HashMap();
        hashMap.put("searchcar", SearchMotoFilterModel.toBrandSeriesJson(Integer.parseInt(str), z));
        return RetrofitHelper.getObjectObservable(((ChooseCarService) RetrofitHelper.getRetrofit().create(ChooseCarService.class)).searchNewMotoModelsV2(RetrofitHelper.getRequestBody(hashMap)), CarFilterSearchModel.class).observeOn(AndroidSchedulers.mainThread());
    }
    

    拼接searchcar到map中,通过getRequestBody获取加密请求参数。接下来尝试hook SearchMotoFilterModel.toBrandSeriesJson 拿到入参,利用frida实现主动调用。

    function hook_searchv2(id){
        Java.perform(function(){
            var search_map = Java.use('java.util.HashMap').$new();
            var StringClass = Java.use("java.lang.String");
            var IntegerClass = Java.use("java.lang.Integer");
            var BooleanClass = Java.use("java.lang.Boolean");
            var SearchMotoFilterModel = Java.use('com.motoband.core.model.SearchMotoFilterModel').$new();
            // for brandinfo
            // search_map.put("type", IntegerClass.$new(1));
            // search_map.put("brandid", StringClass.$new(id));
            search_map.put("searchcar",SearchMotoFilterModel.toBrandSeriesJson(id,false));
            var RetrofitHelper = Java.use("com.motoband.core.http.RetrofitHelper");
            RetrofitHelper.getRequestBody(search_map);
        })
    }
    

    主动调用serials_info

    查看品牌详情时,搜索seriesinfo

    @POST("car/seriesinfo")
    Observable<ResponseBody> motoInfo(@Body RequestBody requestBody);
    

    查找用例

    public Observable<MotorbikeSeriesModel> requestMotorInfo(String str, int i) {
        HashMap hashMap = new HashMap();
        hashMap.put(IntentConstants.MODELID, str);
        hashMap.put("source", Integer.valueOf(i));
        return RetrofitHelper.getObjectObservable(((ChooseCarService) RetrofitHelper.getRetrofit().create(ChooseCarService.class)).motoInfo(RetrofitHelper.getRequestBody(hashMap)), MotorbikeSeriesModel.class).observeOn(AndroidSchedulers.mainThread()).doOnNext($$Lambda$ChooseCarManager$XcbjKQVeNSK4TPlk0mzi1vIv6Z0.INSTANCE);
    }
    

    hook实现

    function hook_seriesinfo(id){
        Java.perform(function(){
            var map = Java.use('java.util.HashMap').$new();
            var StringClass = Java.use("java.lang.String");
            map.put("modelid", StringClass.$new(id));
            var RetrofitHelper = Java.use("com.motoband.core.http.RetrofitHelper");
            RetrofitHelper.getRequestBody(map);
        })
    }
    

    rpc调用

    frida主动调用各个方法时,同时间hook RequestBody.create方法,拿到关键加密参数,rpc发送给python,完成爬虫数据拼装,实现数据抓取。

    js

    rpc.exports = {
        hookseriesinfo: hook_seriesinfo,
        hooksearchv2: hook_searchv2,
        hookbodybreate: hook_body_create
    }
    

    python

    
    device = frida.get_usb_device()
    # pid = device.spawn(["com.motoband"])
    # device.resume(pid)
    # time.sleep(10)
    session = device.attach("com.motoband")
    with open("motoband.js") as f:
        script = session.create_script(f.read())
    script.on("message", my_message_handler) 
    script.load()
    
    # request for brandinfo 
    headers = {
        'Source': 'source',
        'Date': 'Wed, 28 Jul 2021 10:42:37 GMT',
        'Authorization': 'hmac id="AKIDKpo6me25b14nzcNefQeoqR95syh2ayx97s0g", algorithm="hmac-sha1", headers="date source", signature="LueIYYQhihnHza8ZIzzH3X1J6xM="',
        'Content-Type': 'application/json;*/jg charset=utf-8',
        'Content-Length': '396',
        'Host': 'api.motuobang.com',
        'Connection': 'Keep-Alive',
        'Accept-Encoding': 'gzip',
        'User-Agent': 'okhttp/3.14.9'
    }
    param_str = '{"jpushregistrationid":"18071adc03d4364a59f","ctype":"2","citycode":"0512","requestid":"10120210728184237309B6FABE44946F25C3","brandid":0,"sign":"Un9ld6EYErQmE2ab0CgGP4pbqGKz8taTYlT2d4vgJlR1e6N3vp2Ld/YHpZVHLAYQgdYxmHDPDmdPiapY/Irewg==","type":0,"cversion":"4.8.0.2021070601","userid":"53AEB07289854E91A74DA4718D86617F","token":"6A057F7AB0654DEBA3A9BAFE51A17D62","lonlat":"[120.670592,31.295319]"}'
    data = requests.post('http://api.motuobang.com/release/car/brandinfo', data=param_str,headers=headers).json()["data"]
    brandlist = json.loads(data)["brandlist"]
    
    for brand in brandlist:
        brandname = brand["name"]
        brandid = str(brand["brandid"])
        # 1.创建文件夹
        # 2.request for searchv2
        script.exports.hooksearchv2(brandid)
        # print(name_model_dict)
        # 3.request for seriesinfo
        for (key,value) in name_model_dict.items():
            # print(key+":"+str(value))
            script.exports.hookseriesinfo(str(value))
        # input()    
    
    image-20210729111227782

    本文由博客群发一文多发等运营工具平台 OpenWrite 发布

    相关文章

      网友评论

          本文标题:摩托x的逆向分析

          本文链接:https://www.haomeiwen.com/subject/fpxtfrtx.html