Root Detection Bypass - Early Instrumentation

笔者近日在测试一只 Android App 的时候, 发现常规的 hooking 并不能正常地使用. 尽管已经动态修改了 isRooted的返回值, App 依旧提示手机是 Root 的.

由于 App 用了 Proguard, 使用Jadx-GUI decompile 的 code, 并未能正确地反应实际写法. 经过一轮的搜索, 按字面估计以下 class 是用来判断手机是否 root 的.

// com/package/company/abc.java

private static /* synthetic */ boolean[] a() {
    boolean[] zArr = b;
    if (zArr != null) {
        return zArr;
    }
    zArr = Offline.getProbes(485531345684164119L, "com/package/company/RootManager", 69);
    b = zArr;
    return zArr;
}

幸好 App 是 In-House 开发的, 能拿到源码.

// com/package/company/RootManager

public static boolean isRooted() {
    return checkRoot1() || checkRoot2() || checkRoot3() || checkRoot4() || checkRoot5();
}

后来结合 Brida, 对比之后确定 abc.java的确是检测 Root 的 class. 于是, 就撰写代码

var myclass = Java.use("com.package.company.abc");
myclass.f.overload().implementation = function(){
	return false;
}	
myclass.b.overload().implementation = function(){
	return false;
}	
myclass.c.overload().implementation = function(){
	return false;
}	
myclass.d.overload().implementation = function(){
	return false;
}	
myclass.e.overload().implementation = function(){
	return false;
}
myclass.a.overload().implementation = function(){
	return false;
}

当我满怀希望地运行 command 的时候, 结果却令人失望. 每点界面上的 Login, SignUp 按钮, App 都提示手机是 Root 的.

$ frida -U -f com.package.company -l root-bypass.js --no-pause

后来我回想到Frida - Learn by Example 一文中Example 3. 看来是 onCreate 的问题.

于是一轮搜索后, 我们来到了 MyActivity. 然而 Proguard 过后的 class 依然惨不忍睹. 苦无对策之时, 笔者在 Google 中看到 @enovella在 GitHub 上创建以下一个Issue - Early instrumentation: Intercepting method onCreate() from MainActivity on Android ART.

Issue 大概的内容就是, 无法 hook 第一个加载的 class, 假如这个 class 是从 class - Activity 中 extend 过来.

public class MainActivity extends Activity{

}

@jhscheer@enovella 分别给出了他们的 solution. 他们说, 部分机型需要按 Home 将 App 放到背景中, 然后点击 App Icon 重新打开 App, Hooking 才生效.

笔者在华为畅玩4, Lingeage OS 14.1 上直接就成功了, 无需将 App 放到背景, 重新打开.

➜  frida -U -f com.package.company -l root-bypass.js --no-pause
     ____
    / _  |   Frida 10.7.7 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at http://www.frida.re/docs/home/
Spawned `com.package.company`. Resuming main thread!
[HUAWEI G620S-UL00::com.package.company]-> message: {u'type': u'send', u'payload': u'Placing Java hooks...'} data: None
message: {u'type': u'send', u'payload': u'Done Java hooks installed.'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onCreate() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'com.package.company.abc.a()Z  Root check 3 HIT!  Root packages'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onCreate() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'com.package.company.abc.a()Z  Root check 3 HIT!  Root packages'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
message: {u'type': u'send', u'payload': u'MainActivity.onStart() HIT!!!'} data: None
Show Comments