Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Check environment patch #3610

Merged
merged 29 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bd69298
feat: Add `Check environment` patch
oSumAtrIX Sep 1, 2024
87e2d0e
move check before calling function
oSumAtrIX Sep 1, 2024
20d001d
rename method
oSumAtrIX Sep 1, 2024
0c3865a
use activity context
oSumAtrIX Sep 1, 2024
5acebd2
small changes
oSumAtrIX Sep 1, 2024
f1036e0
Use last three digits to prevent brute forcing the hashed IP
oSumAtrIX Sep 2, 2024
6280d13
fix some issues add todos
oSumAtrIX Sep 2, 2024
fed02f8
refactor
LisoUseInAIKyrios Sep 2, 2024
29506c2
fix: Check data returned from ip service. Try other services if needed.
LisoUseInAIKyrios Sep 3, 2024
285131d
fix: Remove Check if manager is installed
LisoUseInAIKyrios Sep 3, 2024
dbcea08
fix: Remove ip check that sometimes fails due to privacy concerns and…
LisoUseInAIKyrios Sep 3, 2024
2f74e88
fix: Remove social media links, as the main website is where they sh…
LisoUseInAIKyrios Sep 3, 2024
19a1b53
fix: Don't show any dialog buttons until after a few seconds
LisoUseInAIKyrios Sep 3, 2024
e64ba5b
fix: Adjust text
LisoUseInAIKyrios Sep 3, 2024
116d343
fix: Adjust text
LisoUseInAIKyrios Sep 3, 2024
e0fcbe1
fix: Add patch as dependency to Settings, until a way for mandatory p…
LisoUseInAIKyrios Sep 3, 2024
1329337
fix: Remove unused network address code
LisoUseInAIKyrios Sep 3, 2024
5840c75
fix: adjust text
LisoUseInAIKyrios Sep 3, 2024
f4132cd
Update src/main/resources/addresources/values/strings.xml
LisoUseInAIKyrios Sep 3, 2024
4a9793e
fix: Adjust text
LisoUseInAIKyrios Sep 3, 2024
da65772
fix: Show how old the patched apk is if any other checks fail
LisoUseInAIKyrios Sep 4, 2024
fadd7a4
Remove name so the patch does not appear as selectable
oSumAtrIX Sep 4, 2024
f52dd9f
Fix correctness of strings
oSumAtrIX Sep 4, 2024
ff969e3
fix: Use same base64 encoding for integrations and patches
LisoUseInAIKyrios Sep 5, 2024
36de93c
fix: use UTF8 just in case `Build` has foreign characters
LisoUseInAIKyrios Sep 5, 2024
98e143d
Update src/main/resources/addresources/values/strings.xml
LisoUseInAIKyrios Sep 5, 2024
7620abf
fix: Use more concise text
LisoUseInAIKyrios Sep 3, 2024
5f857a8
fix: Use consistent line break elements
LisoUseInAIKyrios Sep 6, 2024
a7115d7
fix: Use paragraph for last element to add some padding between the d…
LisoUseInAIKyrios Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions api/revanced-patches.api
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,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 @@ -1862,6 +1868,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(
oSumAtrIX marked this conversation as resolved.
Show resolved Hide resolved
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",
oSumAtrIX marked this conversation as resolved.
Show resolved Hide resolved
) ?: 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;
}
Loading