mirror of
https://github.com/revanced/revanced-patches
synced 2024-12-25 19:45:49 +01:00
build: Bump ReVanced Patcher (#3862)
Co-authored-by: Ushie <ushiekane@gmail.com>
This commit is contained in:
parent
e32b19e170
commit
8da05ab46d
@ -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"
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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")) {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
@ -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 ->
|
||||||
|
@ -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())
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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\"")
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
|
@ -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,
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
"""
|
"""
|
||||||
|
@ -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",
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
)
|
)
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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)}"
|
||||||
|
@ -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",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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",
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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\"",
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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",
|
||||||
)
|
)
|
||||||
|
@ -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(
|
||||||
|
@ -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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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()
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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\"",
|
||||||
)
|
)
|
||||||
|
@ -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",
|
||||||
)
|
)
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
)
|
)
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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 },
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user