zhkl0228 / unidbg

Allows you to emulate an Android native library, and an experimental iOS emulation
Apache License 2.0
3.86k stars 967 forks source link

open文件夹时 报错 #39

Closed 18712886438 closed 5 years ago

18712886438 commented 5 years ago

附上示例

public class DemoTest extends AbstractJni implements IOResolver {

    private static LibraryResolver createLibraryResolver() {
        return new AndroidResolver(23);
    }

    private static ARMEmulator createARMEmulator() {
        return new AndroidARMEmulator("zzz.me.unidbg_d");
    }

    private final ARMEmulator emulator;
    private final VM vm;
    private final Module module;

    private final DvmClass MainActivity;

    private DemoTest() throws IOException {
        emulator = createARMEmulator();
        emulator.getSyscallHandler().addIOResolver(this);
        final Memory memory = emulator.getMemory();
        memory.setLibraryResolver(createLibraryResolver());
        memory.setCallInitFunction();

        vm = emulator.createDalvikVM(new File("src/test/resources/app/app-debug.apk"));
        DalvikModule dm = vm.loadLibrary("native-lib", false);
        dm.callJNI_OnLoad(emulator);
        module = dm.getModule();

        MainActivity = vm.resolveClass("zzz.me.unidbg_d.MainActivity".replace(".", "/"));
    }

    public static void main(String[] args) throws Exception {
        DemoTest test = new DemoTest();

        test.test();

        test.destroy();
    }

    private void destroy() throws IOException {
        emulator.close();
        System.out.println("destroy module=" + module);
    }

    private void test() {
        vm.setJni(this);
        IWhale whale = Whale.getInstance(emulator);

        final Symbol compress;
        try {
            compress = emulator.getMemory().findModule("libz.so").findSymbolByName("compress");
            if (compress != null) {
                whale.WInlineHookFunction(compress, new ReplaceCallback() {
                    @Override
                    public HookStatus onCall(Emulator emulator, long originFunction) {

                        RegisterContext context = emulator.getContext();

                        Pointer dest = context.getPointerArg(0);
                        Pointer destLen = context.getPointerArg(1);
                        Pointer src = context.getPointerArg(2);
                        long srcLen = context.getLongArg(3);

                        String src_Compress = new String(src.getByteArray(0, (int) srcLen));

                        System.out.println("Let's compress: " + src_Compress);
                        return HookStatus.RET(emulator, originFunction);
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        Number ret = MainActivity.callStaticJniMethod(emulator, "stringFromJNI()Ljava/lang/String;");
        long hash = ret.intValue() & 0xffffffffL;
        StringObject obj = vm.getObject(hash);
        vm.deleteLocalRefs();
        System.err.println(obj.getValue());
    }

    @Override
    public FileIO resolve(File workDir, String pathname, int oflags) {
        return null;
    }
}

cpp代码:

#include <jni.h>
#include <string>
#include <zlib.h>
#include <fcntl.h>
#include <cstring>

#ifndef NELEM
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
#endif

const char *className = "zzz/me/unidbg_d/MainActivity";     // the jni class

jstring stringFromJNI(JNIEnv *env, jobject /* this */) {

    Byte compr[200];
    uLongf destLen = sizeof(compr) / sizeof(compr[0]);
    const char* hello = "12345678901234567890123456789012345678901234567890";
    uLong len = strlen(hello) + 1;

    if(compress(compr, &destLen, (const Bytef*)hello, len) == Z_OK) {
        int fd = open("/proc", O_RDONLY);
        if(fd == -1) {
            printf("打开失败\n");
        }
        close(fd);
    }
    printf("打开Proc\n");
    return env->NewStringUTF(hello);
}

/**
 * name:      stringFromJni
 * signature: ()Ljava/lang/String;
 * fnPtr:     stringFromJni
 *
 * jni.h struct JNINativeMethod
 */
static const JNINativeMethod sMethods[] = {                                  // jni methods table
        {"stringFromJNI", "()Ljava/lang/String;", (void *) stringFromJNI},
};

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
    JNIEnv *env;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_EVERSION;
    } //if

    jclass clazz = env->FindClass(className);              // find the jni class
    if (clazz == NULL) {
        return JNI_ERR;
    }

    if (env->RegisterNatives(clazz, sMethods, NELEM(sMethods)) < 0) {      //register jni methods
        return JNI_ERR;
    }

    return JNI_VERSION_1_6;
}

报错日志:

java.lang.IllegalStateException: java.io.FileNotFoundException: /tmp/proc (是一个目录)
    at cn.banny.unidbg.linux.android.AndroidResolver.resolve(AndroidResolver.java:143)
    at cn.banny.unidbg.unix.UnixSyscallHandler.resolve(UnixSyscallHandler.java:55)
    at cn.banny.unidbg.unix.UnixSyscallHandler.open(UnixSyscallHandler.java:146)
    at cn.banny.unidbg.linux.ARMSyscallHandler.openat(ARMSyscallHandler.java:1542)
    at cn.banny.unidbg.linux.ARMSyscallHandler.hook(ARMSyscallHandler.java:340)
    at unicorn.Unicorn.invokeInterruptCallbacks(Unicorn.java:123)
    at unicorn.Unicorn.emu_start(Native Method)
    at cn.banny.unidbg.AbstractEmulator.emulate(AbstractEmulator.java:267)
    at cn.banny.unidbg.AbstractEmulator.eFunc(AbstractEmulator.java:360)
    at cn.banny.unidbg.arm.AbstractARMEmulator.eFunc(AbstractARMEmulator.java:201)
    at cn.banny.unidbg.linux.LinuxModule.emulateFunction(LinuxModule.java:154)
    at cn.banny.unidbg.linux.android.dvm.DvmClass.callStaticJniMethod(DvmClass.java:140)
    at zzz.me.unidbg_d.DemoTest.test(DemoTest.java:102)
    at zzz.me.unidbg_d.DemoTest.main(DemoTest.java:61)
Caused by: java.io.FileNotFoundException: /tmp/proc (是一个目录)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:270)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:162)
    at cn.banny.unidbg.linux.android.AndroidResolver.resolve(AndroidResolver.java:139)
    ... 13 more

附上app:

app.zip

18712886438 commented 5 years ago

同时想请教一下这块c的代码, hook compress的时候,想改变第三四个参数的值,然后调用原方法需要怎么做呢?

zhkl0228 commented 5 years ago


import cn.banny.auxiliary.Inspector;
import cn.banny.unidbg.Emulator;
import cn.banny.unidbg.LibraryResolver;
import cn.banny.unidbg.Module;
import cn.banny.unidbg.Symbol;
import cn.banny.unidbg.arm.ARMEmulator;
import cn.banny.unidbg.arm.HookStatus;
import cn.banny.unidbg.arm.context.EditableArm32RegisterContext;
import cn.banny.unidbg.file.FileIO;
import cn.banny.unidbg.file.IOResolver;
import cn.banny.unidbg.hook.ReplaceCallback;
import cn.banny.unidbg.hook.whale.IWhale;
import cn.banny.unidbg.hook.whale.Whale;
import cn.banny.unidbg.linux.android.AndroidARMEmulator;
import cn.banny.unidbg.linux.android.AndroidResolver;
import cn.banny.unidbg.linux.android.dvm.*;
import cn.banny.unidbg.memory.Memory;
import cn.banny.unidbg.pointer.UnicornPointer;
import com.sun.jna.Pointer;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;

public class DemoTest extends AbstractJni implements IOResolver {

    private static LibraryResolver createLibraryResolver() {
        return new AndroidResolver(23);
    }

    private static ARMEmulator createARMEmulator() {
        return new AndroidARMEmulator("zzz.me.unidbg_d");
    }

    private final ARMEmulator emulator;
    private final VM vm;
    private final Module module;

    private final DvmClass MainActivity;

    private DemoTest() throws IOException {
        emulator = createARMEmulator();
        emulator.getSyscallHandler().addIOResolver(this);
        final Memory memory = emulator.getMemory();
        memory.setLibraryResolver(createLibraryResolver());
        memory.setCallInitFunction();

        vm = emulator.createDalvikVM(new File("src/test/resources/app/app-debug.apk"));
        DalvikModule dm = vm.loadLibrary("native-lib", false);
        dm.callJNI_OnLoad(emulator);
        module = dm.getModule();

        MainActivity = vm.resolveClass("zzz.me.unidbg_d.MainActivity".replace(".", "/"));
    }

    public static void main(String[] args) throws Exception {
        DemoTest test = new DemoTest();

        test.test();

        test.destroy();
    }

    private void destroy() throws IOException {
        emulator.close();
        System.out.println("destroy module=" + module);
    }

    private void test() {
        vm.setJni(this);
        IWhale whale = Whale.getInstance(emulator);

        final Symbol compress;
        try {
            compress = emulator.getMemory().findModule("libz.so").findSymbolByName("compress");
            if (compress != null) {
                whale.WInlineHookFunction(compress, new ReplaceCallback() {
                    @Override
                    public HookStatus onCall(Emulator emulator, long originFunction) {
                        EditableArm32RegisterContext context = emulator.getContext();

                        byte[] fake = new byte[16];
                        ThreadLocalRandom.current().nextBytes(fake);
                        UnicornPointer pointer = emulator.getMemory().malloc(fake.length, true).getPointer();
                        pointer.write(0, fake, 0, fake.length);
                        context.setR2((int) pointer.toUIntPeer());
                        context.setR3(fake.length);

                        Pointer dest = context.getPointerArg(0);
                        Pointer destLen = context.getPointerArg(1);
                        Pointer src = context.getPointerArg(2);
                        long srcLen = context.getLongArg(3);

                        Inspector.inspect(src.getByteArray(0, (int) srcLen), "Let's compress");

                        return HookStatus.RET(emulator, originFunction);
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        Number ret = MainActivity.callStaticJniMethod(emulator, "stringFromJNI()Ljava/lang/String;");
        long hash = ret.intValue() & 0xffffffffL;
        StringObject obj = vm.getObject(hash);
        vm.deleteLocalRefs();
        System.err.println(obj.getValue());
    }

    @Override
    public FileIO resolve(File workDir, String pathname, int oflags) {
        return null;
    }
}
zhkl0228 commented 5 years ago

你再试下,unidbg的代码也有小更新

18712886438 commented 5 years ago

你再试下,unidbg的代码也有小更新

感谢大神,没问题了

zhkl0228 commented 5 years ago

以上这段malloc会有内存泄露

zhkl0228 commented 5 years ago

hook compress的时候,想改变第三四个参数的值,如果要改变的值比原来内存小的话,可以直接覆盖原来的数据,再改变第四个参数

18712886438 commented 5 years ago

hook compress的时候,想改变第三四个参数的值,如果要改变的值比原来内存小的话,可以直接覆盖原来的数据,再改变第四个参数

收到, 我这边可以改变之前值的长度, 增加到大于要修改的值,就可以尽量避免了吧