unidbg
unidbg copied to clipboard
这种情况怎么解决Write to write-protected memory (UC_ERR_WRITE_PROT)
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;
// }
// });