feat(core): hidden api bypass

This commit is contained in:
rhunk 2024-08-19 22:52:29 +02:00
parent 1d4cd7c6b8
commit a43e4049a3
5 changed files with 15 additions and 3 deletions

View File

@ -47,4 +47,5 @@ dependencies {
implementation(libs.androidx.material.ripple) implementation(libs.androidx.material.ripple)
implementation(libs.androidx.material.icons.extended) implementation(libs.androidx.material.icons.extended)
implementation(libs.androidx.material3) implementation(libs.androidx.material3)
implementation(libs.hiddenapibypass)
} }

View File

@ -30,6 +30,7 @@ import me.rhunk.snapenhance.core.ui.InAppOverlay
import me.rhunk.snapenhance.core.util.LSPatchUpdater import me.rhunk.snapenhance.core.util.LSPatchUpdater
import me.rhunk.snapenhance.core.util.hook.HookAdapter import me.rhunk.snapenhance.core.util.hook.HookAdapter
import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.HookStage
import me.rhunk.snapenhance.core.util.hook.findRestrictedMethod
import me.rhunk.snapenhance.core.util.hook.hook import me.rhunk.snapenhance.core.util.hook.hook
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.system.exitProcess import kotlin.system.exitProcess
@ -240,12 +241,12 @@ class SnapEnhance {
appContext.log.warn("sif is disabled") appContext.log.warn("sif is disabled")
} }
Runtime::class.java.declaredMethods.first { Runtime::class.java.findRestrictedMethod {
it.name == "loadLibrary0" && it.parameterTypes.contentEquals( it.name == "loadLibrary0" && it.parameterTypes.contentEquals(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) arrayOf(Class::class.java, String::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) arrayOf(Class::class.java, String::class.java)
else arrayOf(ClassLoader::class.java, String::class.java) else arrayOf(ClassLoader::class.java, String::class.java)
) )
}.apply { }!!.apply {
if (safeMode) { if (safeMode) {
hook(HookStage.BEFORE) { param -> hook(HookStage.BEFORE) { param ->
if (param.arg<String>(1) != "scplugin") return@hook if (param.arg<String>(1) != "scplugin") return@hook

View File

@ -30,6 +30,7 @@ import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder
import me.rhunk.snapenhance.core.features.impl.experiments.BetterTranscript import me.rhunk.snapenhance.core.features.impl.experiments.BetterTranscript
import me.rhunk.snapenhance.core.features.impl.spying.StealthMode import me.rhunk.snapenhance.core.features.impl.spying.StealthMode
import me.rhunk.snapenhance.core.util.hook.HookStage import me.rhunk.snapenhance.core.util.hook.HookStage
import me.rhunk.snapenhance.core.util.hook.findRestrictedMethod
import me.rhunk.snapenhance.core.util.hook.hook import me.rhunk.snapenhance.core.util.hook.hook
import me.rhunk.snapenhance.core.util.ktx.setObjectField import me.rhunk.snapenhance.core.util.ktx.setObjectField
import me.rhunk.snapenhance.core.util.media.PreviewUtils import me.rhunk.snapenhance.core.util.media.PreviewUtils
@ -509,7 +510,7 @@ class Notifications : Feature("Notifications") {
} }
} }
NotificationManager::class.java.declaredMethods.find { NotificationManager::class.java.findRestrictedMethod {
it.name == "cancelAsUser" it.name == "cancelAsUser"
}?.hook(HookStage.AFTER) { param -> }?.hook(HookStage.AFTER) { param ->
val notificationId = param.arg<Int>(1) val notificationId = param.arg<Int>(1)

View File

@ -3,6 +3,7 @@ package me.rhunk.snapenhance.core.util.hook
import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedBridge
import me.rhunk.snapenhance.common.logger.AbstractLogger import me.rhunk.snapenhance.common.logger.AbstractLogger
import org.lsposed.hiddenapibypass.HiddenApiBypass
import java.lang.reflect.Member import java.lang.reflect.Member
import java.lang.reflect.Method import java.lang.reflect.Method
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
@ -183,3 +184,9 @@ fun Array<Method>.hookAll(stage: HookStage, param: (HookAdapter) -> Unit) {
it.hook(stage, param) it.hook(stage, param)
} }
} }
fun Class<*>.findRestrictedMethod(
predicate: (Method) -> Boolean
): Method? {
return declaredMethods.find(predicate) ?: HiddenApiBypass.getDeclaredMethods(this).filterIsInstance<Method>().find(predicate)
}

View File

@ -24,6 +24,7 @@ okhttp = "5.0.0-alpha.14"
rhino = "1.7.15" rhino = "1.7.15"
rhino-android = "1.6.0" rhino-android = "1.6.0"
rust-android = "0.9.4" rust-android = "0.9.4"
hiddenapibypass = "4.3"
[libraries] [libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" }
@ -51,6 +52,7 @@ jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
junit = { group = "org.junit.vintage", name = "junit-vintage-engine", version.ref = "junit" } junit = { group = "org.junit.vintage", name = "junit-vintage-engine", version.ref = "junit" }
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" } okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
osmdroid-android = { group = "org.osmdroid", name = "osmdroid-android", version.ref = "osmdroid-android" } osmdroid-android = { group = "org.osmdroid", name = "osmdroid-android", version.ref = "osmdroid-android" }
hiddenapibypass = { module = "org.lsposed.hiddenapibypass:hiddenapibypass", version.ref = "hiddenapibypass" }
recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" } recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
rhino = { module = "org.mozilla:rhino", version.ref = "rhino" } rhino = { module = "org.mozilla:rhino", version.ref = "rhino" }
rhino-android = { group = "com.faendir.rhino", name = "rhino-android", version.ref = "rhino-android" } rhino-android = { group = "com.faendir.rhino", name = "rhino-android", version.ref = "rhino-android" }