Skip to content

Commit

Permalink
android: Android64Test.java support NestedRun.
Browse files Browse the repository at this point in the history
  • Loading branch information
zhkl0228 committed Jan 12, 2024
1 parent 7a32be7 commit 3c73988
Show file tree
Hide file tree
Showing 11 changed files with 106 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.arm.ArmHook;
import com.github.unidbg.arm.ArmSvc;
import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.arm.backend.BackendException;
import com.github.unidbg.arm.context.EditableArm32RegisterContext;
import com.github.unidbg.arm.context.RegisterContext;
Expand Down Expand Up @@ -2013,9 +2015,9 @@ public long handle(Emulator<?> emulator) {
}
});

Pointer _CallStaticLongMethod = svcMemory.registerSvc(new ArmSvc() {
Pointer _CallStaticLongMethod = svcMemory.registerSvc(new ArmHook() {
@Override
public long handle(Emulator<?> emulator) {
protected HookStatus hook(Emulator<?> emulator) {
EditableArm32RegisterContext context = emulator.getContext();
UnidbgPointer clazz = context.getPointerArg(1);
UnidbgPointer jmethodID = context.getPointerArg(2);
Expand All @@ -2033,7 +2035,7 @@ public long handle(Emulator<?> emulator) {
System.out.printf("JNIEnv->CallStaticLongMethod(%s, %s(%s)) was called from %s%n", dvmClass, dvmMethod.methodName, varArg.formatArgs(), context.getLRPointer());
}
context.setR1((int) (value >> 32));
return (value & 0xffffffffL);
return HookStatus.LR(emulator, value & 0xffffffffL);
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.github.unidbg.arm.Arm64Hook;
import com.github.unidbg.arm.Arm64Svc;
import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.arm.NestedRun;
import com.github.unidbg.arm.backend.BackendException;
import com.github.unidbg.arm.context.Arm64RegisterContext;
import com.github.unidbg.arm.context.RegisterContext;
Expand Down Expand Up @@ -2019,9 +2020,9 @@ public long handle(Emulator<?> emulator) {
}
});

Pointer _CallStaticLongMethod = svcMemory.registerSvc(new Arm64Svc() {
Pointer _CallStaticLongMethod = svcMemory.registerSvc(new Arm64Hook() {
@Override
public long handle(Emulator<?> emulator) {
protected HookStatus hook(Emulator<?> emulator) throws NestedRun {
RegisterContext context = emulator.getContext();
UnidbgPointer clazz = context.getPointerArg(1);
UnidbgPointer jmethodID = context.getPointerArg(2);
Expand All @@ -2038,7 +2039,7 @@ public long handle(Emulator<?> emulator) {
if (verbose || verboseMethodOperation) {
System.out.printf("JNIEnv->CallStaticLongMethod(%s, %s(%s)) was called from %s%n", dvmClass, dvmMethod.methodName, varArg.formatArgs(), context.getLRPointer());
}
return value;
return HookStatus.LR(emulator, value);
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.NestedRun;
import com.github.unidbg.arm.backend.DynarmicFactory;
import com.github.unidbg.arm.backend.HypervisorFactory;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.arm.context.EditableArm64RegisterContext;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.linux.ARM64SyscallHandler;
import com.github.unidbg.linux.android.AndroidARM64Emulator;
Expand All @@ -17,17 +19,22 @@
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.DvmObject;
import com.github.unidbg.linux.android.dvm.StringObject;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.linux.android.dvm.VarArg;
import com.github.unidbg.linux.struct.Stat64;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.pointer.UnidbgPointer;
import com.github.unidbg.unix.UnixSyscallHandler;
import com.sun.jna.Pointer;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import unicorn.Arm64Const;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;

public class Android64Test extends AbstractJni {
Expand Down Expand Up @@ -160,6 +167,31 @@ public void setStaticFloatField(BaseVM vm, DvmClass dvmClass, String signature,
super.setStaticFloatField(vm, dvmClass, signature, value);
}

@Override
public long callStaticLongMethod(BaseVM vm, DvmClass dvmClass, String signature, VarArg varArg) {
if ("com/github/unidbg/android/JniTest->nestedRun(Ljava/lang/String;JID)J".equals(signature)) {
{ // fix call context
StringObject str = varArg.getObjectArg(0);
long l1 = varArg.getLongArg(1);
int i1 = varArg.getIntArg(2);
double d1 = varArg.getDoubleArg(3);
System.out.println("nestedRunInJava l1=0x" + Long.toHexString(l1 / 2) + ", i1=0x" + Integer.toHexString(i1 / 2) + ", d1=" + d1 / 2 + ", str=" + str.getValue());
EditableArm64RegisterContext context = emulator.getContext();
context.setXLong(2, str.hashCode());
context.setXLong(3, l1);
context.setXLong(4, i1);
ByteBuffer buffer = ByteBuffer.allocate(16);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putDouble(d1);
emulator.getBackend().reg_write_vector(Arm64Const.UC_ARM64_REG_Q0, buffer.array());
}
UnidbgPointer fun = dvmClass.findNativeFunction(emulator, "nestedRun(Ljava/lang/String;JID)J");
throw NestedRun.runToFunction(UnidbgPointer.nativeValue(fun));
}

return super.callStaticLongMethod(vm, dvmClass, signature, varArg);
}

private void test() {
cJniTest.callStaticJniMethod(emulator, "testJni(Ljava/lang/String;JIDZSFDBJF)V",
getClass().getName(), 0x123456789abcdefL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.NestedRun;
import com.github.unidbg.arm.backend.DynarmicFactory;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.arm.context.EditableArm32RegisterContext;
import com.github.unidbg.file.linux.AndroidFileIO;
import com.github.unidbg.linux.ARM32SyscallHandler;
import com.github.unidbg.linux.android.AndroidARMEmulator;
Expand All @@ -16,11 +18,13 @@
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.DvmObject;
import com.github.unidbg.linux.android.dvm.StringObject;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.linux.android.dvm.VarArg;
import com.github.unidbg.linux.struct.Dirent;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.memory.SvcMemory;
import com.github.unidbg.pointer.UnidbgPointer;
import com.github.unidbg.unix.UnixSyscallHandler;
import com.sun.jna.Pointer;
import org.apache.log4j.Level;
Expand Down Expand Up @@ -161,6 +165,27 @@ public void setStaticFloatField(BaseVM vm, DvmClass dvmClass, String signature,
super.setStaticFloatField(vm, dvmClass, signature, value);
}

@Override
public long callStaticLongMethod(BaseVM vm, DvmClass dvmClass, String signature, VarArg varArg) {
if ("com/github/unidbg/android/JniTest->nestedRun(Ljava/lang/String;JID)J".equals(signature)) {
{ // fix call context, can't fix stack args.
StringObject str = varArg.getObjectArg(0);
long l1 = varArg.getLongArg(1);
int i1 = varArg.getIntArg(2);
double d1 = varArg.getDoubleArg(3);
System.out.println("nestedRunInJava l1=0x" + Long.toHexString(l1 / 2) + ", i1=0x" + Integer.toHexString(i1 / 2) + ", d1=" + d1 / 2 + ", str=" + str.getValue());
EditableArm32RegisterContext context = emulator.getContext();
context.setR2(str.hashCode());
context.setR3((int) (l1 & 0xffffffffL));
context.setR4((int) ((l1 >>> 32) & 0xffffffffL));
}
UnidbgPointer fun = dvmClass.findNativeFunction(emulator, "nestedRun(Ljava/lang/String;JID)J");
throw NestedRun.runToFunction(UnidbgPointer.nativeValue(fun));
}

return super.callStaticLongMethod(vm, dvmClass, signature, varArg);
}

private void test() {
cJniTest.callStaticJniMethod(emulator, "testJni(Ljava/lang/String;JIDZSFDBJF)V",
getClass().getName(), 0x123456789abcdefL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ public class JniTest {

public static native void testJni(String str, long l1, int i, double d1, boolean b, short s, float f1, double d2, byte bt, long l2, float f2);

public static native long nestedRun(String str, long l1, int i, double d1);

}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified unidbg-android/src/test/native/android/libs/arm64-v8a/libnative.so
Binary file not shown.
Binary file not shown.
19 changes: 18 additions & 1 deletion unidbg-android/src/test/native/android/native.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,25 @@ JNIEXPORT void JNICALL Java_com_github_unidbg_android_JniTest_testJni
printf("testJni str=%s, l1=0x%llx, i=0x%x, d1=%f, b=%d, s=0x%x, f1=%f, d2=%f, bs=0x%x, l2=0x%llx, f2=%f\n", bytes, l1, i, d1, b, s, f1, d2, bs, l2, f2);
const char *ap = (*env)->GetStringUTFChars(env, str, NULL);
const char *bp = (*env)->GetStringUTFChars(env, str, NULL);
printf("testJni bytes=%p, ap=%p, bp=%p\n", bytes, ap, bp);
jmethodID nestedRun = (*env)->GetStaticMethodID(env, clazz, "nestedRun", "(Ljava/lang/String;JID)J");
jlong nestedLong = (*env)->CallStaticLongMethod(env, clazz, nestedRun, str, l1 * 2, i * 2, d1 * 2);
printf("testJni bytes=%p, ap=%p, bp=%p, nestedLong=0x%llx\n", bytes, ap, bp, nestedLong);
(*env)->ReleaseStringUTFChars(env, str, bytes);
(*env)->ReleaseStringUTFChars(env, str, ap);
(*env)->ReleaseStringUTFChars(env, str, bp);
}

/*
* Class: com_github_unidbg_android_JniTest
* Method: nestedRun
* Signature: (Ljava/lang/String;JID)J
*/
JNIEXPORT jlong JNICALL Java_com_github_unidbg_android_JniTest_nestedRun
(JNIEnv *env, jclass clazz, jstring str, jlong l1, jint i, jdouble d1) {
const char *bytes = (*env)->GetStringUTFChars(env, str, NULL);
printf("nestedRun str=%s, l1=0x%llx, i=0x%x, d1=%f\n", bytes, l1, i, d1);
(*env)->ReleaseStringUTFChars(env, str, bytes);
return l1 * 2;
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ protected Arm64Hook(boolean enablePostCall) {
this.enablePostCall = enablePostCall;
}

@SuppressWarnings("unused")
public Arm64Hook(String name, boolean enablePostCall) {
super(name);
this.enablePostCall = enablePostCall;
Expand Down
13 changes: 11 additions & 2 deletions unidbg-api/src/main/java/com/github/unidbg/arm/ArmHook.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ protected ArmHook(boolean enablePostCall) {
this.enablePostCall = enablePostCall;
}

@SuppressWarnings("unused")
public ArmHook(String name, boolean enablePostCall) {
super(name);
this.enablePostCall = enablePostCall;
Expand Down Expand Up @@ -95,7 +96,7 @@ public final long handle(Emulator<?> emulator) {
}
UnidbgPointer sp = UnidbgPointer.register(emulator, ArmConst.UC_ARM_REG_SP);
try {
HookStatus status = hook(emulator);
HookStatus status = doHook(emulator);
if (status.forward || !enablePostCall) {
sp = sp.share(-4, 0);
sp.setInt(0, (int) status.jump);
Expand All @@ -110,6 +111,14 @@ public final long handle(Emulator<?> emulator) {
}
}

protected abstract HookStatus hook(Emulator<?> emulator);
private HookStatus doHook(Emulator<?> emulator) {
try {
return hook(emulator);
} catch (NestedRun run) {
return HookStatus.RET(emulator, run.pc);
}
}

protected abstract HookStatus hook(Emulator<?> emulator) throws NestedRun;

}

0 comments on commit 3c73988

Please sign in to comment.