一、引言 fork from Unidbg 的基本使用(九) 
二、初探 Context 报错如下
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:532) - handleInterrupt intno=2, NR=-1073744548, svcNumber=0x170, PC=unidbg@0xfffe0794, LR=RX@0x4004db2f[libnet_crypto.so]0x4db2f, syscall=null
按照前面讨论的各类规范,应该占位为 Context 实例。
1 DvmObject<?> context = vm.resolveClass("android/content/Context" ).newObject(null );
但我们却占位为 AppController 实例。
1 DvmObject<?> context = vm.resolveClass("cn/xiaochuankeji/tieba/AppController" ).newObject(null );
假设按照规范补,后面会出现什么问题?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package  com.izuiyou;import  com.github.unidbg.AndroidEmulator;import  com.github.unidbg.arm.backend.Unicorn2Factory;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.memory.Memory;import  com.github.unidbg.virtualmodule.android.AndroidModule;import  java.io.File;import  java.nio.charset.StandardCharsets;public  class  NetWorkNew  extends  AbstractJni {private  final  AndroidEmulator emulator;private  final  DvmClass NetCrypto;private  final  VM vm;public  NetWorkNew ()  {new  Unicorn2Factory (true ))"cn.xiaochuankeji.tieba" )Memory  memory  =  emulator.getMemory();new  AndroidResolver (23 ));new  File ("unidbg-android/src/test/resources/zuiyou/right573.apk" ));this );true );new  AndroidModule (emulator, vm).register(memory);DalvikModule  dm  =  vm.loadLibrary("net_crypto" , true );"com.izuiyou.network.NetCrypto" );public  String callSign () {String  arg1  =  "hello world" ;byte [] arg2 = "V I 50" .getBytes(StandardCharsets.UTF_8);String  ret  =  NetCrypto.callStaticJniMethodObject(emulator, "sign(Ljava/lang/String;[B)Ljava/lang/String;" , arg1, arg2).getValue().toString();return  ret;@Override public  DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {switch  (signature){case  "com/izuiyou/common/base/BaseApplication->getAppContext()Landroid/content/Context;" :{return  vm.resolveClass("android/content/Context" ).newObject(null );return  super .callStaticObjectMethodV(vm, dvmClass, signature, vaList);public  static  void  main (String[] args)  {NetWorkNew  nw  =  new  NetWorkNew ();String  result  =  nw.callSign();"call s result:" +result);
继续运行,获取对象的类实例
1 2 3 4 java.lang.UnsupportedOperationException: android/content/Context->getClass()Ljava/lang/Class;416 )262 )89 )
DvmObject的getObjectType()用于实现这个功能。
1 2 3 4 5 6 7 8 9 @Override public  DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {switch  (signature){case  "android/content/Context->getClass()Ljava/lang/Class;" :{return  dvmObject.getObjectType();return  super .callObjectMethodV(vm, dvmObject, signature, vaList);
继续运行
1 2 3 java.lang.UnsupportedOperationException: java/lang/Class->getSimpleName()Ljava/lang/String;
这是在获取类的简写名,比如android.content.Context简写名就是Context。
DvmClass的getClassName可以获取类名,我们要截取末尾的名字。
1 2 3 4 5 case  "java/lang/Class->getSimpleName()Ljava/lang/String;" :{String  className  =  ((DvmClass) dvmObject).getClassName();"/" );return  new  StringObject (vm, name[name.length - 1 ]);
继续运行
1 2 3 java.lang.UnsupportedOperationException: cn/xiaochuankeji/tieba/common/debug/AppLogReporter->reportAppRuntime(Ljava/lang/String;Ljava/lang/String;)V697 )692 )
样本在调用reportAppRuntime函数,看这个名字是在上报运行情况,打印它的参数看看。
1 2 3 4 5 6 7 8 9 10 11 12 @Override public  void  callStaticVoidMethodV (BaseVM vm, DvmClass dvmClass, String signature, VaList vaList)  {switch  (signature){case  "cn/xiaochuankeji/tieba/common/debug/AppLogReporter->reportAppRuntime(Ljava/lang/String;Ljava/lang/String;)V" :{String  arg1  =  vaList.getObjectArg(0 ).getValue().toString();String  arg2  =  vaList.getObjectArg(1 ).getValue().toString();"arg1:" +arg1);"arg2:" +arg2);super .callStaticVoidMethodV(vm, dvmClass, signature, vaList);
运行
1 2 arg1:runtiem
这个上报信息很微妙,参数 1 看起来是 runtime 运行时的错误拼写,参数 2 则是具体信息—— Application 名字不合规。
为什么会出现这样的问题?让我们回到最初的问题上
1 2 3 4 5 6 7 8 9 @Override public  DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {switch  (signature){case  "com/izuiyou/common/base/BaseApplication->getAppContext()Landroid/content/Context;" :{return  vm.resolveClass("android/content/Context" ).newObject(null );return  super .callStaticObjectMethodV(vm, dvmClass, signature, vaList);
问题就出在这里,getAppContext的返回值类型是 Context,它是一个抽象类,返回的是抽象类的子类对象。在一般情况里我们不需要讲究,但这里它获取了返回的 Context 的类名,因此不得不确认样本到底返回了 Context 的什么子类对象,否则类名就对不上了。 
我这里使用 r0tracer 做确认
1 2 3 4 5 6 7 function  main (Java .perform (function  (console .Purple ("r0tracer begin ... !" )hook ("com.izuiyou.common.base.BaseApplication" , "" );
运行
1 2 3 4 *** entered com.izuiyou.common.base.BaseApplication.getAppContext
 可以发现具体的实现子类是cn.xiaochuankeji.tieba.AppController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package  cn.xiaochuankeji.tieba;import  android.app.Application;import  android.content.Context;import  android.content.Intent;import  android.os.Build;import  android.os.Bundle;import  com.facebook.common.memory.MemoryTrimType;import  com.izuiyou.common.base.BaseApplication;import  com.meituan.robust.ChangeQuickRedirect;import  com.meituan.robust.PatchProxy;import  com.meituan.robust.PatchProxyResult;import  defpackage.u36;import  java.util.Map;import  okhttp3.OkHttpClient;public  class  AppController  extends  BaseApplication  {public  static  ChangeQuickRedirect changeQuickRedirect;public  boolean  a  =  false ;public  boolean  b;
因此修改前面的代码为
1 2 3 4 5 6 7 8 9 @Override public  DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {switch  (signature){case  "com/izuiyou/common/base/BaseApplication->getAppContext()Landroid/content/Context;" :{return  vm.resolveClass("cn/xiaochuankeji/tieba/AppController" ).newObject(null );return  super .callStaticObjectMethodV(vm, dvmClass, signature, vaList);