build: Bump ReVanced Patcher (#3862)

Co-authored-by: Ushie <ushiekane@gmail.com>
This commit is contained in:
oSumAtrIX 2024-11-05 19:28:51 +01:00
parent e32b19e170
commit 8da05ab46d
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
230 changed files with 1068 additions and 1733 deletions

View File

@ -1,5 +1,5 @@
[versions] [versions]
revanced-patcher = "20.0.2" revanced-patcher = "21.0.0"
# Tracking https://github.com/google/smali/issues/64. # Tracking https://github.com/google/smali/issues/64.
#noinspection GradleDependency #noinspection GradleDependency
smali = "3.0.5" smali = "3.0.5"
@ -7,7 +7,7 @@ gson = "2.11.0"
# 8.3.0 causes java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818. # 8.3.0 causes java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818.
#noinspection GradleDependency #noinspection GradleDependency
agp = "8.2.2" agp = "8.2.2"
annotation = "1.9.0" annotation = "1.9.1"
appcompat = "1.7.0" appcompat = "1.7.0"
okhttp = "5.0.0-alpha.14" okhttp = "5.0.0-alpha.14"
retrofit = "2.11.0" retrofit = "2.11.0"

View File

@ -533,7 +533,7 @@ public final class app/revanced/patches/shared/misc/checks/BaseCheckEnvironmentP
public final class app/revanced/patches/shared/misc/extension/ExtensionHook { public final class app/revanced/patches/shared/misc/extension/ExtensionHook {
public final fun getFingerprint ()Lapp/revanced/patcher/Fingerprint; public final fun getFingerprint ()Lapp/revanced/patcher/Fingerprint;
public final fun invoke (Ljava/lang/String;)V public final fun invoke (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;)V
} }
public final class app/revanced/patches/shared/misc/extension/SharedExtensionPatchKt { public final class app/revanced/patches/shared/misc/extension/SharedExtensionPatchKt {
@ -551,10 +551,10 @@ public final class app/revanced/patches/shared/misc/gms/FingerprintsKt {
} }
public final class app/revanced/patches/shared/misc/gms/GmsCoreSupportPatchKt { public final class app/revanced/patches/shared/misc/gms/GmsCoreSupportPatchKt {
public static final fun gmsCoreSupportPatch (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch; public static final fun gmsCoreSupportPatch (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/BytecodePatch;
public static synthetic fun gmsCoreSupportPatch$default (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch; public static synthetic fun gmsCoreSupportPatch$default (Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/Fingerprint;Ljava/util/Set;Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/Patch;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/BytecodePatch;
public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch; public static final fun gmsCoreSupportResourcePatch (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/ResourcePatch;
public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch; public static synthetic fun gmsCoreSupportResourcePatch$default (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/patch/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
} }
public final class app/revanced/patches/shared/misc/hex/HexPatchKt { public final class app/revanced/patches/shared/misc/hex/HexPatchKt {
@ -979,13 +979,8 @@ public final class app/revanced/patches/twitter/misc/hook/json/JsonHook {
public fun <init> (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;)V public fun <init> (Lapp/revanced/patcher/patch/BytecodePatchContext;Ljava/lang/String;)V
} }
public final class app/revanced/patches/twitter/misc/hook/json/JsonHookPatchHook : java/io/Closeable {
public fun <init> (Lapp/revanced/patcher/Fingerprint;)V
public final fun addHook (Lapp/revanced/patches/twitter/misc/hook/json/JsonHook;)V
public fun close ()V
}
public final class app/revanced/patches/twitter/misc/hook/json/JsonHookPatchKt { public final class app/revanced/patches/twitter/misc/hook/json/JsonHookPatchKt {
public static final fun addJsonHook (Lapp/revanced/patcher/patch/BytecodePatchContext;Lapp/revanced/patches/twitter/misc/hook/json/JsonHook;)V
public static final fun getJsonHookPatch ()Lapp/revanced/patcher/patch/BytecodePatch; public static final fun getJsonHookPatch ()Lapp/revanced/patcher/patch/BytecodePatch;
} }
@ -1432,7 +1427,6 @@ public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPat
} }
public final class app/revanced/util/BytecodeUtilsKt { public final class app/revanced/util/BytecodeUtilsKt {
public static final fun applyMatch (Lapp/revanced/patcher/Fingerprint;Lapp/revanced/patcher/patch/BytecodePatchContext;Lapp/revanced/patcher/Match;)Lapp/revanced/patcher/Match;
public static final fun containsLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z public static final fun containsLiteralInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;J)Z
public static final fun findInstructionIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List; public static final fun findInstructionIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)Ljava/util/List;
public static final fun findInstructionIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun findInstructionIndicesReversed (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
@ -1440,8 +1434,6 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun findInstructionIndicesReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun findInstructionIndicesReversedOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Lkotlin/jvm/functions/Function1;)Ljava/util/List;
public static final fun findMutableMethodOf (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod; public static final fun findMutableMethodOf (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
public static final fun forEachLiteralValueInstruction (Lapp/revanced/patcher/patch/BytecodePatchContext;JLkotlin/jvm/functions/Function2;)V public static final fun forEachLiteralValueInstruction (Lapp/revanced/patcher/patch/BytecodePatchContext;JLkotlin/jvm/functions/Function2;)V
public static final fun getException (Lapp/revanced/patcher/Fingerprint;)Lapp/revanced/patcher/patch/PatchException;
public static final fun getMatchOrThrow (Lapp/revanced/patcher/Fingerprint;)Lapp/revanced/patcher/Match;
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;)I public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILcom/android/tools/smali/dexlib2/Opcode;)I
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;)I public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;ILkotlin/jvm/functions/Function1;)I
public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I public static final fun indexOfFirstInstruction (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/Opcode;)I
@ -1468,12 +1460,8 @@ public final class app/revanced/util/BytecodeUtilsKt {
public static final fun indexOfFirstResourceIdOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I public static final fun indexOfFirstResourceIdOrThrow (Lcom/android/tools/smali/dexlib2/iface/Method;Ljava/lang/String;)I
public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V public static final fun injectHideViewCall (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;IILjava/lang/String;Ljava/lang/String;)V
public static final fun literal (Lapp/revanced/patcher/FingerprintBuilder;Lkotlin/jvm/functions/Function0;)V public static final fun literal (Lapp/revanced/patcher/FingerprintBuilder;Lkotlin/jvm/functions/Function0;)V
public static final fun returnEarly (Lapp/revanced/patcher/Fingerprint;Z)V
public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V public static final fun returnEarly (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Z)V
public static final fun returnEarly (Ljava/lang/Iterable;Z)V
public static synthetic fun returnEarly$default (Lapp/revanced/patcher/Fingerprint;ZILjava/lang/Object;)V
public static synthetic fun returnEarly$default (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ZILjava/lang/Object;)V public static synthetic fun returnEarly$default (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ZILjava/lang/Object;)V
public static synthetic fun returnEarly$default (Ljava/lang/Iterable;ZILjava/lang/Object;)V
public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V public static final fun transformMethods (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
public static final fun traverseClassHierarchy (Lapp/revanced/patcher/patch/BytecodePatchContext;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V public static final fun traverseClassHierarchy (Lapp/revanced/patcher/patch/BytecodePatchContext;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;Lkotlin/jvm/functions/Function1;)V
} }

View File

@ -21,6 +21,12 @@ dependencies {
compileOnly(project(":patches:stub")) compileOnly(project(":patches:stub"))
} }
kotlin {
compilerOptions {
freeCompilerArgs = listOf("-Xcontext-receivers")
}
}
publishing { publishing {
repositories { repositories {
maven { maven {

View File

@ -8,10 +8,10 @@ val exportAllActivitiesPatch = resourcePatch(
description = "Makes all app activities exportable.", description = "Makes all app activities exportable.",
use = false, use = false,
) { ) {
execute { context -> execute {
val exportedFlag = "android:exported" val exportedFlag = "android:exported"
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
val activities = document.getElementsByTagName("activity") val activities = document.getElementsByTagName("activity")
for (i in 0..activities.length) { for (i in 0..activities.length) {

View File

@ -8,8 +8,8 @@ val enableAndroidDebuggingPatch = resourcePatch(
description = "Enables Android debugging capabilities. This can slow down the app.", description = "Enables Android debugging capabilities. This can slow down the app.",
use = false, use = false,
) { ) {
execute { context -> execute {
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
val applicationNode = val applicationNode =
document document
.getElementsByTagName("application") .getElementsByTagName("application")

View File

@ -8,10 +8,10 @@ val predictiveBackGesturePatch = resourcePatch(
description = "Enables the predictive back gesture introduced on Android 13.", description = "Enables the predictive back gesture introduced on Android 13.",
use = false, use = false,
) { ) {
execute { context -> execute {
val flag = "android:enableOnBackInvokedCallback" val flag = "android:enableOnBackInvokedCallback"
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
with(document.getElementsByTagName("application").item(0)) { with(document.getElementsByTagName("application").item(0)) {
if (attributes.getNamedItem(flag) != null) return@with if (attributes.getNamedItem(flag) != null) return@with

View File

@ -14,11 +14,11 @@ val overrideCertificatePinningPatch = resourcePatch(
) { ) {
dependsOn(enableAndroidDebuggingPatch) dependsOn(enableAndroidDebuggingPatch)
execute { context -> execute {
val resXmlDirectory = context["res/xml"] val resXmlDirectory = get("res/xml")
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist. // Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
val applicationNode = document.getElementsByTagName("application").item(0) as Element val applicationNode = document.getElementsByTagName("application").item(0) as Element
if (!applicationNode.hasAttribute("networkSecurityConfig")) { if (!applicationNode.hasAttribute("networkSecurityConfig")) {

View File

@ -41,8 +41,8 @@ val changePackageNamePatch = resourcePatch(
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
} }
finalize { context -> finalize {
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
val replacementPackageName = packageNameOption.value val replacementPackageName = packageNameOption.value

View File

@ -275,7 +275,7 @@ val addResourcesPatch = resourcePatch(
After all patches that depend on addResourcesPatch have been executed, After all patches that depend on addResourcesPatch have been executed,
addResourcesPatch#finalize is finally called to add all staged resources to the app. addResourcesPatch#finalize is finally called to add all staged resources to the app.
*/ */
execute { context -> execute {
stagedResources = buildMap { stagedResources = buildMap {
/** /**
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map. * Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
@ -299,7 +299,7 @@ val addResourcesPatch = resourcePatch(
// instead of overwriting it. // instead of overwriting it.
// This covers the example case such as adding strings and arrays of the same value. // This covers the example case such as adding strings and arrays of the same value.
getOrPut(destValue, ::mutableMapOf).apply { getOrPut(destValue, ::mutableMapOf).apply {
context.document[stream].use { document -> document(stream).use { document ->
document.getElementsByTagName("app").asSequence().forEach { app -> document.getElementsByTagName("app").asSequence().forEach { app ->
val appId = app.attributes.getNamedItem("id").textContent val appId = app.attributes.getNamedItem("id").textContent
@ -343,7 +343,7 @@ val addResourcesPatch = resourcePatch(
* Adds all resources staged in [addResourcesPatch] to the app. * Adds all resources staged in [addResourcesPatch] to the app.
* This is called after all patches that depend on [addResourcesPatch] have been executed. * This is called after all patches that depend on [addResourcesPatch] have been executed.
*/ */
finalize { context -> finalize {
operator fun MutableMap<String, Pair<Document, Node>>.invoke( operator fun MutableMap<String, Pair<Document, Node>>.invoke(
value: Value, value: Value,
resource: BaseResource, resource: BaseResource,
@ -359,8 +359,7 @@ val addResourcesPatch = resourcePatch(
} }
getOrPut(resourceFileName) { getOrPut(resourceFileName) {
val targetFile = val targetFile = this@finalize["res/$value/$resourceFileName.xml"].also {
context["res/$value/$resourceFileName.xml"].also {
it.parentFile?.mkdirs() it.parentFile?.mkdirs()
if (it.createNewFile()) { if (it.createNewFile()) {
@ -368,7 +367,7 @@ val addResourcesPatch = resourcePatch(
} }
} }
context.document[targetFile.path].let { document -> document(targetFile.path).let { document ->
// Save the target node here as well // Save the target node here as well
// in order to avoid having to call document.getNode("resources") // in order to avoid having to call document.getNode("resources")

View File

@ -10,8 +10,8 @@ import org.w3c.dom.Element
private val removeCaptureRestrictionResourcePatch = resourcePatch( private val removeCaptureRestrictionResourcePatch = resourcePatch(
description = "Sets allowAudioPlaybackCapture in manifest to true.", description = "Sets allowAudioPlaybackCapture in manifest to true.",
) { ) {
execute { context -> execute {
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
// Get the application node. // Get the application node.
val applicationNode = val applicationNode =
document document

View File

@ -13,9 +13,9 @@ val removeShareTargetsPatch = resourcePatch(
description = "Removes share targets like directly sharing to a frequent contact.", description = "Removes share targets like directly sharing to a frequent contact.",
use = false, use = false,
) { ) {
execute { context -> execute {
try { try {
context.document["res/xml/shortcuts.xml"] document("res/xml/shortcuts.xml")
} catch (_: FileNotFoundException) { } catch (_: FileNotFoundException) {
return@execute Logger.getLogger(this::class.java.name).warning("The app has no shortcuts") return@execute Logger.getLogger(this::class.java.name).warning("The app has no shortcuts")
}.use { document -> }.use { document ->

View File

@ -12,16 +12,15 @@ fun <T> transformInstructionsPatch(
transform: (MutableMethod, T) -> Unit, transform: (MutableMethod, T) -> Unit,
) = bytecodePatch { ) = bytecodePatch {
// Returns the patch indices as a Sequence, which will execute lazily. // Returns the patch indices as a Sequence, which will execute lazily.
fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? { fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? =
return method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) -> method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) ->
filterMap(classDef, method, instruction, index) filterMap(classDef, method, instruction, index)
} }
}
execute { context -> execute {
// Find all methods to patch // Find all methods to patch
buildMap { buildMap {
context.classes.forEach { classDef -> classes.forEach { classDef ->
val methods = buildList { val methods = buildList {
classDef.methods.forEach { method -> classDef.methods.forEach { method ->
// Since the Sequence executes lazily, // Since the Sequence executes lazily,
@ -37,7 +36,7 @@ fun <T> transformInstructionsPatch(
} }
}.forEach { (classDef, methods) -> }.forEach { (classDef, methods) ->
// And finally transform the methods... // And finally transform the methods...
val mutableClass = context.proxy(classDef).mutableClass val mutableClass = proxy(classDef).mutableClass
methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod -> methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque()) val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())

View File

@ -25,8 +25,8 @@ val changeVersionCodePatch = resourcePatch(
required = true, required = true,
) { versionCode -> versionCode!! >= 1 } ) { versionCode -> versionCode!! >= 1 }
execute { context -> execute {
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
val manifestElement = document.getNode("manifest") as Element val manifestElement = document.getNode("manifest") as Element
manifestElement.setAttribute("android:versionCode", "$versionCode") manifestElement.setAttribute("android:versionCode", "$versionCode")
} }

View File

@ -10,10 +10,8 @@ val deepLinkingPatch = bytecodePatch(
) { ) {
compatibleWith("com.amazon.mShop.android.shopping") compatibleWith("com.amazon.mShop.android.shopping")
val deepLinkingMatch by deepLinkingFingerprint()
execute { execute {
deepLinkingMatch.mutableMethod.addInstructions( deepLinkingFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -11,15 +11,13 @@ val proUnlockPatch = bytecodePatch(
) { ) {
compatibleWith("com.backdrops.wallpapers") compatibleWith("com.backdrops.wallpapers")
val proUnlockMatch by proUnlockFingerprint()
execute { execute {
val registerIndex = proUnlockMatch.patternMatch!!.endIndex - 1 val registerIndex = proUnlockFingerprint.patternMatch!!.endIndex - 1
proUnlockMatch.mutableMethod.apply { proUnlockFingerprint.method.apply {
val register = getInstruction<OneRegisterInstruction>(registerIndex).registerA val register = getInstruction<OneRegisterInstruction>(registerIndex).registerA
addInstruction( addInstruction(
proUnlockMatch.patternMatch!!.endIndex, proUnlockFingerprint.patternMatch!!.endIndex,
"const/4 v$register, 0x1", "const/4 v$register, 0x1",
) )
} }

View File

@ -10,9 +10,7 @@ val removePlayLimitsPatch = bytecodePatch(
) { ) {
compatibleWith("com.bandcamp.android") compatibleWith("com.bandcamp.android")
val handlePlaybackLimitsMatch by handlePlaybackLimitsFingerprint()
execute { execute {
handlePlaybackLimitsMatch.mutableMethod.addInstructions(0, "return-void") handlePlaybackLimitsFingerprint.method.addInstructions(0, "return-void")
} }
} }

View File

@ -10,9 +10,7 @@ val bypassRootChecksPatch = bytecodePatch(
) { ) {
compatibleWith("it.ipzs.cieid") compatibleWith("it.ipzs.cieid")
val checkRootMatch by checkRootFingerprint()
execute { execute {
checkRootMatch.mutableMethod.addInstruction(1, "return-void") checkRootFingerprint.method.addInstruction(1, "return-void")
} }
} }

View File

@ -11,8 +11,6 @@ val disableAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.duolingo") compatibleWith("com.duolingo")
val initializeMonetizationDebugSettingsMatch by initializeMonetizationDebugSettingsFingerprint()
execute { execute {
// Couple approaches to remove ads exist: // Couple approaches to remove ads exist:
// //
@ -21,8 +19,8 @@ val disableAdsPatch = bytecodePatch(
// SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS". // SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS".
// //
// MonetizationDebugSettings seems to be the most general setting to work fine. // MonetizationDebugSettings seems to be the most general setting to work fine.
initializeMonetizationDebugSettingsMatch.mutableMethod.apply { initializeMonetizationDebugSettingsFingerprint.method.apply {
val insertIndex = initializeMonetizationDebugSettingsMatch.patternMatch!!.startIndex val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(

View File

@ -12,11 +12,9 @@ val enableDebugMenuPatch = bytecodePatch(
) { ) {
compatibleWith("com.duolingo"("5.158.4")) compatibleWith("com.duolingo"("5.158.4"))
val initializeBuildConfigProviderMatch by initializeBuildConfigProviderFingerprint()
execute { execute {
initializeBuildConfigProviderMatch.mutableMethod.apply { initializeBuildConfigProviderFingerprint.method.apply {
val insertIndex = initializeBuildConfigProviderMatch.patternMatch!!.startIndex val insertIndex = initializeBuildConfigProviderFingerprint.patternMatch!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstructions( addInstructions(

View File

@ -19,13 +19,9 @@ val hideSponsoredStoriesPatch = bytecodePatch(
) { ) {
compatibleWith("com.facebook.katana") compatibleWith("com.facebook.katana")
val getStoryVisibilityMatch by getStoryVisibilityFingerprint()
val getSponsoredDataModelTemplateMatch by getSponsoredDataModelTemplateFingerprint()
val baseModelMapperMatch by baseModelMapperFingerprint()
execute { execute {
val sponsoredDataModelTemplateMethod = getSponsoredDataModelTemplateMatch.method val sponsoredDataModelTemplateMethod = getSponsoredDataModelTemplateFingerprint.originalMethod
val baseModelMapperMethod = baseModelMapperMatch.method val baseModelMapperMethod = baseModelMapperFingerprint.originalMethod
val baseModelWithTreeType = baseModelMapperMethod.returnType val baseModelWithTreeType = baseModelMapperMethod.returnType
val graphQlStoryClassDescriptor = "Lcom/facebook/graphql/model/GraphQLStory;" val graphQlStoryClassDescriptor = "Lcom/facebook/graphql/model/GraphQLStory;"
@ -33,8 +29,9 @@ val hideSponsoredStoriesPatch = bytecodePatch(
// The "SponsoredDataModelTemplate" methods has the ids in its body to extract sponsored data // The "SponsoredDataModelTemplate" methods has the ids in its body to extract sponsored data
// from GraphQL models, but targets the wrong derived type of "BaseModelWithTree". Since those ids // from GraphQL models, but targets the wrong derived type of "BaseModelWithTree". Since those ids
// could change in future version, we need to extract them and call the base implementation directly. // could change in future version, we need to extract them and call the base implementation directly.
val getSponsoredDataHelperMethod = ImmutableMethod( val getSponsoredDataHelperMethod = ImmutableMethod(
getStoryVisibilityMatch.classDef.type, getStoryVisibilityFingerprint.originalClassDef.type,
"getSponsoredData", "getSponsoredData",
listOf(ImmutableMethodParameter(graphQlStoryClassDescriptor, null, null)), listOf(ImmutableMethodParameter(graphQlStoryClassDescriptor, null, null)),
baseModelWithTreeType, baseModelWithTreeType,
@ -68,12 +65,12 @@ val hideSponsoredStoriesPatch = bytecodePatch(
) )
} }
getStoryVisibilityMatch.mutableClass.methods.add(getSponsoredDataHelperMethod) getStoryVisibilityFingerprint.classDef.methods.add(getSponsoredDataHelperMethod)
// Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value. // Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value.
// If so, hide the story by setting the visibility to StoryVisibility.GONE. // If so, hide the story by setting the visibility to StoryVisibility.GONE.
getStoryVisibilityMatch.mutableMethod.addInstructionsWithLabels( getStoryVisibilityFingerprint.method.addInstructionsWithLabels(
getStoryVisibilityMatch.patternMatch!!.startIndex, getStoryVisibilityFingerprint.patternMatch!!.startIndex,
""" """
instance-of v0, p0, $graphQlStoryClassDescriptor instance-of v0, p0, $graphQlStoryClassDescriptor
if-eqz v0, :resume_normal if-eqz v0, :resume_normal

View File

@ -10,12 +10,12 @@ val hideStoryAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.facebook.katana") compatibleWith("com.facebook.katana")
val fetchMoreAdsMatch by fetchMoreAdsFingerprint()
val adsInsertionMatch by adsInsertionFingerprint()
execute { execute {
setOf(fetchMoreAdsMatch, adsInsertionMatch).forEach { match -> setOf(
match.mutableMethod.replaceInstruction(0, "return-void") fetchMoreAdsFingerprint,
adsInsertionFingerprint,
).forEach { fingerprint ->
fingerprint.method.replaceInstruction(0, "return-void")
} }
} }
} }

View File

@ -10,12 +10,9 @@ val bootloaderDetectionPatch = bytecodePatch(
) { ) {
compatibleWith("at.gv.bmf.bmf2go") compatibleWith("at.gv.bmf.bmf2go")
val createKeyMatch by createKeyFingerprint()
val bootStateMatch by bootStateFingerprint()
execute { execute {
setOf(createKeyMatch, bootStateMatch).forEach { match -> setOf(createKeyFingerprint, bootStateFingerprint).forEach { fingerprint ->
match.mutableMethod.addInstructions( fingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -10,10 +10,8 @@ val rootDetectionPatch = bytecodePatch(
) { ) {
compatibleWith("at.gv.bmf.bmf2go") compatibleWith("at.gv.bmf.bmf2go")
val rootDetectionMatch by rootDetectionFingerprint()
execute { execute {
rootDetectionMatch.mutableMethod.addInstructions( rootDetectionFingerprint.method.addInstructions(
0, 0,
""" """
sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;

View File

@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused") @Suppress("unused")
val enableCustomTabsPatch = bytecodePatch( val enableCustomTabsPatch = bytecodePatch(
@ -12,11 +13,9 @@ val enableCustomTabsPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.magazines") compatibleWith("com.google.android.apps.magazines")
val launchCustomTabMatch by launchCustomTabFingerprint()
execute { execute {
launchCustomTabMatch.mutableMethod.apply { launchCustomTabFingerprint.method.apply {
val checkIndex = launchCustomTabMatch.patternMatch!!.endIndex + 1 val checkIndex = launchCustomTabFingerprint.patternMatch!!.endIndex + 1
val register = getInstruction<OneRegisterInstruction>(checkIndex).registerA val register = getInstruction<OneRegisterInstruction>(checkIndex).registerA
replaceInstruction(checkIndex, "const/4 v$register, 0x1") replaceInstruction(checkIndex, "const/4 v$register, 0x1")

View File

@ -54,8 +54,6 @@ val spoofFeaturesPatch = bytecodePatch(
required = true, required = true,
) )
val initializeFeaturesEnumMatch by initializeFeaturesEnumFingerprint()
execute { execute {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val featuresToEnable = featuresToEnable!!.toSet() val featuresToEnable = featuresToEnable!!.toSet()
@ -63,7 +61,7 @@ val spoofFeaturesPatch = bytecodePatch(
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val featuresToDisable = featuresToDisable!!.toSet() val featuresToDisable = featuresToDisable!!.toSet()
initializeFeaturesEnumMatch.mutableMethod.apply { initializeFeaturesEnumFingerprint.method.apply {
instructions.filter { it.opcode == Opcode.CONST_STRING }.forEach { instructions.filter { it.opcode == Opcode.CONST_STRING }.forEach {
val feature = it.getReference<StringReference>()!!.string val feature = it.getReference<StringReference>()!!.string

View File

@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused") @Suppress("unused")
val restoreHiddenBackUpWhileChargingTogglePatch = bytecodePatch( val restoreHiddenBackUpWhileChargingTogglePatch = bytecodePatch(
@ -12,12 +13,10 @@ val restoreHiddenBackUpWhileChargingTogglePatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.photos") compatibleWith("com.google.android.apps.photos")
val backupPreferencesMatch by backupPreferencesFingerprint()
execute { execute {
// Patches 'backup_prefs_had_backup_only_when_charging_enabled' to always be true. // Patches 'backup_prefs_had_backup_only_when_charging_enabled' to always be true.
val chargingPrefStringIndex = backupPreferencesMatch.stringMatches!!.first().index val chargingPrefStringIndex = backupPreferencesFingerprint.stringMatches!!.first().index
backupPreferencesMatch.mutableMethod.apply { backupPreferencesFingerprint.method.apply {
// Get the register of move-result. // Get the register of move-result.
val resultRegister = getInstruction<OneRegisterInstruction>(chargingPrefStringIndex + 2).registerA val resultRegister = getInstruction<OneRegisterInstruction>(chargingPrefStringIndex + 2).registerA
// Insert const after move-result to override register as true. // Insert const after move-result to override register as true.

View File

@ -5,6 +5,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused") @Suppress("unused")
val removeDeviceRestrictionsPatch = bytecodePatch( val removeDeviceRestrictionsPatch = bytecodePatch(
@ -13,12 +14,10 @@ val removeDeviceRestrictionsPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.recorder") compatibleWith("com.google.android.apps.recorder")
val onApplicationCreateMatch by onApplicationCreateFingerprint()
execute { execute {
val featureStringIndex = onApplicationCreateMatch.stringMatches!!.first().index val featureStringIndex = onApplicationCreateFingerprint.stringMatches!!.first().index
onApplicationCreateMatch.mutableMethod.apply { onApplicationCreateFingerprint.method.apply {
// Remove check for device restrictions. // Remove check for device restrictions.
removeInstructions(featureStringIndex - 2, 5) removeInstructions(featureStringIndex - 2, 5)

View File

@ -9,10 +9,8 @@ val disableAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.myprog.hexedit") compatibleWith("com.myprog.hexedit")
val primaryAdsMatch by primaryAdsFingerprint()
execute { execute {
primaryAdsMatch.mutableMethod.replaceInstructions( primaryAdsFingerprint.method.replaceInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -9,10 +9,8 @@ val unlockProPatch = bytecodePatch(
) { ) {
compatibleWith("ginlemon.iconpackstudio"("2.2 build 016")) compatibleWith("ginlemon.iconpackstudio"("2.2 build 016"))
val checkProMatch by checkProFingerprint()
execute { execute {
checkProMatch.mutableMethod.addInstructions( checkProFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -10,11 +10,11 @@ val rootDetectionPatch = bytecodePatch(
) { ) {
compatibleWith("at.gv.oe.app") compatibleWith("at.gv.oe.app")
attestationSupportedCheckFingerprint()
bootloaderCheckFingerprint()
rootCheckFingerprint()
execute { execute {
setOf(attestationSupportedCheckFingerprint, bootloaderCheckFingerprint, rootCheckFingerprint).returnEarly(true) setOf(
attestationSupportedCheckFingerprint,
bootloaderCheckFingerprint,
rootCheckFingerprint,
).forEach { it.method.returnEarly(true) }
} }
} }

View File

@ -10,8 +10,6 @@ val spoofSignaturePatch = bytecodePatch(
) { ) {
compatibleWith("at.gv.oe.app") compatibleWith("at.gv.oe.app")
val spoofSignatureMatch by spoofSignatureFingerprint()
execute { execute {
val expectedSignature = val expectedSignature =
"OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" + "OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" +
@ -26,7 +24,7 @@ val spoofSignaturePatch = bytecodePatch(
"77ef1be61b2c01ebdabddcbf53cc4b6fd9a3c445606ee77b3758162c80ad8f8137b3c6864e92db904807dcb2be9d7717dd21" + "77ef1be61b2c01ebdabddcbf53cc4b6fd9a3c445606ee77b3758162c80ad8f8137b3c6864e92db904807dcb2be9d7717dd21" +
"bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}" "bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}"
spoofSignatureMatch.mutableMethod.addInstructions( spoofSignatureFingerprint.method.addInstructions(
0, 0,
""" """
const-string v0, "$expectedSignature" const-string v0, "$expectedSignature"

View File

@ -9,10 +9,8 @@ val hideAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.nis.app") compatibleWith("com.nis.app")
val inshortsAdsMatch by inshortsAdsFingerprint()
execute { execute {
inshortsAdsMatch.mutableMethod.addInstruction( inshortsAdsFingerprint.method.addInstruction(
0, 0,
""" """
return-void return-void

View File

@ -11,10 +11,8 @@ val hideAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.instagram.android") compatibleWith("com.instagram.android")
val adInjectorMatch by adInjectorFingerprint()
execute { execute {
adInjectorMatch.mutableMethod.addInstructions( adInjectorFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x0 const/4 v0, 0x0

View File

@ -9,11 +9,9 @@ val removeAdsPatch = bytecodePatch(
) { ) {
compatibleWith("net.binarymode.android.irplus") compatibleWith("net.binarymode.android.irplus")
val irplusAdsMatch by irplusAdsFingerprint()
execute { execute {
// By overwriting the second parameter of the method, // By overwriting the second parameter of the method,
// the view which holds the advertisement is removed. // the view which holds the advertisement is removed.
irplusAdsMatch.mutableMethod.addInstruction(0, "const/4 p2, 0x0") irplusAdsFingerprint.method.addInstruction(0, "const/4 p2, 0x0")
} }
} }

View File

@ -9,10 +9,8 @@ val disableMandatoryLoginPatch = bytecodePatch(
) { ) {
compatibleWith("com.adobe.lrmobile") compatibleWith("com.adobe.lrmobile")
val isLoggedInMatch by isLoggedInFingerprint()
execute { execute {
isLoggedInMatch.mutableMethod.apply { isLoggedInFingerprint.method.apply {
val index = implementation!!.instructions.lastIndex - 1 val index = implementation!!.instructions.lastIndex - 1
// Set isLoggedIn = true. // Set isLoggedIn = true.
replaceInstruction(index, "const/4 v0, 0x1") replaceInstruction(index, "const/4 v0, 0x1")

View File

@ -9,10 +9,8 @@ val unlockPremiumPatch = bytecodePatch(
) { ) {
compatibleWith("com.adobe.lrmobile") compatibleWith("com.adobe.lrmobile")
val hasPurchasedMatch by hasPurchasedFingerprint()
execute { execute {
// Set hasPremium = true. // Set hasPremium = true.
hasPurchasedMatch.mutableMethod.replaceInstruction(2, "const/4 v2, 0x1") hasPurchasedFingerprint.method.replaceInstruction(2, "const/4 v2, 0x1")
} }
} }

View File

@ -6,10 +6,9 @@ import app.revanced.patcher.patch.bytecodePatch
val licenseValidationPatch = bytecodePatch( val licenseValidationPatch = bytecodePatch(
description = "Disables Firebase license validation.", description = "Disables Firebase license validation.",
) { ) {
val licenseValidationMatch by licenseValidationFingerprint()
execute { execute {
licenseValidationMatch.mutableMethod.replaceInstructions( licenseValidationFingerprint.method.replaceInstructions(
0, 0,
""" """
const/4 p0, 0x1 const/4 p0, 0x1

View File

@ -6,10 +6,9 @@ import app.revanced.patcher.patch.bytecodePatch
val signatureVerificationPatch = bytecodePatch( val signatureVerificationPatch = bytecodePatch(
description = "Disables detection of incorrect signature.", description = "Disables detection of incorrect signature.",
) { ) {
val verifySignatureMatch by verifySignatureFingerprint()
execute { execute {
verifySignatureMatch.mutableMethod.replaceInstructions( verifySignatureFingerprint.method.replaceInstructions(
0, 0,
""" """
const/4 p0, 0x1 const/4 p0, 0x1

View File

@ -13,10 +13,8 @@ val unlockProVersionPatch = bytecodePatch(
compatibleWith("com.zombodroid.MemeGenerator"("4.6364", "4.6370", "4.6375", "4.6377")) compatibleWith("com.zombodroid.MemeGenerator"("4.6364", "4.6370", "4.6375", "4.6377"))
val isFreeVersionMatch by isFreeVersionFingerprint()
execute { execute {
isFreeVersionMatch.mutableMethod.replaceInstructions( isFreeVersionFingerprint.method.replaceInstructions(
0, 0,
""" """
sget-object p0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; sget-object p0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;

View File

@ -10,9 +10,7 @@ val hideInboxAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.facebook.orca") compatibleWith("com.facebook.orca")
val loadInboxAdsMatch by loadInboxAdsFingerprint()
execute { execute {
loadInboxAdsMatch.mutableMethod.replaceInstruction(0, "return-void") loadInboxAdsFingerprint.method.replaceInstruction(0, "return-void")
} }
} }

View File

@ -10,9 +10,7 @@ val hideInboxSubtabsPatch = bytecodePatch(
) { ) {
compatibleWith("com.facebook.orca") compatibleWith("com.facebook.orca")
val createInboxSubTabsMatch by createInboxSubTabsFingerprint()
execute { execute {
createInboxSubTabsMatch.mutableMethod.replaceInstruction(2, "const/4 v0, 0x0") createInboxSubTabsFingerprint.method.replaceInstruction(2, "const/4 v0, 0x0")
} }
} }

View File

@ -4,6 +4,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused") @Suppress("unused")
val disableSwitchingEmojiToStickerPatch = bytecodePatch( val disableSwitchingEmojiToStickerPatch = bytecodePatch(
@ -12,12 +13,9 @@ val disableSwitchingEmojiToStickerPatch = bytecodePatch(
) { ) {
compatibleWith("com.facebook.orca"("439.0.0.29.119")) compatibleWith("com.facebook.orca"("439.0.0.29.119"))
val switchMessangeInputEmojiButtonMatch by switchMessangeInputEmojiButtonFingerprint()
execute { execute {
val setStringIndex = switchMessangeInputEmojiButtonMatch.patternMatch!!.startIndex + 2 switchMessengeInputEmojiButtonFingerprint.method.apply {
val setStringIndex = switchMessengeInputEmojiButtonFingerprint.patternMatch!!.startIndex + 2
switchMessangeInputEmojiButtonMatch.mutableMethod.apply {
val targetRegister = getInstruction<OneRegisterInstruction>(setStringIndex).registerA val targetRegister = getInstruction<OneRegisterInstruction>(setStringIndex).registerA
replaceInstruction(setStringIndex, "const-string v$targetRegister, \"expression\"") replaceInstruction(setStringIndex, "const-string v$targetRegister, \"expression\"")

View File

@ -10,9 +10,7 @@ val disableTypingIndicatorPatch = bytecodePatch(
) { ) {
compatibleWith("com.facebook.orca") compatibleWith("com.facebook.orca")
val sendTypingIndicatorMatch by sendTypingIndicatorFingerprint()
execute { execute {
sendTypingIndicatorMatch.mutableMethod.replaceInstruction(0, "return-void") sendTypingIndicatorFingerprint.method.replaceInstruction(0, "return-void")
} }
} }

View File

@ -16,7 +16,7 @@ internal val sendTypingIndicatorFingerprint = fingerprint {
} }
} }
internal val switchMessangeInputEmojiButtonFingerprint = fingerprint { internal val switchMessengeInputEmojiButtonFingerprint = fingerprint {
returns("V") returns("V")
parameters("L", "Z") parameters("L", "Z")
opcodes( opcodes(

View File

@ -15,14 +15,10 @@ val forceEnglishLocalePatch = bytecodePatch(
dependsOn(fixLoginPatch) dependsOn(fixLoginPatch)
val syncBluetoothLanguageMatch by syncBluetoothLanguageFingerprint()
execute { execute {
val resolvePhoneLocaleInstruction = syncBluetoothLanguageMatch.patternMatch!!.startIndex syncBluetoothLanguageFingerprint.method.apply {
val resolvePhoneLocaleInstruction = syncBluetoothLanguageFingerprint.patternMatch!!.startIndex
syncBluetoothLanguageMatch.mutableMethod.apply { val registerIndexToUpdate = getInstruction<OneRegisterInstruction>(resolvePhoneLocaleInstruction).registerA
val registerIndexToUpdate =
getInstruction<OneRegisterInstruction>(resolvePhoneLocaleInstruction).registerA
replaceInstruction( replaceInstruction(
resolvePhoneLocaleInstruction, resolvePhoneLocaleInstruction,

View File

@ -9,9 +9,7 @@ val fixLoginPatch = bytecodePatch(
) { ) {
compatibleWith("com.xiaomi.wearable") compatibleWith("com.xiaomi.wearable")
val xiaomiAccountManagerConstructorMatch by xiaomiAccountManagerConstructorFingerprint()
execute { execute {
xiaomiAccountManagerConstructorMatch.mutableMethod.addInstruction(0, "const/16 p2, 0x0") xiaomiAccountManagerConstructorFingerprint.method.addInstruction(0, "const/16 p2, 0x0")
} }
} }

View File

@ -10,13 +10,10 @@ val hideVideoAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val showVideoAdsParentMatch by showVideoAdsParentFingerprint() execute {
navigate(showVideoAdsParentFingerprint.originalMethod)
execute { context -> .to(showVideoAdsParentFingerprint.patternMatch!!.startIndex + 1)
val showVideoAdsMethod = context .stop()
.navigate(showVideoAdsParentMatch.mutableMethod) .addInstruction(0, "const/4 p1, 0x0")
.at(showVideoAdsParentMatch.patternMatch!!.startIndex + 1).mutable()
showVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0")
} }
} }

View File

@ -10,10 +10,8 @@ val enableExclusiveAudioPlaybackPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val allowExclusiveAudioPlaybackMatch by allowExclusiveAudioPlaybackFingerprint()
execute { execute {
allowExclusiveAudioPlaybackMatch.mutableMethod.apply { allowExclusiveAudioPlaybackFingerprint.method.apply {
addInstructions( addInstructions(
0, 0,
""" """

View File

@ -13,13 +13,12 @@ val permanentRepeatPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val repeatTrackMatch by repeatTrackFingerprint()
execute { execute {
val startIndex = repeatTrackMatch.patternMatch!!.endIndex
val startIndex = repeatTrackFingerprint.patternMatch!!.endIndex
val repeatIndex = startIndex + 1 val repeatIndex = startIndex + 1
repeatTrackMatch.mutableMethod.apply { repeatTrackFingerprint.method.apply {
addInstructionsWithLabels( addInstructionsWithLabels(
startIndex, startIndex,
"goto :repeat", "goto :repeat",

View File

@ -20,9 +20,7 @@ val permanentShufflePatch = bytecodePatch(
), ),
) )
val disableShuffleMatch by disableShuffleFingerprint()
execute { execute {
disableShuffleMatch.mutableMethod.addInstruction(0, "return-void") disableShuffleFingerprint.method.addInstruction(0, "return-void")
} }
} }

View File

@ -13,11 +13,9 @@ val hideCategoryBar = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val constructCategoryBarMatch by constructCategoryBarFingerprint()
execute { execute {
constructCategoryBarMatch.mutableMethod.apply { constructCategoryBarFingerprint.method.apply {
val insertIndex = constructCategoryBarMatch.patternMatch!!.startIndex val insertIndex = constructCategoryBarFingerprint.patternMatch!!.startIndex
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
addInstructions( addInstructions(

View File

@ -14,12 +14,9 @@ val hideGetPremiumPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val hideGetPremiumMatch by hideGetPremiumFingerprint()
val membershipSettingsMatch by membershipSettingsFingerprint()
execute { execute {
hideGetPremiumMatch.mutableMethod.apply { hideGetPremiumFingerprint.method.apply {
val insertIndex = hideGetPremiumMatch.patternMatch!!.endIndex val insertIndex = hideGetPremiumFingerprint.patternMatch!!.endIndex
val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(insertIndex) val setVisibilityInstruction = getInstruction<FiveRegisterInstruction>(insertIndex)
val getPremiumViewRegister = setVisibilityInstruction.registerC val getPremiumViewRegister = setVisibilityInstruction.registerC
@ -37,7 +34,7 @@ val hideGetPremiumPatch = bytecodePatch(
) )
} }
membershipSettingsMatch.mutableMethod.addInstructions( membershipSettingsFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x0 const/4 v0, 0x0

View File

@ -20,12 +20,10 @@ val removeUpgradeButtonPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val pivotBarConstructorMatch by pivotBarConstructorFingerprint()
execute { execute {
pivotBarConstructorMatch.mutableMethod.apply { pivotBarConstructorFingerprint.method.apply {
val pivotBarElementFieldReference = val pivotBarElementFieldReference =
getInstruction(pivotBarConstructorMatch.patternMatch!!.endIndex - 1) getInstruction(pivotBarConstructorFingerprint.patternMatch!!.endIndex - 1)
.getReference<FieldReference>() .getReference<FieldReference>()
val register = getInstruction<FiveRegisterInstruction>(0).registerC val register = getInstruction<FiveRegisterInstruction>(0).registerC
@ -39,7 +37,7 @@ val removeUpgradeButtonPatch = bytecodePatch(
iput-object v0, v$register, $pivotBarElementFieldReference iput-object v0, v$register, $pivotBarElementFieldReference
""".toInstructions().toMutableList() """.toInstructions().toMutableList()
val endIndex = pivotBarConstructorMatch.patternMatch!!.endIndex val endIndex = pivotBarConstructorFingerprint.patternMatch!!.endIndex
// Replace the instruction to retain the label at given index. // Replace the instruction to retain the label at given index.
replaceInstruction( replaceInstruction(

View File

@ -10,10 +10,8 @@ val bypassCertificateChecksPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val checkCertificateMatch by checkCertificateFingerprint()
execute { execute {
checkCertificateMatch.mutableMethod.addInstructions( checkCertificateFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -11,16 +11,13 @@ val backgroundPlaybackPatch = bytecodePatch(
) { ) {
compatibleWith("com.google.android.apps.youtube.music") compatibleWith("com.google.android.apps.youtube.music")
val kidsBackgroundPlaybackPolicyControllerMatch by kidsBackgroundPlaybackPolicyControllerFingerprint()
val backgroundPlaybackDisableMatch by backgroundPlaybackDisableFingerprint()
execute { execute {
kidsBackgroundPlaybackPolicyControllerMatch.mutableMethod.addInstruction( kidsBackgroundPlaybackPolicyControllerFingerprint.method.addInstruction(
0, 0,
"return-void", "return-void",
) )
backgroundPlaybackDisableMatch.mutableMethod.addInstructions( backgroundPlaybackDisableFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -9,10 +9,8 @@ val unlockProPatch = bytecodePatch(
) { ) {
compatibleWith("org.totschnig.myexpenses") compatibleWith("org.totschnig.myexpenses")
val isEnabledMatch by isEnabledFingerprint()
execute { execute {
isEnabledMatch.mutableMethod.addInstructions( isEnabledFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -10,12 +10,9 @@ val hideAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.myfitnesspal.android"("24.14.2")) compatibleWith("com.myfitnesspal.android"("24.14.2"))
val isPremiumUseCaseImplMatch by isPremiumUseCaseImplFingerprint()
val mainActivityNavigateToNativePremiumUpsellMatch by mainActivityNavigateToNativePremiumUpsellFingerprint()
execute { execute {
// Overwrite the premium status specifically for ads. // Overwrite the premium status specifically for ads.
isPremiumUseCaseImplMatch.mutableMethod.replaceInstructions( isPremiumUseCaseImplFingerprint.method.replaceInstructions(
0, 0,
""" """
sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean; sget-object v0, Ljava/lang/Boolean;->TRUE:Ljava/lang/Boolean;
@ -25,7 +22,7 @@ val hideAdsPatch = bytecodePatch(
// Prevent the premium upsell dialog from showing when the main activity is launched. // Prevent the premium upsell dialog from showing when the main activity is launched.
// In other places that are premium-only the dialog will still show. // In other places that are premium-only the dialog will still show.
mainActivityNavigateToNativePremiumUpsellMatch.mutableMethod.replaceInstructions( mainActivityNavigateToNativePremiumUpsellFingerprint.method.replaceInstructions(
0, 0,
"return-void", "return-void",
) )

View File

@ -10,8 +10,8 @@ val removeBroadcastsRestrictionPatch = resourcePatch(
) { ) {
compatibleWith("eu.faircode.netguard") compatibleWith("eu.faircode.netguard")
execute { context -> execute {
context.document["AndroidManifest.xml"].use { document -> document("AndroidManifest.xml").use { document ->
val applicationNode = val applicationNode =
document document
.getElementsByTagName("application") .getElementsByTagName("application")

View File

@ -9,10 +9,8 @@ val unlockProPatch = bytecodePatch(
) { ) {
compatibleWith("com.wakdev.apps.nfctools.se") compatibleWith("com.wakdev.apps.nfctools.se")
val isLicenseRegisteredMatch by isLicenseRegisteredFingerprint()
execute { execute {
isLicenseRegisteredMatch.mutableMethod.addInstructions( isLicenseRegisteredFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -9,10 +9,8 @@ val unlockProPatch = bytecodePatch(
) { ) {
compatibleWith("com.awedea.nyx") compatibleWith("com.awedea.nyx")
val checkProMatch by checkProFingerprint()
execute { execute {
checkProMatch.mutableMethod.addInstructions( checkProFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -17,10 +17,8 @@ val fixCrashPatch = bytecodePatch(
) { ) {
compatibleWith("de.simon.openinghours"("1.0")) compatibleWith("de.simon.openinghours"("1.0"))
val setPlaceMatch by setPlaceFingerprint()
execute { execute {
val indexedInstructions = setPlaceMatch.mutableMethod.instructions.withIndex().toList() val indexedInstructions = setPlaceFingerprint.method.instructions.withIndex().toList()
/** /**
* This function replaces all `checkNotNull` instructions in the integer interval * This function replaces all `checkNotNull` instructions in the integer interval
@ -29,7 +27,7 @@ val fixCrashPatch = bytecodePatch(
* the value is indeed null, we jump to a newly created label at `endIndex + 1`. * the value is indeed null, we jump to a newly created label at `endIndex + 1`.
*/ */
fun avoidNullPointerException(startIndex: Int, endIndex: Int) { fun avoidNullPointerException(startIndex: Int, endIndex: Int) {
val continueLabel = setPlaceMatch.mutableMethod.newLabel(endIndex + 1) val continueLabel = setPlaceFingerprint.method.newLabel(endIndex + 1)
for (index in startIndex..endIndex) { for (index in startIndex..endIndex) {
val instruction = indexedInstructions[index].value val instruction = indexedInstructions[index].value
@ -41,7 +39,7 @@ val fixCrashPatch = bytecodePatch(
val checkNotNullInstruction = instruction as FiveRegisterInstruction val checkNotNullInstruction = instruction as FiveRegisterInstruction
val originalRegister = checkNotNullInstruction.registerC val originalRegister = checkNotNullInstruction.registerC
setPlaceMatch.mutableMethod.replaceInstruction( setPlaceFingerprint.method.replaceInstruction(
index, index,
BuilderInstruction21t( BuilderInstruction21t(
Opcode.IF_EQZ, Opcode.IF_EQZ,

View File

@ -14,10 +14,8 @@ val getDeviceIdPatch = bytecodePatch(
compatibleWith("com.microblink.photomath"("8.37.0")) compatibleWith("com.microblink.photomath"("8.37.0"))
val getDeviceIdMatch by getDeviceIdFingerprint()
execute { execute {
getDeviceIdMatch.mutableMethod.replaceInstructions( getDeviceIdFingerprint.method.replaceInstructions(
0, 0,
""" """
const-string v0, "${Random.nextLong().toString(16)}" const-string v0, "${Random.nextLong().toString(16)}"

View File

@ -8,17 +8,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
val signatureDetectionPatch = bytecodePatch( val signatureDetectionPatch = bytecodePatch(
description = "Disables detection of incorrect signature.", description = "Disables detection of incorrect signature.",
) { ) {
val checkSignatureMatch by checkSignatureFingerprint()
execute { execute {
val signatureCheckInstruction = checkSignatureMatch.mutableMethod.getInstruction( val replacementIndex = checkSignatureFingerprint.patternMatch!!.endIndex
checkSignatureMatch.patternMatch!!.endIndex, val checkRegister =
) checkSignatureFingerprint.method.getInstruction<OneRegisterInstruction>(replacementIndex).registerA
val checkRegister = (signatureCheckInstruction as OneRegisterInstruction).registerA checkSignatureFingerprint.method.replaceInstruction(replacementIndex, "const/4 v$checkRegister, 0x1")
checkSignatureMatch.mutableMethod.replaceInstruction(
signatureCheckInstruction.location.index,
"const/4 v$checkRegister, 0x1",
)
} }
} }

View File

@ -13,10 +13,8 @@ val hideUpdatePopupPatch = bytecodePatch(
compatibleWith("com.microblink.photomath"("8.32.0")) compatibleWith("com.microblink.photomath"("8.32.0"))
val hideUpdatePopupMatch by hideUpdatePopupFingerprint()
execute { execute {
hideUpdatePopupMatch.mutableMethod.addInstructions( hideUpdatePopupFingerprint.method.addInstructions(
2, // Insert after the null check. 2, // Insert after the null check.
"return-void", "return-void",
) )

View File

@ -6,10 +6,9 @@ import app.revanced.patcher.patch.bytecodePatch
val enableBookpointPatch = bytecodePatch( val enableBookpointPatch = bytecodePatch(
description = "Enables textbook access", description = "Enables textbook access",
) { ) {
val isBookpointEnabledMatch by isBookpointEnabledFingerprint()
execute { execute {
isBookpointEnabledMatch.mutableMethod.replaceInstructions( isBookpointEnabledFingerprint.method.replaceInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -13,10 +13,8 @@ val unlockPlusPatch = bytecodePatch(
compatibleWith("com.microblink.photomath"("8.37.0")) compatibleWith("com.microblink.photomath"("8.37.0"))
val isPlusUnlockedMatch by isPlusUnlockedFingerprint()
execute { execute {
isPlusUnlockedMatch.mutableMethod.addInstructions( isPlusUnlockedFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -30,8 +30,6 @@ val spoofAndroidDeviceIdPatch = bytecodePatch(
), ),
) )
val getAndroidIDMatch by getAndroidIdFingerprint()
val androidDeviceId by stringOption( val androidDeviceId by stringOption(
key = "android-device-id", key = "android-device-id",
default = "0011223344556677", default = "0011223344556677",
@ -41,7 +39,7 @@ val spoofAndroidDeviceIdPatch = bytecodePatch(
) { it!!.matches("[A-Fa-f0-9]{16}".toRegex()) } ) { it!!.matches("[A-Fa-f0-9]{16}".toRegex()) }
execute { execute {
getAndroidIDMatch.mutableMethod.addInstructions( getAndroidIdFingerprint.method.addInstructions(
0, 0,
""" """
const-string v0, "$androidDeviceId" const-string v0, "$androidDeviceId"

View File

@ -33,12 +33,8 @@ val disableTrackingPatch = bytecodePatch(
), ),
) )
val facebookSDKMatch by facebookSDKFingerprint()
val firebaseInstallMatch by firebaseInstallFingerprint()
val appMeasurementMatch by appMeasurementFingerprint()
execute { execute {
facebookSDKMatch.mutableMethod.apply { facebookSDKFingerprint.method.apply {
instructions.filter { instruction -> instructions.filter { instruction ->
instruction.opcode == Opcode.CONST_STRING instruction.opcode == Opcode.CONST_STRING
}.forEach { instruction -> }.forEach { instruction ->
@ -51,7 +47,7 @@ val disableTrackingPatch = bytecodePatch(
} }
} }
firebaseInstallMatch.mutableMethod.apply { firebaseInstallFingerprint.method.apply {
instructions.filter { instructions.filter {
it.opcode == Opcode.CONST_STRING it.opcode == Opcode.CONST_STRING
}.filter { }.filter {
@ -66,6 +62,6 @@ val disableTrackingPatch = bytecodePatch(
} }
} }
appMeasurementMatch.mutableMethod.addInstruction(0, "return-void") appMeasurementFingerprint.method.addInstruction(0, "return-void")
} }
} }

View File

@ -9,10 +9,8 @@ val hideAdsPatch = bytecodePatch(
) { ) {
compatibleWith("jp.pxv.android") compatibleWith("jp.pxv.android")
val shouldShowAdsMatch by shouldShowAdsFingerprint()
execute { execute {
shouldShowAdsMatch.mutableMethod.addInstructions( shouldShowAdsFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x0 const/4 v0, 0x0

View File

@ -11,9 +11,7 @@ val hidePurchaseReminderPatch = bytecodePatch(
) { ) {
compatibleWith("com.rarlab.rar") compatibleWith("com.rarlab.rar")
val showReminderMatch by showReminderFingerprint()
execute { execute {
showReminderMatch.mutableMethod.addInstruction(0, "return-void") showReminderFingerprint.method.addInstruction(0, "return-void")
} }
} }

View File

@ -8,10 +8,10 @@ import app.revanced.patcher.patch.resourcePatch
val hideBannerPatch = resourcePatch( val hideBannerPatch = resourcePatch(
description = "Hides banner ads from comments on subreddits.", description = "Hides banner ads from comments on subreddits.",
) { ) {
execute { context -> execute {
val resourceFilePath = "res/layout/merge_listheader_link_detail.xml" val resourceFilePath = "res/layout/merge_listheader_link_detail.xml"
context.document[resourceFilePath].use { document -> document(resourceFilePath).use { document ->
document.getElementsByTagName("merge").item(0).childNodes.apply { document.getElementsByTagName("merge").item(0).childNodes.apply {
val attributes = arrayOf("height", "width") val attributes = arrayOf("height", "width")

View File

@ -6,10 +6,9 @@ import app.revanced.patcher.patch.bytecodePatch
val hideCommentAdsPatch = bytecodePatch( val hideCommentAdsPatch = bytecodePatch(
description = "Removes ads in the comments.", description = "Removes ads in the comments.",
) { ) {
val hideCommentAdsMatch by hideCommentAdsFingerprint()
execute { execute {
hideCommentAdsMatch.mutableMethod.addInstructions( hideCommentAdsFingerprint.method.addInstructions(
0, 0,
""" """
new-instance v0, Ljava/lang/Object; new-instance v0, Ljava/lang/Object;

View File

@ -25,9 +25,6 @@ val hideAdsPatch = bytecodePatch(
// This constraint is necessary due to dependency on hideBannerPatch. // This constraint is necessary due to dependency on hideBannerPatch.
compatibleWith("com.reddit.frontpage"("2024.17.0")) compatibleWith("com.reddit.frontpage"("2024.17.0"))
val adPostMatch by adPostFingerprint()
val newAdPostMatch by newAdPostFingerprint()
execute { execute {
// region Filter promoted ads (does not work in popular or latest feed) // region Filter promoted ads (does not work in popular or latest feed)
@ -35,7 +32,7 @@ val hideAdsPatch = bytecodePatch(
"Lapp/revanced/extension/reddit/patches/FilterPromotedLinksPatch;" + "Lapp/revanced/extension/reddit/patches/FilterPromotedLinksPatch;" +
"->filterChildren(Ljava/lang/Iterable;)Ljava/util/List;" "->filterChildren(Ljava/lang/Iterable;)Ljava/util/List;"
adPostMatch.mutableMethod.apply { adPostFingerprint.method.apply {
val setPostsListChildren = implementation!!.instructions.first { instruction -> val setPostsListChildren = implementation!!.instructions.first { instruction ->
if (instruction.opcode != Opcode.IPUT_OBJECT) return@first false if (instruction.opcode != Opcode.IPUT_OBJECT) return@first false
@ -66,7 +63,8 @@ val hideAdsPatch = bytecodePatch(
// The new feeds work by inserting posts into lists. // The new feeds work by inserting posts into lists.
// AdElementConverter is conveniently responsible for inserting all feed ads. // AdElementConverter is conveniently responsible for inserting all feed ads.
// By removing the appending instruction no ad posts gets appended to the feed. // By removing the appending instruction no ad posts gets appended to the feed.
val index = newAdPostMatch.method.implementation!!.instructions.indexOfFirst {
val index = newAdPostFingerprint.originalMethod.implementation!!.instructions.indexOfFirst {
if (it.opcode != Opcode.INVOKE_VIRTUAL) return@indexOfFirst false if (it.opcode != Opcode.INVOKE_VIRTUAL) return@indexOfFirst false
val reference = (it as ReferenceInstruction).reference as MethodReference val reference = (it as ReferenceInstruction).reference as MethodReference
@ -74,7 +72,7 @@ val hideAdsPatch = bytecodePatch(
reference.name == "add" && reference.definingClass == "Ljava/util/ArrayList;" reference.name == "add" && reference.definingClass == "Ljava/util/ArrayList;"
} }
newAdPostMatch.mutableMethod.removeInstruction(index) newAdPostFingerprint.method.removeInstruction(index)
} }
// endregion // endregion

View File

@ -1,6 +1,6 @@
package app.revanced.patches.reddit.customclients.baconreader.api package app.revanced.patches.reddit.customclients.baconreader.api
import app.revanced.patcher.Match import app.revanced.patcher.Fingerprint
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.reddit.customclients.spoofClientPatch import app.revanced.patches.reddit.customclients.spoofClientPatch
@ -12,16 +12,13 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://baconreader.com/au
"com.onelouder.baconreader.premium", "com.onelouder.baconreader.premium",
) )
val getAuthorizationUrlMatch by getAuthorizationUrlFingerprint()
val requestTokenMatch by requestTokenFingerprint()
val clientId by clientIdOption val clientId by clientIdOption
execute { execute {
fun Match.patch(replacementString: String) { fun Fingerprint.patch(replacementString: String) {
val clientIdIndex = stringMatches!!.first().index val clientIdIndex = stringMatches!!.first().index
mutableMethod.apply { method.apply {
val clientIdRegister = getInstruction<OneRegisterInstruction>(clientIdIndex).registerA val clientIdRegister = getInstruction<OneRegisterInstruction>(clientIdIndex).registerA
replaceInstruction( replaceInstruction(
clientIdIndex, clientIdIndex,
@ -31,9 +28,9 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://baconreader.com/au
} }
// Patch client id in authorization url. // Patch client id in authorization url.
getAuthorizationUrlMatch.patch("client_id=$clientId") getAuthorizationUrlFingerprint.patch("client_id=$clientId")
// Patch client id for access token request. // Patch client id for access token request.
requestTokenMatch.patch(clientId!!) requestTokenFingerprint.patch(clientId!!)
} }
} }

View File

@ -9,12 +9,9 @@ val disableAdsPatch = bytecodePatch(
) { ) {
compatibleWith("com.rubenmayayo.reddit") compatibleWith("com.rubenmayayo.reddit")
val maxMediationMatch by maxMediationFingerprint()
val admobMediationMatch by admobMediationFingerprint()
execute { execute {
arrayOf(maxMediationMatch, admobMediationMatch).forEach { arrayOf(maxMediationFingerprint, admobMediationFingerprint).forEach { fingerprint ->
it.mutableMethod.addInstructions(0, "return-void") fingerprint.method.addInstructions(0, "return-void")
} }
} }
} }

View File

@ -6,15 +6,12 @@ import app.revanced.patches.reddit.customclients.spoofClientPatch
val spoofClientPatch = spoofClientPatch(redirectUri = "http://rubenmayayo.com") { clientIdOption -> val spoofClientPatch = spoofClientPatch(redirectUri = "http://rubenmayayo.com") { clientIdOption ->
compatibleWith("com.rubenmayayo.reddit") compatibleWith("com.rubenmayayo.reddit")
val getClientIdMatch by getClientIdFingerprint()
val buildUserAgentMatch by buildUserAgentFingerprint()
val clientId by clientIdOption val clientId by clientIdOption
execute { execute {
// region Patch client id. // region Patch client id.
getClientIdMatch.mutableMethod.addInstructions( getClientIdFingerprint.method.addInstructions(
0, 0,
""" """
const-string v0, "$clientId" const-string v0, "$clientId"
@ -30,7 +27,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://rubenmayayo.com")
val platformName = (0..100000).random() val platformName = (0..100000).random()
val platformParameter = 0 val platformParameter = 0
buildUserAgentMatch.mutableMethod.addInstructions( buildUserAgentFingerprint.method.addInstructions(
0, 0,
"const-string p$platformParameter, \"$platformName\"", "const-string p$platformParameter, \"$platformName\"",
) )

View File

@ -12,16 +12,14 @@ val fixAudioMissingInDownloadsPatch = bytecodePatch(
) { ) {
compatibleWith("com.rubenmayayo.reddit") compatibleWith("com.rubenmayayo.reddit")
val downloadAudioMatch by downloadAudioFingerprint()
execute { execute {
val endpointReplacements = mapOf( val endpointReplacements = mapOf(
"/DASH_audio.mp4" to "/DASH_AUDIO_128.mp4", "/DASH_audio.mp4" to "/DASH_AUDIO_128.mp4",
"/audio" to "/DASH_AUDIO_64.mp4", "/audio" to "/DASH_AUDIO_64.mp4",
) )
downloadAudioMatch.stringMatches!!.forEach { match -> downloadAudioFingerprint.method.apply {
downloadAudioMatch.mutableMethod.apply { downloadAudioFingerprint.stringMatches!!.forEach { match ->
val replacement = endpointReplacements[match.string] val replacement = endpointReplacements[match.string]
val register = getInstruction<OneRegisterInstruction>(match.index).registerA val register = getInstruction<OneRegisterInstruction>(match.index).registerA

View File

@ -17,13 +17,10 @@ val fixSlinksPatch = fixSLinksPatch(
) { ) {
compatibleWith("com.rubenmayayo.reddit") compatibleWith("com.rubenmayayo.reddit")
val handleNavigationMatch by handleNavigationFingerprint()
val setAccessTokenMatch by getOAuthAccessTokenFingerprint()
execute { execute {
// region Patch navigation handler. // region Patch navigation handler.
handleNavigationMatch.mutableMethod.apply { handleNavigationFingerprint.method.apply {
val urlRegister = "p1" val urlRegister = "p1"
val tempRegister = "v1" val tempRegister = "v1"
@ -43,7 +40,7 @@ val fixSlinksPatch = fixSLinksPatch(
// region Patch set access token. // region Patch set access token.
setAccessTokenMatch.mutableMethod.addInstruction( getOAuthAccessTokenFingerprint.method.addInstruction(
3, 3,
"invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD", "invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD",
) )

View File

@ -10,12 +10,10 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethodImplementation
val spoofClientPatch = spoofClientPatch(redirectUri = "infinity://localhost") { clientIdOption -> val spoofClientPatch = spoofClientPatch(redirectUri = "infinity://localhost") { clientIdOption ->
compatibleWith("ml.docilealligator.infinityforreddit") compatibleWith("ml.docilealligator.infinityforreddit")
val apiUtilsMatch by apiUtilsFingerprint()
val clientId by clientIdOption val clientId by clientIdOption
execute { execute {
apiUtilsMatch.mutableClass.methods.apply { apiUtilsFingerprint.classDef.methods.apply {
val getClientIdMethod = single { it.name == "getId" }.also(::remove) val getClientIdMethod = single { it.name == "getId" }.also(::remove)
val newGetClientIdMethod = ImmutableMethod( val newGetClientIdMethod = ImmutableMethod(

View File

@ -13,10 +13,10 @@ val unlockSubscriptionPatch = bytecodePatch(
compatibleWith("ml.docilealligator.infinityforreddit") compatibleWith("ml.docilealligator.infinityforreddit")
startSubscriptionActivityFingerprint()
billingClientOnServiceConnectedFingerprint()
execute { execute {
setOf(startSubscriptionActivityFingerprint, billingClientOnServiceConnectedFingerprint).returnEarly() setOf(
startSubscriptionActivityFingerprint,
billingClientOnServiceConnectedFingerprint,
).forEach { it.method.returnEarly() }
} }
} }

View File

@ -12,10 +12,8 @@ val disableAdsPatch = bytecodePatch(
compatibleWith("o.o.joey") compatibleWith("o.o.joey")
val isAdFreeUserMatch by isAdFreeUserFingerprint()
execute { execute {
isAdFreeUserMatch.mutableMethod.addInstructions( isAdFreeUserFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -14,15 +14,12 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "https://127.0.0.1:65023/a
"o.o.joey.dev", "o.o.joey.dev",
) )
val getClientIdMatch by getClientIdFingerprint()
val authUtilityUserAgentMatch by authUtilityUserAgentFingerprint()
val clientId by clientIdOption val clientId by clientIdOption
execute { execute {
// region Patch client id. // region Patch client id.
getClientIdMatch.mutableMethod.addInstructions( getClientIdFingerprint.method.addInstructions(
0, 0,
""" """
const-string v0, "$clientId" const-string v0, "$clientId"
@ -38,7 +35,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "https://127.0.0.1:65023/a
val randomName = (0..100000).random() val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)" val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
authUtilityUserAgentMatch.mutableMethod.replaceInstructions( authUtilityUserAgentFingerprint.method.replaceInstructions(
0, 0,
""" """
const-string v0, "$userAgent" const-string v0, "$userAgent"

View File

@ -4,9 +4,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
val disablePiracyDetectionPatch = bytecodePatch { val disablePiracyDetectionPatch = bytecodePatch {
val piracyDetectionMatch by piracyDetectionFingerprint()
execute { execute {
piracyDetectionMatch.mutableMethod.addInstruction(0, "return-void") piracyDetectionFingerprint.method.addInstruction(0, "return-void")
} }
} }

View File

@ -1,5 +1,6 @@
package app.revanced.patches.reddit.customclients.redditisfun.api package app.revanced.patches.reddit.customclients.redditisfun.api
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.Match import app.revanced.patcher.Match
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@ -16,10 +17,6 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
"com.andrewshu.android.redditdonation", "com.andrewshu.android.redditdonation",
) )
val buildAuthorizationStringMatch by buildAuthorizationStringFingerprint()
val basicAuthorizationMatch by basicAuthorizationFingerprint()
val getUserAgentMatch by getUserAgentFingerprint()
val clientId by clientIdOption val clientId by clientIdOption
execute { execute {
@ -33,10 +30,10 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
* @param getReplacementIndex A function that returns the index of the instruction to replace * @param getReplacementIndex A function that returns the index of the instruction to replace
* using the [Match.StringMatch] list from the [Match]. * using the [Match.StringMatch] list from the [Match].
*/ */
fun Match.replaceWith( fun Fingerprint.replaceWith(
string: String, string: String,
getReplacementIndex: List<Match.StringMatch>.() -> Int, getReplacementIndex: List<Match.StringMatch>.() -> Int,
) = mutableMethod.apply { ) = method.apply {
val replacementIndex = stringMatches!!.getReplacementIndex() val replacementIndex = stringMatches!!.getReplacementIndex()
val clientIdRegister = getInstruction<OneRegisterInstruction>(replacementIndex).registerA val clientIdRegister = getInstruction<OneRegisterInstruction>(replacementIndex).registerA
@ -44,10 +41,10 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
} }
// Patch OAuth authorization. // Patch OAuth authorization.
buildAuthorizationStringMatch.replaceWith(clientId!!) { first().index + 4 } buildAuthorizationStringFingerprint.replaceWith(clientId!!) { first().index + 4 }
// Path basic authorization. // Path basic authorization.
basicAuthorizationMatch.replaceWith("$clientId:") { last().index + 7 } basicAuthorizationFingerprint.replaceWith("$clientId:") { last().index + 7 }
// endregion // endregion
@ -57,7 +54,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
val randomName = (0..100000).random() val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)" val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
getUserAgentMatch.mutableMethod.addInstructions( getUserAgentFingerprint.method.addInstructions(
0, 0,
""" """
const-string v0, "$userAgent" const-string v0, "$userAgent"
@ -71,7 +68,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
// Reddit messed up and does not append a redirect uri to the authorization url to old.reddit.com/login. // Reddit messed up and does not append a redirect uri to the authorization url to old.reddit.com/login.
// Replace old.reddit.com with ssl.reddit.com to fix this. // Replace old.reddit.com with ssl.reddit.com to fix this.
buildAuthorizationStringMatch.mutableMethod.apply { buildAuthorizationStringFingerprint.method.apply {
val index = indexOfFirstInstructionOrThrow { val index = indexOfFirstInstructionOrThrow {
getReference<StringReference>()?.contains("old.reddit.com") == true getReference<StringReference>()?.contains("old.reddit.com") == true
} }

View File

@ -15,29 +15,22 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "dbrady://relay") {
"reddit.news", "reddit.news",
) )
val loginActivityClientIdMatch by loginActivityClientIdFingerprint()
val getLoggedInBearerTokenMatch by getLoggedInBearerTokenFingerprint()
val getLoggedOutBearerTokenMatch by getLoggedOutBearerTokenFingerprint()
val getRefreshTokenMatch by getRefreshTokenFingerprint()
val setRemoteConfigMatch by setRemoteConfigFingerprint()
val redditCheckDisableAPIMatch by redditCheckDisableAPIFingerprint()
val clientId by it val clientId by it
execute { execute {
// region Patch client id. // region Patch client id.
setOf( setOf(
loginActivityClientIdMatch, loginActivityClientIdFingerprint,
getLoggedInBearerTokenMatch, getLoggedInBearerTokenFingerprint,
getLoggedOutBearerTokenMatch, getLoggedOutBearerTokenFingerprint,
getRefreshTokenMatch, getRefreshTokenFingerprint,
).forEach { match -> ).forEach { fingerprint ->
val clientIdIndex = match.stringMatches!!.first().index val clientIdIndex = fingerprint.stringMatches!!.first().index
match.mutableMethod.apply { fingerprint.method.apply {
val clientIdRegister = getInstruction<OneRegisterInstruction>(clientIdIndex).registerA val clientIdRegister = getInstruction<OneRegisterInstruction>(clientIdIndex).registerA
match.mutableMethod.replaceInstruction( fingerprint.method.replaceInstruction(
clientIdIndex, clientIdIndex,
"const-string v$clientIdRegister, \"$clientId\"", "const-string v$clientIdRegister, \"$clientId\"",
) )
@ -49,12 +42,12 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "dbrady://relay") {
// region Patch miscellaneous. // region Patch miscellaneous.
// Do not load remote config which disables OAuth login remotely. // Do not load remote config which disables OAuth login remotely.
setRemoteConfigMatch.mutableMethod.addInstructions(0, "return-void") setRemoteConfigFingerprint.method.addInstructions(0, "return-void")
// Prevent OAuth login being disabled remotely. // Prevent OAuth login being disabled remotely.
val checkIsOAuthRequestIndex = redditCheckDisableAPIMatch.patternMatch!!.startIndex val checkIsOAuthRequestIndex = redditCheckDisableAPIFingerprint.patternMatch!!.startIndex
redditCheckDisableAPIMatch.mutableMethod.apply { redditCheckDisableAPIFingerprint.method.apply {
val returnNextChain = getInstruction<BuilderInstruction21t>(checkIsOAuthRequestIndex).target val returnNextChain = getInstruction<BuilderInstruction21t>(checkIsOAuthRequestIndex).target
replaceInstruction(checkIsOAuthRequestIndex, BuilderInstruction10t(Opcode.GOTO, returnNextChain)) replaceInstruction(checkIsOAuthRequestIndex, BuilderInstruction10t(Opcode.GOTO, returnNextChain))
} }

View File

@ -6,12 +6,10 @@ import app.revanced.patches.reddit.customclients.spoofClientPatch
val spoofClientPatch = spoofClientPatch(redirectUri = "http://www.ccrama.me") { clientIdOption -> val spoofClientPatch = spoofClientPatch(redirectUri = "http://www.ccrama.me") { clientIdOption ->
compatibleWith("me.ccrama.redditslide") compatibleWith("me.ccrama.redditslide")
val getClientIdMatch by getClientIdFingerprint()
val clientId by clientIdOption val clientId by clientIdOption
execute { execute {
getClientIdMatch.mutableMethod.addInstructions( getClientIdFingerprint.method.addInstructions(
0, 0,
""" """
const-string v0, "$clientId" const-string v0, "$clientId"

View File

@ -7,10 +7,8 @@ import app.revanced.util.returnEarly
fun disableAdsPatch(block: BytecodePatchBuilder.() -> Unit = {}) = bytecodePatch( fun disableAdsPatch(block: BytecodePatchBuilder.() -> Unit = {}) = bytecodePatch(
name = "Disable ads", name = "Disable ads",
) { ) {
isAdsEnabledFingerprint()
execute { execute {
isAdsEnabledFingerprint.returnEarly() isAdsEnabledFingerprint.method.returnEarly()
} }
block() block()

View File

@ -6,11 +6,10 @@ import app.revanced.patcher.patch.bytecodePatch
val disablePiracyDetectionPatch = bytecodePatch( val disablePiracyDetectionPatch = bytecodePatch(
description = "Disables detection of modified versions.", description = "Disables detection of modified versions.",
) { ) {
val piracyDetectionMatch by piracyDetectionFingerprint()
execute { execute {
// Do not throw an error if the fingerprint is not resolved. // Do not throw an error if the fingerprint is not resolved.
// This is fine because new versions of the target app do not need this patch. // This is fine because new versions of the target app do not need this patch.
piracyDetectionMatch.mutableMethod.addInstruction(0, "return-void") piracyDetectionFingerprint.method.addInstruction(0, "return-void")
} }
} }

View File

@ -14,10 +14,8 @@ val disableSyncForLemmyBottomSheetPatch = bytecodePatch(
"com.laurencedawson.reddit_sync.dev"(), // Version unknown. "com.laurencedawson.reddit_sync.dev"(), // Version unknown.
) )
val mainActivityOnCreateMatch by mainActivityOnCreateFingerprint()
execute { execute {
mainActivityOnCreateMatch.mutableMethod.apply { mainActivityOnCreateFingerprint.method.apply {
val showBottomSheetIndex = implementation!!.instructions.lastIndex - 1 val showBottomSheetIndex = implementation!!.instructions.lastIndex - 1
removeInstruction(showBottomSheetIndex) removeInstruction(showBottomSheetIndex)

View File

@ -5,7 +5,6 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patches.reddit.customclients.spoofClientPatch import app.revanced.patches.reddit.customclients.spoofClientPatch
import app.revanced.patches.reddit.customclients.sync.detection.piracy.disablePiracyDetectionPatch import app.revanced.patches.reddit.customclients.sync.detection.piracy.disablePiracyDetectionPatch
import app.revanced.util.matchOrThrow
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference import com.android.tools.smali.dexlib2.iface.reference.StringReference
@ -22,18 +21,12 @@ val spoofClientPatch = spoofClientPatch(
"com.laurencedawson.reddit_sync.dev", "com.laurencedawson.reddit_sync.dev",
) )
val imgurImageAPIMatch by imgurImageAPIFingerprint()
val getAuthorizationStringMatch by getAuthorizationStringFingerprint()
val getUserAgentMatch by getUserAgentFingerprint()
val clientId by clientIdOption val clientId by clientIdOption
execute { context -> execute {
// region Patch client id. // region Patch client id.
getBearerTokenFingerprint.apply { getBearerTokenFingerprint.match(getAuthorizationStringFingerprint.originalClassDef).method.apply {
match(context, getAuthorizationStringMatch.classDef)
}.matchOrThrow.mutableMethod.apply {
val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8)) val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8))
addInstructions( addInstructions(
0, 0,
@ -43,9 +36,9 @@ val spoofClientPatch = spoofClientPatch(
""", """,
) )
val occurrenceIndex = val occurrenceIndex =
getAuthorizationStringMatch.stringMatches!!.first().index getAuthorizationStringFingerprint.stringMatches!!.first().index
getAuthorizationStringMatch.mutableMethod.apply { getAuthorizationStringFingerprint.method.apply {
val authorizationStringInstruction = getInstruction<ReferenceInstruction>(occurrenceIndex) val authorizationStringInstruction = getInstruction<ReferenceInstruction>(occurrenceIndex)
val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA
val reference = authorizationStringInstruction.reference as StringReference val reference = authorizationStringInstruction.reference as StringReference
@ -70,7 +63,7 @@ val spoofClientPatch = spoofClientPatch(
val randomName = (0..100000).random() val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)" val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
imgurImageAPIMatch.mutableMethod.replaceInstruction( imgurImageAPIFingerprint.method.replaceInstruction(
0, 0,
""" """
const-string v0, "$userAgent" const-string v0, "$userAgent"
@ -82,8 +75,8 @@ val spoofClientPatch = spoofClientPatch(
// region Patch Imgur API URL. // region Patch Imgur API URL.
val apiUrlIndex = getUserAgentMatch.stringMatches!!.first().index val apiUrlIndex = getUserAgentFingerprint.stringMatches!!.first().index
getUserAgentMatch.mutableMethod.replaceInstruction( getUserAgentFingerprint.method.replaceInstruction(
apiUrlIndex, apiUrlIndex,
"const-string v1, \"https://api.imgur.com/3/image\"", "const-string v1, \"https://api.imgur.com/3/image\"",
) )

View File

@ -6,6 +6,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.util.smali.ExternalLabel import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patches.reddit.customclients.RESOLVE_S_LINK_METHOD import app.revanced.patches.reddit.customclients.RESOLVE_S_LINK_METHOD
import app.revanced.patches.reddit.customclients.SET_ACCESS_TOKEN_METHOD import app.revanced.patches.reddit.customclients.SET_ACCESS_TOKEN_METHOD
import app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.getOAuthAccessTokenFingerprint
import app.revanced.patches.reddit.customclients.boostforreddit.fix.slink.handleNavigationFingerprint
import app.revanced.patches.reddit.customclients.fixSLinksPatch import app.revanced.patches.reddit.customclients.fixSLinksPatch
import app.revanced.patches.reddit.customclients.sync.syncforreddit.extension.sharedExtensionPatch import app.revanced.patches.reddit.customclients.sync.syncforreddit.extension.sharedExtensionPatch
@ -21,13 +23,10 @@ val fixSLinksPatch = fixSLinksPatch(
"com.laurencedawson.reddit_sync.dev", "com.laurencedawson.reddit_sync.dev",
) )
val handleNavigationMatch by linkHelperOpenLinkFingerprint()
val setAccessTokenMatch by setAuthorizationHeaderFingerprint()
execute { execute {
// region Patch navigation handler. // region Patch navigation handler.
handleNavigationMatch.mutableMethod.apply { handleNavigationFingerprint.method.apply {
val urlRegister = "p3" val urlRegister = "p3"
val tempRegister = "v2" val tempRegister = "v2"
@ -47,7 +46,7 @@ val fixSLinksPatch = fixSLinksPatch(
// region Patch set access token. // region Patch set access token.
setAccessTokenMatch.mutableMethod.addInstruction( getOAuthAccessTokenFingerprint.method.addInstruction(
0, 0,
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD", "invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD",
) )

View File

@ -20,22 +20,17 @@ val useUserEndpointPatch = bytecodePatch(
"com.laurencedawson.reddit_sync.dev", "com.laurencedawson.reddit_sync.dev",
) )
val oAuthFriendRequestMatch by oAuthFriendRequestFingerprint()
val oAuthSubredditInfoRequestConstructorMatch by oAuthSubredditInfoRequestConstructorFingerprint()
val oAuthSubredditInfoRequestHelperMatch by oAuthSubredditInfoRequestHelperFingerprint()
val oAuthUnfriendRequestMatch by oAuthUnfriendRequestFingerprint()
val oAuthUserIdRequestMatch by oAuthUserIdRequestFingerprint()
val oAuthUserInfoRequestMatch by oAuthUserInfoRequestFingerprint()
execute { execute {
arrayOf( arrayOf(
oAuthFriendRequestMatch, oAuthFriendRequestFingerprint,
oAuthSubredditInfoRequestConstructorMatch, oAuthSubredditInfoRequestConstructorFingerprint,
oAuthSubredditInfoRequestHelperMatch, oAuthSubredditInfoRequestHelperFingerprint,
oAuthUnfriendRequestMatch, oAuthUnfriendRequestFingerprint,
oAuthUserIdRequestMatch, oAuthUserIdRequestFingerprint,
oAuthUserInfoRequestMatch, oAuthUserInfoRequestFingerprint,
).map { it.stringMatches!!.first().index to it.mutableMethod }.forEach { (userPathStringIndex, method) -> ).map { fingerprint ->
fingerprint.stringMatches!!.first().index to fingerprint.method
}.forEach { (userPathStringIndex, method) ->
val userPathStringInstruction = method.getInstruction<OneRegisterInstruction>(userPathStringIndex) val userPathStringInstruction = method.getInstruction<OneRegisterInstruction>(userPathStringIndex)
val userPathStringRegister = userPathStringInstruction.registerA val userPathStringRegister = userPathStringInstruction.registerA

View File

@ -23,16 +23,15 @@ val fixVideoDownloadsPatch = bytecodePatch(
"com.laurencedawson.reddit_sync.dev", "com.laurencedawson.reddit_sync.dev",
) )
val parseRedditVideoNetworkResponseMatch by parseRedditVideoNetworkResponseFingerprint()
execute { execute {
val scanResult = parseRedditVideoNetworkResponseMatch.patternMatch!! val scanResult = parseRedditVideoNetworkResponseFingerprint.patternMatch!!
val newInstanceIndex = scanResult.startIndex val newInstanceIndex = scanResult.startIndex
val invokeDirectIndex = scanResult.endIndex - 1 val invokeDirectIndex = scanResult.endIndex - 1
val buildResponseInstruction = parseRedditVideoNetworkResponseMatch.mutableMethod.getInstruction<Instruction35c>(invokeDirectIndex) val buildResponseInstruction =
parseRedditVideoNetworkResponseFingerprint.method.getInstruction<Instruction35c>(invokeDirectIndex)
parseRedditVideoNetworkResponseMatch.mutableMethod.addInstructions( parseRedditVideoNetworkResponseFingerprint.method.addInstructions(
newInstanceIndex + 1, newInstanceIndex + 1,
""" """
# Get byte array from response. # Get byte array from response.

View File

@ -10,9 +10,7 @@ val disableScreenshotPopupPatch = bytecodePatch(
) { ) {
compatibleWith("com.reddit.frontpage") compatibleWith("com.reddit.frontpage")
val disableScreenshotPopupMatch by disableScreenshotPopupFingerprint()
execute { execute {
disableScreenshotPopupMatch.mutableMethod.addInstruction(0, "return-void") disableScreenshotPopupFingerprint.method.addInstruction(0, "return-void")
} }
} }

View File

@ -10,10 +10,8 @@ val unlockPremiumIconPatch = bytecodePatch(
) { ) {
compatibleWith("com.reddit.frontpage") compatibleWith("com.reddit.frontpage")
val hasPremiumIconAccessMatch by hasPremiumIconAccessFingerprint()
execute { execute {
hasPremiumIconAccessMatch.mutableMethod.addInstructions( hasPremiumIconAccessFingerprint.method.addInstructions(
0, 0,
""" """
const/4 v0, 0x1 const/4 v0, 0x1

View File

@ -10,10 +10,8 @@ val sanitizeUrlQueryPatch = bytecodePatch(
) { ) {
compatibleWith("com.reddit.frontpage") compatibleWith("com.reddit.frontpage")
val shareLinkFormatterMatch by shareLinkFormatterFingerprint()
execute { execute {
shareLinkFormatterMatch.mutableMethod.addInstructions( shareLinkFormatterFingerprint.method.addInstructions(
0, 0,
"return-object p0", "return-object p0",
) )

View File

@ -10,9 +10,7 @@ val rootDetectionPatch = bytecodePatch(
) { ) {
compatibleWith("at.gv.bka.serviceportal") compatibleWith("at.gv.bka.serviceportal")
val rootDetectionMatch by rootDetectionFingerprint()
execute { execute {
rootDetectionMatch.mutableMethod.addInstruction(0, "return-void") rootDetectionFingerprint.method.addInstruction(0, "return-void")
} }
} }

View File

@ -2,7 +2,6 @@ package app.revanced.patches.shared.misc.checks
import android.os.Build.* import android.os.Build.*
import app.revanced.patcher.Fingerprint import app.revanced.patcher.Fingerprint
import app.revanced.patcher.Match
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
@ -35,20 +34,24 @@ fun checkEnvironmentPatch(
addResourcesPatch, addResourcesPatch,
) )
val patchInfoMatch by patchInfoFingerprint()
val patchInfoBuildMatch by patchInfoBuildFingerprint()
val mainActivityOnCreateMatch by mainActivityOnCreateFingerprint()
execute { execute {
addResources("shared", "misc.checks.checkEnvironmentPatch") addResources("shared", "misc.checks.checkEnvironmentPatch")
fun setPatchInfo() { fun setPatchInfo() {
patchInfoMatch.setClassFields( fun <T : MutableEncodedValue> Fingerprint.setClassFields(vararg fieldNameValues: Pair<String, T>) {
val fieldNameValueMap = mapOf(*fieldNameValues)
classDef.fields.forEach { field ->
field.initialValue = fieldNameValueMap[field.name] ?: return@forEach
}
}
patchInfoFingerprint.setClassFields(
"PATCH_TIME" to System.currentTimeMillis().encoded, "PATCH_TIME" to System.currentTimeMillis().encoded,
) )
fun setBuildInfo() { fun setBuildInfo() {
patchInfoBuildMatch.setClassFields( patchInfoBuildFingerprint.setClassFields(
"PATCH_BOARD" to BOARD.encodedAndHashed, "PATCH_BOARD" to BOARD.encodedAndHashed,
"PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed, "PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed,
"PATCH_BRAND" to BRAND.encodedAndHashed, "PATCH_BRAND" to BRAND.encodedAndHashed,
@ -79,7 +82,7 @@ fun checkEnvironmentPatch(
} }
} }
fun invokeCheck() = mainActivityOnCreateMatch.mutableMethod?.addInstructions( fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstructions(
0, 0,
"invoke-static/range { p0 .. p0 },$EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V", "invoke-static/range { p0 .. p0 },$EXTENSION_CLASS_DESCRIPTOR->check(Landroid/app/Activity;)V",
) )
@ -101,11 +104,3 @@ private val String.encodedAndHashed
) )
private val Long.encoded get() = MutableLongEncodedValue(ImmutableLongEncodedValue(this)) private val Long.encoded get() = MutableLongEncodedValue(ImmutableLongEncodedValue(this))
private fun <T : MutableEncodedValue> Match.setClassFields(vararg fieldNameValues: Pair<String, T>) {
val fieldNameValueMap = mapOf(*fieldNameValues)
mutableClass.fields.forEach { field ->
field.initialValue = fieldNameValueMap[field.name] ?: return@forEach
}
}

View File

@ -5,9 +5,9 @@ import app.revanced.patcher.FingerprintBuilder
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.fingerprint import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.PatchException import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.matchOrThrow
import com.android.tools.smali.dexlib2.iface.Method import com.android.tools.smali.dexlib2.iface.Method
import java.net.URLDecoder import java.net.URLDecoder
import java.util.jar.JarFile import java.util.jar.JarFile
@ -19,11 +19,8 @@ fun sharedExtensionPatch(
) = bytecodePatch { ) = bytecodePatch {
extendWith("extensions/shared.rve") extendWith("extensions/shared.rve")
val revancedUtilsPatchesVersionMatch by revancedUtilsPatchesVersionFingerprint() execute {
hooks.forEach { it.fingerprint() } if (classBy { EXTENSION_CLASS_DESCRIPTOR in it.type } == null) {
execute { context ->
if (context.classBy { EXTENSION_CLASS_DESCRIPTOR in it.type } == null) {
throw PatchException( throw PatchException(
"Shared extension has not been merged yet. This patch can not succeed without merging it.", "Shared extension has not been merged yet. This patch can not succeed without merging it.",
) )
@ -32,7 +29,7 @@ fun sharedExtensionPatch(
hooks.forEach { hook -> hook(EXTENSION_CLASS_DESCRIPTOR) } hooks.forEach { hook -> hook(EXTENSION_CLASS_DESCRIPTOR) }
// Modify Utils method to include the patches release version. // Modify Utils method to include the patches release version.
revancedUtilsPatchesVersionMatch.mutableMethod.apply { revancedUtilsPatchesVersionFingerprint.method.apply {
/** /**
* @return The file path for the jar this classfile is contained inside. * @return The file path for the jar this classfile is contained inside.
*/ */
@ -79,19 +76,18 @@ class ExtensionHook internal constructor(
private val insertIndexResolver: ((Method) -> Int), private val insertIndexResolver: ((Method) -> Int),
private val contextRegisterResolver: (Method) -> String, private val contextRegisterResolver: (Method) -> String,
) { ) {
context(BytecodePatchContext)
operator fun invoke(extensionClassDescriptor: String) { operator fun invoke(extensionClassDescriptor: String) {
fingerprint.matchOrThrow.mutableMethod.let { method -> val insertIndex = insertIndexResolver(fingerprint.method)
val insertIndex = insertIndexResolver(method) val contextRegister = contextRegisterResolver(fingerprint.method)
val contextRegister = contextRegisterResolver(method)
method.addInstruction( fingerprint.method.addInstruction(
insertIndex, insertIndex,
"invoke-static/range { $contextRegister .. $contextRegister }, " + "invoke-static/range { $contextRegister .. $contextRegister }, " +
"$extensionClassDescriptor->setContext(Landroid/content/Context;)V", "$extensionClassDescriptor->setContext(Landroid/content/Context;)V",
) )
} }
} }
}
fun extensionHook( fun extensionHook(
insertIndexResolver: ((Method) -> Int) = { 0 }, insertIndexResolver: ((Method) -> Int) = { 0 },

View File

@ -8,11 +8,10 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
val verticalScrollPatch = bytecodePatch( val verticalScrollPatch = bytecodePatch(
description = "Fixes issues with refreshing the feed when the first component is of type EmptyComponent.", description = "Fixes issues with refreshing the feed when the first component is of type EmptyComponent.",
) { ) {
val canScrollVerticallyMatch by canScrollVerticallyFingerprint()
execute { execute {
canScrollVerticallyMatch.mutableMethod.apply { canScrollVerticallyFingerprint.method.apply {
val moveResultIndex = canScrollVerticallyMatch.patternMatch!!.endIndex val moveResultIndex = canScrollVerticallyFingerprint.patternMatch!!.endIndex
val moveResultRegister = getInstruction<OneRegisterInstruction>(moveResultIndex).registerA val moveResultRegister = getInstruction<OneRegisterInstruction>(moveResultIndex).registerA
val insertIndex = moveResultIndex + 1 val insertIndex = moveResultIndex + 1

Some files were not shown because too many files have changed in this diff Show More