unidbg实战笔记(1)–基本的SoLoad调用流程
unidbg基本的加载流程
1.创建Android虚拟机
初始化的一个安卓模拟环境 32位或者 64位 ,指定SDK版本和进程
类似代码如下:
AndroidEmulator emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.xhs").build(); // 创建模拟器实例,要模拟32位或者64位,在这里区分
final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析
File file = new File("unidbg-android/src/test/resources/example_binaries/apk/xhs6830.apk");
vm = emulator.createDalvikVM(file);
vm.setVerbose(true);
我们在创建时刻 把apk load 进去了,方便后续查找so
2.load so file
基于load apk file,我们可以按需找到我们的libso文件,输入名字即可。
DalvikModule dm = vm.loadLibrary("shield", true); // 加载libttEncrypt.so到unicorn虚拟内存,加载成功以后会默认调用init_array等函数
vm.setJni(this);
module = dm.getModule(); //so的内存空间
System.out.println("call JNIOnLoad");
dm.callJNI_OnLoad(emulator);
找到指定的so文件同时 我们进行jnionload初始化并且开辟一段内存空间记录so文件的内存位置。
3.find Class
DvmClass XhsHttpInterceptor = vm.resolveClass("com/xingin/shield/http/XhsHttpInterceptor");
找到我们的目标调用类
使用resolveClass创建类加载即可 注意路径
4.call method
String methodSign = "initializeNative()V";
XhsHttpInterceptor.callStaticJniMethod(emulator, methodSign, null);
使用创建的类 直接接调用方法名 注意方法名的类型 是smail风格的
callStaticJniMethod 表示静态方法 最后传入参数就可以了
5.java call implement(非必需)
java层的调用实现,通常so层都会调用java层的方法来完成操作。
虽然一些涉及底层的方法已经由unidbg实现
但是关于程序本身的方法实现还是要手动
举一个例子:
"com/xingin/shield/http/ContextHolder->deviceId:Ljava/lang/String;"
这个方法调用没有实现 很显然是返回string类型的设备id
对应的我们在方法里实现这个调用
@Override
public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {
switch (signature) {
//author
/**
* 获取了deviceid
*/
case "com/xingin/shield/http/ContextHolder->deviceId:Ljava/lang/String;":{
return new StringObject(vm, DEVICE_ID);
}
case "com/xingin/shield/http/ContextHolder->sAppId:I":{
return DvmInteger.valueOf(vm, (int) 3975851777L);
}
}
return super.getStaticObjectField(vm, dvmClass, signature);
}
6.代码调试 解决异常((非必需))
如果上面的步骤全部走位 依然没有完成调用。接下来就到了最重要也是最难的部分,代码调试。
关于这点我们放到后面来说。因为需要非常大的篇幅。
总结
unidbg非常实用,对于安全学习,逆向分析非常有意义。