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(这个贴子要好好研究)