package com.yaotong.crackme;
import
com.github.unidbg.AndroidEmulator;
import
com.github.unidbg.Module;
import
com.github.unidbg.arm.backend.DynarmicFactory;
import
com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import
com.github.unidbg.linux.android.AndroidResolver;
import
com.github.unidbg.linux.android.dvm.AbstractJni;
import
com.github.unidbg.linux.android.dvm.DalvikModule;
import
com.github.unidbg.linux.android.dvm.DvmObject;
import
com.github.unidbg.linux.android.dvm.VM;
import
com.github.unidbg.memory.Memory;
import
com.github.unidbg.pointer.UnidbgPointer;
import
java.nio.charset.Charset;
import
java.io.
File
;
public
class
MainActivity extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
private final Memory memory;
MainActivity() {
/
/
创建模拟器
emulator
=
AndroidEmulatorBuilder.for32Bit().addBackendFactory(new DynarmicFactory(true)).build();
/
/
内存
memory
=
emulator.getMemory();
/
/
设置SDK
memory.setLibraryResolver(new AndroidResolver(
23
));
/
/
创建虚拟机
vm
=
emulator.createDalvikVM(new
File
(
"unidbg-android/src/test/java/com/yaotong/crackme/you.apk"
));
/
/
设置jni
vm.setJni(this);
/
/
打印日志
vm.setVerbose(true);
/
/
运行so文件
DalvikModule dalvikModule
=
vm.loadLibrary(new
File
(
"unidbg-android/src/test/java/com/yaotong/crackme/libcrackme.so"
), true);
/
/
module
module
=
dalvikModule.getModule();
/
/
调用JNI——onload
/
/
dalvikModule.callJNI_OnLoad(emulator);
vm.callJNI_OnLoad(emulator, module);
HookAddr();
}
/
*
*
*
打印
Hex
Dump 格式的数据
*
*
@param data 要打印的字节数组
*
/
private static void printHexDump(byte[] data) {
int
bytesPerLine
=
16
;
/
/
每行打印
16
个字节
for
(
int
i
=
0
; i < data.length; i
+
=
bytesPerLine) {
/
/
打印当前行的地址(偏移量)
System.out.printf(
"%08X "
, i);
/
/
打印当前行的十六进制数据
for
(
int
j
=
0
; j < bytesPerLine; j
+
+
) {
if
(i
+
j < data.length) {
System.out.printf(
"%02X "
, data[i
+
j]);
}
else
{
System.out.
print
(
" "
);
/
/
如果剩余字节不足
16
个,填充空格
}
}
System.out.
print
(
" |"
);
/
/
打印当前行的字符内容(ASCII)
for
(
int
j
=
0
; j < bytesPerLine; j
+
+
) {
if
(i
+
j < data.length) {
byte b
=
data[i
+
j];
if
(b >
=
32
&& b <
=
126
) {
System.out.
print
((char) b);
/
/
打印可打印字符
}
else
{
System.out.
print
(
"."
);
/
/
打印不可打印字符
}
}
else
{
System.out.
print
(
" "
);
/
/
填充空格
}
}
System.out.println(
"|"
);
}
}
public static void main(String[] args) {
MainActivity test
=
new MainActivity();
System.out.println(test.getSName());
}
public void HookAddr() {
/
/
目标地址,这里是示例地址
0x628C
0x4450
long
targetAddress
=
module.base
+
0x4450
;
/
/
使用 UnidbgPointer 来获取目标地址的数据
UnidbgPointer pointer
=
UnidbgPointer.pointer(emulator, targetAddress);
/
/
读取目标地址的数据,假设它是一个字符串,长度为
16
字节
byte[] data
=
pointer.getByteArray(
0
,
16
);
/
/
读取
16
个字节
printHexDump(data);
/
/
将读取的字节转换为字符串
/
/
将读取的字节转换为字符串,并指定正确的编码(例如 UTF
-
8
或 GBK)
String value
=
new String(data, Charset.forName(
"GBK"
));
/
/
使用 UTF
-
8
编码
/
/
打印地址和读取的内容
System.out.println(
"Address: "
+
Long
.toHexString(targetAddress));
System.out.println(
"Data at address: "
+
value);
}
/
/
符号调用
public Boolean getSName() {
/
/
创建一个vm对象
DvmObject> dvmObject
=
vm.resolveClass(
"com/yaotong/crackme/MainActivity"
).newObject(null);
String
input
=
"123"
;
/
/
byte[] inputByte
=
input
.getBytes(StandardCharsets.UTF_8);
boolean success
=
dvmObject.callJniMethodBoolean(emulator,
"securityCheck(Ljava/lang/string;)Z"
,
input
);
System.out.println(
"[symble] Call the so md5 function result is ==> "
+
success);
return
success;
}
}