天天看點

Android 系統分身及應用多開實戰 frida hook

常見的分身/多開

  1. 工具修改包名,早的時候可以,現在的應用,換包名功能就殘缺不能好好用了…
  2. 修改 Framework(Android多使用者機制。例:小米分身、訪客模式等),國産手機中挺常見。但如果系統不提供該功能,自己很難開分身,本文就是告訴你怎麼開了它。
  3. 通過虛拟化技術實作(例:360分身大師、LBE平行空間),這個應用索要權限非常高,别輕易使用非官方的該類軟體。
  4. 以插件機制運作

目前很多人都會有應用多開和系統分身的需要,多個帳号要登入在一個手機,或者體驗下一個手機兩個系統自由切換的感覺,完全隔離,隐私再也不怕被翻到。本文主要是通過系統隐藏 API 調用來完成系統分身,使用 Android 多使用者機制,注意這裡系統分為兩種:1.應用在兩個使用者中(如 MIUI 中的系統分身) 2.影子使用者,雙開應用顯示在原使用者桌面中(如 MIUI 中的應用雙開)。兩種情況差不多,都是要先建立使用者,然後需要顯示在原桌面就再調用一下 API 即可。

主要手機配置足夠高,你理論上可以建無數個系統分身和多開應用。

後面的内容全是針對多使用者機制的操作辦法啦。

Android與Linux的使用者概念異同

從 Android 5.0 開始引入多使用者 API,都是隐藏 API 且需要系統簽名并持有 managed_user 相關權限,雖然 Android 是基于 Linxu 系統,但兩者賬戶管理體系不通,可以多用 ps 指令觀察應用所屬及 Android 應用的 uid,下面的 u0_a144 即為微信程序 uid,:push 結尾的程序則是微信的推送程序(對,這是個多程序應用),u0_ 代表該程序運作在 id 為 0 的使用者上。

shell@rolex:/ $ ps | grep tencent
u0_a144   29866 623   1762984 236024            0000000000 R com.tencent.mm
u0_a144   30068 623   1611740 98396 SyS_epoll_ 0000000000 S com.tencent.mm:push
           

要使用的技術和工具

即使 root 提權應用但如果不是系統簽名應用仍然不能調用成功,這也是為什麼本文要使用 frida 來 hook 系統應用的原因(使用 Xposed 同樣可以做到,熟悉的同學可以自己嘗試)。下面直接使用代碼示範,實戰開始!為什麼使用 frida 架構寫而不用 xposed 呢,當然是因為 frida 快啦,而且手機隻要 root 就可以用,不用擔心 xposed 安裝不上去的情況,當然,本文就不科普 frida 使用了。如果之前從沒聽說過 frida …推薦這篇

提示:

  1. 使用了語言 python 、 js 和 java (反射)
  2. 本文所用裝置 Nexus 6P (Android 6.0)
  3. python 版本 3.7,frida 版本 12.4.0
  4. 檢視 Android 源碼 (6.0為例),各個版本源碼友情連結

核心代碼

//一些需要用到的類
var IUserManager = Java.use("android.os.IUserManager");
var UserManager = Java.use("android.os.UserManager");
var UserInfo = Java.use("android.content.pm.UserInfo")
var ActivityManagerNative = Java.use("android.app.ActivityManagerNative")
var Integer = Java.use("java.lang.Integer")
var int = Integer.class.getField("TYPE").get(null)

var Application = Java.use("android.app.Application")
Application.attach.implementation = function(context) {
    console.log("Application.attach()")
    this.attach(context)
    
    //1.開始建立使用者
    var mUserManager = context.getSystemService("user")
    mUserManager = Java.cast(mUserManager, UserManager)
    console.log("mUserManager:" + mUserManager)
    var mMyParallelSpaceUserInfo = mUserManager.createProfileForUser("MyParallelSpace", 32, 0)
    //此時使用者已經建立完成 mMyParallelSpaceUserInfo 及為剛建立的使用者資訊
    //如果不需要影子使用者(雙開)隻需要系統分身,則第一步執行完成即可停止    
    
    //2.擷取建立的使用者id #也可以使用 adb shell dumpsys user檢視
    //注意,本例第二步是為了示範如何擷取使用者id,事實上第一步最後結果mMyParallelSpaceUserInfo中就有我們需要的id,如果第一步執行順利,可直接執行第三步,及 "var id = 10" 應替換為 "var id = mMyParallelSpaceUserInfo.id.value"
    var users = mUserManager.getUsers()
    console.log("users:"+users)
    for (var i=0; i < users.size(); i++) {
        console.log("user" + i + ":"+users.get(i))
        var UserInfo_id = UserInfo.class.getDeclaredField("id")
        var id = UserInfo_id.get(users.get(i))
        console.log("user" + i + ":"+id)
    }
    
    //3.該使用者id設定為影子使用者(本例為10) 
  	//這一步是為了讓建立的使用者成為影子使用者,在該使用者安裝的應用會顯示在原桌面上(即雙開)
    var id = 10 
    var iActivityManager = ActivityManagerNative.class.getMethod("getDefault", null).invoke(null, null)
    var method_startUserInBackground = ActivityManagerNative.class.getMethod("startUserInBackground", [int])
    var isOK = method_startUserInBackground.invoke(iActivityManager, [Integer.$new(id)])
    console.log("startUserInBackground() userId = " + id + " isOK = " + isOK)
}

//frida 以 spawn 方式運作在系統應用 "設定" 上,就實作了系統應用調用
process = device.attach('com.android.settings')
           

spawn 方式運作步驟:

  1. 指令行 frida -U -f com.android.settings,提示等待下一步
  2. python 運作腳本
  3. 指令行輸入 $resume,啟動"設定"應用,因為腳本 hook 了 Application.attach 方法,自動運作完成。

啟動微信和影子微信後檢視程序

shell@rolex:/ $ ps | grep tencent
u10_a144 9054  623   1672156 172756 binder_thr 0000000000 S com.tencent.mm
u10_a144 9234  623   1610788 95400 futex_wait 0000000000 S com.tencent.mm:push
u0_a144   29866 623   1855536 159340 SyS_epoll_ 0000000000 S com.tencent.mm
u0_a144   30068 623   1605200 58676 SyS_epoll_ 0000000000 S com.tencent.mm:push
           

具體源碼已放到 GitHub 倉庫,以上就是一次多開應用的實戰操作,不同版本可能存在部分 API 小改動,也可能有的手機商系統會改動較大,本文隻是抛磚引玉,有什麼問題可以留言讨論。

繼續閱讀