sun博客

记录点滴!

java.lang.AbstractMethodError: com.github.unidbg.linux.file.PipedWriteFileIO
at com.github.unidbg.file.AbstractFileIO.dup2(AbstractFileIO.java:160)
at com.github.unidbg.linux.ARM32SyscallHandler.dup3(ARM32SyscallHandler.java:2103)
at com.github.unidbg.linux.ARM32SyscallHandler.hook(ARM32SyscallHandler.java:437)
at com.github.unidbg.arm.backend.UnicornBackend$6.hook(UnicornBackend.java:299)
at unicorn.Unicorn$NewHook.onInterrupt(Unicorn.java:128)
at unicorn.Unicorn.emu_start(Native Method)
at com.github.unidbg.arm.backend.UnicornBackend.emu_start(UnicornBackend.java:325)
at com.github.unidbg.AbstractEmulator.emulate(AbstractEmulator.java:370)
at com.github.unidbg.AbstractEmulator.eFunc(AbstractEmulator.java:446)
at com.github.unidbg.arm.AbstractARMEmulator.eFunc(AbstractARMEmulator.java:220)
at com.github.unidbg.Module.emulateFunction(Module.java:158)
at com.github.unidbg.linux.LinuxModule.callFunction(LinuxModule.java:232)

unidbg调用喜马拉雅9.2.40.3版本的apk时,里面的libnativelib.so时,在补全了proc\sys\kernel\random\boot_id文件后,出现此问题。

其原因在于调用系统函数 popen()时, 而unidbg没有实现导致的报错。

解决办法:创建MyARMSyscallHandler 类实现此功能后,AndroidEmulatorBuilder创建时override build

package com.utils;

import com.github.unidbg.Emulator;
import com.github.unidbg.arm.context.EditableArm32RegisterContext;
import com.github.unidbg.linux.file.ByteArrayFileIO;
import com.github.unidbg.linux.file.DumpFileIO;
import com.github.unidbg.memory.SvcMemory;
import com.sun.jna.Pointer;

import java.util.concurrent.ThreadLocalRandom;

public class MyARMSyscallHandler extends com.github.unidbg.linux.ARM32SyscallHandler {
    public MyARMSyscallHandler(SvcMemory svcMemory) {
        super(svcMemory);
    }
    @Override
    protected boolean handleUnknownSyscall(Emulator emulator, int NR) {
        switch (NR) {
            case 190:
                vfork(emulator);
                return true;
            case 359:
                pipe2(emulator);
                return true;
        }

        return super.handleUnknownSyscall(emulator, NR);
    }

    private void vfork(Emulator<?> emulator) {
        EditableArm32RegisterContext context = (EditableArm32RegisterContext) emulator.getContext();
        int childPid = emulator.getPid() + ThreadLocalRandom.current().nextInt(256);
        int r0 = 0;
        r0 = childPid;
        System.out.println("vfork pid=" + r0);
        context.setR0(r0);
    }

    protected int pipe2(Emulator emulator) {
        EditableArm32RegisterContext context = (EditableArm32RegisterContext) emulator.getContext();
        Pointer pipefd = context.getPointerArg(0);
        int flags = context.getIntArg(1);
        int write = getMinFd();
        this.fdMap.put(write, new DumpFileIO(write));
        int read = getMinFd();
        String stdout = "myid\n"; // getprop ro.build.id
        this.fdMap.put(read, new ByteArrayFileIO(0, "pipe2_read_side", stdout.getBytes()));
        pipefd.setInt(0, read);
        pipefd.setInt(4, write);
        System.out.println("pipe2 pipefd=" + pipefd + ", flags=0x" + flags + ", read=" + read + ", write=" + write + ", stdout=" + stdout);
        context.setR0(0);
        return 1;
    }
}

//目标加密文件
public static void init() {
        AndroidEmulatorBuilder builder = new AndroidEmulatorBuilder(false) {
            @Override
            public AndroidEmulator build() {
                return new AndroidARMEmulator(processName, rootDir, backendFactories) {
                    @Override
                    protected UnixSyscallHandler<AndroidFileIO> createSyscallHandler(SvcMemory svcMemory) {
                        return new MyARMSyscallHandler(svcMemory);
                    }
                };
            }
        };

        emulator = builder.addBackendFactory(new DynarmicFactory(true)).build();

        //AndroidEmulator  emulator = AndroidEmulatorBuilder.for32Bit().addBackendFactory(new Unicorn2Factory(true)).build();
        // emulator.getBackend().registerEmuCountHook(100000);
        // emulator.getSyscallHandler().setVerbose(true);
        //  emulator.getSyscallHandler().setEnableThreadDispatcher(true);


        Memory memory = emulator.getMemory();
        memory.setLibraryResolver(new AndroidResolver(23));
        //memory.setCallInitFunction(true);
        Module module = emulator.loadLibrary(new File("d:\\libxmnativelib.so"));

        vm = emulator.createDalvikVM();
        // vm.setVerbose(true);
        //vm.callJNI_OnLoad(emulator,module);
        XuidSign sign = new XuidSign();
        vm.setJni(sign);


        System.out.println("xuid Sign初始化完成");
    }

之后调用成功输出结果:

注意此so有init操作,单独调用encode方法会报错,只有在init操作执行后再次调用encode方法才可以。

另外正常情况下,unidbg调用函数报错时不会有明细说明,这时候要把 日志全开 ,可以看到

  • JNI 调用
  • 系统调用
  • 标准库函数调用
  • 汇编trace

以下代码全开:

emulator.getBackend().registerEmuCountHook(100000);
emulator.getSyscallHandler().setVerbose(true);//设置是否打印系统调用细节
emulator.getSyscallHandler().setEnableThreadDispatcher(true);//启用线程调度程序,如[main]W/libc: pthread_create failed: clone failed: Out of memory出错

memory.setCallInitFunction(true);
vm.setVerbose(true);// 设置是否打印Jni调用细节

参考文档:

https://www.jianshu.com/p/9b53af35d5f7

https://blog.csdn.net/qq_38851536/article/details/118073818(这个贴子要好好研究)

https://github.com/zhkl0228/unidbg/issues/342

发表评论

邮箱地址不会被公开。 必填项已用*标注