Fix BridgeService

This commit is contained in:
Nullptr 2023-01-08 19:34:06 +08:00
commit a8b165c5cd
No known key found for this signature in database
3 changed files with 39 additions and 98 deletions

View file

@ -37,7 +37,7 @@ val buildToolsVer by extra("33.0.1")
val appVerName by extra("3.1.0-beta")
val configVerCode by extra(90)
val serviceVerCode by extra(94)
val serviceVerCode by extra(95)
val minBackupVerCode by extra(65)
val androidSourceCompatibility = JavaVersion.VERSION_11

View file

@ -2,12 +2,9 @@ package icu.nullptr.hidemyapplist.xposed
import android.content.pm.IPackageManager
import android.os.Binder
import android.os.IBinder
import android.os.Parcel
import com.github.kyuubiran.ezxhelper.utils.argTypes
import com.github.kyuubiran.ezxhelper.utils.findMethod
import com.github.kyuubiran.ezxhelper.utils.hookBefore
import com.github.kyuubiran.ezxhelper.utils.method
import com.github.kyuubiran.ezxhelper.utils.staticMethod
import icu.nullptr.hidemyapplist.common.BuildConfig
import icu.nullptr.hidemyapplist.common.Constants
@ -17,7 +14,7 @@ object BridgeService {
private var appUid = 0
fun start(pms: IPackageManager) {
fun register(pms: IPackageManager) {
logI(TAG, "Initialize HMAService - Version ${BuildConfig.SERVICE_VERSION}")
val service = HMAService(pms)
appUid = Utils.getPackageUidCompat(service.pms, Constants.APP_PACKAGE_NAME, 0, 0)
@ -27,69 +24,40 @@ object BridgeService {
return
}
logD(TAG, "Client uid: $appUid")
doHooks()
logI(TAG, "Bridge service initialized")
}
private fun doHooks() {
logD(TAG, "Hook binder transact")
Binder::class.java.method(
"execTransact",
argTypes = argTypes(Int::class.java, Long::class.java, Long::class.java, Int::class.java)
).hookBefore { param ->
logI(TAG, "Initialize service proxy")
pms.javaClass.findMethod(true) {
name == "onTransact"
}.hookBefore { param ->
val code = param.args[0] as Int
val dataObj = param.args[1] as Long
val replyObj = param.args[2] as Long
val flags = param.args[3] as Int
if (code == Constants.TRANSACTION) {
param.result = execTransact(code, dataObj, replyObj, flags)
}
val data = param.args[1] as Parcel
val reply = param.args[2] as Parcel?
if (myTransact(code, data, reply)) param.result = true
}
}
private val fromNativePointerMethod by lazy {
Parcel::class.java.staticMethod("obtain", argTypes = argTypes(Long::class.java))
}
private fun execTransact(code: Int, dataObj: Long, replyObj: Long, flags: Int): Boolean {
val data = fromNativePointerMethod.invoke(null, dataObj) as Parcel? ?: return false
val reply = fromNativePointerMethod.invoke(null, replyObj) as Parcel?
val res = try {
onTransact(code, data, reply, flags)
} catch (e: Exception) {
if (flags and IBinder.FLAG_ONEWAY != 0) {
logW(TAG, "Caught an exception from the binder stub implementation.")
} else if (reply != null) {
reply.setDataPosition(0)
reply.writeException(e)
private fun myTransact(code: Int, data: Parcel, reply: Parcel?): Boolean {
if (code == Constants.TRANSACTION) {
if (Binder.getCallingUid() == appUid) {
logD(TAG, "Transaction from client")
runCatching {
data.enforceInterface(Constants.DESCRIPTOR)
when (data.readInt()) {
Constants.ACTION_GET_BINDER -> {
reply?.writeNoException()
reply?.writeStrongBinder(HMAService.instance)
return true
}
else -> logW(TAG, "Unknown action")
}
}.onFailure {
logE(TAG, "Transaction error", it)
}
} else {
logW(TAG, "Someone else trying to get my binder?")
}
false
} finally {
data.setDataPosition(0)
reply?.setDataPosition(0)
}
if (res) {
data.recycle()
reply?.recycle()
}
return res
}
private fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
data.enforceInterface(Constants.DESCRIPTOR)
return when (data.readInt()) {
Constants.ACTION_GET_BINDER -> {
if (Binder.getCallingUid() == appUid && HMAService.instance != null) {
reply?.writeNoException()
reply?.writeStrongBinder(HMAService.instance!!.asBinder())
true
} else {
logW(TAG, "Invalid connection")
false
}
}
else -> false
}
return false
}
}

View file

@ -1,33 +1,16 @@
package icu.nullptr.hidemyapplist.xposed
import android.content.pm.IPackageManager
import android.os.ServiceManager
import android.util.Log
import com.github.kyuubiran.ezxhelper.init.EzXHelperInit
import com.github.kyuubiran.ezxhelper.utils.findMethod
import com.github.kyuubiran.ezxhelper.utils.getFieldByDesc
import com.github.kyuubiran.ezxhelper.utils.hookAfter
import com.github.kyuubiran.ezxhelper.utils.hookAllConstructorAfter
import com.github.kyuubiran.ezxhelper.utils.*
import de.robv.android.xposed.IXposedHookLoadPackage
import de.robv.android.xposed.IXposedHookZygoteInit
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.callbacks.XC_LoadPackage
import icu.nullptr.hidemyapplist.common.Constants
import kotlin.concurrent.thread
private const val TAG = "HMA-XposedEntry"
private fun waitSystemService(name: String) {
while (ServiceManager.getService(name) == null) {
try {
logD(TAG, "service $name is not started, wait 1s")
Thread.sleep(1000)
} catch (e: InterruptedException) {
logE(TAG, Log.getStackTraceString(e))
}
}
}
class XposedEntry : IXposedHookZygoteInit, IXposedHookLoadPackage {
override fun initZygote(startupParam: IXposedHookZygoteInit.StartupParam) {
@ -44,30 +27,20 @@ class XposedEntry : IXposedHookZygoteInit, IXposedHookLoadPackage {
EzXHelperInit.initHandleLoadPackage(lpparam)
logI(TAG, "Hook entry")
var pms: IPackageManager? = null
var serviceManagerHook: XC_MethodHook.Unhook? = null
serviceManagerHook = findMethod("android.os.ServiceManager") {
name == "addService"
}.hookAfter { param ->
}.hookBefore { param ->
if (param.args[0] == "package") {
pms = param.args[1] as IPackageManager
logI(TAG, "Got pms: $pms")
serviceManagerHook?.unhook()
}
}
logD(TAG, "ServiceManager hook installed")
thread {
runCatching {
waitSystemService("package")
logI(TAG, "PackageManagerService ready, load bridge service")
if (pms != null) {
BridgeService.start(pms!!)
} else {
logE(TAG, "Package service started, but instance is not captured")
val pms = param.args[1] as IPackageManager
logD(TAG, "Got pms: $pms")
runCatching {
BridgeService.register(pms)
logI(TAG, "Bridge service injected")
}.onFailure {
logE(TAG, "System service crashed", it)
}
}.onFailure {
logE(TAG, "System service crashed", it)
}
}
}