从案例中学习unidbg的使用(五)

一、引言

目标 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);

// 使用 libandroid.so 虚拟模块, 需早于目标 SO 加载的时机
// new AndroidModule(emulator, vm).register(memory);
// 使用 libjnigraphics.so 的虚拟模块
// new JniGraphics(emulator, vm).register(memory);

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
// 使用 libandroid.so 虚拟模块, 需早于目标 SO 加载的时机
new AndroidModule(emulator, vm).register(memory);
// 使用 libjnigraphics.so 的虚拟模块
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|

五、getEnvironmentInfoExtra

调用代码如下

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@0x12005f5d[libmtguard.so]0x5f5d
[14:19:27 954] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x117, PC=unidbg@0xfffe0204, LR=RX@0x12007443[libmtguard.so]0x7443, 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) => 0xad81ca9c was called from RX@0x12006369[libmtguard.so]0x6369
[14:24:36 014] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x13b, PC=unidbg@0xfffe0444, LR=RX@0x120095f1[libmtguard.so]0x95f1, 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;": {
// 把之前运行getEnvironmentInfo得到的结果封装给unidbg
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;) => 0x7b1bffd9 was called from RX@0x12006369[libmtguard.so]0x6369
[14:36:50 617] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x120, PC=unidbg@0xfffe0294, LR=RX@0x120085d9[libmtguard.so]0x85d9, 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();
//执行append
builder.append(arg1);
// 封装给unidbg
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;) => 0xc458fdce was called from RX@0x1200668b[libmtguard.so]0x668b
[14:44:50 042] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x15b, PC=unidbg@0xfffe0644, LR=RX@0x120090c9[libmtguard.so]0x90c9, 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/mtguard/NBridge$SIUACollector.brightness(Landroid/content/Context;)Ljava/lang/String;) => 0x2437a7e4 was called from RX@0x12006369[libmtguard.so]0x6369
[14:48:49 208] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x120, PC=unidbg@0xfffe0294, LR=RX@0x12009cbb[libmtguard.so]0x9cbb, syscall=null
java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/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
/**
* 获取系统默认屏幕亮度值 屏幕亮度值范围(0-255)
* **/
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/mtguard/NBridge$SIUACollector.systemVolume(Landroid/content/Context;)Ljava/lang/String;) => 0x80b60b0c was called from RX@0x12006369[libmtguard.so]0x6369
[14:51:10 180] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x120, PC=unidbg@0xfffe0294, LR=RX@0x1200980b[libmtguard.so]0x980b, syscall=null
java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/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 "";
}
}

搜索getStreamVolumegetStreamMaxVolume可以获知相关信息,我这里直接返回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) => 0xf45f6eaa was called from RX@0x12006369[libmtguard.so]0x6369
[14:53:26 404] WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x123, PC=unidbg@0xfffe02c4, LR=RX@0x12007a8f[libmtguard.so]0x7a8f, 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.valueOf
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=0x12f, PC=unidbg@0xfffe0384, LR=RX@0x12007c73[libmtguard.so]0x7c73, 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对象
StringBuilder builder = (StringBuilder) dvmObject.getValue();
// 执行 toString
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=0x120, PC=unidbg@0xfffe0294, LR=RX@0x1203ddd7[libmtguard.so]0x3ddd7, 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;" {
// 先占位,后续报错再frida hook 具体值解决
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": {
//String permissionName = vaList.getObjectArg(0).getValue().toString();
//System.out.println("check permission:"+permissionName);
// 权限都给
return true;
}

继续运行,报错

1
2
3
4
[15:19:04 185]  WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x192, PC=unidbg@0xfffe09b4, LR=RX@0x1203c723[libmtguard.so]0x3c723, 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": {
//返回sdk版本
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(){
// 获取 TelephonyManager 类
var TelephonyManager = Java.use("android.telephony.TelephonyManager");

// 获取系统上下文
var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
var context = currentApplication.getApplicationContext();

// 获取 TelephonyManager 的实例
var telephonyManager = context.getSystemService("phone");
var TelephonyManager = Java.use("android.telephony.TelephonyManager");
telephonyManager = Java.cast(telephonyManager, TelephonyManager);//强转类型,否则无法调用getDeviceId
// 主动调用 getDeviceId()
var deviceId = telephonyManager.getDeviceId();

console.log("Active Device ID: " + deviceId);

}
);
}

结果如下!?(也许哪里出错了)

1
Active Device ID: null

由于返回值是String,所以将null封装成StringObject

1
2
3
4
case "android/telephony/TelephonyManager->getDeviceId()Ljava/lang/String;": {
//frida hook 获取对应值
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=0x12f, PC=unidbg@0xfffe0384, LR=RX@0x1203a291[libmtguard.so]0x3a291, 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();
//执行append
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();
//执行append
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=0x12f, PC=unidbg@0xfffe0384, LR=RX@0x1203e717[libmtguard.so]0x3e717, 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=24GB

补环境代码如下

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=24GB

补环境代码如下

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(){
// 获取 TelephonyManager 类
var TelephonyManager = Java.use("android.telephony.TelephonyManager");

// 获取系统上下文
var currentApplication = Java.use('android.app.ActivityThread').currentApplication();
var context = currentApplication.getApplicationContext();

// 获取 TelephonyManager 的实例
var telephonyManager = context.getSystemService("phone");
var TelephonyManager = Java.use("android.telephony.TelephonyManager");
telephonyManager = Java.cast(telephonyManager, TelephonyManager);//强转类型,否则无法调用getDeviceId
// 主动调用 getSimOperator()
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;//"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;//"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=0x117, PC=unidbg@0xfffe0204, LR=RX@0x1202bcef[libmtguard.so]0x2bcef, 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": {
//这里的 dvmClass 等价于vm.resolveClass("java/io/BufferedReader")
return dvmClass.newObject(null);
//return vm.resolveClass("java/io/BufferedReader").newObject(null);
}

接下来是InputStreamReaderallocObject

1
2
3
4
WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x117, PC=unidbg@0xfffe0204, LR=RX@0x1202a687[libmtguard.so]0x2a687, 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);
}

然后是FileInputStreamallocObject

1
2
3
4
WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:538) - handleInterrupt intno=2, NR=-452987096, svcNumber=0x117, PC=unidbg@0xfffe0204, LR=RX@0x1202c66f[libmtguard.so]0x2c66f, 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)

这是个重点!!!之前我们对于FileInputStreamallocObject仅仅只是做了占位处理,而且因为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=0x13b, PC=unidbg@0xfffe0444, LR=RX@0x12030391[libmtguard.so]0x30391, 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;
}

接下来是InputStreamReaderinit,做同样处理,先全局声明

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;
}

之后是BufferedReaderinit,做同样处理,先全局声明

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=0x13b, PC=unidbg@0xfffe0444, LR=RX@0x1202bcbf[libmtguard.so]0x2bcbf, 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) {
// TODO: need to be smarter, for now, just return the 1st sensor
List<Sensor> l = getSensorList(type);
boolean wakeUpSensor = false;
// For the following sensor types, return a wake-up sensor. These types are by default
// defined as wake-up sensors. For the rest of the SDK defined sensor types return a
// non_wake-up version.
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
Sensor type:1

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
BMI160 accelerometer

补环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case "android/hardware/Sensor->getName()Ljava/lang/String;": {
// 不是安卓环境,用不了android的Sensor
// Sensor sensor = (Sensor) dvmObject.getValue();
// 获取的是type!?
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
Bosch

补环境

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);
}

结果如下

1
marlin

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
//demo
public void getManufacturer(){
Log.e("gal2xy", "getManufacturer: " + Build.MANUFACTURER);
}
//结果
getManufacturer: Google

//adb
> 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=0x120, PC=unidbg@0xfffe0294, LR=RX@0x120102b3[libmtguard.so]0x102b3, 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=0x120, PC=unidbg@0xfffe0294, LR=RX@0x12012e8b[libmtguard.so]0x12e8b, 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=0x15b, PC=unidbg@0xfffe0644, LR=RX@0x1201187f[libmtguard.so]0x1187f, 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)

获取Configurationlocale属性,具体而言,是获取区域信息,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.descriptionro.securero.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=0x123, PC=unidbg@0xfffe02c4, LR=RX@0x12026075[libmtguard.so]0x26075, 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":
// nfc
case "android.hardware.nfc":
// gps
case "android.hardware.location.gps":
// USB 配件API
case "android.hardware.usb.accessory":
// 电话
case "android.hardware.telephony":
// 蓝牙低功耗
case "android.hardware.bluetooth_le":
// 蓝牙
case "android.hardware.bluetooth":
// wifi
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=0x12f, PC=unidbg@0xfffe0384, LR=RX@0x12021bb9[libmtguard.so]0x21bb9, 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": {
//获取参数
//Boolean arg = (Boolean) vaList.getObjectArg(0).getValue();//获取的是null!?
//return arg ? 1 : 0;
return vaList.getIntArg(0);
}

继续运行,又是报错getSysProp,获取的属性是gsm.version.basebandgsm.version.ril-implgsm.sim.stategsm.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=0x117, PC=unidbg@0xfffe0204, LR=RX@0x1202009d[libmtguard.so]0x2009d, 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=0x123, PC=unidbg@0xfffe02c4, LR=RX@0x1201dc27[libmtguard.so]0x1dc27, 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=0x12f, PC=unidbg@0xfffe0384, LR=RX@0x120549c9[libmtguard.so]0x549c9, 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=0x12f, PC=unidbg@0xfffe0384, LR=RX@0x12050943[libmtguard.so]0x50943, 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|-|

十一、getPlatformInfo

调用代码

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);
//或者
// return dvmClass.newObject(new SimpleDateFormat());
}

接下来是它的构造函数报错

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 dvmClass.newObject(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();
//获取实例对象, 实例对象就是刚才全局化的dataFormat
// SimpleDateFormat dateFormat = (SimpleDateFormat) dvmObject.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=0x12f, PC=unidbg@0xfffe0384, LR=RX@0x1204845f[libmtguard.so]0x4845f, 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=0x15b, PC=unidbg@0xfffe0644, LR=RX@0x120424c5[libmtguard.so]0x424c5, syscall=null
java.lang.UnsupportedOperationException: com/meituan/android/common/mtguard/NBridge$SIUACollector->batteryHelper:Lcom/meituan/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=0x123, PC=unidbg@0xfffe02c4, LR=RX@0x120414af[libmtguard.so]0x414af, 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;//电池当前的电量级别(例如,0 到 100 之间的整数值)。
this.scale = batteryStatus.batteryScale;//电池的最大电量。
int i = batteryStatus.batteryStatus;//电池的充电状态,值为:1 表示充电。2 表示正在放电。3 表示电池状态未知。
int i2 = batteryStatus.batteryPlugged;//电池是否插电,值为:1 表示充电器插入(比如 USB 插入)。2 表示通过电源适配器(如电源插座)插电充电。0 表示没有插电。
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代码中进行了赋值,它代表的是电池当前的电量级别。

接下来报错是关于这四个属性的获取,即levelscalestatusplugged

查看实例中某些字段的值,这个场景用 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|-|52706c36-ec3d-4d2a-9e35-d11bd1580e5f|0|

十三、参考

[Unidbg 的基本使用(六)](https://www.yuque.com/lilac-2hqvv/xdwlsg/avlc01hrko6yvr26?# 《Unidbg 的基本使用(六)》)


从案例中学习unidbg的使用(五)
http://example.com/2024/12/05/Unidbg模拟执行/从案例中学习unidbg的使用(五)/
作者
gla2xy
发布于
2024年12月5日
许可协议