Skip to content

Commit

Permalink
feat: Add Check environment patch (#3610)
Browse files Browse the repository at this point in the history
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com>
Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 6, 2024
1 parent 04e1375 commit fbcbdaf
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 2 deletions.
10 changes: 10 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,12 @@ public final class app/revanced/patches/serviceportalbund/detection/root/RootDet
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public abstract class app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch : app/revanced/patcher/patch/BytecodePatch {
public fun <init> (Lapp/revanced/patcher/fingerprint/MethodFingerprint;Ljava/util/Set;Lapp/revanced/patches/shared/misc/integrations/BaseIntegrationsPatch;)V
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public final class app/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/shared/misc/fix/verticalscroll/VerticalScrollPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
Expand Down Expand Up @@ -1870,6 +1876,10 @@ public final class app/revanced/patches/youtube/misc/backgroundplayback/Backgrou
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}

public final class app/revanced/patches/youtube/misc/check/CheckEnvironmentPatch : app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentPatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/check/CheckEnvironmentPatch;
}

public final class app/revanced/patches/youtube/misc/debugging/DebuggingPatch : app/revanced/patcher/patch/ResourcePatch {
public static final field INSTANCE Lapp/revanced/patches/youtube/misc/debugging/DebuggingPatch;
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ dependencies {
implementation(libs.guava)
// Used in JsonGenerator.
implementation(libs.gson)
// Android API stubs defined here.
compileOnly(project(":stub"))
}

kotlin {
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ buildCache {
isEnabled = "CI" !in System.getenv()
}
}

include(":stub")
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package app.revanced.patches.shared.misc.checks

import android.os.Build.*
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableLongEncodedValue
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableStringEncodedValue
import app.revanced.patches.all.misc.resources.AddResourcesPatch
import app.revanced.patches.shared.misc.checks.fingerprints.PatchInfoBuildFingerprint
import app.revanced.patches.shared.misc.checks.fingerprints.PatchInfoFingerprint
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
import app.revanced.util.exception
import app.revanced.util.resultOrThrow
import com.android.tools.smali.dexlib2.immutable.value.ImmutableLongEncodedValue
import com.android.tools.smali.dexlib2.immutable.value.ImmutableStringEncodedValue
import java.nio.charset.StandardCharsets
import java.security.MessageDigest
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi

abstract class BaseCheckEnvironmentPatch(
private val mainActivityOnCreateFingerprint: MethodFingerprint,
compatiblePackages: Set<CompatiblePackage>,
integrationsPatch: BaseIntegrationsPatch,
) : BytecodePatch(
description = "Checks, if the application was patched by, otherwise warns the user.",
compatiblePackages = compatiblePackages,
dependencies = setOf(
AddResourcesPatch::class,
integrationsPatch::class,
),
fingerprints = setOf(
PatchInfoFingerprint,
PatchInfoBuildFingerprint,
mainActivityOnCreateFingerprint,
),
) {
override fun execute(context: BytecodeContext) {
AddResourcesPatch(BaseCheckEnvironmentPatch::class)

setPatchInfo()
invokeCheck()
}

private fun setPatchInfo() {
PatchInfoFingerprint.setClassFields(
"PATCH_TIME" to System.currentTimeMillis().encoded,
)

fun setBuildInfo() {
PatchInfoBuildFingerprint.setClassFields(
"PATCH_BOARD" to BOARD.encodedAndHashed,
"PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed,
"PATCH_BRAND" to BRAND.encodedAndHashed,
"PATCH_CPU_ABI" to CPU_ABI.encodedAndHashed,
"PATCH_CPU_ABI2" to CPU_ABI2.encodedAndHashed,
"PATCH_DEVICE" to DEVICE.encodedAndHashed,
"PATCH_DISPLAY" to DISPLAY.encodedAndHashed,
"PATCH_FINGERPRINT" to FINGERPRINT.encodedAndHashed,
"PATCH_HARDWARE" to HARDWARE.encodedAndHashed,
"PATCH_HOST" to HOST.encodedAndHashed,
"PATCH_ID" to ID.encodedAndHashed,
"PATCH_MANUFACTURER" to MANUFACTURER.encodedAndHashed,
"PATCH_MODEL" to MODEL.encodedAndHashed,
"PATCH_ODM_SKU" to ODM_SKU.encodedAndHashed,
"PATCH_PRODUCT" to PRODUCT.encodedAndHashed,
"PATCH_RADIO" to RADIO.encodedAndHashed,
"PATCH_SKU" to SKU.encodedAndHashed,
"PATCH_SOC_MANUFACTURER" to SOC_MANUFACTURER.encodedAndHashed,
"PATCH_SOC_MODEL" to SOC_MODEL.encodedAndHashed,
"PATCH_TAGS" to TAGS.encodedAndHashed,
"PATCH_TYPE" to TYPE.encodedAndHashed,
"PATCH_USER" to USER.encodedAndHashed,
)
}

try {
Class.forName("android.os.Build")
// This only works on Android,
// because it uses Android APIs.
setBuildInfo()
} catch (_: ClassNotFoundException) { }
}

private fun invokeCheck() = mainActivityOnCreateFingerprint.result?.mutableMethod?.addInstructions(
0,
"invoke-static/range { p0 .. p0 },$INTEGRATIONS_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
) ?: throw mainActivityOnCreateFingerprint.exception

private companion object {
private const val INTEGRATIONS_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/shared/checks/CheckEnvironmentPatch;"

@OptIn(ExperimentalEncodingApi::class)
private val String.encodedAndHashed
get() = MutableStringEncodedValue(
ImmutableStringEncodedValue(
Base64.encode(MessageDigest.getInstance("SHA-1")
.digest(this.toByteArray(StandardCharsets.UTF_8))),
),
)

private val Long.encoded get() = MutableLongEncodedValue(ImmutableLongEncodedValue(this))

private fun <T : MutableEncodedValue> MethodFingerprint.setClassFields(vararg fieldNameValues: Pair<String, T>) {
val fieldNameValueMap = mapOf(*fieldNameValues)

resultOrThrow().mutableClass.fields.forEach { field ->
field.initialValue = fieldNameValueMap[field.name] ?: return@forEach
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package app.revanced.patches.shared.misc.checks.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object PatchInfoBuildFingerprint : MethodFingerprint(
customFingerprint = { _, classDef -> classDef.type == "Lapp/revanced/integrations/shared/checks/PatchInfo\$Build;" },
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.revanced.patches.shared.misc.checks.fingerprints

import app.revanced.patcher.fingerprint.MethodFingerprint

internal object PatchInfoFingerprint : MethodFingerprint(
customFingerprint = { _, classDef ->
classDef.type == "Lapp/revanced/integrations/shared/checks/PatchInfo;"
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ abstract class BaseGmsCoreSupportPatch(

// Verify GmsCore is installed and whitelisted for power optimizations and background usage.
mainActivityOnCreateFingerprint.result?.mutableMethod?.apply {
// Temporary fix for Google photos integration.
var setContextIndex = indexOfFirstInstruction {
// Temporary fix for patches with an integrations patch that hook the onCreate method as well.
val setContextIndex = indexOfFirstInstruction {
val reference = getReference<MethodReference>() ?: return@indexOfFirstInstruction false

reference.toString() == "Lapp/revanced/integrations/shared/Utils;->setContext(Landroid/content/Context;)V"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package app.revanced.patches.youtube.misc.check

import app.revanced.patches.shared.misc.checks.BaseCheckEnvironmentPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.shared.fingerprints.MainActivityOnCreateFingerprint

@Suppress("unused")
object CheckEnvironmentPatch :
BaseCheckEnvironmentPatch(
mainActivityOnCreateFingerprint = MainActivityOnCreateFingerprint,
integrationsPatch = IntegrationsPatch,
compatiblePackages = setOf(CompatiblePackage("com.google.android.youtube")),
)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import app.revanced.patches.shared.misc.settings.preference.IntentPreference
import app.revanced.patches.shared.misc.settings.preference.NonInteractivePreference
import app.revanced.patches.shared.misc.settings.preference.PreferenceScreen.Sorting
import app.revanced.patches.shared.misc.settings.preference.TextPreference
import app.revanced.patches.youtube.misc.check.CheckEnvironmentPatch
import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
import app.revanced.patches.youtube.misc.settings.fingerprints.LicenseActivityOnCreateFingerprint
import app.revanced.patches.youtube.misc.settings.fingerprints.SetThemeFingerprint
Expand All @@ -30,6 +31,9 @@ import java.io.Closeable
IntegrationsPatch::class,
SettingsResourcePatch::class,
AddResourcesPatch::class,
// Currently there is no easy way to make a mandatory patch,
// so for now this is a dependent of this patch.
CheckEnvironmentPatch::class,
],
)
object SettingsPatch :
Expand Down
11 changes: 11 additions & 0 deletions src/main/resources/addresources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ This is because Crowdin requires temporarily flattening this file and removing t
-->
<resources>
<app id="shared">
<patch id="misc.checks.BaseCheckEnvironmentPatch">
<string name="revanced_check_environment_failed_title">Checks failed</string>
<string name="revanced_check_environment_dialog_open_official_source_button">Open official website</string>
<string name="revanced_check_environment_dialog_ignore_button">Ignore</string>
<string name="revanced_check_environment_failed_message">&lt;h5>This app does not appear to be patched by you.&lt;/h5>&lt;br>This app may not function correctly, &lt;b>could be harmful or even dangerous to use&lt;/b>.&lt;br>&lt;br>These checks imply this app is pre-patched or obtained from someone else:&lt;br>&lt;br>&lt;small>%1$s&lt;/small>&lt;br>It is strongly recommended to &lt;b>uninstall this app and patch it yourself&lt;/b> to ensure you are using a validated and secure app.&lt;p>&lt;br>If ignored, this warning will only be shown twice.</string>
<string name="revanced_check_environment_not_same_patching_device">Patched on a different device</string>
<string name="revanced_check_environment_manager_not_expected_installer">Not installed by ReVanced Manager</string>
<string name="revanced_check_environment_not_near_patch_time">Patched more than 10 minutes ago</string>
<string name="revanced_check_environment_not_near_patch_time_days">Patched %s days ago</string>
<string name="revanced_check_environment_not_near_patch_time_invalid">APK build date is corrupted</string>
</patch>
<patch id="misc.settings.BaseSettingsResourcePatch">
<string name="revanced_settings_title">ReVanced</string>
<string name="revanced_settings_confirm_user_dialog_title">Do you wish to proceed?</string>
Expand Down
10 changes: 10 additions & 0 deletions stub/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
`java-library`
}

description = "Provide Android API stubs for ReVanced Patches."

java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
26 changes: 26 additions & 0 deletions stub/src/main/java/android/os/Build.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package android.os;

public class Build {
public static final String BOARD = null;
public static final String BOOTLOADER = null;
public static final String BRAND = null;
public static final String CPU_ABI = null;
public static final String CPU_ABI2 = null;
public static final String DEVICE = null;
public static final String DISPLAY = null;
public static final String FINGERPRINT = null;
public static final String HARDWARE = null;
public static final String HOST = null;
public static final String ID = null;
public static final String MANUFACTURER = null;
public static final String MODEL = null;
public static final String ODM_SKU = null;
public static final String PRODUCT = null;
public static final String RADIO = null;
public static final String SKU = null;
public static final String SOC_MANUFACTURER = null;
public static final String SOC_MODEL = null;
public static final String TAGS = null;
public static final String TYPE = null;
public static final String USER = null;
}

0 comments on commit fbcbdaf

Please sign in to comment.