美文网首页
汽车之家apisign unidbg实现

汽车之家apisign unidbg实现

作者: ever_hu | 来源:发表于2022-01-10 12:49 被阅读0次

    汽车之家apisign unidbg实现

    Java分析

    抓包

    image-20220109114223655 image-20220109114319108

    找到一个疑似的,进去看看

    image-20220109114426827

    可惜的是,无法查看源码,不过addHeader极有可能就是加密的地方,hook看看。

    function printReq(req, tag) {
        console.log("=========== ", tag, " ============");
        console.log("url:", req.url.value);
        var vmap = req.headers.value;
        var it = vmap.keySet().iterator();
        while (it.hasNext()) {
            var key = it.next().toString();
            console.log(key + ": " + vmap.get(key).toString());
        }
    }
    
    function hook_util(){
        var util = Java.use("com.autohome.mainlib.common.util.ApisignUtils");
        util.addHeader.implementation = function(str, req) {
            console.log(str);
            printReq(req, "in");
            util.addHeader(str, req);
            printReq(req, "out");
        }
    }
    
    function searchClassLoader(className) {
        Java.enumerateClassLoaders({
            onMatch: function (loader) {
                try {
                    if (loader.findClass(className)) {
                        Java.classFactory.loader = loader;
                        console.log("find", loader);
                    }
                } catch (error) {
                }
            }, 
            onComplete: function () {
                console.log("finish search");
            }
        })
    }
    
    function main() {
        Java.perform(function() {
            searchClassLoader("com.autohome.mainlib.common.util.ApisignUtils");
            hook_util();
        }) 
    }
    
    image-20220109115555275

    可以看到,apisign就是在这里被加上去的。

    之后该怎么办,我的选择是hook一下NewStringUTF,看看sign是不是在so里面生成的。

    function hook_libart() {
        var symbols = Module.enumerateSymbolsSync("libart.so");
        var addrNewStringUTF = null;
        var so_name = "lib";
    
        for (var i = 0; i < symbols.length; i++) {
            var symbol = symbols[i];
            if (symbol.name.indexOf("art") >= 0 &&
                symbol.name.indexOf("JNI") >= 0 &&
                symbol.name.indexOf("CheckJNI") < 0 &&
                symbol.name.indexOf("_ZN3art3JNI") >= 0
            ) {
                if (symbol.name.indexOf("NewStringUTF") >= 0) {
                    addrNewStringUTF = symbol.address;
                    console.log("NewStringUTF is at ", symbol.address, symbol.name);
                }
            }
        }
    
        if (addrNewStringUTF != null) {
            Interceptor.attach(addrNewStringUTF, {
                onEnter: function (args) {
                    if (args[1] != null) {
                        var module = Process.findModuleByAddress(this.returnAddress);
                        if (module != null && module.name.indexOf(so_name) == 0) {
                            var string = Memory.readCString(args[1]);
                            if (string && string.length == 32) {
                                console.log("====================");
                                console.log("[NewStringUTF] bytes:" + string, DebugSymbol.fromAddress(this.returnAddress));
                                console.log(Thread.backtrace(this.context, Backtracer.FUZZY).map(DebugSymbol.fromAddress).join("\n"));
                                var stack = Java.use('java.lang.Thread').$new().currentThread().getStackTrace();
                                console.log(stack.join("\n"));
                            }
                        }
    
                    }
                },
                onLeave: function (retval) { }
            });
        }
    }
    
    image-20220109144853574

    可以清楚看到Java层最后调用的地方,也可以看到对应的so是libblackBox.so

    看看com.autohome.mainlib.common.util.BlackBox.getInterfaceSign

    image-20220109145148328

    hook一下

    function hook_box() {
        var box = Java.use("com.autohome.mainlib.common.util.BlackBox");
        box.getInterfaceSign.overload('java.util.List').implementation = function(list) {
            console.log("box-arg:", list);
            console.log("list.size:", list.size());
            for (var i=0; i<list.size(); i++) {
                console.log("\t", i, "=> ", list.get(i));
            }
            var ret = this.getInterfaceSign(list);
            console.log("ret:", ret);
            return ret;
        }
    }
    
    image-20220109152421930

    unidbg实现

    基础代码

    package com.autohome;
    
    import com.github.unidbg.AndroidEmulator;
    import com.github.unidbg.Module;
    import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
    import com.github.unidbg.linux.android.AndroidResolver;
    import com.github.unidbg.linux.android.dvm.*;
    import com.github.unidbg.memory.Memory;
    import org.apache.http.NameValuePair;
    import org.apache.http.message.BasicNameValuePair;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    
    public class AutoHome extends AbstractJni{
        private final AndroidEmulator emulator;
        private final VM vm;
        private final Module module;
    
        public static String pkgName = "com.cubic.autohome";
        public static String apkPath = "unidbg-android/src/test/java/com/autohome/autohome1197.apk";
        public static String soPath = "unidbg-android/src/test/java/com/autohome/libblackBox.so";
    
        public AutoHome() {
            emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
            Memory memory = emulator.getMemory();
            memory.setLibraryResolver(new AndroidResolver(23));
            vm = emulator.createDalvikVM(new File(apkPath));
            vm.setJni(this);
            vm.setVerbose(true);
            DalvikModule dm = vm.loadLibrary(new File(soPath), false);
            module = dm.getModule();
            dm.callJNI_OnLoad(emulator);
        }
    
        public void call_sign() {
            List<Object> list = new ArrayList<>(10);
            list.add(vm.getJNIEnv());
            list.add(0);
    
            List<NameValuePair> pairs = new ArrayList<>(10);
            pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
            list.add(vm.addLocalObject(vm.resolveClass("java/util/List").newObject(pairs)));
            // 1C4E5C182F7FFF5C350E1BB1B4C2B50C
            module.callFunction(emulator, 0x2d91d, list.toArray());
        }
    
        public static void main(String[] args) {
            AutoHome test = new AutoHome();
            test.call_sign();
        }
    }
    

    又到了喜闻乐见的报错与补环境环节。

    image-20220109154357531

    直接出结果,可惜是个空的。。

    ida跳转到0x2d91d看看。

    image-20220109154912799

    似乎没有正确识别。按D解析为数据

    image-20220109155128509

    选取0x2d91c0x2d937,按C转换为代码。

    image-20220109155259324

    选取0x2d91c0x2d937,按P转换为函数。

    image-20220109155329196

    F5查看伪代码

    image-20220109155358867

    看看sub_2D8C0

    image-20220109155426627

    可以看到a1, a2, a3都有检查,我们的a2只是传了个0进去,所以要改改,传入真的jobject

    public void call_sign() {
        List<Object> list = new ArrayList<>(10);
        list.add(vm.getJNIEnv());
        // list.add(0);
        list.add(vm.addLocalObject(vm.resolveClass("com/autohome/mainlib/common/util/BlackBox").newObject(null)));
    
        List<NameValuePair> pairs = new ArrayList<>(10);
        pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
        list.add(vm.addLocalObject(vm.resolveClass("java/util/List").newObject(pairs)));
        // 1C4E5C182F7FFF5C350E1BB1B4C2B50C
        module.callFunction(emulator, 0x2d91d, list.toArray());
    }
    

    也可以通过另外一种方式来调用函数

    public void call_sign2() {
        DvmClass clz = vm.resolveClass("com/autohome/mainlib/common/util/BlackBox");
        String method = "getInterfaceSign(Ljava/util/List;)Ljava/lang/String;";
    
        List<NameValuePair> pairs = new ArrayList<>(10);
        pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
        // 1C4E5C182F7FFF5C350E1BB1B4C2B50C
        clz.callStaticJniMethodObject(emulator, method, vm.resolveClass("java/util/List").newObject(pairs));
    }
    

    再次运行

    image-20220109155819650

    好像需要读文件,然后报错了,我们还是先补函数。

    @Override
    public void callVoidMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
        switch (signature) {
            case "com/autohome/mainlib/common/util/BlackBox->reportNativeErrorCode(ILjava/lang/String;)V": {
    
            }
        }
    }
    
    image-20220109160003908

    补了之后,好像继续执行下去了,这样看来好像不用补文件。看看现在的报错,看看AbstractJni.java:364

    image-20220109160152571

    看来需要自己写代码把org.apache.http.message.BasicNameValuePair转为com.github.unidbg.linux.android.dvm.DvmObject

    @Override
    public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
        switch (signature) {
            case "java/util/List->get(I)Ljava/lang/Object;": {
                List<?> list = (List<?>) dvmObject.getValue();
                Object obj = list.get(vaList.getIntArg(0));
                if (obj instanceof BasicNameValuePair) {
                    return vm.resolveClass("org/apache/http/message/BasicNameValuePair").newObject(obj);
                }
            }
        }
        return super.callObjectMethodV(vm, dvmObject, signature, vaList);
    }
    
    image-20220109160430819
    case "org/apache/http/message/BasicNameValuePair->getName()Ljava/lang/String;": {
        BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
        return new StringObject(vm, pair.getName());
    }
    
    image-20220109160509515
    case "org/apache/http/message/BasicNameValuePair->getValue()Ljava/lang/String;": {
        BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
        return new StringObject(vm, pair.getValue());
    }
    
    image-20220109160556803

    出结果了。

    完整代码

    package com.autohome;
    
    import com.github.unidbg.AndroidEmulator;
    import com.github.unidbg.Module;
    import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
    import com.github.unidbg.linux.android.AndroidResolver;
    import com.github.unidbg.linux.android.dvm.*;
    import com.github.unidbg.memory.Memory;
    import org.apache.http.NameValuePair;
    import org.apache.http.message.BasicNameValuePair;
    
    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    
    public class AutoHome extends AbstractJni{
        private final AndroidEmulator emulator;
        private final VM vm;
        private final Module module;
    
        public static String pkgName = "com.cubic.autohome";
        public static String apkPath = "unidbg-android/src/test/java/com/autohome/autohome1197.apk";
        public static String soPath = "unidbg-android/src/test/java/com/autohome/libblackBox.so";
    
        public AutoHome() {
            emulator = AndroidEmulatorBuilder.for32Bit().setProcessName(pkgName).build();
            Memory memory = emulator.getMemory();
            memory.setLibraryResolver(new AndroidResolver(23));
            vm = emulator.createDalvikVM(new File(apkPath));
            vm.setJni(this);
            vm.setVerbose(true);
            DalvikModule dm = vm.loadLibrary(new File(soPath), false);
            module = dm.getModule();
            dm.callJNI_OnLoad(emulator);
        }
    
        @Override
        public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
            switch (signature) {
                case "java/util/List->get(I)Ljava/lang/Object;": {
                    List<?> list = (List<?>) dvmObject.getValue();
                    Object obj = list.get(vaList.getIntArg(0));
                    if (obj instanceof BasicNameValuePair) {
                        return vm.resolveClass("org/apache/http/message/BasicNameValuePair").newObject(obj);
                    }
                }
                case "org/apache/http/message/BasicNameValuePair->getName()Ljava/lang/String;": {
                    BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
                    return new StringObject(vm, pair.getName());
                }
                case "org/apache/http/message/BasicNameValuePair->getValue()Ljava/lang/String;": {
                    BasicNameValuePair pair = (BasicNameValuePair) dvmObject.getValue();
                    return new StringObject(vm, pair.getValue());
                }
            }
            return super.callObjectMethodV(vm, dvmObject, signature, vaList);
        }
    
        @Override
        public void callVoidMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
            switch (signature) {
                case "com/autohome/mainlib/common/util/BlackBox->reportNativeErrorCode(ILjava/lang/String;)V": {
    
                }
            }
        }
    
        public void call_sign() {
            List<Object> list = new ArrayList<>(10);
            list.add(vm.getJNIEnv());
    //        list.add(0);
            list.add(vm.addLocalObject(vm.resolveClass("com/autohome/mainlib/common/util/BlackBox").newObject(null)));
    
            List<NameValuePair> pairs = new ArrayList<>(10);
            pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
            list.add(vm.addLocalObject(vm.resolveClass("java/util/List").newObject(pairs)));
            // 1C4E5C182F7FFF5C350E1BB1B4C2B50C
            module.callFunction(emulator, 0x2d91d, list.toArray());
        }
    
        public void call_sign2() {
            DvmClass clz = vm.resolveClass("com/autohome/mainlib/common/util/BlackBox");
            String method = "getInterfaceSign(Ljava/util/List;)Ljava/lang/String;";
    
            List<NameValuePair> pairs = new ArrayList<>(10);
            pairs.add(new BasicNameValuePair("apisign", "2|f17a9663_acd3_42e8_93ef_f93c5fdbcf50|autohomebrush|1641713028"));
            // 1C4E5C182F7FFF5C350E1BB1B4C2B50C
            clz.callStaticJniMethodObject(emulator, method, vm.resolveClass("java/util/List").newObject(pairs));
        }
    
        public static void main(String[] args) {
            AutoHome test = new AutoHome();
            test.call_sign();
    //        test.call_sign2();
        }
    }
    

    相关文章

      网友评论

          本文标题:汽车之家apisign unidbg实现

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