- 监控so文件加载成功
- 动态注册方法
package com.github.unidbg.android;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Emulator;
import com.github.unidbg.LibraryResolver;
import com.github.unidbg.Module;
import com.github.unidbg.ModuleListener;
import com.github.unidbg.Symbol;
import com.github.unidbg.arm.HookStatus;
import com.github.unidbg.arm.backend.DynarmicFactory;
import com.github.unidbg.hook.ReplaceCallback;
import com.github.unidbg.hook.xhook.IxHook;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.XHookImpl;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.StringObject;
import com.github.unidbg.linux.android.dvm.VM;
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.utils.Inspector;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.File;
import java.io.IOException;
public class QDReaderJni implements ModuleListener {
private static final int SDK = 23;
private static LibraryResolver createLibraryResolver() {
return new AndroidResolver(SDK);
}
private static AndroidEmulator createARMEmulator() {
return AndroidEmulatorBuilder.for32Bit()
.setProcessName("a.d.c")
.addBackendFactory(new DynarmicFactory(true))
.build();
}
private final AndroidEmulator emulator;
private final VM vm;
private final DvmClass d;
private QDReaderJni() {
// 创建模拟器
emulator = createARMEmulator();
// 获取内存对象
final Memory memory = emulator.getMemory();
// 设置AndroidResolver
memory.setLibraryResolver(createLibraryResolver());
// 重点: 设置模块加载监听
memory.addModuleListener(this);
// 使用模拟器创建虚拟机
vm = emulator.createDalvikVM();
vm.setDvmClassFactory(new ProxyClassFactory());
// 设置是否打印Jni调用细节
vm.setVerbose(true);
// 加载so文件
DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/example_binaries/armeabi-v7a/libd-lib.so"), false);
// 手动调用JNI_OnLoad方法
dm.callJNI_onLoad(emulator);
// 模拟类a.d
d = vm.resolveClass("a/d");
}
private void destroy() throws IOException {
emulator.close();
System.out.println("destroy");
}
public static void main(String[] args) throws Exception {
// 初始化类
QDReaderJni test = new QDReaderJni();
//调用方法c
test.c();
test.destroy();
}
@Override
public void onLoaded(Emulator> emulator, Module module) {
// 监控so文件加载完成后调用的方法
if ("libcrypto.so".equals(module.name)) {
Symbol DES_set_key = module.findSymbolByName("DES_set_key", false);
Symbol DES_set_key_unchecked = module.findSymbolByName("DES_set_key_unchecked", false);
if (DES_set_key_unchecked == null && DES_set_key != null) {
// 注册DES_set_key_unchecked
module.registerSymbol("DES_set_key_unchecked", DES_set_key.getAddress());
}
}
}
private void c() throws Exception {
// 注册hook方法,对libd-lib.so里的free进行hook
IxHook xHook = XHookImpl.getInstance(emulator);
xHook.register("libd-lib.so", "free", new ReplaceCallback() {
@Override
public HookStatus onCall(Emulator> emulator, long originFunction) {
return HookStatus.LR(emulator, 0);
}
});
xHook.refresh();
final String data = "359250054370919||1551086094";
long start = System.currentTimeMillis();
// emulator.traceCode();
// 模拟调用jni方法boolean c(String)
ByteArray array = d.callStaticJniMethodObject(emulator, "c(Ljava/lang/String;)[B", new StringObject(vm, data));
// 打印返回结果
Inspector.inspect(array.getValue(), "c offset=" + (System.currentTimeMillis() - start) + "ms");
final String key = "sewxf03hhz3ew9qcCXMHiDMk";
final String iv = "sh331nt1";
// 加密和解密
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
DESedeKeySpec keySpec = new DESedeKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey secretKey = keyFactory.generateSecret(keySpec);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
byte[] encrypted = cipher.doFinal(data.getBytes());
// 打印加密后的二进制字节信息
Inspector.inspect(encrypted, "Encrypted");
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv.getBytes()));
byte[] decrypted = cipher.doFinal(array.getValue());
// 打印解密后的二进制字节信息
Inspector.inspect(decrypted, "Decrypted");
}
}
备注
1:动态监测so文件加载成功需要实现接口ModuleListener,并注册自己
2:动态注册符号,需要使用方法
module.registerSymbol
3 在线arm汇编指令与HEX转换网站:https://armconverter.com/
其他有问题请留言,一起进步。



