一、引言 目标 APK:dazhongdianping.apk
目标类:com.meituan.android.common.mtguard.NBridge$SIUACollector
目标方法:见第二小节
目标方法实现:libmtguard.so
二、任务介绍 JADX
反编译 APK,找到com.meituan.android.common.mtguard.NBridge
类,其中有一个叫SIUACollector
的内部类,里面有以下这些 Native 方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private native String getEnvironmentInfo () ;private native String getEnvironmentInfoExtra () ;private native String getExternalEquipmentInfo () ;private native String getHWEquipmentInfo () ;private native String getHWProperty () ;private native String getHWStatus () ;private native String getLocationInfo () ;private native String getPlatformInfo () ;private native String getUserAction () ;public native String startCollection () ;
请在 Unidbg 中依次执行这十个函数,本篇的重点是巩固 Unidbg 补环境的形式,以及学习 Unidbg 补环境的内容。
三、初始化 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 package com.meituan.android.common.mtguard;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 com.github.unidbg.virtualmodule.android.JniGraphics;import java.io.File;public class NBridge extends AbstractJni { private final AndroidEmulator emulator; private final VM vm; private final Memory memory; private final DvmObject<?> cSIUACollectorObj; public NBridge () { emulator = AndroidEmulatorBuilder .for32Bit() .addBackendFactory(new Unicorn2Factory (true )) .setProcessName("com.dianping.v1" ) .build(); memory = emulator.getMemory(); memory.setLibraryResolver(new AndroidResolver (23 )); vm = emulator.createDalvikVM(new File ("unidbg-android/src/test/resources/dazhongdianping/dazhongdianping.apk" )); vm.setJni(this ); vm.setVerbose(true ); DalvikModule dm = vm.loadLibrary("mtguard" , true ); DvmClass cSIUACollector = vm.resolveClass("com.meituan.android.common.mtguard.NBridge$SIUACollector" ); cSIUACollectorObj = cSIUACollector.newObject(null ); dm.callJNI_OnLoad(emulator); } public static void main (String[] args) { NBridge nBridge = new NBridge (); } }
由于我们所需要执行的这十个函数都是实例方法,为了免于重复newObject
,将SIUACollector
处理为DvmObject
。
执行会提示
1 2 [14:11:16 565] INFO [com.github.unidbg.linux.AndroidElfLoader] (AndroidElfLoader:481 ) - libmtguard.so load dependency libandroid.so failed[14:11:16 579] INFO [com.github.unidbg.linux.AndroidElfLoader] (AndroidElfLoader:481 ) - libmtguard.so load dependency libjnigraphics.so failed
意思是加载 libandroid.so、libjnigraphics.so 失败, unidbg 提供了这两个库的虚拟模块,只需早于 目标 SO 加载的时机之前加载即可
1 2 3 4 new AndroidModule (emulator, vm).register(memory);new JniGraphics (emulator, vm).register(memory);
四、getEnvironmentInfo 调用代码如下
1 2 3 4 5 6 public String getEnvironmentInfo () { String envInfo = cSIUACollectorObj.callJniMethodObject(emulator, "getEnvironmentInfo()Ljava/lang/String;" ) .getValue() .toString(); return envInfo; }
运行发现直接得出了结果,无需补环境。
1 getEnvironmentInfo call result: 0|0 |0 |- |0 |
调用代码如下
1 2 3 4 5 6 public String getEnvironmentInfoExtra () { String envInfoEx = cSIUACollectorObj.callJniMethodObject(emulator, "getEnvironmentInfoExtra()Ljava/lang/String;" ) .getValue() .toString(); return envInfoEx; }
运行报错如下
1 2 3 4 5 JNIEnv->NewGlobalRef (class java/lang/StringBuilder) was called from RX@0 x12005f5d[libmtguard.so] 0 x5f5d[14:19:27 954] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x117, PC=unidbg@0 xfffe0204, LR=RX@0 x12007443[libmtguard.so] 0 x7443, syscall=null java.lang .UnsupportedOperationException : java/lang/StringBuilder->allocObject at com.github .unidbg .linux .android .dvm .AbstractJni .allocObject (AbstractJni.java :812 ) at com.github .unidbg .linux .android .dvm .DvmClass .allocObject (DvmClass.java :74 )
参考 AbstractJni 中的 allocObject 处理
做相同处理
1 2 3 4 5 6 7 8 9 10 @Override public DvmObject<?> allocObject(BaseVM vm, DvmClass dvmClass, String signature) { switch (signature){ case "java/lang/StringBuilder->allocObject" : { StringBuilder builder = new StringBuilder (); return dvmClass.newObject(builder); } } return super .allocObject(vm, dvmClass, signature); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetMethodID (java/lang/StringBuilder.<init>()V) => 0 xad81ca9c was called from RX@0 x12006369[libmtguard.so] 0 x6369[14:24:36 014] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x13b, PC=unidbg@0 xfffe0444, LR=RX@0 x120095f1[libmtguard.so] 0 x95f1, syscall=null java.lang .UnsupportedOperationException : java/lang/StringBuilder-><init>()V at com.github .unidbg .linux .android .dvm .AbstractJni .callVoidMethodV (AbstractJni.java :1007 ) at com.github .unidbg .linux .android .dvm .AbstractJni .callVoidMethodV (AbstractJni.java :990 )
刚分配的StirngBuilder需要初始化,这里什么也不做,直接返回
1 2 3 4 5 6 7 8 9 @Override public void callVoidMethodV (BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) { switch (signature){ case "java/lang/StringBuilder-><init>()V" : { return ; } } super .callVoidMethodV(vm, dvmObject, signature, vaList); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetMethodID(com / meituan / android / common / mtguard / NBridge$SIUACollector .getEnvironmentInfo () Ljava/lang/String;) => 0xa10d6eee was called from RX@0x12006369 [libmtguard .so ] 0x6369 [14 :29 :42 737 ] WARN [com .github .unidbg .linux .ARM32SyscallHandler ] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0x120 , PC=unidbg@0xfffe0294 , LR=RX@0x12008403 [libmtguard .so ] 0x8403 , syscall=null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector->getEnvironmentInfo() Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni . callObjectMethodV(AbstractJni.java :417) at com.github.unidbg.linux.android.dvm.AbstractJni . callObjectMethodV(AbstractJni.java :262)
这个方法就是我们上一个补的 getEnvironmentInfo,你可能希望像下面这样处理
1 2 3 4 5 6 7 8 9 @Override public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) { switch (signature){ case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getEnvironmentInfo()Ljava/lang/String;" :{ return new StringObject (vm, getEnvironmentInfo()); } } return super .callObjectMethodV(vm, dvmObject, signature, vaList); }
但这是行不通的,Native 方法里调用另一个 Native 方法,这属于嵌套调用,Unidbg 暂不支持这么做,所以这里手动填入先前得到的结果。
1 2 3 4 5 6 7 8 9 10 @Override public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) { switch (signature){ case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getEnvironmentInfo()Ljava/lang/String;" : { return new StringObject (vm, "0|0|0|-|0|" ); } } return super .callObjectMethodV(vm, dvmObject, signature, vaList); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetMethodID(java/lang/ StringBuilder.append (Ljava/lang/ String;)Ljava/lang/ StringBuilder;) => 0 x7b1bffd9 was called from RX@0 x12006369[libmtguard.so]0 x6369 [14 :36 :50 617 ] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x120, PC=unidbg@0 xfffe0294, LR=RX@0 x120085d9[libmtguard.so]0 x85d9, syscall=null java.lang.UnsupportedOperationException: java/lang/ StringBuilder->append (Ljava/lang/ String;)Ljava/lang/ StringBuilder; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417 ) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:94 )
修补代码如下
1 2 3 4 5 6 7 8 9 10 case "java/lang/StringBuilder->append(Ljava/lang/String;)Ljava/lang/StringBuilder;" : { StringBuilder builder = (StringBuilder)dvmObject.getValue(); String arg1 = vaList.getObjectArg(0 ).getValue().toString(); builder.append(arg1); return ProxyDvmObject.createObject(vm, builder); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetMethodID(com / meituan / android / common / mtguard / NBridge$SIUACollector .isVPN () Ljava/lang/String;) => 0xdd0ce7bd was called from RX@0x12006369 [libmtguard .so ] 0x6369 [14 :39 :40 524 ] WARN [com .github .unidbg .linux .ARM32SyscallHandler ] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0x120 , PC=unidbg@0xfffe0294 , LR=RX@0x120079dd [libmtguard .so ] 0x79dd , syscall=null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector->isVPN() Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni . callObjectMethodV(AbstractJni.java :417) at com.meituan.android.common.mtguard.NBridge . callObjectMethodV(NBridge.java :104)
这是样本里的函数,要么代码copy过来并调用,要么静态分析看出具体值(显然很麻烦),要么frida hook 具体值。
这里直接frida hook 该函数并主动调用获取具体值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function test ( ){ Java .perform ( function ( ){ let SIUACollector = Java .use ("com.meituan.android.common.mtguard.NBridge$SIUACollector" ); SIUACollector ["isVPN" ].implementation = function ( ) { console .log (`SIUACollector.isVPN is called` ); let result = this ["isVPN" ](); console .log (`SIUACollector.isVPN result=${result} ` ); return result; }; var currentApplication = Java .use ('android.app.ActivityThread' ).currentApplication (); var context = currentApplication.getApplicationContext (); SIUACollector .$new(context)["isVPN" ](); } ); }
结果如下
1 2 SIUACollector.isVPN is called SIUACollector.isVPN result =0
在callObjectMethodV
方法下添加如下分支
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->isVPN()Ljava/lang/String;" : { return new StringObject (vm, "0" ); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetFieldID (com/meituan/android/common/mtguard/NBridge$SIUACollector .mContext Landroid/content /Context;) => 0 xc458fdce was called from RX@0 x1200668b[libmtguard.so] 0 x668b[14:44:50 042] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x15b, PC=unidbg@0 xfffe0644, LR=RX@0 x120090c9[libmtguard.so] 0 x90c9, syscall=null java.lang .UnsupportedOperationException : com/meituan/android/common/mtguard/NBridge$SIUACollector ->mContext:Landroid/content /Context; at com.github .unidbg .linux .android .dvm .AbstractJni .getObjectField (AbstractJni.java :171 ) at com.github .unidbg .linux .android .dvm .AbstractJni .getObjectField (AbstractJni.java :141 )
先占位,后续报错再通过Frida Hook出具体值来解决
1 2 3 4 5 6 7 8 9 10 @Override public DvmObject<?> getObjectField(BaseVM vm, DvmObject<?> dvmObject, String signature) { switch (signature) { case "com/meituan/android/common/mtguard/NBridge$SIUACollector->mContext:Landroid/content/Context;" : { return vm.resolveClass("android/content/Context" ).newObject(null ); } } return super .getObjectField(vm, dvmObject, signature); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetMethodID(com/meituan/ android/common/m tguard/NBridge$SIUACollector.brightness(Landroid/ content/Context;)Ljava/ lang/String;) => 0 x2437a7e4 was called from RX@0 x12006369[libmtguard.so]0 x6369 [14 :48 :49 208 ] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x120, PC=unidbg@0 xfffe0294, LR=RX@0 x12009cbb[libmtguard.so]0 x9cbb, syscall=null java.lang.UnsupportedOperationException: com/meituan/ android/common/m tguard/NBridge$SIUACollector->brightness(Landroid/ content/Context;)Ljava/ lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417 ) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:108 )
看函数名应该是个关于屏幕亮度的函数,代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private String brightness (Context context) { Object[] objArr = {context}; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; return PatchProxy.isSupport(objArr, this , changeQuickRedirect2, false , "e3c10305f195ff2aac2fd606a6235fb2" , RobustBitConfig.DEFAULT_VALUE) ? (String) PatchProxy.accessDispatch(objArr, this , changeQuickRedirect2, false , "e3c10305f195ff2aac2fd606a6235fb2" ) : DeviceInfoWorker.brightness(context); }public static String brightness (Context context) { Object[] objArr = {context}; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, null , changeQuickRedirect2, true , "af80a1c664fdf95866b7caabf24ab495" , RobustBitConfig.DEFAULT_VALUE)) { return (String) PatchProxy.accessDispatch(objArr, null , changeQuickRedirect2, true , "af80a1c664fdf95866b7caabf24ab495" ); } try { return StringUtils.toString(Settings.System.getInt(context.getContentResolver(), "screen_brightness" ) / 255.0f ); } catch (Throwable th) { c.a(th); return StringUtils.toString(0.0f ); } }
Google 搜索getContentResolver
+screen_brightness
,找到如下代码。
1 2 3 4 5 6 7 8 9 private int getScreenBrightness (Context context) { ContentResolver contentResolver = context.getContentResolver(); int defVal = 0 ; return Settings.System.getInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS, defVal); }
也就是说,最终获取的值是是 0-1 之间的一个数,然后转字符串,我这里选择 0.8。
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->brightness(Landroid/content/Context;)Ljava/lang/String;" : { return new StringObject (vm, "0.8" ); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetMethodID(com/meituan/ android/common/m tguard/NBridge$SIUACollector.systemVolume(Landroid/ content/Context;)Ljava/ lang/String;) => 0 x80b60b0c was called from RX@0 x12006369[libmtguard.so]0 x6369 [14 :51 :10 180 ] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x120, PC=unidbg@0 xfffe0294, LR=RX@0 x1200980b[libmtguard.so]0 x980b, syscall=null java.lang.UnsupportedOperationException: com/meituan/ android/common/m tguard/NBridge$SIUACollector->systemVolume(Landroid/ content/Context;)Ljava/ lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417 ) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:111 )
systemVolume
具体实现代码如下,明显是获取音量的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static String systemVolume (Context context) { Object[] objArr = {context}; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, null , changeQuickRedirect2, true , "94db8653238995da6df94fea33fbbf79" , RobustBitConfig.DEFAULT_VALUE)) { return (String) PatchProxy.accessDispatch(objArr, null , changeQuickRedirect2, true , "94db8653238995da6df94fea33fbbf79" ); } try { AudioManager audioManager = (AudioManager) context.getSystemService("audio" ); return StringUtils.toString((audioManager.getStreamVolume(1 ) * 100 ) / audioManager.getStreamMaxVolume(1 )); } catch (Throwable th) { c.a(th); return "" ; } }
搜索getStreamVolume
和getStreamMaxVolume
可以获知相关信息,我这里直接返回0,表示静音
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->systemVolume(Landroid/content/Context;)Ljava/lang/String;" : { return new StringObject (vm, "0" ); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetMethodID (com/meituan/android/common/mtguard/NBridge$SIUACollector .isAccessibilityEnable ()Z) => 0 xf45f6eaa was called from RX@0 x12006369[libmtguard.so] 0 x6369[14:53:26 404] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x123, PC=unidbg@0 xfffe02c4, LR=RX@0 x12007a8f[libmtguard.so] 0 x7a8f, syscall=null java.lang .UnsupportedOperationException : com/meituan/android/common/mtguard/NBridge$SIUACollector ->isAccessibilityEnable ()Z at com.github .unidbg .linux .android .dvm .AbstractJni .callBooleanMethodV (AbstractJni.java :625 ) at com.github .unidbg .linux .android .dvm .AbstractJni .callBooleanMethodV (AbstractJni.java :603 )
isAccessibilityEnable
是无障碍服务。无障碍服务的本意是帮助残障人士、老人小孩等等,但长久以来被用于自动化控制,比如抢单,因此检测无障碍服务是风险检测、环境检测、反欺诈检测的重要一环。
1 2 3 4 5 6 7 8 9 @Override public boolean callBooleanMethodV (BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) { switch (signature) { case "com/meituan/android/common/mtguard/NBridge$SIUACollector->isAccessibilityEnable()Z" : { return false ; } } return super .callBooleanMethodV(vm, dvmObject, signature, vaList); }
继续运行,报错
1 2 3 4 5 JNIEnv->GetStaticMethodID(java/lang/String.valueOf(I)Ljava/lang/String;) => 0x382c5880 was called from RX@0x12006369[libmtguard.so]0x6369 [14:56:03 539] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x171, PC =unidbg@0xfffe07a4, LR =RX@0x1200a2a9[libmtguard.so]0xa2a9, syscall =null java.lang.UnsupportedOperationException: java/lang/String->valueOf(I)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethodV(AbstractJni.java:504) at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethodV(AbstractJni.java:438)
完善valueOf
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Override public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) { switch (signature){ case "java/lang/String->valueOf(I)Ljava/lang/String;" : { int arg = vaList.getIntArg(0 ); String result = String.valueOf(arg); return new StringObject (vm, result); } } return super .callStaticObjectMethodV(vm, dvmClass, signature, vaList); }
继续运行,报错
1 2 3 4 [14:58:45 968] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x12f, PC=unidbg@0 xfffe0384, LR=RX@0 x12007c73[libmtguard.so] 0 x7c73, syscall=null java.lang .UnsupportedOperationException : com/meituan/android/common/mtguard/NBridge$SIUACollector ->uiAutomatorClickCount ()I at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :563 ) at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :529 )
Frida hook 该函数并主动调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function test () { Java.perform( function(){ let SIUACollector = Java.use("com.meituan.android.common.mtguard.NBridge$SIUACollector" ); SIUACollector["uiAutomatorClickCount" ].implementation = function () { console.log(`SIUACollector.uiAutomatorClickCount is called`); let result = this ["uiAutomatorClickCount" ](); console.log(`SIUACollector.uiAutomatorClickCount result=${result}`); return result; }; var currentApplication = Java.use('android.app.ActivityThread' ).currentApplication(); var context = currentApplication.getApplicationContext(); SIUACollector.$new (context)["uiAutomatorClickCount" ](); } ); }
hook 结果如下
1 2 SIUACollector.uiAutomatorClickCount is called SIUACollector.uiAutomatorClickCount result =0
那么补环境时直接返回0即可
1 2 3 4 5 6 7 8 9 @Override public int callIntMethodV (BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) { switch (signature) { case "com/meituan/android/common/mtguard/NBridge$SIUACollector->uiAutomatorClickCount()I" : { return 0 ; } } return super .callIntMethodV(vm, dvmObject, signature, vaList); }
继续报错
1 2 3 4 [15:02:38 832] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x120096f3[libmtguard.so]0x96f3, syscall =null java.lang.UnsupportedOperationException: java/lang/StringBuilder->toString()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:114)
这个比较简单,完善toString
方法即可
1 2 3 4 5 6 7 8 case "java/lang/StringBuilder->toString()Ljava/lang/String;" : { StringBuilder builder = (StringBuilder) dvmObject.getValue(); String str = builder.toString(); return new StringObject (vm, str); }
运行成功,结果如下
1 getEnvironmentInfoExtra call result:0 |0 |0 |-|0 |0 |0 .8 |0 |0 |0 |
六、getExternalEquipmentInfo 调用代码如下
1 2 3 4 5 6 public String getExternalEquipmentInfo () { String exEqInfo = cSIUACollectorObj.callJniMethodObject(emulator, "getExternalEquipmentInfo()Ljava/lang/String;" ) .getValue() .toString(); return exEqInfo; }
运行报错
1 2 3 4 [15:07:29 158] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x120, PC=unidbg@0 xfffe0294, LR=RX@0 x1203ddd7[libmtguard.so] 0 x3ddd7, syscall=null java.lang .UnsupportedOperationException : android/content /Context->getApplicationContext ()Landroid/content/Context; at com.github .unidbg .linux .android .dvm .AbstractJni .callObjectMethodV (AbstractJni.java :417 ) at com.meituan .android .common .mtguard .NBridge .callObjectMethodV (NBridge.java :129 )
跟上一小节的报错一样,仍然是简单的占位即可
1 2 3 4 case "android/content/Context->getApplicationContext()Landroid/content/Context;" { return vm.resolveClass("android/content/Context" ).newObject(null ); }
运行报错
1 2 3 4 [15:10:05 165] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x120396b5[libmtguard.so]0x396b5, syscall =null java.lang.UnsupportedOperationException: android/content/Context->getSystemService(Ljava/lang/String;)Ljava/lang/Object; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:133)
系统服务是 Android 所提供的一项重要服务,在 JNI 补环境中出现频率相当高, Unidbg 对它做了专门处理,可以参考 AbstractJni,其中有如下代码片段。
抄一下
1 2 3 4 5 case "android/content/Context->getSystemService(Ljava/lang/String;)Ljava/lang/Object;" : { StringObject serviceName = vaList.getObjectArg(0 ); assert serviceName != null ; return new SystemService (vm, serviceName.getValue()); }
运行还是报错
1 2 3 4 [15:16:59 472] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x123, PC =unidbg@0xfffe02c4, LR =RX@0x1203994d[libmtguard.so]0x3994d, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->isPermissionGranted(Ljava/lang/String;Landroid/content/Context;)Z at com.github.unidbg.linux.android.dvm.AbstractJni.callBooleanMethodV(AbstractJni.java:625) at com.meituan.android.common.mtguard.NBridge.callBooleanMethodV(NBridge.java:148)
isPermissionGranted
显然是检查App是否具有某项权限,我这里直接返回true,要是想分类讨论,可以先打印权限名称然后决定是否给予权限。
1 2 3 4 5 6 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->isPermissionGranted(Ljava/lang/String;Landroid/content/Context;)Z" : { return true ; }
继续运行,报错
1 2 3 4 [15:19:04 185] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x192, PC=unidbg@0 xfffe09b4, LR=RX@0 x1203c723[libmtguard.so] 0 x3c723, syscall=null java.lang .UnsupportedOperationException : android/os/Build$VERSION ->SDK_INT:I at com.github .unidbg .linux .android .dvm .AbstractJni .getStaticIntField (AbstractJni.java :136 ) at com.github .unidbg .linux .android .dvm .AbstractJni .getStaticIntField (AbstractJni.java :128 )
SDK_INT
顾名思义是sdk版本,这里返回unidbg使用的sdk版本(其他的也行)。
1 2 3 4 5 6 7 8 9 10 @Override public int getStaticIntField (BaseVM vm, DvmClass dvmClass, String signature) { switch (signature) { case "android/os/Build$VERSION->SDK_INT:I" : { return 23 ; } } return super .getStaticIntField(vm, dvmClass, signature); }
运行,继续报错(由于选的是sdk23,会出现如下错误)
1 2 3 4 [15:21:18 191] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12035f07[libmtguard.so]0x35f07, syscall =null java.lang.UnsupportedOperationException: android/telephony/TelephonyManager->getDeviceId()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:138)
frida hook 具体值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function test () { Java.perform( function(){ var TelephonyManager = Java.use("android.telephony.TelephonyManager" ); var currentApplication = Java.use('android.app.ActivityThread' ).currentApplication(); var context = currentApplication.getApplicationContext(); var telephonyManager = context.getSystemService("phone" ); var TelephonyManager = Java.use("android.telephony.TelephonyManager" ); telephonyManager = Java.cast(telephonyManager, TelephonyManager); var deviceId = telephonyManager.getDeviceId(); console.log("Active Device ID: " + deviceId); } ); }
结果如下!?(也许哪里出错了)
由于返回值是String,所以将null封装成StringObject
1 2 3 4 case "android/telephony/TelephonyManager->getDeviceId()Ljava/lang/String;" : { return new StringObject (vm, null ); }
继续运行,报错
1 2 3 4 [15:23:02 435] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1203c617[libmtguard.so]0x3c617, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->checkBuildAttribute(Ljava/lang/String;)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:142)
checkBuildAttribute
代码如下
1 2 3 4 5 private String checkBuildAttribute (String str) { Object[] objArr = {str}; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; return PatchProxy.isSupport(objArr, this , changeQuickRedirect2, false , "3b097946787cf593049f918e4d2f8a4e" , RobustBitConfig.DEFAULT_VALUE) ? (String) PatchProxy.accessDispatch(objArr, this , changeQuickRedirect2, false , "3b097946787cf593049f918e4d2f8a4e" ) : (TextUtils.isEmpty(str) || str.equalsIgnoreCase("unknown" )) ? CommonConstant.Symbol.MINUS : str; }
逻辑很简单,就是
1 (TextUtils.isEmpty(str) || str.equalsIgnoreCase("unknown" )) ? CommonConstant.Symbol.MINUS : str;
CommonConstant.Symbol.MINUS
的值是”-“,所以补环境代码如下:
1 2 3 4 5 6 7 8 9 10 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->checkBuildAttribute(Ljava/lang/String;)Ljava/lang/String;" : { String arg = (String) vaList.getObjectArg(0 ).getValue(); if (arg.isEmpty() || arg.equalsIgnoreCase("unknown" )) { return new StringObject (vm, "-" ); } else { return new StringObject (vm, arg); } }
继续运行,报错
1 2 3 4 [11:40:36 615] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1203ce83[libmtguard.so]0x3ce83, syscall =null java.lang.UnsupportedOperationException: android/view/WindowManager->getDefaultDisplay()Landroid/view/Display; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:152)
这是一个 Android 对象,按照前面所说的补环境原则直接处理。
1 2 3 4 case "android/view/WindowManager->getDefaultDisplay()Landroid/view/Display;" : { return vm.resolveClass("android/view/Display" ).newObject(null ); }
继续运行
1 2 3 4 [11:42:08 615] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x12f, PC=unidbg@0 xfffe0384, LR=RX@0 x1203a291[libmtguard.so] 0 x3a291, syscall=null java.lang .UnsupportedOperationException : android/view/Display->getHeight ()I at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :563 ) at com.meituan .android .common .mtguard .NBridge .callIntMethodV (NBridge.java :194 )
又是 Android FrameWork 层的 API ,Google 搜索发现它和getWidth一起用于获取屏幕的宽高。对于这类基本设备信息,完全可以通过 ADB 获取。
1 2 > adb shell wm size Physical size: 1440x2560
补环境
1 2 3 case "android/view/Display->getHeight()I" : { return 2560 ; }
报错
1 2 3 4 [11:47:20 967] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1203f1e1[libmtguard.so]0x3f1e1, syscall =null java.lang.UnsupportedOperationException: java/lang/StringBuilder->append(I)Ljava/lang/StringBuilder; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:156)
遇见过相同的情况
1 2 3 4 5 6 7 8 9 10 case "java/lang/StringBuilder->append(I)Ljava/lang/StringBuilder;" : { int arg = (int ) vaList.getIntArg(0 ); StringBuilder builder = (StringBuilder) dvmObject.getValue(); builder.append(arg); return ProxyDvmObject.createObject(vm, builder); }
报错
1 2 3 4 [11:51:06 660] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1203bd31[libmtguard.so]0x3bd31, syscall =null java.lang.UnsupportedOperationException: java/lang/StringBuilder->append(C)Ljava/lang/StringBuilder; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:166)
补环境
1 2 3 4 5 6 7 8 9 10 case "java/lang/StringBuilder->append(C)Ljava/lang/StringBuilder;" : { char arg = (char ) vaList.getIntArg(0 ); StringBuilder builder = (StringBuilder) dvmObject.getValue(); builder.append(arg); return ProxyDvmObject.createObject(vm, builder); }
报错
1 2 3 4 [11:53:27 955] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x12f, PC=unidbg@0 xfffe0384, LR=RX@0 x1203e717[libmtguard.so] 0 x3e717, syscall=null java.lang .UnsupportedOperationException : android/view/Display->getWidth ()I at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :563 ) at com.meituan .android .common .mtguard .NBridge .callIntMethodV (NBridge.java :217 )
之前补的是高,现在是宽。
1 2 3 case "android/view/Display->getWidth()I" : { return 1440 ; }
报错
1 2 3 4 [11:55:06 439] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1203a117[libmtguard.so]0x3a117, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getTotalInternalMemorySize()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:176)
Frida Hook该函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function test ( ){ Java .perform ( function ( ){ let SIUACollector = Java .use ("com.meituan.android.common.mtguard.NBridge$SIUACollector" ); SIUACollector ["getTotalInternalMemorySize" ].implementation = function ( ) { console .log (`SIUACollector.getTotalInternalMemorySize is called` ); let result = this ["getTotalInternalMemorySize" ](); console .log (`SIUACollector.getTotalInternalMemorySize result=${result} ` ); return result; }; var currentApplication = Java .use ('android.app.ActivityThread' ).currentApplication (); var context = currentApplication.getApplicationContext (); SIUACollector .$new(context).getTotalInternalMemorySize (); } ); }
得到结果如下
1 2 SIUACollector.getTotalInternalMemorySize is called SIUACollector.getTotalInternalMemorySize result =24 GB
补环境代码如下
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getTotalInternalMemorySize()Ljava/lang/String;" : { return new StringObject (vm, "24GB" ); }
继续报错
1 2 3 4 [12:04:11 864] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12036db3[libmtguard.so]0x36db3, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getTotalExternalMemorySize()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:182)
Frida Hook该函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function test ( ){ Java .perform ( function ( ){ let SIUACollector = Java .use ("com.meituan.android.common.mtguard.NBridge$SIUACollector" ); SIUACollector ["getTotalExternalMemorySize" ].implementation = function ( ) { console .log (`SIUACollector.getTotalExternalMemorySize is called` ); let result = this ["getTotalExternalMemorySize" ](); console .log (`SIUACollector.getTotalExternalMemorySize result=${result} ` ); return result; }; var currentApplication = Java .use ('android.app.ActivityThread' ).currentApplication (); var context = currentApplication.getApplicationContext (); SIUACollector .$new(context).getTotalExternalMemorySize (); } ); }
得到结果如下
1 2 SIUACollector.getTotalExternalMemorySize is called SIUACollector.getTotalExternalMemorySize result =24 GB
补环境代码如下
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getTotalInternalMemorySize()Ljava/lang/String;" : { return new StringObject (vm, "24GB" ); }
继续报错
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x16f, PC =unidbg@0xfffe0784, LR =RX@0x12036961[libmtguard.so]0x36961, syscall =null java.lang.UnsupportedOperationException: android/text/TextUtils->isEmpty(Ljava/lang/CharSequence;)Z at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticBooleanMethodV(AbstractJni.java:191) at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticBooleanMethodV(AbstractJni.java:186)
这是 Android FrameWork 中处理字符串的工具类,这种工具函数往往不会很复杂,在 AOSP 中找一下它的实现。
1 2 3 public static boolean isEmpty (CharSequence str) { return str == null || str.length() == 0 ; }
复写一下
1 2 3 4 5 6 7 8 9 10 @Override public boolean callStaticBooleanMethodV (BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) { switch (signature) { case "android/text/TextUtils->isEmpty(Ljava/lang/CharSequence;)Z" : { CharSequence str = (CharSequence) vaList.getObjectArg(0 ).getValue(); return str == null || str.length() == 0 ; } } return super .callStaticBooleanMethodV(vm, dvmClass, signature, vaList); }
继续运行,报错
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12039247[libmtguard.so]0x39247, syscall =null java.lang.UnsupportedOperationException: android/telephony/TelephonyManager->getSimOperator()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:180)
又是 Android FrameWork 里的函数,搜索getSimOperator
发现是获取SIM卡的运营商信息。同样可以使用 ADB 获取到相关信息。这里使用Frida Hook 获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function test ( ){ Java .perform ( function ( ){ var TelephonyManager = Java .use ("android.telephony.TelephonyManager" ); var currentApplication = Java .use ('android.app.ActivityThread' ).currentApplication (); var context = currentApplication.getApplicationContext (); var telephonyManager = context.getSystemService ("phone" ); var TelephonyManager = Java .use ("android.telephony.TelephonyManager" ); telephonyManager = Java .cast (telephonyManager, TelephonyManager ); var simOp = telephonyManager.getSimOperator (); console .log ("getSimOperator: " + simOp); } ); }
由于我的测试机没有SIM卡,所以返回的结果是空的。
后面搜索发现 SimOperator 由 MCC + MNC 组成。
MCC
由国际电信联盟 ITU 在全世界范围内统一分配和管理,唯一识别移动用户所属的国家,共3位,中国为460。
MNC
用于识别移动用户所归属的移动通信网,2~3位。中国移动系统使用 00、02、04、07,中国联通系统使用 01、06、09,中国电信使用 03、05、11,中国铁通系统使用 20 。
于是随意组了一个数
1 2 3 case "android/telephony/TelephonyManager->getSimOperator()Ljava/lang/String;" : { return new StringObject (vm, "46000" ); }
继续报错
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1203a91b[libmtguard.so]0x3a91b, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getAccessSubType()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:183)
getAccessSubType
代码如下
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 private String getAccessSubType () { Object[] objArr = new Object [0 ]; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, this , changeQuickRedirect2, false , "4e473c1fae47c0bf65e6f819cd3eaf7c" , RobustBitConfig.DEFAULT_VALUE)) { return (String) PatchProxy.accessDispatch(objArr, this , changeQuickRedirect2, false , "4e473c1fae47c0bf65e6f819cd3eaf7c" ); } Context context = this .mContext; if (context == null ) { return StringUtil.NULL; } if (isPermissionGranted("android.permission.ACCESS_NETWORK_STATE" , context)) { ConnectivityManager connectivityManager = (ConnectivityManager) this .mContext.getApplicationContext().getSystemService("connectivity" ); NetworkInfo activeNetworkInfo = connectivityManager != null ? connectivityManager.getActiveNetworkInfo() : null ; if (activeNetworkInfo == null ) { return StringUtil.NULL; } if (activeNetworkInfo.getType() == 1 ) { return "wifi" ; } if (activeNetworkInfo.getType() == 0 ) { int subtype = activeNetworkInfo.getSubtype(); return (subtype == 4 || subtype == 1 || subtype == 2 ) ? "2G" : (subtype == 3 || subtype == 8 || subtype == 6 || subtype == 5 || subtype == 12 ) ? "3G" : subtype == 13 ? "4G" : "" ; } return "" ; } return CommonConstant.Symbol.MINUS; }
看起来是获取网络类型,具体有”wifi”、”2G”、”3G”、”4G”,随便选一个
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getAccessSubType()Ljava/lang/String;" : { return new StringObject (vm, "wifi" ); }
最终运行成功
1 getExternalEquipmentInfo call result: -|- |- |2560*1440 |24GB |24GB |AQmac |46000 |wifi |
七、getHWEquipmentInfo 调用代码如下
1 2 3 4 5 public String getHWEquipmentInfo () { return cSIUACollectorObj.callJniMethodObject(emulator, "getHWEquipmentInfo()Ljava/lang/String;" ) .getValue() .toString(); }
运行报错
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12030eaf[libmtguard.so]0x30eaf, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getCpuInfoType()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417) at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:193)
顾名思义,获取CPU的架构,通过源码也可知其返回值为”x86”、”arm”,这里选择”arm”。
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getCpuInfoType()Ljava/lang/String;" : { return new StringObject (vm, "arm" ); }
运行报错
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x117, PC=unidbg@0 xfffe0204, LR=RX@0 x1202bcef[libmtguard.so] 0 x2bcef, syscall=null java.lang .UnsupportedOperationException : java/io/BufferedReader->allocObject at com.github .unidbg .linux .android .dvm .AbstractJni .allocObject (AbstractJni.java :812 ) at com.meituan .android .common .mtguard .NBridge .allocObject (NBridge.java :88 )
同样的allocObject
情况,但是当创建BufferedReader
的时候,需要参数,即确定缓冲区大小,它所需要的初始化参数在allocObject
阶段并没有展露出来,在后续真正初始化的时候才有值 。这里直接用空的dvmObject
占位。
1 2 3 4 5 case "java/io/BufferedReader->allocObject" : { return dvmClass.newObject(null ); }
接下来是InputStreamReader
的allocObject
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x117, PC=unidbg@0 xfffe0204, LR=RX@0 x1202a687[libmtguard.so] 0 x2a687, syscall=null java.lang .UnsupportedOperationException : java/io/InputStreamReader->allocObject at com.github .unidbg .linux .android .dvm .AbstractJni .allocObject (AbstractJni.java :812 ) at com.meituan .android .common .mtguard .NBridge .allocObject (NBridge.java :94 )
同样进行占位处理
1 2 3 case "java/io/InputStreamReader->allocObject" : { return dvmClass.newObject(null ); }
然后是FileInputStream
的allocObject
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x117, PC=unidbg@0 xfffe0204, LR=RX@0 x1202c66f[libmtguard.so] 0 x2c66f, syscall=null java.lang .UnsupportedOperationException : java/io/FileInputStream->allocObject at com.github .unidbg .linux .android .dvm .AbstractJni .allocObject (AbstractJni.java :812 ) at com.meituan .android .common .mtguard .NBridge .allocObject (NBridge.java :96 )
同样进行占位处理
1 2 3 case "java/io/FileInputStream->allocObject" : { return dvmClass.newObject(null ); }
继续报错
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x13b, PC =unidbg@0xfffe0444, LR =RX@0x12030391[libmtguard.so]0x30391, syscall =null java.lang.UnsupportedOperationException: java/io/FileInputStream-><init>(Ljava/lang/String;)V at com.github.unidbg.linux.android.dvm.AbstractJni.callVoidMethodV(AbstractJni.java:1007) at com.meituan.android.common.mtguard.NBridge.callVoidMethodV(NBridge.java:110)
这是个重点!!!之前我们对于FileInputStream
的allocObject
仅仅只是做了占位处理,而且因为callVoid
系列 API 没有返回值,它的操作基于原先的占位dvmObject
,因为我们没法对它重新赋值,所以需要声明为一个全局变量处理它以及后面的逻辑。
1 2 3 4 5 6 public class NBridge extends AbstractJni { private final AndroidEmulator emulator; private final VM vm; private final Memory memory; private final DvmObject<?> cSIUACollectorObj; public FileInputStream fileInputStream;
然后补具体逻辑
1 2 3 4 5 6 7 8 9 case "java/io/FileInputStream-><init>(Ljava/lang/String;)V" : { String arg = vaList.getObjectArg(0 ).getValue().toString(); System.out.println("FileInputStream-><init>: " + arg); try { fileInputStream = new FileInputStream (arg); } catch (FileNotFoundException e) { throw new RuntimeException (e); } }
运行后发现报错
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x13b, PC=unidbg@0 xfffe0444, LR=RX@0 x12030391[libmtguard.so] 0 x30391, syscall=null java.lang .RuntimeException : java.io .FileNotFoundException : \proc\cpuinfo (系统找不到指定的路径。) at com.meituan .android .common .mtguard .NBridge .callVoidMethodV (NBridge.java :112 ) at com.github .unidbg .linux .android .dvm .AbstractJni .callVoidMethodV (AbstractJni.java :990 )
程序在访问 /proc/cpuinfo 文件,那么我们将 /proc/cpuinfo 文件拖到本地项目中,然后做路径的重定位。
1 2 3 4 5 6 7 8 9 10 11 12 13 case "java/io/FileInputStream-><init>(Ljava/lang/String;)V" : { String arg = vaList.getObjectArg(0 ).getValue().toString(); System.out.println("FileInputStream-><init>: " + arg); if (arg.equals("/proc/cpuinfo" )){ arg = "unidbg-android/src/test/resources/dazhongdianping/cpuinfo" ; } try { fileInputStream = new FileInputStream (arg); } catch (FileNotFoundException e) { throw new RuntimeException (e); } return ; }
接下来是InputStreamReader
的init
,做同样处理,先全局声明
1 2 3 4 5 6 7 public class NBridge extends AbstractJni { private final AndroidEmulator emulator; private final VM vm; private final Memory memory; private final DvmObject<?> cSIUACollectorObj; public FileInputStream fileInputStream; public InputStreamReader inputStreamReader;
再处理具体逻辑
1 2 3 4 5 case "java/io/InputStreamReader-><init>(Ljava/io/InputStream;)V" : { InputStream arg = (InputStream) vaList.getObjectArg(0 ).getValue(); inputStreamReader = new InputStreamReader (arg); return ; }
然而这样做会报错,这是因为这个 InputStream
参数就是我们之前定义的全局变量 InputStream
,然而我们通过 vaList
获取的则是占位符而已,无法对其进行初始化,因此需要使用全局变量进行初始化。
1 2 3 4 case "java/io/InputStreamReader-><init>(Ljava/io/InputStream;)V" : { inputStreamReader = new InputStreamReader (fileInputStream); return ; }
之后是BufferedReader
的init
,做同样处理,先全局声明
1 public BufferedReader bufferedReader;
再处理具体逻辑,同样的,使用全局变量inputStreamReader
作为参数传入,刚才这几个文件读取相关的函数处理相当于套娃了。
1 2 3 4 case "java/io/BufferedReader-><init>(Ljava/io/Reader;)V" : { bufferedReader = new BufferedReader (inputStreamReader); return ; }
继续运行,报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1202e89f[libmtguard.so]0x2e89f, syscall =null java.lang.UnsupportedOperationException: java/io/BufferedReader->readLine()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
这个处理起来很简单
1 2 3 4 5 6 7 8 9 10 11 12 case "java/io/BufferedReader->readLine()Ljava/lang/String;" : { String line = null ; try { line = bufferedReader.readLine(); } catch (IOException e) { throw new RuntimeException (e); } if (line != null ){ return new StringObject (vm, line); } return null ; }
运行报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x12f, PC =unidbg@0xfffe0384, LR =RX@0x1202c179[libmtguard.so]0x2c179, syscall =null java.lang.UnsupportedOperationException: java/lang/String->compareToIgnoreCase(Ljava/lang/String;)I at com.github.unidbg.linux.android.dvm.AbstractJni.callIntMethodV(AbstractJni.java:563)
补环境代码如下
1 2 3 4 5 6 7 8 case "java/lang/String->compareToIgnoreCase(Ljava/lang/String;)I" : { String arg = (String) vaList.getObjectArg(0 ).getValue(); String obj = (String) dvmObject.getValue(); return obj.compareToIgnoreCase(arg); }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x13b, PC=unidbg@0 xfffe0444, LR=RX@0 x1202bcbf[libmtguard.so] 0 x2bcbf, syscall=null java.lang .UnsupportedOperationException : java/io/BufferedReader->close ()V at com.github .unidbg .linux .android .dvm .AbstractJni .callVoidMethodV (AbstractJni.java :1007 )
补环境代码如下
1 2 3 4 5 6 7 8 case "java/io/BufferedReader->close()V" : { try { bufferedReader.close(); } catch (IOException e) { throw new RuntimeException (e); } return ; }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x120312c3[libmtguard.so]0x312c3, syscall =null java.lang.UnsupportedOperationException: android/hardware/SensorManager->getDefaultSensor(I)Landroid/hardware/Sensor; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
getDefaultSensor
是唤醒传感器,参数是传感器类型,源码在/frameworks/base/core/java/android/hardware/SensorManager.java
下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public Sensor getDefaultSensor (int type) { List<Sensor> l = getSensorList(type); boolean wakeUpSensor = false ; if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION || type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE || type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE || type == Sensor.TYPE_WRIST_TILT_GESTURE || type == Sensor.TYPE_DYNAMIC_SENSOR_META) { wakeUpSensor = true ; } for (Sensor sensor : l) { if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor; } return null ; }
Sensor 表示的是传感器类,其源码在/frameworks/base/core/java/android/hardware/Sensor.java
下,所具有的传感器类型部分如下:
1 2 3 4 5 6 7 8 9 10 11 12 public static final int TYPE_ACCELEROMETER = 1 ; public static final int TYPE_ORIENTATION = 3 ;public static final int TYPE_POSE_6DOF = 28 ;public static final int TYPE_PRESSURE = 6 ;public static final int TYPE_PROXIMITY = 8 ;public static final int TYPE_RELATIVE_HUMIDITY = 12 ;public static final int TYPE_ROTATION_VECTOR = 11 public static final int TYPE_SIGNIFICANT_MOTION = 17 ;public static final int TYPE_STATIONARY_DETECT = 29 ;public static final int TYPE_STEP_COUNTER = 19 ;public static final int TYPE_STEP_DETECTOR = 18 ;public static final int TYPE_GRAVITY = 9 ;
打印参数,看样本在获取哪类传感器
1 2 3 4 case "android/hardware/SensorManager->getDefaultSensor(I)Landroid/hardware/Sensor;" : { int type = vaList.getIntArg(0 ); System.out.println("Sensor type:" +type); }
结果如下
1 对应于加速度传感器,那么创建相应的传感器即可(这里仅占位)
1 2 3 4 5 case "android/hardware/SensorManager->getDefaultSensor(I)Landroid/hardware/Sensor;" : { int type = vaList.getIntArg(0 ); System.out.println("Sensor type:" +type); return vm.resolveClass("android/hardware/Sensor" ).newObject(type); }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12031b3b[libmtguard.so]0x31b3b, syscall =null java.lang.UnsupportedOperationException: android/hardware/Sensor->getName()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
需要获取传感器的名字。这里我们可以写个Android项目的小demo来获取加速度传感器的名字
1 2 3 4 5 public void getSensorName () { SensorManager manager= (SensorManager)getSystemService(SENSOR_SERVICE); Sensor accelSensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); Log.e("gal2xy" ,accelSensor.getName()); }
日志输出
补环境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 case "android/hardware/Sensor->getName()Ljava/lang/String;" : { int type = (int ) dvmObject.getValue(); System.out.println("Sensor getName:" +type); if (type == 1 ){ return new StringObject (vm, "BMI160 accelerometer" ); } else { throw new UnsupportedOperationException (signature); } }
接下来是
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1202e717[libmtguard.so]0x2e717, syscall =null java.lang.UnsupportedOperationException: android/hardware/Sensor->getVendor()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
同样在Android项目中获取一下
1 2 3 4 5 public void getVendor () { SensorManager manager= (SensorManager)getSystemService(SENSOR_SERVICE); Sensor accelSensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); Log.e("gal2xy" ,accelSensor.getVendor()); }
输出
补环境
1 2 3 4 5 6 7 8 9 10 case "android/hardware/Sensor->getVendor()Ljava/lang/String;" : { int type = (int ) dvmObject.getValue(); System.out.println("Sensor getVendor:" +type); if (type == 1 ){ return new StringObject (vm, "Bosch" ); } else { throw new UnsupportedOperationException (signature); } }
继续运行,报错
1 2 3 4 Sensor getName:9 [15:15:28 547] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1202ad4f[libmtguard.so]0x2ad4f, syscall =null java.lang.UnsupportedOperationException: android/hardware/Sensor->getName()Ljava/lang/String; at com.meituan.android.common.mtguard.NBridge.callObjectMethodV(NBridge.java:264)
这次获取的type=9的传感器信息,相关操作如法炮制一下,最终得到设备名为Gravity,供应商为Google,继续完善补环境。
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 case "android/hardware/Sensor->getName()Ljava/lang/String;" : { int type = (int ) dvmObject.getValue(); System.out.println("Sensor getName:" +type); if (type == 1 ){ return new StringObject (vm, "BMI160 accelerometer" ); } else if (type == 9 ){ return new StringObject (vm, "Gravity" ); } else { throw new UnsupportedOperationException (signature); } }case "android/hardware/Sensor->getVendor()Ljava/lang/String;" : { int type = (int ) dvmObject.getValue(); System.out.println("Sensor getVendor:" +type); if (type == 1 ){ return new StringObject (vm, "Bosch" ); } else if (type == 9 ){ return new StringObject (vm, "Google" ); } else { throw new UnsupportedOperationException (signature); } }
然后报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x13b, PC =unidbg@0xfffe0444, LR =RX@0x1202c103[libmtguard.so]0x2c103, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->safeClose(Ljava/io/Closeable;)V at com.github.unidbg.linux.android.dvm.AbstractJni.callVoidMethodV(AbstractJni.java:1007)
jadx中查看safeClose
代码,发现是关闭某种资源,这里简单处理即可
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->safeClose(Ljava/io/Closeable;)V" :{ return ; }
最终跑通
1 getHWEquipmentInfo call result: -|- |4 |BMI160 accelerometer |Bosch |Gravity |Google |
八、getHWProperty 调用代码
1 2 3 4 5 public String getHWProperty () { return cSIUACollectorObj.callJniMethodObject(emulator, "getHWProperty()Ljava/lang/String;" ) .getValue() .toString(); }
运行报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x18d, PC =unidbg@0xfffe0964, LR =RX@0x1200fbfd[libmtguard.so]0xfbfd, syscall =null java.lang.UnsupportedOperationException: android/os/Build->BOARD:Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.getStaticObjectField(AbstractJni.java:103)
需要获取设备的品牌方。对于 Build 下的信息,同样可以写 demo 看,这个办法相当灵活好用,或者使用 ADB 也行。
1 2 3 public void getBoard () { Log.e("gal2xy" , "getBoard: " + Build.BOARD); }
结果如下
adb结果如下
1 2 3 > getprop | grep board [ro.board.platform]: [msm8996] [ro.product.board]: [marlin]
补环境代如下
1 2 3 4 5 6 7 8 9 @Override public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) { switch (signature) { case "android/os/Build->BOARD:Ljava/lang/String;" : { return new StringObject (vm, "marlin" ); } } return super .getStaticObjectField(vm, dvmClass, signature); }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x18d, PC =unidbg@0xfffe0964, LR =RX@0x120160ab[libmtguard.so]0x160ab, syscall =null java.lang.UnsupportedOperationException: android/os/Build->MANUFACTURER:Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.getStaticObjectField(AbstractJni.java:103)
demo运行和adb结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public void getManufacturer () { Log.e("gal2xy" , "getManufacturer: " + Build.MANUFACTURER); } getManufacturer: Google > getprop | grep manufacturer [media.recorder.show_manufacturer_and_model]: [true ] [ro.product.manufacturer]: [Google] [ro.product.odm.manufacturer]: [Google] [ro.product.system.manufacturer]: [Google] [ro.product.vendor.manufacturer]: [Google]
补环境代码如下
1 2 3 case "android/os/Build->MANUFACTURER:Ljava/lang/String;" : { return new StringObject (vm, "Google" ); }
还是获取Build类下的信息
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x18d, PC =unidbg@0xfffe0964, LR =RX@0x12016b1b[libmtguard.so]0x16b1b, syscall =null java.lang.UnsupportedOperationException: android/os/Build->BRAND:Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.getStaticObjectField(AbstractJni.java:103)
相同操作不再叙述,直接展示补环境代码
1 2 3 case "android/os/Build->BRAND:Ljava/lang/String;" : { return new StringObject (vm,"Google" ); }
仍旧是Build类
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x18d, PC =unidbg@0xfffe0964, LR =RX@0x12014c13[libmtguard.so]0x14c13, syscall =null java.lang.UnsupportedOperationException: android/os/Build->MODEL:Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.getStaticObjectField(AbstractJni.java:103)
补环境代码如下
1 2 3 case "android/os/Build->MODEL:Ljava/lang/String;" : { return new StringObject (vm,"Pixel XL" ); }
终于不再是Build类的报错了
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1200d2a7[libmtguard.so]0xd2a7, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getSysProp(Ljava/lang/String;)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
jadx查看了该函数,发现是获取系统的相关信息,先来看一下传入的参数是啥
1 2 3 4 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getSysProp(Ljava/lang/String;)Ljava/lang/String;" : { String arg = (String) vaList.getObjectArg(0 ).getValue(); System.out.println("getSysProp param: " + arg); }
打印结果如下
1 getSysProp param: ro.product .cpu .abi
这个属性信息用 ADB 获取很方便,第一个就是。
1 2 3 4 5 marlin:/ # getprop | grep ro.product.cpu.abi [ro.product.cpu.abi]: [arm64-v8a] [ro.product.cpu.abilist]: [arm64-v8a,armeabi-v7a,armeabi] [ro.product.cpu.abilist32]: [armeabi-v7a,armeabi] [ro.product.cpu.abilist64]: [arm64-v8a]
补环境
1 2 3 4 5 6 7 8 9 10 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getSysProp(Ljava/lang/String;)Ljava/lang/String;" : { String arg = (String) vaList.getObjectArg(0 ).getValue(); System.out.println("getSysProp param: " + arg); switch (arg) { case "ro.product.cpu.abi" : return new StringObject (vm, "arm64-v8a" ); default : throw new UnsupportedOperationException (signature); } }
继续报错
1 2 3 4 getSysProp param: ro.product.cpu.abi2 [15:54:19 964] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12018613[libmtguard.so]0x18613, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getSysProp(Ljava/lang/String;)Ljava/lang/String; at com.meituan.android.common.mtguard.MyAbstractJni.callObjectMethodV(MyAbstractJni.java:221)
这次获取的属性是ro.product.cpu.abi2,同样adb获取,adb getprop 找不到这个属性,所以返回空字符串 。
1 2 case "ro.product.cpu.abi2" : return new StringObject (vm, "" );
接下来的报错按顺序分别是 PRODUCT、HARDWARE、DEVICE。补环境代码如下
1 2 3 4 5 case "android/os/Build->PRODUCT:Ljava/lang/String;" :case "android/os/Build->HARDWARE:Ljava/lang/String;" :case "android/os/Build->DEVICE:Ljava/lang/String;" : { return new StringObject (vm,"marlin" ); }
接下来报错
1 2 3 4 getSysProp param: ro.build.product [16:02:00 388] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1201831f[libmtguard.so]0x1831f, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getSysProp(Ljava/lang/String;)Ljava/lang/String; at com.meituan.android.common.mtguard.MyAbstractJni.callObjectMethodV(MyAbstractJni.java:224)
补充ro.build.product
的属性获取
1 2 case "ro.build.product" : return new StringObject (vm, "marlin" );
接下来又续上了Build类属性:HOST、ID。补相应环境
1 2 3 4 5 6 case "android/os/Build->HOST:Ljava/lang/String;" : { return new StringObject (vm,"abfarm830" ); }case "android/os/Build->ID:Ljava/lang/String;" : { return new StringObject (vm,"QP1A.191005.007.A3" ); }
然后报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x18d, PC =unidbg@0xfffe0964, LR =RX@0x12010777[libmtguard.so]0x10777, syscall =null java.lang.UnsupportedOperationException: android/os/Build$VERSION ->RELEASE:Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.getStaticObjectField(AbstractJni.java:103)
写个demo获取
1 2 3 4 5 public void getRelease () { Log.e("gal2xy" , "getRelease: " + Build.VERSION.RELEASE); } getRelease: 10
补环境
1 2 3 case "android/os/Build$VERSION->RELEASE:Ljava/lang/String;" : { return new StringObject (vm,"10" ); }
接下来是个简单的报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x171, PC =unidbg@0xfffe07a4, LR =RX@0x1200c9c1[libmtguard.so]0xc9c1, syscall =null java.lang.UnsupportedOperationException: java/lang/Integer->toString(I)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethodV(AbstractJni.java:504)
jdk中函数,按照一般步骤走即可:获取对象、获取参数、调用方法、封装。由于这个是静态方法,不需要实例对象即可调用
1 2 3 4 5 6 7 8 case "java/lang/Integer->toString(I)Ljava/lang/String;" : { Integer arg = vaList.getIntArg(0 ); String result = Integer.toString(arg); return new StringObject (vm, result); }
继续运行,报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x120, PC=unidbg@0 xfffe0294, LR=RX@0 x120102b3[libmtguard.so] 0 x102b3, syscall=null java.lang .UnsupportedOperationException : android/content /Context->getResources ()Landroid/content/res/Resources; at com.github .unidbg .linux .android .dvm .AbstractJni .callObjectMethodV (AbstractJni.java :417 )
本想刚才所说的一般步骤走,结果发现这个是Android里的库方法,所以占位即可
1 2 3 case "android/content/Context->getResources()Landroid/content/res/Resources;" : { return vm.resolveClass("android/content/res/Resources" ).newObject(null ); }
接下来是获取资源配置信息
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x120, PC=unidbg@0 xfffe0294, LR=RX@0 x12012e8b[libmtguard.so] 0 x12e8b, syscall=null java.lang .UnsupportedOperationException : android/content /res/Resources->getConfiguration ()Landroid/content/res/Configuration; at com.github .unidbg .linux .android .dvm .AbstractJni .callObjectMethodV (AbstractJni.java :417 )
同样进行占位
1 2 3 case "android/content/res/Resources->getConfiguration()Landroid/content/res/Configuration;" : { return vm.resolveClass("android/content/res/Configuration" ).newObject(null ); }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x15b, PC=unidbg@0 xfffe0644, LR=RX@0 x1201187f[libmtguard.so] 0 x1187f, syscall=null java.lang .UnsupportedOperationException : android/content /res/Configuration->locale:Ljava/util/Locale; at com.github .unidbg .linux .android .dvm .AbstractJni .getObjectField (AbstractJni.java :171 )
获取Configuration
的locale
属性,具体而言,是获取区域信息,locale
在 JDK 里也有,所以改用 createObject
。
1 2 3 case "android/content/res/Configuration->locale:Ljava/util/Locale;" : { return ProxyDvmObject.createObject(vm, Locale.getDefault()); }
接下来还是Build类的报错:TAGS、FINGERPRINT、TYPE。demo跑一下获取对应值,补环境代码如下
1 2 3 4 5 6 7 8 9 case "android/os/Build->TAGS:Ljava/lang/String;" : { return new StringObject (vm, "release-keys" ); }case "android/os/Build->FINGERPRINT:Ljava/lang/String;" : { return new StringObject (vm,"google/marlin/marlin:10/QP1A.191005.007" ); }case "android/os/Build->TYPE:Ljava/lang/String;" : { return new StringObject (vm,"user" ); }
接下来是又是getSysProp
报错,获取的属性是:ro.build.description
、ro.secure
、ro.debuggable
。
adb获取
1 2 3 4 5 6 marlin:/ # getprop | grep ro.build.description [ro.build.description ]: [marlin-user 10 QP1A.191005.007.A3 5972272 release-keys] marlin:/ # getprop | grep ro.secure [ro.secure ]: [1] marlin:/ # getprop | grep ro.debuggable [ro.debuggable ]: [1]
补环境
1 2 3 4 5 case "ro.build.description" : return new StringObject (vm, "marlin-user 10 QP1A.191005.007.A3 5972272 release-keys" );case "ro.secure" :case "ro.debuggable" : return new StringObject (vm, "1" );
最终执行成功
1 getHWProperty call result: marlin|Google |Google |Pixel XL |arm64-v8a |- |marlin |marlin |marlin |marlin |abfarm830 |QP1A.191005.007.A3 |10 |29 |zh |CN |release-keys |google/marlin/marlin:10/QP1A.191005.007 |user |marlin-user 10 QP1A.191005.007.A3 5972272 release-keys |1 |1 |
九、getHWStatus 调用代码
1 2 3 4 5 public String getHWStatus () { return cSIUACollectorObj.callJniMethodObject(emulator, "getHWStatus()Ljava/lang/String;" ) .getValue() .toString(); }
运行报错
1 2 3 4 getSysProp param: persist.sys.usb.config [16:43:17 924] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12023a11[libmtguard.so]0x23a11, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getSysProp(Ljava/lang/String;)Ljava/lang/String; at com.meituan.android.common.mtguard.MyAbstractJni.callObjectMethodV(MyAbstractJni.java:233)
这是在获取设备是否连接了 ADB,因此我返回空字符串,接连三个都是类似的属性。
1 2 3 4 5 case "sys.usb.state" :case "sys.usb.config" :case "persist.sys.usb.config" : { return new StringObject (vm, "" ); }
接下来报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x123, PC=unidbg@0 xfffe02c4, LR=RX@0 x12026075[libmtguard.so] 0 x26075, syscall=null java.lang .UnsupportedOperationException : android/content /pm/PackageManager->hasSystemFeature (Ljava/lang/String;)Z at com.github .unidbg .linux .android .dvm .AbstractJni .callBooleanMethodV (AbstractJni.java :625 )
搜索发现 hasSystemFeature()
判断系统是否有特定的模块功能,这里我们打印参数看看
1 2 3 4 case "android/content/pm/PackageManager->hasSystemFeature(Ljava/lang/String;)Z" : { String arg = (String) vaList.getObjectArg(0 ).getValue(); System.out.println("hasSystemFeature: " + arg); }
发现是检测是否存在加速度传感器
1 hasSystemFeature: android.hardware .sensor .accelerometer
返回 True,然后又检测了不少传感器和硬件支持。
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 case "android/content/pm/PackageManager->hasSystemFeature(Ljava/lang/String;)Z" : { String arg = (String) vaList.getObjectArg(0 ).getValue(); System.out.println("hasSystemFeature: " + arg); switch (arg){ case "android.hardware.sensor.accelerometer" : case "android.hardware.nfc" : case "android.hardware.location.gps" : case "android.hardware.usb.accessory" : case "android.hardware.telephony" : case "android.hardware.bluetooth_le" : case "android.hardware.bluetooth" : case "android.hardware.wifi" : case "android.hardware.sensor.gyroscope" : { return true ; } default : { throw new UnsupportedOperationException (); } } }
期间报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x12f, PC=unidbg@0 xfffe0384, LR=RX@0 x12021bb9[libmtguard.so] 0 x21bb9, syscall=null java.lang .UnsupportedOperationException : com/meituan/android/common/mtguard/NBridge$SIUACollector ->boolean2Integer (Z)I at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :563 )
查看boolean2Integer
发现是将true转成1,false转成0。但是 Unidbg 没法 getBoolean,连这步都节省了。
1 2 3 4 5 6 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->boolean2Integer(Z)I" : { return vaList.getIntArg(0 ); }
继续运行,又是报错getSysProp
,获取的属性是gsm.version.baseband
、gsm.version.ril-impl
、gsm.sim.state
、gsm.sim.state.2
,先adb获取信息,再补环境
1 2 3 4 5 6 7 8 9 10 11 12 case "gsm.version.baseband" : { return new StringObject (vm,"8996-130361-1905270421" ); }case "gsm.version.ril-impl" : { return new StringObject (vm,"Qualcomm RIL 1.0" ); }case "gsm.sim.state" : { return new StringObject (vm,"ABSENT" ); }case "gsm.sim.state.2" : { return new StringObject (vm,"" ); }
接下来报错的是 File
1 2 3 4 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x117, PC=unidbg@0 xfffe0204, LR=RX@0 x1202009d[libmtguard.so] 0 x2009d, syscall=null java.lang .UnsupportedOperationException : java/io/File->allocObject at com.github .unidbg .linux .android .dvm .AbstractJni .allocObject (AbstractJni.java :812 ) at com.meituan .android .common .mtguard .MyAbstractJni .allocObject (MyAbstractJni.java :35 )
File 同样像之前处理,进行占位
1 2 3 case "java/io/File->allocObject" : { return dvmClass.newObject(null ); }
然后是 File 的构造函数报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x13b, PC =unidbg@0xfffe0444, LR =RX@0x1201d887[libmtguard.so]0x1d887, syscall =null java.lang.UnsupportedOperationException: java/io/File-><init>(Ljava/lang/String;)V at com.github.unidbg.linux.android.dvm.AbstractJni.callVoidMethodV(AbstractJni.java:1007)
和先前一样,用全局变量处理,因为担心会初始化多个文件,所以命名为 file1。
先打印看一下是哪个文件
1 2 3 4 case "java/io/File-><init>(Ljava/lang/String;)V" :{ String filePath = vaList.getObjectArg(0 ).getValue().toString(); System.out.println("File-><init> param: " +filePath); }
打印结果如下
1 File -><init> param: /sys/ class /power_supply/ battery/voltage_now
这是电池信息相关的文件。
在 Unidbg 中建立对应的文件,补环境,做重定向。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 case "java/io/File-><init>(Ljava/lang/String;)V" : { String filePath = (String) vaList.getObjectArg(0 ).getValue(); System.out.println("File-><init> param: " + filePath); switch (filePath) { case "/sys/class/power_supply/battery/voltage_now" : { file1 = new File ("unidbg-android/src/test/resources/dazhongdianping/voltage_now" ); break ; } default :{ throw new UnsupportedOperationException (); } } return ; }
继续运行,报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x123, PC=unidbg@0 xfffe02c4, LR=RX@0 x1201dc27[libmtguard.so] 0 x1dc27, syscall=null java.lang .UnsupportedOperationException : java/io/File->exists ()Z at com.github .unidbg .linux .android .dvm .AbstractJni .callBooleanMethodV (AbstractJni.java :625 )
很明显,这里是判断刚才创建的file1是否存在,补环境代码如下
1 2 3 case "java/io/File->exists()Z" : { return file1.exists(); }
然后样本开始处理另一个文件
1 2 3 4 File-><init> param: /sys/class/power_supply/battery/temp [17:27:35 259] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x13b, PC =unidbg@0xfffe0444, LR =RX@0x12026601[libmtguard.so]0x26601, syscall =null java.lang.UnsupportedOperationException at com.meituan.android.common.mtguard.MyAbstractJni.callVoidMethodV(MyAbstractJni.java:87)
补环境
1 2 3 4 case "/sys/class/power_supply/battery/temp" : { file2 = new File ("unidbg-android/src/test/resources/dazhongdianping/temp" ); break ; }
由于存在多个文件的使用,因此将java/io/File->exists()Z
的处理改为始终返回true
,因为样本所使用的两个文件我们都弄到了unidbg项目中,所以是存在的。
1 2 3 case "java/io/File->exists()Z" : { return true ; }
最后一个报错
1 2 3 4 getSysProp param: wifi.interface [17:18:47 564] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1201f0a3[libmtguard.so]0x1f0a3, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getSysProp(Ljava/lang/String;)Ljava/lang/String; at com.meituan.android.common.mtguard.MyAbstractJni.callObjectMethodV(MyAbstractJni.java:262)
adb获取信息并添加wifi.interface
分支
1 2 3 case "wifi.interface" : { return new StringObject (vm,"wlan0" ); }
最终运行成功,结果如下
1 getHWStatus call result: -|- |- |1 |1 |8996-130361-1905270421 |Qualcomm RIL 1.0 |ABSENT |- |0 |0 |1 |wlan0 |1 |1 |1 |1 |1 |1 |1 |
十、getLocationInfo 调用代码
1 2 3 4 5 public String getLocationInfo () { return cSIUACollectorObj.callJniMethodObject(emulator, "getLocationInfo()Ljava/lang/String;" ) .getValue() .toString(); }
运行报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12053cf7[libmtguard.so]0x53cf7, syscall =null java.lang.UnsupportedOperationException: android/net/wifi/WifiManager->getConnectionInfo()Landroid/net/wifi/WifiInfo; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
android的库函数,而且返回的是android库函数里的对象,那只能占位处理
1 2 3 case "android/net/wifi/WifiManager->getConnectionInfo()Landroid/net/wifi/WifiInfo;" : { return vm.resolveClass("android/net/wifi/WifiInfo" ).newObject(null ); }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12058323[libmtguard.so]0x58323, syscall =null java.lang.UnsupportedOperationException: android/net/wifi/WifiInfo->getSSID()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
搜索getSSID
发现是获取wifi名称,查看手机所连接的 WIFI 名,做补环境
1 2 3 case "android/net/wifi/WifiInfo->getSSID()Ljava/lang/String;" : { return new StringObject (vm, "CMCC" ); }
接下来报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x123, PC =unidbg@0xfffe02c4, LR =RX@0x1205980f[libmtguard.so]0x5980f, syscall =null java.lang.UnsupportedOperationException: java/lang/String->equalsIgnoreCase(Ljava/lang/String;)Z at com.github.unidbg.linux.android.dvm.AbstractJni.callBooleanMethodV(AbstractJni.java:625)
jdk函数,按照之前所提到的步骤走就行
1 2 3 4 5 6 7 8 9 10 case "java/lang/String->equalsIgnoreCase(Ljava/lang/String;)Z" : { String arg = vaList.getObjectArg(0 ).getValue().toString(); String obj = (String) dvmObject.getValue(); Boolean result = obj.equalsIgnoreCase(arg); return result; }
然后报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x123, PC =unidbg@0xfffe02c4, LR =RX@0x120508b3[libmtguard.so]0x508b3, syscall =null java.lang.UnsupportedOperationException: java/lang/String->equals(Ljava/lang/Object;)Z at com.github.unidbg.linux.android.dvm.AbstractJni.callBooleanMethodV(AbstractJni.java:625)
处理类似
1 2 3 4 5 6 7 8 9 10 case "java/lang/String->equals(Ljava/lang/Object;)Z" : { String arg = vaList.getObjectArg(0 ).getValue().toString(); String obj = (String) dvmObject.getValue(); Boolean result = obj.equals(arg); return result; }
报错,仍旧是跟String类相关的
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x12f, PC=unidbg@0 xfffe0384, LR=RX@0 x120549c9[libmtguard.so] 0 x549c9, syscall=null java.lang .UnsupportedOperationException : java/lang/String->length ()I at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :563 )
处理类似
1 2 3 4 5 6 7 8 case "java/lang/String->length()I" : { String obj = (String) dvmObject.getValue(); int length = obj.length(); return length; }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x120577c7[libmtguard.so]0x577c7, syscall =null java.lang.UnsupportedOperationException: java/lang/StringBuilder->append(Ljava/lang/CharSequence;II)Ljava/lang/StringBuilder; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
都是以前见过的,处理起来很顺手
1 2 3 4 5 6 7 8 9 10 11 12 case "java/lang/StringBuilder->append(Ljava/lang/CharSequence;II)Ljava/lang/StringBuilder;" : { StringBuilder builder = (StringBuilder) dvmObject.getValue(); CharSequence sequence = (CharSequence) vaList.getObjectArg(0 ).getValue(); int start = vaList.getIntArg(1 ); int end = vaList.getIntArg(2 ); StringBuilder newBuilder = builder.append(sequence, start, end); return ProxyDvmObject.createObject(vm,newBuilder); }
报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x120515e3[libmtguard.so]0x515e3, syscall =null java.lang.UnsupportedOperationException: android/net/wifi/WifiInfo->getBSSID()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
getBSSID
获取的是WIFI的MAC地址,直接ifconfig获取,或者写个Android demo也行。补环境
1 2 3 case "android/net/wifi/WifiInfo->getBSSID()Ljava/lang/String;" : { return new StringObject (vm, "ac:37:43:48:ec:7a" ); }
然后还是WIFI相关报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x12f, PC=unidbg@0 xfffe0384, LR=RX@0 x12050943[libmtguard.so] 0 x50943, syscall=null java.lang .UnsupportedOperationException : android/net/wifi/WifiInfo->getRssi ()I at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :563 )
getRssi
获取WIFI强度,范围值是 -100到0之前,值越大表示信号越好,补环境时随便返回一个数即可
1 2 3 case "android/net/wifi/WifiInfo->getRssi()I" : { return -10 ; }
接下来TelephonyManager
报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12058f2f[libmtguard.so]0x58f2f, syscall =null java.lang.UnsupportedOperationException: android/telephony/TelephonyManager->getNetworkOperator()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
getNetworkOperator()
方法用于获取当前设备所连接的移动网络的运营商标识符,返回值的格式通常是 MCCMNC
,这是我们前面遇到的情况,仍然返回46000
1 2 3 case "android/telephony/TelephonyManager->getNetworkOperator()Ljava/lang/String;" : { return new StringObject (vm,"46000" ); }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x120588d3[libmtguard.so]0x588d3, syscall =null java.lang.UnsupportedOperationException: java/lang/String->substring(I)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
jdk函数,处理简单
1 2 3 4 5 6 7 8 9 10 case "java/lang/String->substring(I)Ljava/lang/String;" : { String obj = (String) dvmObject.getValue(); int arg = vaList.getIntArg(0 ); String result = obj.substring(arg); return new StringObject (vm,result); }
最后成功运行
1 getLocationInfo call result: -|- |MC |ac:37:43:48:ec:7a |1 |-10 |460 |00 |- |
调用代码
1 2 3 4 5 public String getPlatformInfo () { return cSIUACollectorObj.callJniMethodObject(emulator, "getPlatformInfo()Ljava/lang/String;" ) .getValue() .toString(); }
运行报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x117, PC =unidbg@0xfffe0204, LR =RX@0x120479cd[libmtguard.so]0x479cd, syscall =null java.lang.UnsupportedOperationException: java/text/SimpleDateFormat->allocObject at com.github.unidbg.linux.android.dvm.AbstractJni.allocObject(AbstractJni.java:812)
进行占位处理。
1 2 3 4 5 case "java/text/SimpleDateFormat->allocObject" : { return dvmClass.newObject(null ); }
接下来是它的构造函数报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x13b, PC =unidbg@0xfffe0444, LR =RX@0x12047cf3[libmtguard.so]0x47cf3, syscall =null java.lang.UnsupportedOperationException: java/text/SimpleDateFormat-><init>(Ljava/lang/String;Ljava/util/Locale;)V at com.github.unidbg.linux.android.dvm.AbstractJni.callVoidMethodV(AbstractJni.java:1007)
处理为全局变量,然后补环境。
1 2 3 4 5 6 7 8 case "java/text/SimpleDateFormat-><init>(Ljava/lang/String;Ljava/util/Locale;)V" : { String pattern = (String) vaList.getObjectArg(0 ).getValue(); Locale locale = (Locale) vaList.getObjectArg(1 ).getValue(); dataFormat = new SimpleDateFormat (pattern, locale); return ; }
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x18d, PC =unidbg@0xfffe0964, LR =RX@0x120476db[libmtguard.so]0x476db, syscall =null java.lang.UnsupportedOperationException: android/os/Build$VERSION ->SDK:Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.getStaticObjectField(AbstractJni.java:103)
获取sdk版本,跟之前的对上就行
1 2 3 case "android/os/Build$VERSION->SDK:Ljava/lang/String;" : { return new StringObject (vm,"29" ); }
报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x117, PC =unidbg@0xfffe0204, LR =RX@0x12047a29[libmtguard.so]0x47a29, syscall =null java.lang.UnsupportedOperationException: java/util/Date->allocObject at com.github.unidbg.linux.android.dvm.AbstractJni.allocObject(AbstractJni.java:812)
补环境
1 2 3 case "java/util/Date->allocObject" : { return dvmClass.newObject(null ); }
接下来是它的init
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x13b, PC =unidbg@0xfffe0444, LR =RX@0x1204aa6b[libmtguard.so]0x4aa6b, syscall =null java.lang.UnsupportedOperationException: java/util/Date-><init>()V at com.github.unidbg.linux.android.dvm.AbstractJni.callVoidMethodV(AbstractJni.java:1007)
由于这是一个无参构造 ,可以回头修改 allocObject 那儿的代码,使得思路更流畅。
1 2 3 4 5 case "java/util/Date->allocObject" : { Date date = new Date (); return ProxyDvmObject.createObject(vm, date); }
然后下面初始化时就不用做什么了
1 2 3 case "java/util/Date-><init>()V" :{ return ; }
做个小结,带参的init必须全局化变量处理,对应的allocObject仅占位即可,对于不带参的init,在allocObject中可以创建实例对象并返回,然后init处仅需return即可(目前开来是jdk库函数适合)
继续报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12048993[libmtguard.so]0x48993, syscall =null java.lang.UnsupportedOperationException: java/text/SimpleDateFormat->format(Ljava/util/Date;)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
补环境
1 2 3 4 5 6 7 8 9 10 case "java/text/SimpleDateFormat->format(Ljava/util/Date;)Ljava/lang/String;" : { Date date = (Date) vaList.getObjectArg(0 ).getValue(); String result = dataFormat.format(date); return new StringObject (vm, result); }
报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x12f, PC=unidbg@0 xfffe0384, LR=RX@0 x1204845f[libmtguard.so] 0 x4845f, syscall=null java.lang .UnsupportedOperationException : com/meituan/android/common/mtguard/NBridge$SIUACollector ->androidAppCnt (Landroid/content /Context;)I at com.github .unidbg .linux .android .dvm .AbstractJni .callIntMethodV (AbstractJni.java :563 )
jadx 中看 androidAppCnt 的实现
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 public static int androidAppCnt (Context context) { int i; Object[] objArr = {context}; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, null , changeQuickRedirect2, true , "e2af58080aad5d311267bb7c71e6cce2" , RobustBitConfig.DEFAULT_VALUE)) { return ((Integer) PatchProxy.accessDispatch(objArr, null , changeQuickRedirect2, true , "e2af58080aad5d311267bb7c71e6cce2" )).intValue(); } int i2 = androidAppCntCache; if (i2 != 0 ) { return i2; } if (context == null ) { return 0 ; } if (Thread.currentThread() == Looper.getMainLooper().getThread()) { return androidAppCntCache; } try { lock.lock(); } catch (Throwable th) { c.a(th); } if (androidAppCntCache != 0 ) { i = androidAppCntCache; } else { PackageManager pkgManager = getPkgManager(context); if (pkgManager == null ) { i = androidAppCntCache; } else { androidAppCntCache = pkgManager.getInstalledApplications(128 ).size(); lock.unlock(); return androidAppCntCache; } } lock.unlock(); return i; }
getInstalledApplications
用于获取设备上已安装的应用程序列表,整个代码逻辑就是在获取设备安装了多少 App,补环境时返回一个合适的数就行。
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->androidAppCnt(Landroid/content/Context;)I" : { return 50 ; }
然后又报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12048f23[libmtguard.so]0x48f23, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->appCache(Landroid/content/Context;)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
appCache
函数如下,主要功能是获取当前 Android 应用的缓存大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static synchronized String appCache (Context context) { synchronized (AppInfoWorker.class) { Object[] objArr = {context}; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, null , changeQuickRedirect2, true , "cf8fe1c6518d456cb61aad67de922620" , RobustBitConfig.DEFAULT_VALUE)) { return (String) PatchProxy.accessDispatch(objArr, null , changeQuickRedirect2, true , "cf8fe1c6518d456cb61aad67de922620" ); } else if (appCacheSizeCache != null ) { return appCacheSizeCache; } else if (context == null ) { return "unknown" ; } else { long fileSize = FileUtils.getFileSize(context.getCacheDir(), true ) + FileUtils.getFileSize(context.getFilesDir(), true ) + FileUtils.getFileSize(new File (context.getFilesDir().getPath() + File.separator + context.getPackageName() + "/shared_prefs" ), true ); if (Environment.getExternalStorageState().equals("mounted" )) { fileSize += FileUtils.getFileSize(context.getCacheDir(), true ); } String str = fileSize + "" ; appCacheSizeCache = str; return str; } } }
Frida Hook获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function test ( ){ Java .perform ( function ( ){ let SIUACollector = Java .use ("com.meituan.android.common.mtguard.NBridge$SIUACollector" ); SIUACollector ["appCache" ].implementation = function (context ) { console .log (`SIUACollector.appCache is called: context=${context} ` ); let result = this ["appCache" ](context); console .log (`SIUACollector.appCache result=${result} ` ); return result; }; var currentApplication = Java .use ('android.app.ActivityThread' ).currentApplication (); var context = currentApplication.getApplicationContext (); SIUACollector .$new(context).appCache (context); } ); }
结果如下
1 2 SIUACollector.appCache is called: context =com.dianping.v1.NovaHydraApplication@1fc5fc1 SIUACollector.appCache result =96458538
补环境代码如下
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->appCache(Landroid/content/Context;)Ljava/lang/String;" : { return new StringObject (vm,"96458538" ); }
报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1204adf7[libmtguard.so]0x4adf7, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->availableSystem()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
availableSystem
代码逻辑如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public static String availableSystem () { Object[] objArr = new Object [0 ]; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, null , changeQuickRedirect2, true , "234b4d16d3aab7d4062d61d2146219de" , RobustBitConfig.DEFAULT_VALUE)) { return (String) PatchProxy.accessDispatch(objArr, null , changeQuickRedirect2, true , "234b4d16d3aab7d4062d61d2146219de" ); } try { File dataDirectory = Environment.getDataDirectory(); if (readable(dataDirectory)) { StatFs statFs = new StatFs (dataDirectory.getPath()); return StringUtils.toString(statFs.getAvailableBlocks() * statFs.getBlockSize()); } return "unknown" ; } catch (Throwable th) { c.a(th); return "unknown" ; } }
返回值都是”unknown”,所以补环境时也这样返回
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->availableSystem()Ljava/lang/String;" : { return new StringObject (vm,"unknown" ); }
报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1204a037[libmtguard.so]0x4a037, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->totalMemory()Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
totalMemory
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static String totalMemory () { Object[] objArr = new Object [0 ]; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, null , changeQuickRedirect2, true , "a240e07aebe4d91708d281e29b9fc189" , RobustBitConfig.DEFAULT_VALUE)) { return (String) PatchProxy.accessDispatch(objArr, null , changeQuickRedirect2, true , "a240e07aebe4d91708d281e29b9fc189" ); } try { FileReader fileReader = new FileReader ("/proc/meminfo" ); BufferedReader bufferedReader = new BufferedReader (fileReader); bufferedReader.close(); fileReader.close(); return StringUtils.toString(Long.valueOf(bufferedReader.readLine().split("\\s+" )[1 ]).intValue() * 1024 ); } catch (Throwable th) { c.a(th); return "unknown" ; } }
获取”/proc/meminfo”文件的第一行,取分隔后的第二个值乘以1024返回。这里 frida hook 或者 查看对应文件都可以,具体操作不展示。
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->totalMemory()Ljava/lang/String;" : { return new StringObject (vm, "3948355584" ); }
报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x1204d603[libmtguard.so]0x4d603, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getFirstLaunchTime(Landroid/content/Context;)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
getFirstLaunchTime
顾名思义,获取应用程序首次启动的时间。
同样还是 frida hook返回值,补环境代码如下
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getFirstLaunchTime(Landroid/content/Context;)Ljava/lang/String;" : { return new StringObject (vm,"1732634813346" ); }
最终运行成功,结果如下
1 getPlatformInfo call result: Android|com.dianping.v1|10 .41 .15 |29 |-|2024 -11 -28 15 :33 :42 :042 |50 |96458538 |-|3948355584 |1732634813346 |-|-|
十二、getUserAction 调用代码
1 2 3 4 5 public String getUserAction () { return cSIUACollectorObj.callJniMethodObject(emulator, "getUserAction()Ljava/lang/String;" ) .getValue() .toString(); }
运行报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x15b, PC=unidbg@0 xfffe0644, LR=RX@0 x120424c5[libmtguard.so]0 x424c5, syscall=null java.lang.UnsupportedOperationException: com/meituan/ android/common/m tguard/NBridge$SIUACollector->batteryHelper:Lcom/m eituan/android/ common/dfingerprint/ collection/utils/ BatteryHelper; at com.github.unidbg.linux.android.dvm.AbstractJni.getObjectField(AbstractJni.java:171 )
获取batteryHelper
实例对象报错,这里直接占位处理,后面肯定会遇到与它相关的函数调用的。
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->batteryHelper:Lcom/meituan/android/common/dfingerprint/collection/utils/BatteryHelper;" : { return vm.resolveClass("com/meituan/android/common/dfingerprint/collection/utils/BatteryHelper" ).newObject(signature); }
果真没错,继续运行报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538 ) - handleInterrupt intno=2 , NR=-452987096 , svcNumber=0 x123, PC=unidbg@0 xfffe02c4, LR=RX@0 x120414af[libmtguard.so] 0 x414af, syscall=null java.lang .UnsupportedOperationException : com/meituan/android/common/mtguard/NBridge$SIUACollector ->getBatteryInfo ()Z at com.github .unidbg .linux .android .dvm .AbstractJni .callBooleanMethodV (AbstractJni.java :625 )
查看getBatteryInfo
代码,是在获取电源状态信息
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 private boolean getBatteryInfo () { Object[] objArr = new Object [0 ]; ChangeQuickRedirect changeQuickRedirect2 = changeQuickRedirect; if (PatchProxy.isSupport(objArr, this , changeQuickRedirect2, false , "2d10aac5384d6818e2765f99df76bffe" , RobustBitConfig.DEFAULT_VALUE)) { return ((Boolean) PatchProxy.accessDispatch(objArr, this , changeQuickRedirect2, false , "2d10aac5384d6818e2765f99df76bffe" )).booleanValue(); } Context context = this .mContext; if (context == null ) { return false ; } BatteryStatus batteryStatus = BatteryHelper.getInstance(context).getBatteryStatus(); this .level = batteryStatus.batteryLevel; this .scale = batteryStatus.batteryScale; int i = batteryStatus.batteryStatus; int i2 = batteryStatus.batteryPlugged; if (i == 2 && i2 == 2 ) { this .status = 1 ; } else { this .status = 0 ; } if (i2 == 2 ) { this .plugged = true ; } else { this .plugged = false ; } return true ; }
选择返回true,这意味着获取到了电源状态信息,补环境代码如下
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getBatteryInfo()Z" : { return true ; }
运行报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x160, PC =unidbg@0xfffe0694, LR =RX@0x120458d9[libmtguard.so]0x458d9, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->level:I at com.github.unidbg.linux.android.dvm.AbstractJni.getIntField(AbstractJni.java:648)
在刚才的getBatteryInfo
代码中进行了赋值,它代表的是电池当前的电量级别。
接下来报错是关于这四个属性的获取,即level
、scale
、status
、plugged
。
查看实例中某些字段的值,这个场景用 r0tracer 会很舒服,尤其是批量追踪包含某个关键字的所有类 。我这里手写hook脚本,由于我是attach模式下进行hook,尝试使用java.choose()
搜索SIUACollector
实例,并没有找到,但可以通过主动调用getBatteryInfo
,然后获取字段值。
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 function test ( ){ Java .perform ( function ( ){ let SIUACollector = Java .use ("com.meituan.android.common.mtguard.NBridge$SIUACollector" ); SIUACollector ["getBatteryInfo" ].implementation = function ( ) { console .log (`SIUACollector.getBatteryInfo is called` ); let result = this ["getBatteryInfo" ](); console .log (`SIUACollector.getBatteryInfo result=${result} ` ); return result; }; var currentApplication = Java .use ('android.app.ActivityThread' ).currentApplication (); var context = currentApplication.getApplicationContext (); var collector = SIUACollector .$new(context); collector.getBatteryInfo (); console .log ("level: " + collector.level .value ); console .log ("scale: " + collector.scale .value ); console .log ("status: " + collector.status .value ); console .log ("plugged: " + collector.plugged .value ); } ); }
hook 结果如下
1 2 3 4 5 6 SIUACollector.getBatteryInfo is called SIUACollector.getBatteryInfo result=true level: 100 scale: 100 status: 0 plugged: true
补环境代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Override public int getIntField (BaseVM vm, DvmObject<?> dvmObject, String signature) { switch (signature) { case "com/meituan/android/common/mtguard/NBridge$SIUACollector->level:I" : case "com/meituan/android/common/mtguard/NBridge$SIUACollector->scale:I" : { return 100 ; } case "com/meituan/android/common/mtguard/NBridge$SIUACollector->status:I" : { return 0 ; } } return super .getIntField(vm, dvmObject, signature); }@Override public boolean getBooleanField (BaseVM vm, DvmObject<?> dvmObject, String signature) { switch (signature) { case "com/meituan/android/common/mtguard/NBridge$SIUACollector->plugged:Z" : { return true ; } } return super .getBooleanField(vm, dvmObject, signature); }
接下来报错
1 2 3 WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno =2, NR =-452987096, svcNumber =0x120, PC =unidbg@0xfffe0294, LR =RX@0x12042d93[libmtguard.so]0x42d93, syscall =null java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector ->getDataActivity(Landroid/content/Context;)Ljava/lang/String; at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
还是 frida hook 返回值,然后补环境
1 2 3 case "com/meituan/android/common/mtguard/NBridge$SIUACollector->getDataActivity(Landroid/content/Context;)Ljava/lang/String;" : { return new StringObject (vm,"0" ); }
最终运行成功,结果如下
1 getUserAction call result: -|100 |1 |0 |1 |-|52706 c36-ec3d-4 d2a-9 e35-d11bd1580e5f|0 |
十三、参考 [Unidbg 的基本使用(六)](https://www.yuque.com/lilac-2hqvv/xdwlsg/avlc01hrko6yvr26?# 《Unidbg 的基本使用(六)》)