unidbg icon indicating copy to clipboard operation
unidbg copied to clipboard

这种情况怎么解决Write to write-protected memory (UC_ERR_WRITE_PROT)

Open mr-linge opened this issue 1 year ago • 0 comments

package com.com.qm;

import com.github.unidbg.AndroidEmulator; import com.github.unidbg.Emulator; import com.github.unidbg.Module; import com.github.unidbg.ModuleListener; import com.github.unidbg.arm.HookStatus; import com.github.unidbg.arm.backend.Unicorn2Factory;

import com.github.unidbg.arm.context.Arm32RegisterContext; import com.github.unidbg.arm.context.EditableArm32RegisterContext; import com.github.unidbg.arm.context.RegisterContext; import com.github.unidbg.debugger.BreakPointCallback; import com.github.unidbg.debugger.Debugger; import com.github.unidbg.hook.HookContext; import com.github.unidbg.hook.ReplaceCallback; import com.github.unidbg.hook.hookzz.HookEntryInfo; import com.github.unidbg.hook.hookzz.HookZz; import com.github.unidbg.hook.hookzz.IHookZz; import com.github.unidbg.hook.hookzz.InstrumentCallback; import com.github.unidbg.linux.AndroidElfLoader; 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.linux.android.dvm.api.ClassLoader; import com.github.unidbg.linux.android.dvm.api.SystemService; import com.github.unidbg.linux.android.dvm.array.ByteArray; import com.github.unidbg.linux.android.dvm.jni.ProxyClassFactory; import com.github.unidbg.memory.Memory; import com.github.unidbg.memory.SvcMemory; import com.github.unidbg.pointer.UnidbgPointer; import com.github.unidbg.utils.Inspector; import com.github.unidbg.virtualmodule.android.AndroidModule; import com.github.unidbg.virtualmodule.android.JniGraphics; import com.github.unidbg.virtualmodule.android.MediaNdkModule; import com.sun.jna.Pointer; import com.weibo.sign.weibo; import keystone.Keystone; import keystone.KeystoneArchitecture; import keystone.KeystoneEncoded; import keystone.KeystoneMode; import org.apache.log4j.Level; import org.apache.log4j.Logger; import unicorn.Arm64Const; import unicorn.ArmConst; import unicorn.Unicorn;

import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List;

public class qmSign extends AbstractJni implements ModuleListener {

private final AndroidEmulator emulator;
private final DvmClass Qmsign;
private final VM vm;
private final Module module;
private HookZz hook;


public qmSign(){
    emulator = AndroidEmulatorBuilder
            .for32Bit()
            .setRootDir(new File("target/rootfs"))
            .addBackendFactory(new Unicorn2Factory(true))
            .setProcessName("com.kmxs.reader")
            .build();
    Memory memory = emulator.getMemory();
    memory.setLibraryResolver(new AndroidResolver(23));
    vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/qm/qm7_8_20.apk"));
    vm.setJni(this);
    vm.setVerbose(true);
    // 使用 libandroid.so 的虚拟模块
    new AndroidModule(emulator, vm).register(memory);;
    // 使用 libjnigraphics.so 的虚拟模块

// new JniGraphics(emulator, vm).register(memory); // 使用 libmediaNdkModule.so 的虚拟模块 // new MediaNdkModule(emulator, vm).register(memory); // add emulator.getSyscallHandler().setVerbose(true); emulator.getSyscallHandler().setEnableThreadDispatcher(true); //最好调整一下log级别 // DalvikModule dalvikModule = vm.loadLibrary("libcommon-encryption", false); DalvikModule dalvikModule = vm.loadLibrary(new File("unidbg-android/src/test/resources/qm/libcommon-encryption.so"), true); module = dalvikModule.getModule(); // System.out.println("module: " + module.base); dalvikModule.callJNI_OnLoad(emulator); Qmsign = vm.resolveClass("com.km.encryption.api.Security"); } // // 0x101013a-0x2a0 // 0xa8f90108-0x68f7aae2 static { Logger.getLogger(AndroidElfLoader.class).setLevel(Level.INFO); }

// @Override // public FileResult<AndroidFileIO> resolve(Emulator<AndroidFileIO> emulator, String pathname, int oflags) { // if ("/dev/urandom".equals(pathname)) { // return FileResult.<AndroidFileIO>success(new RandomFileIO(emulator, pathname) { // @Override // protected void randBytes(byte[] buf) { // ThreadLocalRandom.current().nextBytes(buf); // } // }); // } // return null; // }

// public YiDianZXV2() { // emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.xingin.xhs").build(); // final Memory memory = emulator.getMemory(); // memory.setLibraryResolver(new AndroidResolver(23)); // emulator.getSyscallHandler().addIOResolver(this); // // vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/app/Yidianzixun.apk")); // vm.setVerbose(true); // vm.setJni(this); // DalvikModule dm = vm.loadLibrary("util", false); // dm.callJNI_OnLoad(emulator); // }

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





@Override
public void onLoaded(Emulator<?> emulator, Module module) {
    // 提前加载Hook框架

// if(module.name.equals("libc.so")){ // hook = HookZz.getInstance(emulator); // } // System.out.println("********************** logs ****************************"); // // 在目标函数中Hook // if(module.name.equals("libcommon-encryption.so")){ // hook.instrument(module.base + 0x2a0, new InstrumentCallback<RegisterContext>() { // @Override // public void dbiCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) { // System.out.println(ctx.getIntArg(0)); // } // }); // } }

public static void main(String[] args) throws IOException{
    // LDR             R2, =(_ZTVN12_GLOBAL__N_116itanium_demangle9ThrowExprE - 0x15626)
    // mem_read address=0x1561f, size=112
    Logger.getLogger("com.github.unidbg.linux.ARM32SyscallHandler").setLevel(Level.DEBUG);
    Logger.getLogger("com.github.unidbg.unix.UnixSyscallHandler").setLevel(Level.DEBUG);
    Logger.getLogger("com.github.unidbg.AbstractEmulator").setLevel(Level.DEBUG);
    Logger.getLogger("com.github.unidbg.linux.android.dvm.DalvikVM").setLevel(Level.DEBUG);
    Logger.getLogger("com.github.unidbg.linux.android.dvm.BaseVM").setLevel(Level.DEBUG);
    Logger.getLogger("com.github.unidbg.linux.android.dvm").setLevel(Level.DEBUG);
    long start = System.currentTimeMillis();
    qmSign qm = new qmSign();
    System.out.println("load the vm "+( System.currentTimeMillis() - start )+ "ms");

// qm.debugger(); // qm.patch2(); // qm.hook(); qm.CallnativeInit(); qm.destroy(); }

public void CallnativeInit(){
    emulator.traceCode(module.base + 0x2a0, 0xffff0000);
    List<Object> args = new ArrayList<>(10);
    args.add(vm.getJNIEnv());
    args.add(0);
    byte[] input = "book_privacy=1new_user=1page_no=2read_preference=0uid=58CB52512BA1".getBytes(StandardCharsets.UTF_8);
    args.add(vm.addLocalObject(new ByteArray(vm,input)));
    Number number = module.callFunction(emulator, 0x15620+1 , args.toArray());
    System.out.println((vm.getObject(number.intValue()).getValue().toString()));;
}

public void hook(){
    //unidbg集成了HookZz框架
    HookZz hook = HookZz.getInstance(emulator);

    //直接hook add函数的地址,比通过符号hook更具有“普适性”
    hook.replace(module.base + 0x15625+1, new ReplaceCallback() {
        @Override
        public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
            //R2和R3才是参数,R0是env,R1是object
            System.out.println(String.format("R2: %d, R3: %d",context.getIntArg(2),context.getIntArg(3)));
            //把第二个参数R3改成5

// emulator.getBackend().reg_write(ArmConst.UC_ARM_REG_R2,16843068); // // 获取内存操作接口 // // // 将R0寄存器的值设置为16843068 (0x1000004) //// int newValue = 16843068; //// emulator.getUnicorn().reg_write(ArmConst.UC_ARM_REG_R0, newValue); // // // 读取R0寄存器的新值 // int r0Value = emulator.getBackend().reg_read(ArmConst.UC_ARM_REG_R2).intValue(); // System.out.println("R0寄存器的新值:" + r0Value);

            return super.onCall(emulator, context, originFunction);
        }

        @Override
        public void postCall(Emulator<?> emulator, HookContext context) {

// emulator.getBackend().reg_write(Unicorn.UC_ARM_REG_R0,10); //返回值放R0,这里直接修改返回值 super.postCall(emulator, context); } }, true);

// hook.replace(module.base + 0x15625+1, new ReplaceCallback() { // @Override // public HookStatus onCall(Emulator> emulator, HookContext context, long originFunction) { // //R2和R3才是参数,R0是env,R1是object // System.out.println(String.format("R2: %d, R3: %d",context.getIntArg(2),context.getIntArg(3))); // //把第二个参数R3改成5 // emulator.getBackend().reg_write(Unicorn.UC_ARM_REG_R2,16843068); // return super.onCall(emulator, context, originFunction); // } // // @Override // public void postCall(Emulator> emulator, HookContext context) { //// emulator.getBackend().reg_write(Unicorn.UC_ARM_REG_R0,10); // //返回值放R0,这里直接修改返回值 // super.postCall(emulator, context); // } // }, true);

}

// public void qmhook(){ // IHookZz hookZz = HookZz.getInstance(emulator); // 加载HookZz,支持inline hook,文档看https://github.com/jmpews/HookZz // // 2. enable hook // hookZz.enable_arm_arm64_b_branch(); // 测试enable_arm_arm64_b_branch,可有可无 //// index = 0; // hookZz.replace(module.findSymbolByName("lrand48"), new ReplaceCallback() { // @Override // public void postCall(Emulator<?> emulator, HookContext context) { // // ((EditableArm32RegisterContext)context).setR0(0x12345678); // // int ptrace_args0 = context.getIntArg(0); // System.out.println("lrand48=" + ptrace_args0); // // } // },true); // }

public void patch2() {
    UnidbgPointer pointer = UnidbgPointer.pointer(emulator,module.base + 0x15627);

// Keystone keystone = new Keystone(KeystoneArchitecture.Arm64, KeystoneMode.LittleEndian); // String s = "MOV r2,ds[r0]"; // byte[] machineCode = keystone.assemble(s).getMachineCode(); // // System.out.println(Integer.toHexString(machineCode[3])); // pointer.write(machineCode); assert pointer != null; byte[] code = pointer.getByteArray(1, 1); try(Keystone keystone = new Keystone(KeystoneArchitecture.Arm, KeystoneMode.ArmThumb)){ // 修改 KeystoneEncoded keystoneEncoded = keystone.assemble("add r2, [r0]"); byte[] patch = keystoneEncoded.getMachineCode(); // System.out.println("pathch_length:"+patch.length); // System.out.println("code_length:"+code.length); if(patch.length != code.length){ throw new IllegalStateException(Inspector.inspectString(patch, "patch32 length="+patch.length)); } pointer.write(0, patch, 0, patch.length); } }

private void debugger() {
    Debugger debugger = emulator.attach();

// debugger.addBreakPoint(module.base + 0x15623+1); }

@Override
public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
    switch (signature){
        case "com/km/encryption/generator/KeyGenerator->assetManager:Landroid/content/res/AssetManager;":{
            return new StringObject(vm, ((DvmClass) dvmObject).getName());
        }
    }
    return new ClassLoader(vm, signature);
}

@Override
public DvmObject<?> callStaticObjectMethod(BaseVM vm, DvmClass dvmClass, String signature, VarArg varArg) {
    if ("android/app/ActivityThread->currentPackageName()Ljava/lang/String;".equals(signature)) {
        String packageName = vm.getPackageName();
        if (packageName != null) {
            return new StringObject(vm, packageName);
        }
    }
    throw new UnsupportedOperationException(signature);
}

@Override
public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {
    if (signature.equals("com/km/encryption/generator/KeyGenerator->assetManager:Landroid/content/res/AssetManager;")) {
        return vm.resolveClass("android/content/res/AssetManager").newObject(signature);
    }
    throw new UnsupportedOperationException(signature);
}

}

// trcecode开启,找到异常原因。 // patch补丁 //trace指令执行 //emulator.traceCode(long begin, long end); //trace内存读写 // emulator.traceRead(long begin, long end); // emulator.traceWrite(long begin, long end);

// emulator.attach().addBreakPoint(module.base + 0x4001562c , new BreakPointCallback() { // @Override // public boolean onHit(Emulator<?> emulator, long address) { // System.out.println(" ====== traceCode ====== "); // // UnidbgPointer pX = UnidbgPointer.register(emulator, Arm64Const.UC_ARM64_REG_X1); // // byte[] bData = pX.getByteArray(0,16); // String strLabel = String.format("x0值 0x%08x", pX.peer); // Inspector.inspect(bData,strLabel); // // try { // emulator.traceCode(module.base + 0x8EE4, module.base + 0x9C0C).setRedirect(new PrintStream(new File("traceCodeCar.log"))); // } catch (IOException e) { // throw new IllegalStateException(e); // } // return true; // } // }); image

mr-linge avatar Aug 24 '23 19:08 mr-linge