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]
revanced-patcher = "20.0.2"
revanced-patcher = "21.0.0"
# Tracking https://github.com/google/smali/issues/64.
#noinspection GradleDependency
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.
#noinspection GradleDependency
agp = "8.2.2"
annotation = "1.9.0"
annotation = "1.9.1"
appcompat = "1.7.0"
okhttp = "5.0.0-alpha.14"
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 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 {
@ -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 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 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 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 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 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/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/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/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/ResourcePatch;
}
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 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 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;
}
@ -1432,7 +1427,6 @@ public final class app/revanced/patches/yuka/misc/unlockpremium/UnlockPremiumPat
}
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 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;
@ -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 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 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;ILkotlin/jvm/functions/Function1;)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 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 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 (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 (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 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"))
}
kotlin {
compilerOptions {
freeCompilerArgs = listOf("-Xcontext-receivers")
}
}
publishing {
repositories {
maven {

View File

@ -8,10 +8,10 @@ val exportAllActivitiesPatch = resourcePatch(
description = "Makes all app activities exportable.",
use = false,
) {
execute { context ->
execute {
val exportedFlag = "android:exported"
context.document["AndroidManifest.xml"].use { document ->
document("AndroidManifest.xml").use { document ->
val activities = document.getElementsByTagName("activity")
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.",
use = false,
) {
execute { context ->
context.document["AndroidManifest.xml"].use { document ->
execute {
document("AndroidManifest.xml").use { document ->
val applicationNode =
document
.getElementsByTagName("application")

View File

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

View File

@ -14,11 +14,11 @@ val overrideCertificatePinningPatch = resourcePatch(
) {
dependsOn(enableAndroidDebuggingPatch)
execute { context ->
val resXmlDirectory = context["res/xml"]
execute {
val resXmlDirectory = get("res/xml")
// 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
if (!applicationNode.hasAttribute("networkSecurityConfig")) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,15 +11,13 @@ val proUnlockPatch = bytecodePatch(
) {
compatibleWith("com.backdrops.wallpapers")
val proUnlockMatch by proUnlockFingerprint()
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
addInstruction(
proUnlockMatch.patternMatch!!.endIndex,
proUnlockFingerprint.patternMatch!!.endIndex,
"const/4 v$register, 0x1",
)
}

View File

@ -10,9 +10,7 @@ val removePlayLimitsPatch = bytecodePatch(
) {
compatibleWith("com.bandcamp.android")
val handlePlaybackLimitsMatch by handlePlaybackLimitsFingerprint()
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")
val checkRootMatch by checkRootFingerprint()
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")
val initializeMonetizationDebugSettingsMatch by initializeMonetizationDebugSettingsFingerprint()
execute {
// 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".
//
// MonetizationDebugSettings seems to be the most general setting to work fine.
initializeMonetizationDebugSettingsMatch.mutableMethod.apply {
val insertIndex = initializeMonetizationDebugSettingsMatch.patternMatch!!.startIndex
initializeMonetizationDebugSettingsFingerprint.method.apply {
val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
addInstructions(

View File

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

View File

@ -19,13 +19,9 @@ val hideSponsoredStoriesPatch = bytecodePatch(
) {
compatibleWith("com.facebook.katana")
val getStoryVisibilityMatch by getStoryVisibilityFingerprint()
val getSponsoredDataModelTemplateMatch by getSponsoredDataModelTemplateFingerprint()
val baseModelMapperMatch by baseModelMapperFingerprint()
execute {
val sponsoredDataModelTemplateMethod = getSponsoredDataModelTemplateMatch.method
val baseModelMapperMethod = baseModelMapperMatch.method
val sponsoredDataModelTemplateMethod = getSponsoredDataModelTemplateFingerprint.originalMethod
val baseModelMapperMethod = baseModelMapperFingerprint.originalMethod
val baseModelWithTreeType = baseModelMapperMethod.returnType
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
// 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.
val getSponsoredDataHelperMethod = ImmutableMethod(
getStoryVisibilityMatch.classDef.type,
getStoryVisibilityFingerprint.originalClassDef.type,
"getSponsoredData",
listOf(ImmutableMethodParameter(graphQlStoryClassDescriptor, null, null)),
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.
// If so, hide the story by setting the visibility to StoryVisibility.GONE.
getStoryVisibilityMatch.mutableMethod.addInstructionsWithLabels(
getStoryVisibilityMatch.patternMatch!!.startIndex,
getStoryVisibilityFingerprint.method.addInstructionsWithLabels(
getStoryVisibilityFingerprint.patternMatch!!.startIndex,
"""
instance-of v0, p0, $graphQlStoryClassDescriptor
if-eqz v0, :resume_normal

View File

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

View File

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

View File

@ -10,10 +10,8 @@ val rootDetectionPatch = bytecodePatch(
) {
compatibleWith("at.gv.bmf.bmf2go")
val rootDetectionMatch by rootDetectionFingerprint()
execute {
rootDetectionMatch.mutableMethod.addInstructions(
rootDetectionFingerprint.method.addInstructions(
0,
"""
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.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused")
val enableCustomTabsPatch = bytecodePatch(
@ -12,11 +13,9 @@ val enableCustomTabsPatch = bytecodePatch(
) {
compatibleWith("com.google.android.apps.magazines")
val launchCustomTabMatch by launchCustomTabFingerprint()
execute {
launchCustomTabMatch.mutableMethod.apply {
val checkIndex = launchCustomTabMatch.patternMatch!!.endIndex + 1
launchCustomTabFingerprint.method.apply {
val checkIndex = launchCustomTabFingerprint.patternMatch!!.endIndex + 1
val register = getInstruction<OneRegisterInstruction>(checkIndex).registerA
replaceInstruction(checkIndex, "const/4 v$register, 0x1")

View File

@ -54,8 +54,6 @@ val spoofFeaturesPatch = bytecodePatch(
required = true,
)
val initializeFeaturesEnumMatch by initializeFeaturesEnumFingerprint()
execute {
@Suppress("NAME_SHADOWING")
val featuresToEnable = featuresToEnable!!.toSet()
@ -63,7 +61,7 @@ val spoofFeaturesPatch = bytecodePatch(
@Suppress("NAME_SHADOWING")
val featuresToDisable = featuresToDisable!!.toSet()
initializeFeaturesEnumMatch.mutableMethod.apply {
initializeFeaturesEnumFingerprint.method.apply {
instructions.filter { it.opcode == Opcode.CONST_STRING }.forEach {
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.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused")
val restoreHiddenBackUpWhileChargingTogglePatch = bytecodePatch(
@ -12,12 +13,10 @@ val restoreHiddenBackUpWhileChargingTogglePatch = bytecodePatch(
) {
compatibleWith("com.google.android.apps.photos")
val backupPreferencesMatch by backupPreferencesFingerprint()
execute {
// Patches 'backup_prefs_had_backup_only_when_charging_enabled' to always be true.
val chargingPrefStringIndex = backupPreferencesMatch.stringMatches!!.first().index
backupPreferencesMatch.mutableMethod.apply {
val chargingPrefStringIndex = backupPreferencesFingerprint.stringMatches!!.first().index
backupPreferencesFingerprint.method.apply {
// Get the register of move-result.
val resultRegister = getInstruction<OneRegisterInstruction>(chargingPrefStringIndex + 2).registerA
// 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.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused")
val removeDeviceRestrictionsPatch = bytecodePatch(
@ -13,12 +14,10 @@ val removeDeviceRestrictionsPatch = bytecodePatch(
) {
compatibleWith("com.google.android.apps.recorder")
val onApplicationCreateMatch by onApplicationCreateFingerprint()
execute {
val featureStringIndex = onApplicationCreateMatch.stringMatches!!.first().index
val featureStringIndex = onApplicationCreateFingerprint.stringMatches!!.first().index
onApplicationCreateMatch.mutableMethod.apply {
onApplicationCreateFingerprint.method.apply {
// Remove check for device restrictions.
removeInstructions(featureStringIndex - 2, 5)

View File

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

View File

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

View File

@ -10,11 +10,11 @@ val rootDetectionPatch = bytecodePatch(
) {
compatibleWith("at.gv.oe.app")
attestationSupportedCheckFingerprint()
bootloaderCheckFingerprint()
rootCheckFingerprint()
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")
val spoofSignatureMatch by spoofSignatureFingerprint()
execute {
val expectedSignature =
"OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" +
@ -26,7 +24,7 @@ val spoofSignaturePatch = bytecodePatch(
"77ef1be61b2c01ebdabddcbf53cc4b6fd9a3c445606ee77b3758162c80ad8f8137b3c6864e92db904807dcb2be9d7717dd21" +
"bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}"
spoofSignatureMatch.mutableMethod.addInstructions(
spoofSignatureFingerprint.method.addInstructions(
0,
"""
const-string v0, "$expectedSignature"

View File

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

View File

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

View File

@ -9,11 +9,9 @@ val removeAdsPatch = bytecodePatch(
) {
compatibleWith("net.binarymode.android.irplus")
val irplusAdsMatch by irplusAdsFingerprint()
execute {
// By overwriting the second parameter of the method,
// 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")
val isLoggedInMatch by isLoggedInFingerprint()
execute {
isLoggedInMatch.mutableMethod.apply {
isLoggedInFingerprint.method.apply {
val index = implementation!!.instructions.lastIndex - 1
// Set isLoggedIn = true.
replaceInstruction(index, "const/4 v0, 0x1")

View File

@ -9,10 +9,8 @@ val unlockPremiumPatch = bytecodePatch(
) {
compatibleWith("com.adobe.lrmobile")
val hasPurchasedMatch by hasPurchasedFingerprint()
execute {
// 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(
description = "Disables Firebase license validation.",
) {
val licenseValidationMatch by licenseValidationFingerprint()
execute {
licenseValidationMatch.mutableMethod.replaceInstructions(
licenseValidationFingerprint.method.replaceInstructions(
0,
"""
const/4 p0, 0x1

View File

@ -6,10 +6,9 @@ import app.revanced.patcher.patch.bytecodePatch
val signatureVerificationPatch = bytecodePatch(
description = "Disables detection of incorrect signature.",
) {
val verifySignatureMatch by verifySignatureFingerprint()
execute {
verifySignatureMatch.mutableMethod.replaceInstructions(
verifySignatureFingerprint.method.replaceInstructions(
0,
"""
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"))
val isFreeVersionMatch by isFreeVersionFingerprint()
execute {
isFreeVersionMatch.mutableMethod.replaceInstructions(
isFreeVersionFingerprint.method.replaceInstructions(
0,
"""
sget-object p0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;

View File

@ -10,9 +10,7 @@ val hideInboxAdsPatch = bytecodePatch(
) {
compatibleWith("com.facebook.orca")
val loadInboxAdsMatch by loadInboxAdsFingerprint()
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")
val createInboxSubTabsMatch by createInboxSubTabsFingerprint()
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.patch.bytecodePatch
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.sun.org.apache.bcel.internal.generic.InstructionConst.getInstruction
@Suppress("unused")
val disableSwitchingEmojiToStickerPatch = bytecodePatch(
@ -12,12 +13,9 @@ val disableSwitchingEmojiToStickerPatch = bytecodePatch(
) {
compatibleWith("com.facebook.orca"("439.0.0.29.119"))
val switchMessangeInputEmojiButtonMatch by switchMessangeInputEmojiButtonFingerprint()
execute {
val setStringIndex = switchMessangeInputEmojiButtonMatch.patternMatch!!.startIndex + 2
switchMessangeInputEmojiButtonMatch.mutableMethod.apply {
switchMessengeInputEmojiButtonFingerprint.method.apply {
val setStringIndex = switchMessengeInputEmojiButtonFingerprint.patternMatch!!.startIndex + 2
val targetRegister = getInstruction<OneRegisterInstruction>(setStringIndex).registerA
replaceInstruction(setStringIndex, "const-string v$targetRegister, \"expression\"")

View File

@ -10,9 +10,7 @@ val disableTypingIndicatorPatch = bytecodePatch(
) {
compatibleWith("com.facebook.orca")
val sendTypingIndicatorMatch by sendTypingIndicatorFingerprint()
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")
parameters("L", "Z")
opcodes(

View File

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

View File

@ -9,9 +9,7 @@ val fixLoginPatch = bytecodePatch(
) {
compatibleWith("com.xiaomi.wearable")
val xiaomiAccountManagerConstructorMatch by xiaomiAccountManagerConstructorFingerprint()
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")
val showVideoAdsParentMatch by showVideoAdsParentFingerprint()
execute { context ->
val showVideoAdsMethod = context
.navigate(showVideoAdsParentMatch.mutableMethod)
.at(showVideoAdsParentMatch.patternMatch!!.startIndex + 1).mutable()
showVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0")
execute {
navigate(showVideoAdsParentFingerprint.originalMethod)
.to(showVideoAdsParentFingerprint.patternMatch!!.startIndex + 1)
.stop()
.addInstruction(0, "const/4 p1, 0x0")
}
}

View File

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

View File

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

View File

@ -20,9 +20,7 @@ val permanentShufflePatch = bytecodePatch(
),
)
val disableShuffleMatch by disableShuffleFingerprint()
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")
val constructCategoryBarMatch by constructCategoryBarFingerprint()
execute {
constructCategoryBarMatch.mutableMethod.apply {
val insertIndex = constructCategoryBarMatch.patternMatch!!.startIndex
constructCategoryBarFingerprint.method.apply {
val insertIndex = constructCategoryBarFingerprint.patternMatch!!.startIndex
val register = getInstruction<OneRegisterInstruction>(insertIndex - 1).registerA
addInstructions(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,12 +10,9 @@ val hideAdsPatch = bytecodePatch(
) {
compatibleWith("com.myfitnesspal.android"("24.14.2"))
val isPremiumUseCaseImplMatch by isPremiumUseCaseImplFingerprint()
val mainActivityNavigateToNativePremiumUpsellMatch by mainActivityNavigateToNativePremiumUpsellFingerprint()
execute {
// Overwrite the premium status specifically for ads.
isPremiumUseCaseImplMatch.mutableMethod.replaceInstructions(
isPremiumUseCaseImplFingerprint.method.replaceInstructions(
0,
"""
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.
// In other places that are premium-only the dialog will still show.
mainActivityNavigateToNativePremiumUpsellMatch.mutableMethod.replaceInstructions(
mainActivityNavigateToNativePremiumUpsellFingerprint.method.replaceInstructions(
0,
"return-void",
)

View File

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

View File

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

View File

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

View File

@ -17,10 +17,8 @@ val fixCrashPatch = bytecodePatch(
) {
compatibleWith("de.simon.openinghours"("1.0"))
val setPlaceMatch by setPlaceFingerprint()
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
@ -29,7 +27,7 @@ val fixCrashPatch = bytecodePatch(
* the value is indeed null, we jump to a newly created label at `endIndex + 1`.
*/
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) {
val instruction = indexedInstructions[index].value
@ -41,7 +39,7 @@ val fixCrashPatch = bytecodePatch(
val checkNotNullInstruction = instruction as FiveRegisterInstruction
val originalRegister = checkNotNullInstruction.registerC
setPlaceMatch.mutableMethod.replaceInstruction(
setPlaceFingerprint.method.replaceInstruction(
index,
BuilderInstruction21t(
Opcode.IF_EQZ,

View File

@ -14,10 +14,8 @@ val getDeviceIdPatch = bytecodePatch(
compatibleWith("com.microblink.photomath"("8.37.0"))
val getDeviceIdMatch by getDeviceIdFingerprint()
execute {
getDeviceIdMatch.mutableMethod.replaceInstructions(
getDeviceIdFingerprint.method.replaceInstructions(
0,
"""
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(
description = "Disables detection of incorrect signature.",
) {
val checkSignatureMatch by checkSignatureFingerprint()
execute {
val signatureCheckInstruction = checkSignatureMatch.mutableMethod.getInstruction(
checkSignatureMatch.patternMatch!!.endIndex,
)
val checkRegister = (signatureCheckInstruction as OneRegisterInstruction).registerA
checkSignatureMatch.mutableMethod.replaceInstruction(
signatureCheckInstruction.location.index,
"const/4 v$checkRegister, 0x1",
)
val replacementIndex = checkSignatureFingerprint.patternMatch!!.endIndex
val checkRegister =
checkSignatureFingerprint.method.getInstruction<OneRegisterInstruction>(replacementIndex).registerA
checkSignatureFingerprint.method.replaceInstruction(replacementIndex, "const/4 v$checkRegister, 0x1")
}
}

View File

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

View File

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

View File

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

View File

@ -30,8 +30,6 @@ val spoofAndroidDeviceIdPatch = bytecodePatch(
),
)
val getAndroidIDMatch by getAndroidIdFingerprint()
val androidDeviceId by stringOption(
key = "android-device-id",
default = "0011223344556677",
@ -41,7 +39,7 @@ val spoofAndroidDeviceIdPatch = bytecodePatch(
) { it!!.matches("[A-Fa-f0-9]{16}".toRegex()) }
execute {
getAndroidIDMatch.mutableMethod.addInstructions(
getAndroidIdFingerprint.method.addInstructions(
0,
"""
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 {
facebookSDKMatch.mutableMethod.apply {
facebookSDKFingerprint.method.apply {
instructions.filter { instruction ->
instruction.opcode == Opcode.CONST_STRING
}.forEach { instruction ->
@ -51,7 +47,7 @@ val disableTrackingPatch = bytecodePatch(
}
}
firebaseInstallMatch.mutableMethod.apply {
firebaseInstallFingerprint.method.apply {
instructions.filter {
it.opcode == Opcode.CONST_STRING
}.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")
val shouldShowAdsMatch by shouldShowAdsFingerprint()
execute {
shouldShowAdsMatch.mutableMethod.addInstructions(
shouldShowAdsFingerprint.method.addInstructions(
0,
"""
const/4 v0, 0x0

View File

@ -11,9 +11,7 @@ val hidePurchaseReminderPatch = bytecodePatch(
) {
compatibleWith("com.rarlab.rar")
val showReminderMatch by showReminderFingerprint()
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(
description = "Hides banner ads from comments on subreddits.",
) {
execute { context ->
execute {
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 {
val attributes = arrayOf("height", "width")

View File

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

View File

@ -25,9 +25,6 @@ val hideAdsPatch = bytecodePatch(
// This constraint is necessary due to dependency on hideBannerPatch.
compatibleWith("com.reddit.frontpage"("2024.17.0"))
val adPostMatch by adPostFingerprint()
val newAdPostMatch by newAdPostFingerprint()
execute {
// 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;" +
"->filterChildren(Ljava/lang/Iterable;)Ljava/util/List;"
adPostMatch.mutableMethod.apply {
adPostFingerprint.method.apply {
val setPostsListChildren = implementation!!.instructions.first { instruction ->
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.
// AdElementConverter is conveniently responsible for inserting all feed ads.
// 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
val reference = (it as ReferenceInstruction).reference as MethodReference
@ -74,7 +72,7 @@ val hideAdsPatch = bytecodePatch(
reference.name == "add" && reference.definingClass == "Ljava/util/ArrayList;"
}
newAdPostMatch.mutableMethod.removeInstruction(index)
newAdPostFingerprint.method.removeInstruction(index)
}
// endregion

View File

@ -1,6 +1,6 @@
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.replaceInstruction
import app.revanced.patches.reddit.customclients.spoofClientPatch
@ -12,16 +12,13 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://baconreader.com/au
"com.onelouder.baconreader.premium",
)
val getAuthorizationUrlMatch by getAuthorizationUrlFingerprint()
val requestTokenMatch by requestTokenFingerprint()
val clientId by clientIdOption
execute {
fun Match.patch(replacementString: String) {
fun Fingerprint.patch(replacementString: String) {
val clientIdIndex = stringMatches!!.first().index
mutableMethod.apply {
method.apply {
val clientIdRegister = getInstruction<OneRegisterInstruction>(clientIdIndex).registerA
replaceInstruction(
clientIdIndex,
@ -31,9 +28,9 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://baconreader.com/au
}
// Patch client id in authorization url.
getAuthorizationUrlMatch.patch("client_id=$clientId")
getAuthorizationUrlFingerprint.patch("client_id=$clientId")
// 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")
val maxMediationMatch by maxMediationFingerprint()
val admobMediationMatch by admobMediationFingerprint()
execute {
arrayOf(maxMediationMatch, admobMediationMatch).forEach {
it.mutableMethod.addInstructions(0, "return-void")
arrayOf(maxMediationFingerprint, admobMediationFingerprint).forEach { fingerprint ->
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 ->
compatibleWith("com.rubenmayayo.reddit")
val getClientIdMatch by getClientIdFingerprint()
val buildUserAgentMatch by buildUserAgentFingerprint()
val clientId by clientIdOption
execute {
// region Patch client id.
getClientIdMatch.mutableMethod.addInstructions(
getClientIdFingerprint.method.addInstructions(
0,
"""
const-string v0, "$clientId"
@ -30,7 +27,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "http://rubenmayayo.com")
val platformName = (0..100000).random()
val platformParameter = 0
buildUserAgentMatch.mutableMethod.addInstructions(
buildUserAgentFingerprint.method.addInstructions(
0,
"const-string p$platformParameter, \"$platformName\"",
)

View File

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

View File

@ -17,13 +17,10 @@ val fixSlinksPatch = fixSLinksPatch(
) {
compatibleWith("com.rubenmayayo.reddit")
val handleNavigationMatch by handleNavigationFingerprint()
val setAccessTokenMatch by getOAuthAccessTokenFingerprint()
execute {
// region Patch navigation handler.
handleNavigationMatch.mutableMethod.apply {
handleNavigationFingerprint.method.apply {
val urlRegister = "p1"
val tempRegister = "v1"
@ -43,7 +40,7 @@ val fixSlinksPatch = fixSLinksPatch(
// region Patch set access token.
setAccessTokenMatch.mutableMethod.addInstruction(
getOAuthAccessTokenFingerprint.method.addInstruction(
3,
"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 ->
compatibleWith("ml.docilealligator.infinityforreddit")
val apiUtilsMatch by apiUtilsFingerprint()
val clientId by clientIdOption
execute {
apiUtilsMatch.mutableClass.methods.apply {
apiUtilsFingerprint.classDef.methods.apply {
val getClientIdMethod = single { it.name == "getId" }.also(::remove)
val newGetClientIdMethod = ImmutableMethod(

View File

@ -13,10 +13,10 @@ val unlockSubscriptionPatch = bytecodePatch(
compatibleWith("ml.docilealligator.infinityforreddit")
startSubscriptionActivityFingerprint()
billingClientOnServiceConnectedFingerprint()
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")
val isAdFreeUserMatch by isAdFreeUserFingerprint()
execute {
isAdFreeUserMatch.mutableMethod.addInstructions(
isAdFreeUserFingerprint.method.addInstructions(
0,
"""
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",
)
val getClientIdMatch by getClientIdFingerprint()
val authUtilityUserAgentMatch by authUtilityUserAgentFingerprint()
val clientId by clientIdOption
execute {
// region Patch client id.
getClientIdMatch.mutableMethod.addInstructions(
getClientIdFingerprint.method.addInstructions(
0,
"""
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 userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
authUtilityUserAgentMatch.mutableMethod.replaceInstructions(
authUtilityUserAgentFingerprint.method.replaceInstructions(
0,
"""
const-string v0, "$userAgent"

View File

@ -4,9 +4,8 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.bytecodePatch
val disablePiracyDetectionPatch = bytecodePatch {
val piracyDetectionMatch by piracyDetectionFingerprint()
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
import app.revanced.patcher.Fingerprint
import app.revanced.patcher.Match
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
@ -16,10 +17,6 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
"com.andrewshu.android.redditdonation",
)
val buildAuthorizationStringMatch by buildAuthorizationStringFingerprint()
val basicAuthorizationMatch by basicAuthorizationFingerprint()
val getUserAgentMatch by getUserAgentFingerprint()
val clientId by clientIdOption
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
* using the [Match.StringMatch] list from the [Match].
*/
fun Match.replaceWith(
fun Fingerprint.replaceWith(
string: String,
getReplacementIndex: List<Match.StringMatch>.() -> Int,
) = mutableMethod.apply {
) = method.apply {
val replacementIndex = stringMatches!!.getReplacementIndex()
val clientIdRegister = getInstruction<OneRegisterInstruction>(replacementIndex).registerA
@ -44,10 +41,10 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
}
// Patch OAuth authorization.
buildAuthorizationStringMatch.replaceWith(clientId!!) { first().index + 4 }
buildAuthorizationStringFingerprint.replaceWith(clientId!!) { first().index + 4 }
// Path basic authorization.
basicAuthorizationMatch.replaceWith("$clientId:") { last().index + 7 }
basicAuthorizationFingerprint.replaceWith("$clientId:") { last().index + 7 }
// endregion
@ -57,7 +54,7 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "redditisfun://auth") { cl
val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
getUserAgentMatch.mutableMethod.addInstructions(
getUserAgentFingerprint.method.addInstructions(
0,
"""
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.
// Replace old.reddit.com with ssl.reddit.com to fix this.
buildAuthorizationStringMatch.mutableMethod.apply {
buildAuthorizationStringFingerprint.method.apply {
val index = indexOfFirstInstructionOrThrow {
getReference<StringReference>()?.contains("old.reddit.com") == true
}

View File

@ -15,29 +15,22 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "dbrady://relay") {
"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
execute {
// region Patch client id.
setOf(
loginActivityClientIdMatch,
getLoggedInBearerTokenMatch,
getLoggedOutBearerTokenMatch,
getRefreshTokenMatch,
).forEach { match ->
val clientIdIndex = match.stringMatches!!.first().index
match.mutableMethod.apply {
loginActivityClientIdFingerprint,
getLoggedInBearerTokenFingerprint,
getLoggedOutBearerTokenFingerprint,
getRefreshTokenFingerprint,
).forEach { fingerprint ->
val clientIdIndex = fingerprint.stringMatches!!.first().index
fingerprint.method.apply {
val clientIdRegister = getInstruction<OneRegisterInstruction>(clientIdIndex).registerA
match.mutableMethod.replaceInstruction(
fingerprint.method.replaceInstruction(
clientIdIndex,
"const-string v$clientIdRegister, \"$clientId\"",
)
@ -49,12 +42,12 @@ val spoofClientPatch = spoofClientPatch(redirectUri = "dbrady://relay") {
// region Patch miscellaneous.
// 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.
val checkIsOAuthRequestIndex = redditCheckDisableAPIMatch.patternMatch!!.startIndex
val checkIsOAuthRequestIndex = redditCheckDisableAPIFingerprint.patternMatch!!.startIndex
redditCheckDisableAPIMatch.mutableMethod.apply {
redditCheckDisableAPIFingerprint.method.apply {
val returnNextChain = getInstruction<BuilderInstruction21t>(checkIsOAuthRequestIndex).target
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 ->
compatibleWith("me.ccrama.redditslide")
val getClientIdMatch by getClientIdFingerprint()
val clientId by clientIdOption
execute {
getClientIdMatch.mutableMethod.addInstructions(
getClientIdFingerprint.method.addInstructions(
0,
"""
const-string v0, "$clientId"

View File

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

View File

@ -6,11 +6,10 @@ import app.revanced.patcher.patch.bytecodePatch
val disablePiracyDetectionPatch = bytecodePatch(
description = "Disables detection of modified versions.",
) {
val piracyDetectionMatch by piracyDetectionFingerprint()
execute {
// 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.
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.
)
val mainActivityOnCreateMatch by mainActivityOnCreateFingerprint()
execute {
mainActivityOnCreateMatch.mutableMethod.apply {
mainActivityOnCreateFingerprint.method.apply {
val showBottomSheetIndex = implementation!!.instructions.lastIndex - 1
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.patches.reddit.customclients.spoofClientPatch
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.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@ -22,18 +21,12 @@ val spoofClientPatch = spoofClientPatch(
"com.laurencedawson.reddit_sync.dev",
)
val imgurImageAPIMatch by imgurImageAPIFingerprint()
val getAuthorizationStringMatch by getAuthorizationStringFingerprint()
val getUserAgentMatch by getUserAgentFingerprint()
val clientId by clientIdOption
execute { context ->
execute {
// region Patch client id.
getBearerTokenFingerprint.apply {
match(context, getAuthorizationStringMatch.classDef)
}.matchOrThrow.mutableMethod.apply {
getBearerTokenFingerprint.match(getAuthorizationStringFingerprint.originalClassDef).method.apply {
val auth = Base64.getEncoder().encodeToString("$clientId:".toByteArray(Charsets.UTF_8))
addInstructions(
0,
@ -43,9 +36,9 @@ val spoofClientPatch = spoofClientPatch(
""",
)
val occurrenceIndex =
getAuthorizationStringMatch.stringMatches!!.first().index
getAuthorizationStringFingerprint.stringMatches!!.first().index
getAuthorizationStringMatch.mutableMethod.apply {
getAuthorizationStringFingerprint.method.apply {
val authorizationStringInstruction = getInstruction<ReferenceInstruction>(occurrenceIndex)
val targetRegister = (authorizationStringInstruction as OneRegisterInstruction).registerA
val reference = authorizationStringInstruction.reference as StringReference
@ -70,7 +63,7 @@ val spoofClientPatch = spoofClientPatch(
val randomName = (0..100000).random()
val userAgent = "$randomName:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
imgurImageAPIMatch.mutableMethod.replaceInstruction(
imgurImageAPIFingerprint.method.replaceInstruction(
0,
"""
const-string v0, "$userAgent"
@ -82,8 +75,8 @@ val spoofClientPatch = spoofClientPatch(
// region Patch Imgur API URL.
val apiUrlIndex = getUserAgentMatch.stringMatches!!.first().index
getUserAgentMatch.mutableMethod.replaceInstruction(
val apiUrlIndex = getUserAgentFingerprint.stringMatches!!.first().index
getUserAgentFingerprint.method.replaceInstruction(
apiUrlIndex,
"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.patches.reddit.customclients.RESOLVE_S_LINK_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.sync.syncforreddit.extension.sharedExtensionPatch
@ -21,13 +23,10 @@ val fixSLinksPatch = fixSLinksPatch(
"com.laurencedawson.reddit_sync.dev",
)
val handleNavigationMatch by linkHelperOpenLinkFingerprint()
val setAccessTokenMatch by setAuthorizationHeaderFingerprint()
execute {
// region Patch navigation handler.
handleNavigationMatch.mutableMethod.apply {
handleNavigationFingerprint.method.apply {
val urlRegister = "p3"
val tempRegister = "v2"
@ -47,7 +46,7 @@ val fixSLinksPatch = fixSLinksPatch(
// region Patch set access token.
setAccessTokenMatch.mutableMethod.addInstruction(
getOAuthAccessTokenFingerprint.method.addInstruction(
0,
"invoke-static { p0 }, $EXTENSION_CLASS_DESCRIPTOR->$SET_ACCESS_TOKEN_METHOD",
)

View File

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

View File

@ -23,16 +23,15 @@ val fixVideoDownloadsPatch = bytecodePatch(
"com.laurencedawson.reddit_sync.dev",
)
val parseRedditVideoNetworkResponseMatch by parseRedditVideoNetworkResponseFingerprint()
execute {
val scanResult = parseRedditVideoNetworkResponseMatch.patternMatch!!
val scanResult = parseRedditVideoNetworkResponseFingerprint.patternMatch!!
val newInstanceIndex = scanResult.startIndex
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,
"""
# Get byte array from response.

View File

@ -10,9 +10,7 @@ val disableScreenshotPopupPatch = bytecodePatch(
) {
compatibleWith("com.reddit.frontpage")
val disableScreenshotPopupMatch by disableScreenshotPopupFingerprint()
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")
val hasPremiumIconAccessMatch by hasPremiumIconAccessFingerprint()
execute {
hasPremiumIconAccessMatch.mutableMethod.addInstructions(
hasPremiumIconAccessFingerprint.method.addInstructions(
0,
"""
const/4 v0, 0x1

View File

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

View File

@ -10,9 +10,7 @@ val rootDetectionPatch = bytecodePatch(
) {
compatibleWith("at.gv.bka.serviceportal")
val rootDetectionMatch by rootDetectionFingerprint()
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 app.revanced.patcher.Fingerprint
import app.revanced.patcher.Match
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.bytecodePatch
@ -35,20 +34,24 @@ fun checkEnvironmentPatch(
addResourcesPatch,
)
val patchInfoMatch by patchInfoFingerprint()
val patchInfoBuildMatch by patchInfoBuildFingerprint()
val mainActivityOnCreateMatch by mainActivityOnCreateFingerprint()
execute {
addResources("shared", "misc.checks.checkEnvironmentPatch")
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,
)
fun setBuildInfo() {
patchInfoBuildMatch.setClassFields(
patchInfoBuildFingerprint.setClassFields(
"PATCH_BOARD" to BOARD.encodedAndHashed,
"PATCH_BOOTLOADER" to BOOTLOADER.encodedAndHashed,
"PATCH_BRAND" to BRAND.encodedAndHashed,
@ -79,7 +82,7 @@ fun checkEnvironmentPatch(
}
}
fun invokeCheck() = mainActivityOnCreateMatch.mutableMethod?.addInstructions(
fun invokeCheck() = mainActivityOnCreateFingerprint.method.addInstructions(
0,
"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 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.addInstructions
import app.revanced.patcher.fingerprint
import app.revanced.patcher.patch.BytecodePatchContext
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.util.matchOrThrow
import com.android.tools.smali.dexlib2.iface.Method
import java.net.URLDecoder
import java.util.jar.JarFile
@ -19,11 +19,8 @@ fun sharedExtensionPatch(
) = bytecodePatch {
extendWith("extensions/shared.rve")
val revancedUtilsPatchesVersionMatch by revancedUtilsPatchesVersionFingerprint()
hooks.forEach { it.fingerprint() }
execute { context ->
if (context.classBy { EXTENSION_CLASS_DESCRIPTOR in it.type } == null) {
execute {
if (classBy { EXTENSION_CLASS_DESCRIPTOR in it.type } == null) {
throw PatchException(
"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) }
// 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.
*/
@ -79,19 +76,18 @@ class ExtensionHook internal constructor(
private val insertIndexResolver: ((Method) -> Int),
private val contextRegisterResolver: (Method) -> String,
) {
context(BytecodePatchContext)
operator fun invoke(extensionClassDescriptor: String) {
fingerprint.matchOrThrow.mutableMethod.let { method ->
val insertIndex = insertIndexResolver(method)
val contextRegister = contextRegisterResolver(method)
val insertIndex = insertIndexResolver(fingerprint.method)
val contextRegister = contextRegisterResolver(fingerprint.method)
method.addInstruction(
fingerprint.method.addInstruction(
insertIndex,
"invoke-static/range { $contextRegister .. $contextRegister }, " +
"$extensionClassDescriptor->setContext(Landroid/content/Context;)V",
)
}
}
}
fun extensionHook(
insertIndexResolver: ((Method) -> Int) = { 0 },

View File

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

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