美文网首页
汽车之家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