build(Needs bump)!: Update to ReVanced Patcher v22 (#6542)
Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Co-authored-by: Pun Butrach <pun.butrach@gmail.com> Co-authored-by: Ushie <ushiekane@gmail.com> Co-authored-by: ILoveOpenSourceApplications <ILoveOpenSourceApplications@users.noreply.github.com> Co-authored-by: rospino74 <34315725+rospino74@users.noreply.github.com> Co-authored-by: drobotk <pawwwll@gmail.com> Co-authored-by: Sayanth <13906889+SayanthD@users.noreply.github.com> Co-authored-by: kitadai31 <90122968+kitadai31@users.noreply.github.com> BREAKING CHANGE: Deprecated APIs have been removed, and various APIs now use the updated ReVanced Patcher v22 APIs.
This commit is contained in:
parent
376f2af8d8
commit
ab2ac36e30
842 changed files with 12691 additions and 13203 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -24,7 +24,10 @@ dependencies {
|
|||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
freeCompilerArgs = listOf("-Xcontext-receivers")
|
||||
freeCompilerArgs.addAll(
|
||||
"-Xexplicit-backing-fields",
|
||||
"-Xcontext-parameters"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ val exportAllActivitiesPatch = resourcePatch(
|
|||
description = "Makes all app activities exportable.",
|
||||
use = false,
|
||||
) {
|
||||
execute {
|
||||
apply {
|
||||
val exportedFlag = "android:exported"
|
||||
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package app.revanced.patches.all.misc.adb
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
|
|
@ -13,27 +13,26 @@ import com.android.tools.smali.dexlib2.util.MethodUtil
|
|||
private const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/all/misc/hide/adb/HideAdbPatch;"
|
||||
|
||||
private val SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE = ImmutableMethodReference(
|
||||
"Landroid/provider/Settings\$Global;",
|
||||
$$"Landroid/provider/Settings$Global;",
|
||||
"getInt",
|
||||
listOf("Landroid/content/ContentResolver;", "Ljava/lang/String;"),
|
||||
"I"
|
||||
"I",
|
||||
)
|
||||
|
||||
private val SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE = ImmutableMethodReference(
|
||||
"Landroid/provider/Settings\$Global;",
|
||||
$$"Landroid/provider/Settings$Global;",
|
||||
"getInt",
|
||||
listOf("Landroid/content/ContentResolver;", "Ljava/lang/String;", "I"),
|
||||
"I"
|
||||
"I",
|
||||
)
|
||||
|
||||
private fun MethodReference.anyMethodSignatureMatches(vararg anyOf: MethodReference): Boolean {
|
||||
return anyOf.any {
|
||||
MethodUtil.methodSignaturesMatch(it, this)
|
||||
}
|
||||
}
|
||||
private val getIntMethodReferences = listOf(
|
||||
SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE,
|
||||
SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE,
|
||||
)
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdbStatusPatch = bytecodePatch(
|
||||
val hideADBStatusPatch = bytecodePatch(
|
||||
name = "Hide ADB status",
|
||||
description = "Hides enabled development settings and/or ADB.",
|
||||
use = false,
|
||||
|
|
@ -46,11 +45,8 @@ val hideAdbStatusPatch = bytecodePatch(
|
|||
val reference = instruction
|
||||
.takeIf { it.opcode == Opcode.INVOKE_STATIC }
|
||||
?.getReference<MethodReference>()
|
||||
?.takeIf {
|
||||
it.anyMethodSignatureMatches(
|
||||
SETTINGS_GLOBAL_GET_INT_OR_THROW_METHOD_REFERENCE,
|
||||
SETTINGS_GLOBAL_GET_INT_OR_DEFAULT_METHOD_REFERENCE
|
||||
)
|
||||
?.takeIf { reference ->
|
||||
getIntMethodReferences.any { MethodUtil.methodSignaturesMatch(it, reference) }
|
||||
}
|
||||
?: return@filterMap null
|
||||
|
||||
|
|
@ -67,9 +63,9 @@ val hideAdbStatusPatch = bytecodePatch(
|
|||
|
||||
method.replaceInstruction(
|
||||
index,
|
||||
"invoke-static { $registerString }, $EXTENSION_CLASS_DESCRIPTOR->getInt($parameterString)I"
|
||||
"invoke-static { $registerString }, $EXTENSION_CLASS_DESCRIPTOR->getInt($parameterString)I",
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -3,8 +3,8 @@ package app.revanced.patches.all.misc.appicon
|
|||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.util.asSequence
|
||||
import app.revanced.util.childElementsSequence
|
||||
import java.util.logging.Logger
|
||||
import org.w3c.dom.Element
|
||||
import java.util.logging.Logger
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAppIconPatch = resourcePatch(
|
||||
|
|
@ -12,7 +12,7 @@ val hideAppIconPatch = resourcePatch(
|
|||
description = "Hides the app icon from the Android launcher.",
|
||||
use = false,
|
||||
) {
|
||||
execute {
|
||||
apply {
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
var changed = false
|
||||
|
||||
|
|
@ -26,6 +26,7 @@ val hideAppIconPatch = resourcePatch(
|
|||
"action" -> if (child.getAttribute("android:name") == "android.intent.action.MAIN") {
|
||||
hasMainAction = true
|
||||
}
|
||||
|
||||
"category" -> if (child.getAttribute("android:name") == "android.intent.category.LAUNCHER") {
|
||||
launcherCategory = child
|
||||
}
|
||||
|
|
@ -45,4 +46,3 @@ val hideAppIconPatch = resourcePatch(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package app.revanced.patches.all.misc.build
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
|
|
|
|||
|
|
@ -11,172 +11,148 @@ val spoofBuildInfoPatch = bytecodePatch(
|
|||
use = false,
|
||||
) {
|
||||
val board by stringOption(
|
||||
key = "board",
|
||||
default = null,
|
||||
title = "Board",
|
||||
name = "Board",
|
||||
description = "The name of the underlying board, like \"goldfish\".",
|
||||
)
|
||||
|
||||
val bootloader by stringOption(
|
||||
key = "bootloader",
|
||||
default = null,
|
||||
title = "Bootloader",
|
||||
name = "Bootloader",
|
||||
description = "The system bootloader version number.",
|
||||
)
|
||||
|
||||
val brand by stringOption(
|
||||
key = "brand",
|
||||
default = null,
|
||||
title = "Brand",
|
||||
name = "Brand",
|
||||
description = "The consumer-visible brand with which the product/hardware will be associated, if any.",
|
||||
)
|
||||
|
||||
val cpuAbi by stringOption(
|
||||
key = "cpu-abi",
|
||||
default = null,
|
||||
title = "CPU ABI",
|
||||
name = "CPU ABI",
|
||||
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead.",
|
||||
)
|
||||
|
||||
val cpuAbi2 by stringOption(
|
||||
key = "cpu-abi-2",
|
||||
default = null,
|
||||
title = "CPU ABI 2",
|
||||
name = "CPU ABI 2",
|
||||
description = "This field was deprecated in API level 21. Use SUPPORTED_ABIS instead.",
|
||||
)
|
||||
|
||||
val device by stringOption(
|
||||
key = "device",
|
||||
default = null,
|
||||
title = "Device",
|
||||
name = "Device",
|
||||
description = "The name of the industrial design.",
|
||||
)
|
||||
|
||||
val display by stringOption(
|
||||
key = "display",
|
||||
default = null,
|
||||
title = "Display",
|
||||
name = "Display",
|
||||
description = "A build ID string meant for displaying to the user.",
|
||||
)
|
||||
|
||||
val fingerprint by stringOption(
|
||||
key = "fingerprint",
|
||||
default = null,
|
||||
title = "Fingerprint",
|
||||
name = "Fingerprint",
|
||||
description = "A string that uniquely identifies this build.",
|
||||
)
|
||||
|
||||
val hardware by stringOption(
|
||||
key = "hardware",
|
||||
default = null,
|
||||
title = "Hardware",
|
||||
name = "Hardware",
|
||||
description = "The name of the hardware (from the kernel command line or /proc).",
|
||||
)
|
||||
|
||||
val host by stringOption(
|
||||
key = "host",
|
||||
default = null,
|
||||
title = "Host",
|
||||
name = "Host",
|
||||
description = "The host.",
|
||||
)
|
||||
|
||||
val id by stringOption(
|
||||
key = "id",
|
||||
default = null,
|
||||
title = "ID",
|
||||
name = "ID",
|
||||
description = "Either a changelist number, or a label like \"M4-rc20\".",
|
||||
)
|
||||
|
||||
val manufacturer by stringOption(
|
||||
key = "manufacturer",
|
||||
default = null,
|
||||
title = "Manufacturer",
|
||||
name = "Manufacturer",
|
||||
description = "The manufacturer of the product/hardware.",
|
||||
)
|
||||
|
||||
val model by stringOption(
|
||||
key = "model",
|
||||
default = null,
|
||||
title = "Model",
|
||||
name = "Model",
|
||||
description = "The end-user-visible name for the end product.",
|
||||
)
|
||||
|
||||
val odmSku by stringOption(
|
||||
key = "odm-sku",
|
||||
default = null,
|
||||
title = "ODM SKU",
|
||||
name = "ODM SKU",
|
||||
description = "The SKU of the device as set by the original design manufacturer (ODM).",
|
||||
)
|
||||
|
||||
val product by stringOption(
|
||||
key = "product",
|
||||
default = null,
|
||||
title = "Product",
|
||||
name = "Product",
|
||||
description = "The name of the overall product.",
|
||||
)
|
||||
|
||||
val radio by stringOption(
|
||||
key = "radio",
|
||||
default = null,
|
||||
title = "Radio",
|
||||
name = "Radio",
|
||||
description = "This field was deprecated in API level 15. " +
|
||||
"The radio firmware version is frequently not available when this class is initialized, " +
|
||||
"leading to a blank or \"unknown\" value for this string. Use getRadioVersion() instead.",
|
||||
)
|
||||
|
||||
val serial by stringOption(
|
||||
key = "serial",
|
||||
default = null,
|
||||
title = "Serial",
|
||||
name = "Serial",
|
||||
description = "This field was deprecated in API level 26. Use getSerial() instead.",
|
||||
)
|
||||
|
||||
val sku by stringOption(
|
||||
key = "sku",
|
||||
default = null,
|
||||
title = "SKU",
|
||||
name = "SKU",
|
||||
description = "The SKU of the hardware (from the kernel command line).",
|
||||
)
|
||||
|
||||
val socManufacturer by stringOption(
|
||||
key = "soc-manufacturer",
|
||||
default = null,
|
||||
title = "SOC manufacturer",
|
||||
name = "SOC manufacturer",
|
||||
description = "The manufacturer of the device's primary system-on-chip.",
|
||||
)
|
||||
|
||||
val socModel by stringOption(
|
||||
key = "soc-model",
|
||||
default = null,
|
||||
title = "SOC model",
|
||||
name = "SOC model",
|
||||
description = "The model name of the device's primary system-on-chip.",
|
||||
)
|
||||
|
||||
val tags by stringOption(
|
||||
key = "tags",
|
||||
default = null,
|
||||
title = "Tags",
|
||||
name = "Tags",
|
||||
description = "Comma-separated tags describing the build, like \"unsigned,debug\".",
|
||||
)
|
||||
|
||||
val time by longOption(
|
||||
key = "time",
|
||||
default = null,
|
||||
title = "Time",
|
||||
name = "Time",
|
||||
description = "The time at which the build was produced, given in milliseconds since the UNIX epoch.",
|
||||
)
|
||||
|
||||
val type by stringOption(
|
||||
key = "type",
|
||||
default = null,
|
||||
title = "Type",
|
||||
name = "Type",
|
||||
description = "The type of build, like \"user\" or \"eng\".",
|
||||
)
|
||||
|
||||
val user by stringOption(
|
||||
key = "user",
|
||||
default = null,
|
||||
title = "User",
|
||||
name = "User",
|
||||
description = "The user.",
|
||||
)
|
||||
|
||||
|
|
@ -209,6 +185,5 @@ val spoofBuildInfoPatch = bytecodePatch(
|
|||
user,
|
||||
)
|
||||
},
|
||||
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
@file:Suppress("unused")
|
||||
|
||||
package app.revanced.patches.all.misc.connectivity.location.hide
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.IMethodCall
|
||||
import app.revanced.patches.all.misc.transformation.fromMethodReference
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
@Deprecated("Patch was renamed", ReplaceWith("spoofSimProviderPatch"))
|
||||
@Suppress("unused")
|
||||
val spoofSimCountryPatch = bytecodePatch {
|
||||
dependsOn(spoofSimProviderPatch)
|
||||
}
|
||||
|
|
@ -1,21 +1,21 @@
|
|||
package app.revanced.patches.all.misc.connectivity.telephony.sim.spoof
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.intOption
|
||||
import app.revanced.patcher.patch.stringOption
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
import com.android.tools.smali.dexlib2.util.MethodUtil
|
||||
import java.util.Locale
|
||||
import java.util.*
|
||||
|
||||
@Suppress("unused")
|
||||
val spoofSimProviderPatch = bytecodePatch(
|
||||
val spoofSIMProviderPatch = bytecodePatch(
|
||||
name = "Spoof SIM provider",
|
||||
description = "Spoofs information about the SIM card provider.",
|
||||
use = false,
|
||||
|
|
@ -23,13 +23,11 @@ val spoofSimProviderPatch = bytecodePatch(
|
|||
val countries = Locale.getISOCountries().associateBy { Locale("", it).displayCountry }
|
||||
|
||||
fun isoCountryPatchOption(
|
||||
key: String,
|
||||
title: String,
|
||||
name: String,
|
||||
) = stringOption(
|
||||
key,
|
||||
name,
|
||||
null,
|
||||
countries,
|
||||
title,
|
||||
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
|
||||
false,
|
||||
validator = { it: String? -> it == null || it.uppercase() in countries.values },
|
||||
|
|
@ -37,39 +35,29 @@ val spoofSimProviderPatch = bytecodePatch(
|
|||
|
||||
fun isMccMncValid(it: Int?): Boolean = it == null || (it >= 10000 && it <= 999999)
|
||||
|
||||
val networkCountryIso by isoCountryPatchOption(
|
||||
"networkCountryIso",
|
||||
"Network ISO country code",
|
||||
)
|
||||
val networkCountryIso by isoCountryPatchOption("Network ISO country code")
|
||||
|
||||
val networkOperator by intOption(
|
||||
key = "networkOperator",
|
||||
title = "MCC+MNC network operator code",
|
||||
name = "MCC+MNC network operator code",
|
||||
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the network operator.",
|
||||
validator = { isMccMncValid(it) }
|
||||
validator = { isMccMncValid(it) },
|
||||
)
|
||||
|
||||
val networkOperatorName by stringOption(
|
||||
key = "networkOperatorName",
|
||||
title = "Network operator name",
|
||||
name = "Network operator name",
|
||||
description = "The full name of the network operator.",
|
||||
)
|
||||
|
||||
val simCountryIso by isoCountryPatchOption(
|
||||
"simCountryIso",
|
||||
"SIM ISO country code",
|
||||
)
|
||||
val simCountryIso by isoCountryPatchOption("SIM ISO country code")
|
||||
|
||||
val simOperator by intOption(
|
||||
key = "simOperator",
|
||||
title = "MCC+MNC SIM operator code",
|
||||
name = "MCC+MNC SIM operator code",
|
||||
description = "The 5 or 6 digits MCC+MNC (Mobile Country Code + Mobile Network Code) of the SIM operator.",
|
||||
validator = { isMccMncValid(it) }
|
||||
validator = { isMccMncValid(it) },
|
||||
)
|
||||
|
||||
val simOperatorName by stringOption(
|
||||
key = "simOperatorName",
|
||||
title = "SIM operator name",
|
||||
name = "SIM operator name",
|
||||
description = "The full name of the SIM operator.",
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ private const val EXTENSION_CLASS_DESCRIPTOR_PREFIX =
|
|||
private const val EXTENSION_CLASS_DESCRIPTOR = "$EXTENSION_CLASS_DESCRIPTOR_PREFIX;"
|
||||
|
||||
@Suppress("unused")
|
||||
val spoofWifiPatch = bytecodePatch(
|
||||
val spoofWiFiConnectionPatch = bytecodePatch(
|
||||
name = "Spoof Wi-Fi connection",
|
||||
description = "Spoofs an existing Wi-Fi connection.",
|
||||
use = false,
|
||||
|
|
|
|||
|
|
@ -9,34 +9,29 @@ import app.revanced.util.getNode
|
|||
import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
|
||||
|
||||
|
||||
|
||||
@Suppress("unused")
|
||||
val customNetworkSecurityPatch = resourcePatch(
|
||||
name = "Custom network security",
|
||||
description = "Allows trusting custom certificate authorities for a specific domain.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
|
||||
val targetDomains by stringsOption(
|
||||
key = "targetDomains",
|
||||
title = "Target domains",
|
||||
name = "Target domains",
|
||||
description = "List of domains to which the custom trust configuration will be applied (one domain per entry).",
|
||||
default = listOf("example.com"),
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val includeSubdomains by booleanOption(
|
||||
key = "includeSubdomains",
|
||||
title = "Include subdomains",
|
||||
name = "Include subdomains",
|
||||
description = "Applies the configuration to all subdomains of the target domains.",
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val customCAFilePaths by stringsOption(
|
||||
key = "customCAFilePaths",
|
||||
title = "Custom CA file paths",
|
||||
name = "Custom CA file paths",
|
||||
description = """
|
||||
List of paths to files in PEM or DER format (one file path per entry).
|
||||
|
||||
|
|
@ -47,43 +42,35 @@ val customNetworkSecurityPatch = resourcePatch(
|
|||
CA files will be bundled in res/raw/ of resulting APK
|
||||
""".trimIndentMultiline(),
|
||||
default = null,
|
||||
required = false
|
||||
required = false,
|
||||
)
|
||||
|
||||
val allowUserCerts by booleanOption(
|
||||
key = "allowUserCerts",
|
||||
title = "Trust user added CAs",
|
||||
name = "Trust user added CAs",
|
||||
description = "Makes an app trust certificates from the Android user store for the specified domains, and if the option \"Include Subdomains\" is enabled then also the subdomains.",
|
||||
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val allowSystemCerts by booleanOption(
|
||||
key = "allowSystemCerts",
|
||||
title = "Trust system CAs",
|
||||
name = "Trust system CAs",
|
||||
description = "Makes an app trust certificates from the Android system store for the specified domains, and and if the option \"Include Subdomains\" is enabled then also the subdomains.",
|
||||
|
||||
default = true,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val allowCleartextTraffic by booleanOption(
|
||||
key = "allowCleartextTraffic",
|
||||
title = "Allow cleartext traffic (HTTP)",
|
||||
name = "Allow cleartext traffic (HTTP)",
|
||||
description = "Allows unencrypted HTTP traffic for the specified domains, and if \"Include Subdomains\" is enabled then also the subdomains.",
|
||||
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
val overridePins by booleanOption(
|
||||
key = "overridePins",
|
||||
title = "Override certificate pinning",
|
||||
name = "Override certificate pinning",
|
||||
description = "Overrides certificate pinning for the specified domains and their subdomains if the option \"Include Subdomains\" is enabled to allow inspecting app traffic via a proxy.",
|
||||
|
||||
default = false,
|
||||
required = true
|
||||
required = true,
|
||||
)
|
||||
|
||||
fun generateNetworkSecurityConfig(): String {
|
||||
|
|
@ -128,55 +115,47 @@ ${trustAnchorsXML.trimEnd()}
|
|||
</trust-anchors>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
""".trimIndent()
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
|
||||
execute {
|
||||
apply {
|
||||
val nscFileNameBare = "network_security_config"
|
||||
val resXmlDir = "res/xml"
|
||||
val resRawDir = "res/raw"
|
||||
val nscFileNameWithSuffix = "$nscFileNameBare.xml"
|
||||
|
||||
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
val applicationNode = document.getNode("application") as Element
|
||||
applicationNode.setAttribute("android:networkSecurityConfig", "@xml/$nscFileNameBare")
|
||||
}
|
||||
|
||||
|
||||
File(get(resXmlDir), nscFileNameWithSuffix).apply {
|
||||
writeText(generateNetworkSecurityConfig())
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (customCAFilePath in customCAFilePaths ?: emptyList()) {
|
||||
val file = File(customCAFilePath)
|
||||
if (!file.exists()) {
|
||||
throw PatchException(
|
||||
"The custom CA file path cannot be found: " +
|
||||
file.absolutePath
|
||||
file.absolutePath,
|
||||
)
|
||||
}
|
||||
|
||||
if (!file.isFile) {
|
||||
throw PatchException(
|
||||
"The custom CA file path must be a file: "
|
||||
+ file.absolutePath
|
||||
"The custom CA file path must be a file: " +
|
||||
file.absolutePath,
|
||||
)
|
||||
}
|
||||
val caFileNameWithoutSuffix = customCAFilePath.substringAfterLast('/').substringBefore('.')
|
||||
val caFile = File(customCAFilePath)
|
||||
File(
|
||||
get(resRawDir),
|
||||
caFileNameWithoutSuffix
|
||||
caFileNameWithoutSuffix,
|
||||
).writeText(
|
||||
caFile.readText()
|
||||
caFile.readText(),
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ package app.revanced.patches.all.misc.debugging
|
|||
import app.revanced.patcher.patch.resourcePatch
|
||||
import org.w3c.dom.Element
|
||||
|
||||
@Suppress("unused")
|
||||
val enableAndroidDebuggingPatch = resourcePatch(
|
||||
name = "Enable Android debugging",
|
||||
description = "Enables Android debugging capabilities. This can slow down the app.",
|
||||
use = false,
|
||||
) {
|
||||
execute {
|
||||
apply {
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
val applicationNode =
|
||||
document
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
package app.revanced.patches.all.misc.directory
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.directory.documentsprovider.exportInternalDataDocumentsProviderPatch
|
||||
|
||||
@Suppress("unused")
|
||||
@Deprecated(
|
||||
"Superseded by internalDataDocumentsProviderPatch",
|
||||
ReplaceWith("internalDataDocumentsProviderPatch"),
|
||||
)
|
||||
val changeDataDirectoryLocationPatch = bytecodePatch(
|
||||
// name = "Change data directory location",
|
||||
description = "Changes the data directory in the application from " +
|
||||
"the app internal storage directory to /sdcard/android/data accessible by root-less devices." +
|
||||
"Using this patch can cause unexpected issues with some apps.",
|
||||
use = false,
|
||||
) {
|
||||
dependsOn(exportInternalDataDocumentsProviderPatch)
|
||||
}
|
||||
|
|
@ -18,7 +18,7 @@ val exportInternalDataDocumentsProviderPatch = resourcePatch(
|
|||
},
|
||||
)
|
||||
|
||||
execute {
|
||||
apply {
|
||||
val documentsProviderClass =
|
||||
"app.revanced.extension.all.misc.directory.documentsprovider.InternalDataDocumentsProvider"
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ val exportInternalDataDocumentsProviderPatch = resourcePatch(
|
|||
.asSequence()
|
||||
.any { it.attributes.getNamedItem("android:name")?.nodeValue == documentsProviderClass }
|
||||
) {
|
||||
return@execute
|
||||
return@apply
|
||||
}
|
||||
|
||||
val authority =
|
||||
|
|
|
|||
|
|
@ -3,19 +3,16 @@ package app.revanced.patches.all.misc.hex
|
|||
import app.revanced.patcher.patch.PatchException
|
||||
import app.revanced.patcher.patch.rawResourcePatch
|
||||
import app.revanced.patcher.patch.stringsOption
|
||||
import app.revanced.patches.shared.misc.hex.HexPatchBuilder
|
||||
import app.revanced.patches.shared.misc.hex.hexPatch
|
||||
import app.revanced.util.Utils.trimIndentMultiline
|
||||
|
||||
@Suppress("unused")
|
||||
val hexPatch = rawResourcePatch(
|
||||
name = "Hex",
|
||||
val Hex = rawResourcePatch(
|
||||
description = "Replaces a hexadecimal patterns of bytes of files in an APK.",
|
||||
use = false,
|
||||
) {
|
||||
val replacements by stringsOption(
|
||||
key = "replacements",
|
||||
title = "Replacements",
|
||||
name = "Replacements",
|
||||
description = """
|
||||
Hexadecimal patterns to search for and replace with another in a target file.
|
||||
|
||||
|
|
@ -34,10 +31,14 @@ val hexPatch = rawResourcePatch(
|
|||
|
||||
dependsOn(
|
||||
hexPatch(
|
||||
block = fun HexPatchBuilder.() {
|
||||
block = {
|
||||
replacements!!.forEach { replacement ->
|
||||
try {
|
||||
val (pattern, replacementPattern, targetFilePath) = replacement.split("|", limit = 3)
|
||||
val (pattern, replacementPattern, targetFilePath) = replacement.split(
|
||||
"|",
|
||||
limit = 3
|
||||
)
|
||||
|
||||
pattern asPatternTo replacementPattern inFile targetFilePath
|
||||
} catch (e: Exception) {
|
||||
throw PatchException(
|
||||
|
|
@ -49,6 +50,6 @@ val hexPatch = rawResourcePatch(
|
|||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ val predictiveBackGesturePatch = resourcePatch(
|
|||
description = "Enables the predictive back gesture introduced on Android 13.",
|
||||
use = false,
|
||||
) {
|
||||
execute {
|
||||
apply {
|
||||
val flag = "android:enableOnBackInvokedCallback"
|
||||
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package app.revanced.patches.all.misc.network
|
|||
import app.revanced.patcher.patch.resourcePatch
|
||||
import app.revanced.patches.all.misc.debugging.enableAndroidDebuggingPatch
|
||||
import app.revanced.util.Utils.trimIndentMultiline
|
||||
import app.revanced.util.getNode
|
||||
import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
|
||||
|
|
@ -14,16 +15,20 @@ val overrideCertificatePinningPatch = resourcePatch(
|
|||
) {
|
||||
dependsOn(enableAndroidDebuggingPatch)
|
||||
|
||||
execute {
|
||||
apply {
|
||||
val resXmlDirectory = get("res/xml")
|
||||
|
||||
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
val applicationNode = document.getElementsByTagName("application").item(0) as Element
|
||||
|
||||
if (!applicationNode.hasAttribute("networkSecurityConfig")) {
|
||||
document.createAttribute("android:networkSecurityConfig")
|
||||
.apply { value = "@xml/network_security_config" }.let(applicationNode.attributes::setNamedItem)
|
||||
val applicationNode = document.getNode("application") as Element
|
||||
applicationNode.apply {
|
||||
if (!hasAttribute("networkSecurityConfig")) {
|
||||
attributes.setNamedItem(
|
||||
document.createAttribute("android:networkSecurityConfig").apply {
|
||||
value = "@xml/network_security_config"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,15 @@ import app.revanced.util.getNode
|
|||
import org.w3c.dom.Element
|
||||
import java.util.logging.Logger
|
||||
|
||||
lateinit var packageNameOption: Option<String>
|
||||
private val packageNameOption = stringOption(
|
||||
default = "Default",
|
||||
values = mapOf("Default" to "Default"),
|
||||
name = "Package name",
|
||||
description = "The name of the package to rename the app to.",
|
||||
required = true,
|
||||
) {
|
||||
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the package name to use.
|
||||
|
|
@ -26,40 +34,30 @@ fun setOrGetFallbackPackageName(fallbackPackageName: String): String {
|
|||
}
|
||||
}
|
||||
|
||||
@Suppress("ObjectPropertyName")
|
||||
val changePackageNamePatch = resourcePatch(
|
||||
name = "Change package name",
|
||||
description = "Appends \".revanced\" to the package name by default. " +
|
||||
"Changing the package name of the app can lead to unexpected issues.",
|
||||
use = false,
|
||||
) {
|
||||
packageNameOption = stringOption(
|
||||
key = "packageName",
|
||||
default = "Default",
|
||||
values = mapOf("Default" to "Default"),
|
||||
title = "Package name",
|
||||
description = "The name of the package to rename the app to.",
|
||||
required = true,
|
||||
) {
|
||||
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
|
||||
}
|
||||
packageNameOption()
|
||||
|
||||
val updatePermissions by booleanOption(
|
||||
key = "updatePermissions",
|
||||
default = false,
|
||||
title = "Update permissions",
|
||||
name = "Update permissions",
|
||||
description = "Update compatibility receiver permissions. " +
|
||||
"Enabling this can fix installation errors, but this can also break features in certain apps.",
|
||||
)
|
||||
|
||||
val updateProviders by booleanOption(
|
||||
key = "updateProviders",
|
||||
default = false,
|
||||
title = "Update providers",
|
||||
name = "Update providers",
|
||||
description = "Update provider names declared by the app. " +
|
||||
"Enabling this can fix installation errors, but this can also break features in certain apps.",
|
||||
)
|
||||
|
||||
finalize {
|
||||
afterDependents {
|
||||
/**
|
||||
* Apps that are confirmed to not work correctly with this patch.
|
||||
* This is not an exhaustive list, and is only the apps with
|
||||
|
|
@ -80,7 +78,7 @@ val changePackageNamePatch = resourcePatch(
|
|||
val packageName = manifest.getAttribute("package")
|
||||
|
||||
if (incompatibleAppPackages.contains(packageName)) {
|
||||
return@finalize Logger.getLogger(this::class.java.name).severe(
|
||||
return@afterDependents Logger.getLogger(this::class.java.name).severe(
|
||||
"'$packageName' does not work correctly with \"Change package name\"",
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package app.revanced.patches.all.misc.playintegrity
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import com.android.tools.smali.dexlib2.immutable.reference.ImmutableMethodReference
|
||||
|
|
@ -16,10 +15,9 @@ private val CONTEXT_BIND_SERVICE_METHOD_REFERENCE = ImmutableMethodReference(
|
|||
"Landroid/content/Context;",
|
||||
"bindService",
|
||||
listOf("Landroid/content/Intent;", "Landroid/content/ServiceConnection;", "I"),
|
||||
"Z"
|
||||
"Z",
|
||||
)
|
||||
|
||||
|
||||
@Suppress("unused")
|
||||
val disablePlayIntegrityPatch = bytecodePatch(
|
||||
name = "Disable Play Integrity",
|
||||
|
|
@ -43,13 +41,14 @@ val disablePlayIntegrityPatch = bytecodePatch(
|
|||
transform = { method, entry ->
|
||||
val (instruction, index, parameterTypes) = entry
|
||||
val parameterString = parameterTypes.joinToString(separator = "")
|
||||
val registerString = "v${instruction.registerC}, v${instruction.registerD}, v${instruction.registerE}, v${instruction.registerF}"
|
||||
val registerString =
|
||||
"v${instruction.registerC}, v${instruction.registerD}, v${instruction.registerE}, v${instruction.registerF}"
|
||||
|
||||
method.replaceInstruction(
|
||||
index,
|
||||
"invoke-static { $registerString }, $EXTENSION_CLASS_DESCRIPTOR->bindService(Landroid/content/Context;$parameterString)Z"
|
||||
"invoke-static { $registerString }, $EXTENSION_CLASS_DESCRIPTOR->bindService(Landroid/content/Context;$parameterString)Z",
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -215,8 +215,8 @@ fun addResources(
|
|||
* @see addResourcesPatch
|
||||
*/
|
||||
fun addResources(
|
||||
patch: Patch<*>,
|
||||
parseIds: (Patch<*>) -> Map<AppId, Set<PatchId>> = {
|
||||
patch: Patch,
|
||||
parseIds: (Patch) -> Map<AppId, Set<PatchId>> = {
|
||||
val patchId = patch.name ?: throw PatchException("Patch has no name")
|
||||
val packages = patch.compatiblePackages ?: throw PatchException("Patch has no compatible packages")
|
||||
|
||||
|
|
@ -273,9 +273,9 @@ val addResourcesPatch = resourcePatch(
|
|||
from the temporary map to addResourcesPatch.
|
||||
|
||||
After all patches that depend on addResourcesPatch have been executed,
|
||||
addResourcesPatch#finalize is finally called to add all staged resources to the app.
|
||||
addResourcesPatch#afterDependents is finally called to add all staged resources to the app.
|
||||
*/
|
||||
execute {
|
||||
apply {
|
||||
stagedResources = buildMap {
|
||||
/**
|
||||
* Puts resources under `/resources/addresources/<value>/<resourceKind>.xml` into the map.
|
||||
|
|
@ -324,7 +324,7 @@ val addResourcesPatch = resourcePatch(
|
|||
|
||||
// Stage all resources to a temporary map.
|
||||
// Staged resources consumed by addResourcesPatch#invoke(Patch)
|
||||
// are later used in addResourcesPatch#finalize.
|
||||
// are later used in addResourcesPatch#afterDependents.
|
||||
try {
|
||||
val addStringResources = { source: Value, dest: Value ->
|
||||
addResources(source, dest, "strings", StringResource::fromNode)
|
||||
|
|
@ -343,7 +343,7 @@ val addResourcesPatch = resourcePatch(
|
|||
* Adds all resources staged in [addResourcesPatch] to the app.
|
||||
* This is called after all patches that depend on [addResourcesPatch] have been executed.
|
||||
*/
|
||||
finalize {
|
||||
afterDependents {
|
||||
operator fun MutableMap<String, Pair<Document, Node>>.invoke(
|
||||
value: Value,
|
||||
resource: BaseResource,
|
||||
|
|
@ -359,14 +359,14 @@ val addResourcesPatch = resourcePatch(
|
|||
}
|
||||
|
||||
getOrPut(resourceFileName) {
|
||||
this@finalize["res/$value/$resourceFileName.xml"].also {
|
||||
this@afterDependents["res/$value/$resourceFileName.xml"].also {
|
||||
it.parentFile?.mkdirs()
|
||||
|
||||
if (it.createNewFile()) {
|
||||
it.writeText("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n</resources>")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document("res/$value/$resourceFileName.xml").let { document ->
|
||||
|
||||
// Save the target node here as well
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.w3c.dom.Element
|
|||
private val removeCaptureRestrictionResourcePatch = resourcePatch(
|
||||
description = "Sets allowAudioPlaybackCapture in manifest to true.",
|
||||
) {
|
||||
execute {
|
||||
apply {
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
// Get the application node.
|
||||
val applicationNode =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package app.revanced.patches.all.misc.screenshot
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||
import app.revanced.patcher.extensions.removeInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.transformInstructionsPatch
|
||||
import app.revanced.util.getReference
|
||||
|
|
@ -16,7 +16,7 @@ private val registerScreenCaptureCallbackMethodReference = ImmutableMethodRefere
|
|||
"Ljava/util/concurrent/Executor;",
|
||||
"Landroid/app/Activity\$ScreenCaptureCallback;",
|
||||
),
|
||||
"V"
|
||||
"V",
|
||||
)
|
||||
|
||||
private val unregisterScreenCaptureCallbackMethodReference = ImmutableMethodReference(
|
||||
|
|
@ -25,28 +25,30 @@ private val unregisterScreenCaptureCallbackMethodReference = ImmutableMethodRefe
|
|||
listOf(
|
||||
"Landroid/app/Activity\$ScreenCaptureCallback;",
|
||||
),
|
||||
"V"
|
||||
"V",
|
||||
)
|
||||
|
||||
@Suppress("unused")
|
||||
val preventScreenshotDetectionPatch = bytecodePatch(
|
||||
name = "Prevent screenshot detection",
|
||||
description = "Removes the registration of all screen capture callbacks. This prevents the app from detecting screenshots.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
dependsOn(transformInstructionsPatch(
|
||||
filterMap = { _, _, instruction, instructionIndex ->
|
||||
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return@transformInstructionsPatch null
|
||||
|
||||
val reference = instruction.getReference<MethodReference>() ?: return@transformInstructionsPatch null
|
||||
dependsOn(
|
||||
transformInstructionsPatch(
|
||||
filterMap = { _, _, instruction, instructionIndex ->
|
||||
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return@transformInstructionsPatch null
|
||||
|
||||
instructionIndex.takeIf {
|
||||
MethodUtil.methodSignaturesMatch(reference, registerScreenCaptureCallbackMethodReference) ||
|
||||
MethodUtil.methodSignaturesMatch(reference, unregisterScreenCaptureCallbackMethodReference)
|
||||
}
|
||||
},
|
||||
transform = { mutableMethod, instructionIndex ->
|
||||
mutableMethod.removeInstruction(instructionIndex)
|
||||
}
|
||||
))
|
||||
val reference = instruction.getReference<MethodReference>() ?: return@transformInstructionsPatch null
|
||||
|
||||
instructionIndex.takeIf {
|
||||
MethodUtil.methodSignaturesMatch(reference, registerScreenCaptureCallbackMethodReference) ||
|
||||
MethodUtil.methodSignaturesMatch(reference, unregisterScreenCaptureCallbackMethodReference)
|
||||
}
|
||||
},
|
||||
transform = { mutableMethod, instructionIndex ->
|
||||
mutableMethod.removeInstruction(instructionIndex)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package app.revanced.patches.all.misc.screenshot
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.all.misc.transformation.IMethodCall
|
||||
import app.revanced.patches.all.misc.transformation.filterMapInstruction35c
|
||||
|
|
|
|||
|
|
@ -13,12 +13,13 @@ val removeShareTargetsPatch = resourcePatch(
|
|||
description = "Removes share targets like directly sharing to a frequent contact.",
|
||||
use = false,
|
||||
) {
|
||||
execute {
|
||||
apply {
|
||||
try {
|
||||
document("res/xml/shortcuts.xml")
|
||||
} catch (_: FileNotFoundException) {
|
||||
return@execute Logger.getLogger(this::class.java.name).warning(
|
||||
"The app has no shortcuts. No changes applied.")
|
||||
return@apply Logger.getLogger(this::class.java.name).warning(
|
||||
"The app has no shortcuts. No changes applied.",
|
||||
)
|
||||
}.use { document ->
|
||||
val rootNode = document.getNode("shortcuts") as? Element ?: return@use
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import app.revanced.patcher.patch.stringOption
|
|||
import app.revanced.util.getNode
|
||||
import com.android.apksig.ApkVerifier
|
||||
import com.android.apksig.apk.ApkFormatException
|
||||
import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.nio.file.InvalidPathException
|
||||
|
|
@ -15,15 +14,14 @@ import java.security.cert.CertificateFactory
|
|||
import java.util.*
|
||||
|
||||
@Suppress("unused")
|
||||
val enableRomSignatureSpoofing = resourcePatch(
|
||||
val enableROMSignatureSpoofingPatch = resourcePatch(
|
||||
name = "Enable ROM signature spoofing",
|
||||
description = "Spoofs the signature via the manifest meta-data \"fake-signature\". " +
|
||||
"This patch only works with ROMs that support signature spoofing.",
|
||||
"This patch only works with ROMs that support signature spoofing.",
|
||||
use = false,
|
||||
) {
|
||||
val signatureOrPath by stringOption(
|
||||
key = "signatureOrApkFilePath",
|
||||
title = "Signature or APK file path",
|
||||
name = "Signature or APK file path",
|
||||
validator = validator@{ signature ->
|
||||
signature ?: return@validator false
|
||||
|
||||
|
|
@ -32,14 +30,13 @@ val enableRomSignatureSpoofing = resourcePatch(
|
|||
description = "The hex-encoded signature or path to an APK file with the desired signature.",
|
||||
required = true,
|
||||
)
|
||||
execute {
|
||||
apply {
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
val permission = document.createElement("uses-permission").apply {
|
||||
setAttribute("android:name", "android.permission.FAKE_PACKAGE_SIGNATURE")
|
||||
}
|
||||
val manifest = document.getNode("manifest").appendChild(permission)
|
||||
|
||||
|
||||
val fakeSignatureMetadata = document.createElement("meta-data").apply {
|
||||
setAttribute("android:name", "fake-signature")
|
||||
setAttribute("android:value", parseSignature(signatureOrPath!!))
|
||||
|
|
@ -70,15 +67,17 @@ private fun parseSignature(optionValue: String): String? {
|
|||
|
||||
val hexFormat = HexFormat.of()
|
||||
|
||||
val signature = (if (result.isVerifiedUsingV3Scheme) {
|
||||
result.v3SchemeSigners[0].certificate
|
||||
} else if (result.isVerifiedUsingV2Scheme) {
|
||||
result.v2SchemeSigners[0].certificate
|
||||
} else if (result.isVerifiedUsingV1Scheme) {
|
||||
result.v1SchemeSigners[0].certificate
|
||||
} else {
|
||||
return null
|
||||
}).encoded
|
||||
val signature = (
|
||||
if (result.isVerifiedUsingV3Scheme) {
|
||||
result.v3SchemeSigners[0].certificate
|
||||
} else if (result.isVerifiedUsingV2Scheme) {
|
||||
result.v2SchemeSigners[0].certificate
|
||||
} else if (result.isVerifiedUsingV1Scheme) {
|
||||
result.v1SchemeSigners[0].certificate
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
).encoded
|
||||
|
||||
return hexFormat.formatHex(signature)
|
||||
} catch (_: IOException) {
|
||||
|
|
@ -89,4 +88,4 @@ private fun parseSignature(optionValue: String): String? {
|
|||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ import org.w3c.dom.Element
|
|||
import java.util.logging.Logger
|
||||
|
||||
@Suppress("unused")
|
||||
val setTargetSdkVersion34 = resourcePatch(
|
||||
val setTargetSDKVersion34Patch = resourcePatch(
|
||||
name = "Set target SDK version 34",
|
||||
description = "Changes the target SDK to version 34 (Android 14). " +
|
||||
"For devices running Android 15+, this will disable edge-to-edge display.",
|
||||
"For devices running Android 15+, this will disable edge-to-edge display.",
|
||||
use = false,
|
||||
) {
|
||||
execute {
|
||||
apply {
|
||||
val targetSdkOverride = 34 // Android 14.
|
||||
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
|
|
@ -24,12 +24,12 @@ val setTargetSdkVersion34 = resourcePatch(
|
|||
try {
|
||||
val manifestElement = document.getNode("manifest") as Element
|
||||
val compileSdkVersion = Integer.parseInt(
|
||||
manifestElement.getAttribute("android:compileSdkVersion")
|
||||
manifestElement.getAttribute("android:compileSdkVersion"),
|
||||
)
|
||||
if (compileSdkVersion <= targetSdkOverride) {
|
||||
getLogger().warning(
|
||||
"This app does not appear to use a target SDK above $targetSdkOverride: " +
|
||||
"(compileSdkVersion: $compileSdkVersion)"
|
||||
"(compileSdkVersion: $compileSdkVersion)",
|
||||
)
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package app.revanced.patches.all.misc.transformation
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
|
|
|
|||
|
|
@ -1,49 +1,22 @@
|
|||
package app.revanced.patches.all.misc.transformation
|
||||
|
||||
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.util.findMutableMethodOf
|
||||
import app.revanced.util.forEachInstructionAsSequence
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
import com.android.tools.smali.dexlib2.iface.Method
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
|
||||
|
||||
@Deprecated(
|
||||
"Use forEachInstructionAsSequence directly within a bytecodePatch", ReplaceWith(
|
||||
"bytecodePatch { apply { forEachInstructionAsSequence(filterMap, transform) } }",
|
||||
"app.revanced.util.forEachInstructionAsSequence",
|
||||
"app.revanced.patcher.patch.bytecodePatch",
|
||||
)
|
||||
)
|
||||
fun <T> transformInstructionsPatch(
|
||||
filterMap: (ClassDef, Method, Instruction, Int) -> T?,
|
||||
transform: (MutableMethod, T) -> Unit,
|
||||
) = bytecodePatch {
|
||||
// Returns the patch indices as a Sequence, which will execute lazily.
|
||||
fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? =
|
||||
method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) ->
|
||||
filterMap(classDef, method, instruction, index)
|
||||
}
|
||||
|
||||
execute {
|
||||
// Find all methods to patch
|
||||
buildMap {
|
||||
classes.forEach { classDef ->
|
||||
val methods = buildList {
|
||||
classDef.methods.forEach { method ->
|
||||
// Since the Sequence executes lazily,
|
||||
// using any() results in only calling
|
||||
// filterMap until the first index has been found.
|
||||
if (findPatchIndices(classDef, method)?.any() == true) add(method)
|
||||
}
|
||||
}
|
||||
|
||||
if (methods.isNotEmpty()) {
|
||||
put(classDef, methods)
|
||||
}
|
||||
}
|
||||
}.forEach { (classDef, methods) ->
|
||||
// And finally transform the methods...
|
||||
val mutableClass = proxy(classDef).mutableClass
|
||||
|
||||
methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
|
||||
val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
|
||||
?: return@methods
|
||||
|
||||
while (!patchIndices.isEmpty()) transform(mutableMethod, patchIndices.removeLast())
|
||||
}
|
||||
}
|
||||
}
|
||||
apply { forEachInstructionAsSequence(filterMap, transform) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,23 +9,22 @@ import org.w3c.dom.Element
|
|||
val changeVersionCodePatch = resourcePatch(
|
||||
name = "Change version code",
|
||||
description = "Changes the version code of the app. This will turn off app store updates " +
|
||||
"and allows downgrading an existing app install to an older app version.",
|
||||
"and allows downgrading an existing app install to an older app version.",
|
||||
use = false,
|
||||
) {
|
||||
val versionCode by intOption(
|
||||
key = "versionCode",
|
||||
default = Int.MAX_VALUE,
|
||||
values = mapOf(
|
||||
"Lowest" to 1,
|
||||
"Highest" to Int.MAX_VALUE,
|
||||
),
|
||||
title = "Version code",
|
||||
name = "Version code",
|
||||
description = "The version code to use. Using the highest value turns off app store " +
|
||||
"updates and allows downgrading an existing app install to an older app version.",
|
||||
"updates and allows downgrading an existing app install to an older app version.",
|
||||
required = true,
|
||||
) { versionCode -> versionCode!! >= 1 }
|
||||
|
||||
execute {
|
||||
apply {
|
||||
document("AndroidManifest.xml").use { document ->
|
||||
val manifestElement = document.getNode("manifest") as Element
|
||||
manifestElement.setAttribute("android:versionCode", "$versionCode")
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
package app.revanced.patches.amazon
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val deepLinkingPatch = bytecodePatch(
|
||||
val alwaysAllowDeepLinkingPatch = bytecodePatch(
|
||||
name = "Always allow deep-linking",
|
||||
description = "Open Amazon links, even if the app is not set to handle Amazon links.",
|
||||
) {
|
||||
compatibleWith("com.amazon.mShop.android.shopping")
|
||||
|
||||
execute {
|
||||
deepLinkingFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
""",
|
||||
)
|
||||
apply {
|
||||
deepLinkingMethod.returnEarly(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,17 @@
|
|||
package app.revanced.patches.amazon
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val deepLinkingFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.deepLinkingMethod by gettingFirstMethodDeclaratively(
|
||||
"https://www.",
|
||||
"android.intent.action.VIEW"
|
||||
) {
|
||||
accessFlags(AccessFlags.PRIVATE)
|
||||
returns("Z")
|
||||
parameters("L")
|
||||
strings("https://www.", "android.intent.action.VIEW")
|
||||
returnType("Z")
|
||||
parameterTypes("L")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package app.revanced.patches.angulus.ads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
// Keywords to search for in case the method name changes:
|
||||
|
|
@ -9,10 +12,9 @@ import com.android.tools.smali.dexlib2.AccessFlags
|
|||
// dailyAdResetCount
|
||||
// MeasurementPrefs
|
||||
|
||||
// This fingerprint targets a method that returns the daily measurement count.
|
||||
// This targets a method that returns the daily measurement count.
|
||||
// This method is used to determine if the user has reached the daily limit of measurements.
|
||||
internal val getDailyMeasurementCountFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getDailyMeasurementCountMethod by gettingFirstMethodDeclaratively("dailyMeasurementCount") {
|
||||
accessFlags(AccessFlags.PRIVATE)
|
||||
returns("I")
|
||||
strings("dailyMeasurementCount")
|
||||
returnType("I")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
package app.revanced.patches.angulus.ads
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.shared.misc.pairip.license.disableLicenseCheckPatch
|
||||
import app.revanced.patches.shared.misc.pairip.license.disablePairipLicenseCheckPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val angulusPatch = bytecodePatch(name = "Hide ads") {
|
||||
val hideAdsPatch = bytecodePatch("Hide ads") {
|
||||
compatibleWith("com.drinkplusplus.angulus")
|
||||
|
||||
dependsOn(disableLicenseCheckPatch)
|
||||
dependsOn(disablePairipLicenseCheckPatch)
|
||||
|
||||
execute {
|
||||
apply {
|
||||
// Always return 0 as the daily measurement count.
|
||||
getDailyMeasurementCountFingerprint.method.returnEarly(0)
|
||||
getDailyMeasurementCountMethod.returnEarly(0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
package app.revanced.patches.backdrops.misc.pro
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
@Deprecated("Fingerprint no longer resolves and will soon be deleted.")
|
||||
internal val proUnlockFingerprint = fingerprint {
|
||||
opcodes(
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_EQZ,
|
||||
)
|
||||
custom { method, _ ->
|
||||
method.name == "lambda\$existPurchase\$0" &&
|
||||
method.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
package app.revanced.patches.backdrops.misc.pro
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
@Deprecated("This patch no longer works and will soon be deleted.")
|
||||
val proUnlockPatch = bytecodePatch{
|
||||
compatibleWith("com.backdrops.wallpapers")
|
||||
|
||||
execute {
|
||||
val registerIndex = proUnlockFingerprint.patternMatch!!.endIndex - 1
|
||||
|
||||
proUnlockFingerprint.method.apply {
|
||||
val register = getInstruction<OneRegisterInstruction>(registerIndex).registerA
|
||||
addInstruction(
|
||||
proUnlockFingerprint.patternMatch!!.endIndex,
|
||||
"const/4 v$register, 0x1",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package app.revanced.patches.bandcamp.limitations
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val handlePlaybackLimitsFingerprint = fingerprint {
|
||||
strings("track_id", "play_count")
|
||||
}
|
||||
internal val BytecodePatchContext.handlePlaybackLimitsMethod by gettingFirstMethodDeclaratively(
|
||||
"track_id",
|
||||
"play_count"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ val removePlayLimitsPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.bandcamp.android")
|
||||
|
||||
execute {
|
||||
handlePlaybackLimitsFingerprint.method.returnEarly()
|
||||
apply {
|
||||
handlePlaybackLimitsMethod.returnEarly()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package app.revanced.patches.cieid.restrictions.root
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val bypassRootChecksPatch = bytecodePatch(
|
||||
|
|
@ -10,7 +10,7 @@ val bypassRootChecksPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("it.ipzs.cieid")
|
||||
|
||||
execute {
|
||||
checkRootFingerprint.method.addInstruction(1, "return-void")
|
||||
apply {
|
||||
checkRootMethod.returnEarly()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package app.revanced.patches.cieid.restrictions.root
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val checkRootFingerprint = fingerprint {
|
||||
custom { method, _ ->
|
||||
method.name == "onResume" && method.definingClass == "Lit/ipzs/cieid/BaseActivity;"
|
||||
}
|
||||
internal val BytecodePatchContext.checkRootMethod by gettingFirstMethodDeclaratively {
|
||||
name("onResume")
|
||||
definingClass("Lit/ipzs/cieid/BaseActivity;")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,25 @@
|
|||
package app.revanced.patches.com.sbs.ondemand.tv
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val shouldShowAdvertisingTVFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
custom { method, classDef ->
|
||||
method.name == "getShouldShowAdvertisingTV" &&
|
||||
classDef.type == "Lcom/sbs/ondemand/common/InMemoryStorage;"
|
||||
}
|
||||
val BytecodePatchContext.shouldShowAdvertisingTVMethod by gettingFirstMethodDeclaratively {
|
||||
name("getShouldShowAdvertisingTV")
|
||||
definingClass("Lcom/sbs/ondemand/common/InMemoryStorage;")
|
||||
returnType("Z")
|
||||
}
|
||||
|
||||
internal val shouldShowPauseAdFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
custom { method, classDef ->
|
||||
method.name == "shouldShowPauseAd" &&
|
||||
classDef.type == "Lcom/sbs/ondemand/player/viewmodels/PauseAdController;"
|
||||
}
|
||||
internal val BytecodePatchContext.shouldShowPauseAdMethod by gettingFirstMethodDeclaratively {
|
||||
name("shouldShowPauseAd")
|
||||
definingClass("Lcom/sbs/ondemand/player/viewmodels/PauseAdController;")
|
||||
returnType("Z")
|
||||
}
|
||||
|
||||
internal val requestAdStreamFingerprint = fingerprint {
|
||||
returns("V")
|
||||
custom { method, classDef ->
|
||||
method.name == "requestAdStream\$player_googleStoreTvRelease" &&
|
||||
classDef.type == "Lcom/sbs/ondemand/player/viewmodels/AdsController;"
|
||||
}
|
||||
internal val BytecodePatchContext.requestAdStreamMethod by gettingFirstMethodDeclaratively {
|
||||
name("requestAdStream\$player_googleStoreTvRelease")
|
||||
definingClass("Lcom/sbs/ondemand/player/viewmodels/AdsController;")
|
||||
returnType("V")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package app.revanced.patches.com.sbs.ondemand.tv
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.shared.misc.pairip.license.disableLicenseCheckPatch
|
||||
import app.revanced.patches.shared.misc.pairip.license.disablePairipLicenseCheckPatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
|
|
@ -12,11 +12,11 @@ val removeAdsPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.sbs.ondemand.tv")
|
||||
|
||||
dependsOn(disableLicenseCheckPatch)
|
||||
dependsOn(disablePairipLicenseCheckPatch)
|
||||
|
||||
execute {
|
||||
shouldShowAdvertisingTVFingerprint.method.returnEarly(true)
|
||||
shouldShowPauseAdFingerprint.method.returnEarly(false)
|
||||
apply {
|
||||
shouldShowAdvertisingTVMethod.returnEarly(true)
|
||||
shouldShowPauseAdMethod.returnEarly(false)
|
||||
|
||||
// Remove on-demand pre-roll advertisements using exception handling.
|
||||
// Exception handling is used instead of returnEarly() because:
|
||||
|
|
@ -24,14 +24,14 @@ val removeAdsPatch = bytecodePatch(
|
|||
// 2. SBS app has built-in exception handling in handleProviderFailure().
|
||||
// 3. Exception triggers fallbackToAkamaiProvider() which loads actual content.
|
||||
// 4. This preserves the intended app flow: first try ads, then fail gracefully, then load content.
|
||||
requestAdStreamFingerprint.method.addInstructions(
|
||||
0,
|
||||
requestAdStreamMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
new-instance v0, Ljava/lang/RuntimeException;
|
||||
const-string v1, "Ad stream disabled"
|
||||
invoke-direct {v0, v1}, Ljava/lang/RuntimeException;-><init>(Ljava/lang/String;)V
|
||||
throw v0
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package app.revanced.patches.cricbuzz.ads
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.cricbuzz.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.getReference
|
||||
|
|
@ -15,26 +15,25 @@ private const val EXTENSION_CLASS_DESCRIPTOR =
|
|||
"Lapp/revanced/extension/cricbuzz/ads/HideAdsPatch;"
|
||||
|
||||
@Suppress("unused")
|
||||
val disableAdsPatch = bytecodePatch (
|
||||
name = "Hide ads",
|
||||
) {
|
||||
val hideAdsPatch = bytecodePatch("Hide ads") {
|
||||
compatibleWith("com.cricbuzz.android"("6.24.01"))
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
execute {
|
||||
userStateSwitchFingerprint.method.returnEarly(true)
|
||||
apply {
|
||||
userStateSwitchMethod.returnEarly(true)
|
||||
|
||||
// Remove region-specific Cricbuzz11 elements.
|
||||
cb11ConstructorFingerprint.method.addInstruction(0, "const/4 p7, 0x0")
|
||||
getBottomBarFingerprint.method.apply {
|
||||
val getIndex = indexOfFirstInstructionOrThrow() {
|
||||
cb11ConstructorMethod.addInstruction(0, "const/4 p7, 0x0")
|
||||
getBottomBarMethod.apply {
|
||||
val getIndex = indexOfFirstInstructionOrThrow {
|
||||
opcode == Opcode.IGET_OBJECT && getReference<FieldReference>()?.name == "bottomBar"
|
||||
}
|
||||
val getRegister = getInstruction<TwoRegisterInstruction>(getIndex).registerA
|
||||
|
||||
addInstruction(getIndex + 1,
|
||||
"invoke-static { v$getRegister }, $EXTENSION_CLASS_DESCRIPTOR->filterCb11(Ljava/util/List;)V"
|
||||
addInstruction(
|
||||
getIndex + 1,
|
||||
"invoke-static { v$getRegister }, $EXTENSION_CLASS_DESCRIPTOR->filterCb11(Ljava/util/List;)V",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
package app.revanced.patches.cricbuzz.ads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val userStateSwitchFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.userStateSwitchMethod by gettingFirstMethodDeclaratively("key.user.state", "NA") {
|
||||
opcodes(Opcode.SPARSE_SWITCH)
|
||||
strings("key.user.state", "NA")
|
||||
}
|
||||
|
||||
internal val cb11ConstructorFingerprint = fingerprint {
|
||||
parameters(
|
||||
internal val BytecodePatchContext.cb11ConstructorMethod by gettingFirstMethodDeclaratively {
|
||||
definingClass("CB11Details;")
|
||||
parameterTypes(
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/String;",
|
||||
|
|
@ -19,15 +20,11 @@ internal val cb11ConstructorFingerprint = fingerprint {
|
|||
"Z",
|
||||
"Ljava/lang/String;",
|
||||
"Ljava/lang/String;",
|
||||
"L"
|
||||
"L",
|
||||
)
|
||||
custom { _, classDef ->
|
||||
classDef.endsWith("CB11Details;")
|
||||
}
|
||||
}
|
||||
|
||||
internal val getBottomBarFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "getBottomBar" && classDef.endsWith("HomeMenu;")
|
||||
}
|
||||
}
|
||||
internal val BytecodePatchContext.getBottomBarMethod by gettingFirstMethodDeclaratively {
|
||||
name("getBottomBar")
|
||||
definingClass("HomeMenu;")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,5 @@
|
|||
package app.revanced.patches.cricbuzz.misc.extension
|
||||
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
import app.revanced.patches.shared.misc.extension.activityOnCreateExtensionHook
|
||||
|
||||
internal val applicationInitHook = extensionHook {
|
||||
custom { method, classDef ->
|
||||
method.name == "onCreate" && classDef.endsWith("/NyitoActivity;")
|
||||
}
|
||||
}
|
||||
internal val applicationInitHook = activityOnCreateExtensionHook("/NyitoActivity;")
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package app.revanced.patches.crunchyroll.ads
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.composingFirstMethod
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val videoUrlReadyToStringFingerprint = fingerprint {
|
||||
strings("VideoUrlReady(url=", ", enableAds=")
|
||||
internal val BytecodePatchContext.videoUrlReadyToStringMethodMatch by composingFirstMethod {
|
||||
instructions("VideoUrlReady(url="(), ", enableAds="())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package app.revanced.patches.crunchyroll.ads
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstruction
|
||||
|
|
@ -13,34 +13,35 @@ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
|||
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide ads"
|
||||
) {
|
||||
val hideAdsPatch = bytecodePatch("Hide ads") {
|
||||
compatibleWith("com.crunchyroll.crunchyroid")
|
||||
|
||||
execute {
|
||||
apply {
|
||||
// Get obfuscated "enableAds" field from toString method.
|
||||
val enableAdsField = videoUrlReadyToStringFingerprint.let {
|
||||
val strIndex = videoUrlReadyToStringFingerprint.stringMatches!!.last().index
|
||||
val fieldIndex = it.method.indexOfFirstInstruction(strIndex, Opcode.IGET_BOOLEAN)
|
||||
it.method.getInstruction<ReferenceInstruction>(fieldIndex).getReference<FieldReference>()!!
|
||||
val enableAdsField = videoUrlReadyToStringMethodMatch.method.let {
|
||||
val stringIndex = videoUrlReadyToStringMethodMatch[-1]
|
||||
val fieldIndex = it.indexOfFirstInstruction(stringIndex, Opcode.IGET_BOOLEAN)
|
||||
|
||||
it.getInstruction<ReferenceInstruction>(fieldIndex).getReference<FieldReference>()!!
|
||||
}
|
||||
|
||||
// Remove final access flag on field.
|
||||
videoUrlReadyToStringFingerprint.classDef.fields
|
||||
videoUrlReadyToStringMethodMatch.classDef.fields
|
||||
.first { it.name == enableAdsField.name }
|
||||
.removeFlags(AccessFlags.FINAL)
|
||||
|
||||
// Override enableAds field in non-default constructor.
|
||||
val constructor = videoUrlReadyToStringFingerprint.classDef.methods.first {
|
||||
val constructor = videoUrlReadyToStringMethodMatch.classDef.methods.first {
|
||||
AccessFlags.CONSTRUCTOR.isSet(it.accessFlags) && it.parameters.isNotEmpty()
|
||||
}
|
||||
|
||||
constructor.addInstructions(
|
||||
constructor.instructions.count() - 1,
|
||||
"""
|
||||
move-object/from16 v0, p0
|
||||
const/4 v1, 0x0
|
||||
iput-boolean v1, v0, $enableAdsField
|
||||
""")
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
package app.revanced.patches.disneyplus.ads
|
||||
package app.revanced.patches.disneyplus
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val insertionGetPointsFingerprint = fingerprint {
|
||||
returns("Ljava/util/List")
|
||||
custom { method, _ ->
|
||||
method.name == "getPoints" &&
|
||||
method.definingClass == "Lcom/dss/sdk/internal/media/Insertion;"
|
||||
}
|
||||
internal val BytecodePatchContext.insertionGetPointsMethod by gettingFirstMethodDeclaratively {
|
||||
name("getPoints")
|
||||
definingClass("Lcom/dss/sdk/internal/media/Insertion;")
|
||||
returnType("Ljava/util/List")
|
||||
}
|
||||
|
||||
internal val insertionGetRangesFingerprint = fingerprint {
|
||||
returns("Ljava/util/List")
|
||||
custom { method, _ ->
|
||||
method.name == "getRanges" &&
|
||||
method.definingClass == "Lcom/dss/sdk/internal/media/Insertion;"
|
||||
}
|
||||
internal val BytecodePatchContext.insertionGetRangesMethod by gettingFirstMethodDeclaratively {
|
||||
name("getRanges")
|
||||
definingClass("Lcom/dss/sdk/internal/media/Insertion;")
|
||||
returnType("Ljava/util/List")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package app.revanced.patches.disneyplus.ads
|
||||
package app.revanced.patches.disneyplus
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
|
||||
@Suppress("unused")
|
||||
|
|
@ -10,11 +10,11 @@ val skipAdsPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.disney.disneyplus")
|
||||
|
||||
execute {
|
||||
arrayOf(insertionGetPointsFingerprint, insertionGetRangesFingerprint).forEach {
|
||||
it.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
apply {
|
||||
arrayOf(insertionGetPointsMethod, insertionGetRangesMethod).forEach {
|
||||
it.addInstructions(
|
||||
0,
|
||||
"""
|
||||
new-instance v0, Ljava/util/ArrayList;
|
||||
invoke-direct {v0}, Ljava/util/ArrayList;-><init>()V
|
||||
return-object v0
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
package app.revanced.patches.duolingo.ad
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
val disableAdsPatch = bytecodePatch(
|
||||
"Disable ads",
|
||||
) {
|
||||
val disableAdsPatch = bytecodePatch("Disable ads") {
|
||||
// 6.55.3 and higher can show ads after each exercise.
|
||||
compatibleWith("com.duolingo"("6.54.5"))
|
||||
|
||||
execute {
|
||||
apply {
|
||||
// Couple approaches to remove ads exist:
|
||||
//
|
||||
// MonetizationDebugSettings has a boolean value for "disableAds".
|
||||
|
|
@ -20,10 +20,9 @@ val disableAdsPatch = bytecodePatch(
|
|||
// SharedPreferences has a debug boolean value with key "disable_ads", which maps to "DebugCategory.DISABLE_ADS".
|
||||
//
|
||||
// MonetizationDebugSettings seems to be the most general setting to work fine.
|
||||
initializeMonetizationDebugSettingsFingerprint
|
||||
.match(monetizationDebugSettingsToStringFingerprint.classDef)
|
||||
.method.apply {
|
||||
val insertIndex = initializeMonetizationDebugSettingsFingerprint.patternMatch!!.startIndex
|
||||
monetizationDebugSettingsToStringMethod.immutableClassDef.initializeMonetizationDebugSettingsMethodMatch.let {
|
||||
it.method.apply {
|
||||
val insertIndex = it[0]
|
||||
val register = getInstruction<TwoRegisterInstruction>(insertIndex).registerA
|
||||
|
||||
addInstructions(
|
||||
|
|
@ -31,5 +30,6 @@ val disableAdsPatch = bytecodePatch(
|
|||
"const/4 v$register, 0x1",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,19 @@
|
|||
package app.revanced.patches.duolingo.ad
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
|
||||
internal val initializeMonetizationDebugSettingsFingerprint = fingerprint {
|
||||
internal val ClassDef.initializeMonetizationDebugSettingsMethodMatch by ClassDefComposing.composingFirstMethod {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
returns("V")
|
||||
// Parameters have not been reliable for fingerprinting between versions.
|
||||
returnType("V")
|
||||
// Parameters have not been reliable for matching between versions.
|
||||
opcodes(Opcode.IPUT_BOOLEAN)
|
||||
}
|
||||
|
||||
internal val monetizationDebugSettingsToStringFingerprint = fingerprint {
|
||||
strings("MonetizationDebugSettings(") // Partial string match.
|
||||
custom { method, _ -> method.name == "toString" }
|
||||
}
|
||||
internal val BytecodePatchContext.monetizationDebugSettingsToStringMethod by gettingFirstMethodDeclaratively {
|
||||
name("toString")
|
||||
instructions(string("MonetizationDebugSettings(", String::contains))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package app.revanced.patches.duolingo.debug
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
|
@ -9,27 +11,20 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
|||
@Suppress("unused")
|
||||
val enableDebugMenuPatch = bytecodePatch(
|
||||
name = "Enable debug menu",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.duolingo")
|
||||
|
||||
execute {
|
||||
apply {
|
||||
// It seems all categories are allowed on release. Force this on anyway.
|
||||
debugCategoryAllowOnReleaseBuildsFingerprint.method.returnEarly(true)
|
||||
debugCategoryAllowOnReleaseBuildsMethod.returnEarly(true)
|
||||
|
||||
// Change build config debug build flag.
|
||||
buildConfigProviderConstructorFingerprint.match(
|
||||
buildConfigProviderToStringFingerprint.classDef
|
||||
).let {
|
||||
val index = it.patternMatch!!.startIndex
|
||||
buildConfigProviderToStringMethod.immutableClassDef.buildConfigProviderConstructorMethodMatch.let {
|
||||
val index = it[0]
|
||||
|
||||
it.method.apply {
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
addInstruction(
|
||||
index + 1,
|
||||
"const/4 v$register, 0x1"
|
||||
)
|
||||
}
|
||||
val register = it.method.getInstruction<OneRegisterInstruction>(index).registerA
|
||||
it.method.addInstruction(index + 1, "const/4 v$register, 0x1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,27 @@
|
|||
package app.revanced.patches.duolingo.debug
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
|
||||
internal val debugCategoryAllowOnReleaseBuildsFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
method.name == "getAllowOnReleaseBuilds" && classDef.type == "Lcom/duolingo/debug/DebugCategory;"
|
||||
}
|
||||
internal val BytecodePatchContext.debugCategoryAllowOnReleaseBuildsMethod by gettingFirstMethodDeclaratively {
|
||||
name("getAllowOnReleaseBuilds")
|
||||
definingClass("Lcom/duolingo/debug/DebugCategory;")
|
||||
returnType("Z")
|
||||
parameterTypes()
|
||||
}
|
||||
|
||||
internal val buildConfigProviderConstructorFingerprint = fingerprint {
|
||||
internal val ClassDef.buildConfigProviderConstructorMethodMatch by ClassDefComposing.composingFirstMethod {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
parameters()
|
||||
parameterTypes()
|
||||
opcodes(Opcode.CONST_4)
|
||||
}
|
||||
|
||||
internal val buildConfigProviderToStringFingerprint = fingerprint {
|
||||
parameters()
|
||||
returns("Ljava/lang/String;")
|
||||
strings("BuildConfigProvider(") // Partial string match.
|
||||
custom { method, _ ->
|
||||
method.name == "toString"
|
||||
}
|
||||
internal val BytecodePatchContext.buildConfigProviderToStringMethod by gettingFirstMethodDeclaratively {
|
||||
name("toString")
|
||||
parameterTypes()
|
||||
returnType("Ljava/lang/String;")
|
||||
instructions(string("BuildConfigProvider(", String::contains))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,25 @@
|
|||
package app.revanced.patches.duolingo.energy
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||
|
||||
/**
|
||||
* Matches the class found in [energyConfigToStringFingerprint].
|
||||
*/
|
||||
internal val initializeEnergyConfigFingerprint = fingerprint {
|
||||
internal val ClassDef.initializeEnergyConfigMethodMatch by ClassDefComposing.composingFirstMethod {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
opcodes(Opcode.RETURN_VOID)
|
||||
}
|
||||
|
||||
// Class name currently is not obfuscated but it may be in the future.
|
||||
internal val energyConfigToStringFingerprint = fingerprint {
|
||||
parameters()
|
||||
returns("Ljava/lang/String;")
|
||||
strings("EnergyConfig(", "maxEnergy=") // Partial string matches.
|
||||
custom { method, _ -> method.name == "toString" }
|
||||
// Class name currently is not obfuscated, but it may be in the future.
|
||||
internal val BytecodePatchContext.energyConfigToStringMethod by gettingFirstMethodDeclaratively {
|
||||
name("toString")
|
||||
parameterTypes()
|
||||
returnType("Ljava/lang/String;")
|
||||
instructions(
|
||||
predicates=unorderedAllOf(
|
||||
"EnergyConfig("(String::contains),
|
||||
"maxEnergy="(String::contains),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,32 @@
|
|||
package app.revanced.patches.duolingo.energy
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.findFieldFromToString
|
||||
|
||||
@Suppress("unused")
|
||||
val skipEnergyRechargeAdsPatch = bytecodePatch(
|
||||
name = "Skip energy recharge ads",
|
||||
description = "Skips watching ads to recharge energy."
|
||||
description = "Skips watching ads to recharge energy.",
|
||||
) {
|
||||
compatibleWith("com.duolingo")
|
||||
|
||||
execute {
|
||||
initializeEnergyConfigFingerprint
|
||||
.match(energyConfigToStringFingerprint.classDef)
|
||||
.method.apply {
|
||||
val energyField = energyConfigToStringFingerprint.method
|
||||
.findFieldFromToString("energy=")
|
||||
val insertIndex = initializeEnergyConfigFingerprint.patternMatch!!.startIndex
|
||||
apply {
|
||||
energyConfigToStringMethod.immutableClassDef.initializeEnergyConfigMethodMatch.let {
|
||||
it.method.apply {
|
||||
val energyField = energyConfigToStringMethod.findFieldFromToString("energy=")
|
||||
val insertIndex = it[0]
|
||||
|
||||
addInstructions(
|
||||
insertIndex,
|
||||
"""
|
||||
const/16 v0, 99
|
||||
iput v0, p0, $energyField
|
||||
"""
|
||||
const/16 v0, 99
|
||||
iput v0, p0, $energyField
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
package app.revanced.patches.facebook.ads.mainfeed
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val baseModelMapperFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.baseModelMapperMethod by gettingFirstImmutableMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Lcom/facebook/graphql/modelutil/BaseModelWithTree;")
|
||||
parameters("Ljava/lang/Class", "I", "I")
|
||||
returnType("Lcom/facebook/graphql/modelutil/BaseModelWithTree;")
|
||||
parameterTypes("Ljava/lang/Class", "I", "I")
|
||||
opcodes(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.INVOKE_STATIC,
|
||||
|
|
@ -16,11 +17,11 @@ internal val baseModelMapperFingerprint = fingerprint {
|
|||
Opcode.IF_EQ,
|
||||
)
|
||||
}
|
||||
|
||||
internal val getSponsoredDataModelTemplateFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getSponsoredDataModelTemplateMethod by gettingFirstImmutableMethodDeclaratively {
|
||||
definingClass("Lcom/facebook/graphql/model/GraphQLFBMultiAdsFeedUnit;")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("L")
|
||||
parameters()
|
||||
returnType("L")
|
||||
parameterTypes()
|
||||
opcodes(
|
||||
Opcode.CONST,
|
||||
Opcode.CONST,
|
||||
|
|
@ -28,14 +29,10 @@ internal val getSponsoredDataModelTemplateFingerprint = fingerprint {
|
|||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT,
|
||||
)
|
||||
custom { _, classDef ->
|
||||
classDef.type == "Lcom/facebook/graphql/model/GraphQLFBMultiAdsFeedUnit;"
|
||||
}
|
||||
}
|
||||
|
||||
internal val getStoryVisibilityFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.getStoryVisibilityMethodMatch by composingFirstMethod("This should not be called for base class object") {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("Ljava/lang/String;")
|
||||
returnType("Ljava/lang/String;")
|
||||
opcodes(
|
||||
Opcode.INSTANCE_OF,
|
||||
Opcode.IF_NEZ,
|
||||
|
|
@ -45,5 +42,4 @@ internal val getStoryVisibilityFingerprint = fingerprint {
|
|||
Opcode.IF_NEZ,
|
||||
Opcode.CONST,
|
||||
)
|
||||
strings("This should not be called for base class object")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package app.revanced.patches.facebook.ads.mainfeed
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod.Companion.toMutable
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction31i
|
||||
|
|
@ -11,14 +11,11 @@ import com.android.tools.smali.dexlib2.immutable.ImmutableMethod
|
|||
import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter
|
||||
|
||||
@Suppress("unused")
|
||||
val hideSponsoredStoriesPatch = bytecodePatch(
|
||||
name = "Hide 'Sponsored Stories'",
|
||||
) {
|
||||
val hideSponsoredStoriesPatch = bytecodePatch("Hide 'Sponsored Stories'") {
|
||||
compatibleWith("com.facebook.katana"("490.0.0.63.82"))
|
||||
|
||||
execute {
|
||||
val sponsoredDataModelTemplateMethod = getSponsoredDataModelTemplateFingerprint.originalMethod
|
||||
val baseModelMapperMethod = baseModelMapperFingerprint.originalMethod
|
||||
apply {
|
||||
val sponsoredDataModelTemplateMethod = getSponsoredDataModelTemplateMethod
|
||||
val baseModelWithTreeType = baseModelMapperMethod.returnType
|
||||
|
||||
val graphQlStoryClassDescriptor = "Lcom/facebook/graphql/model/GraphQLStory;"
|
||||
|
|
@ -28,7 +25,7 @@ val hideSponsoredStoriesPatch = bytecodePatch(
|
|||
// could change in future version, we need to extract them and call the base implementation directly.
|
||||
|
||||
val getSponsoredDataHelperMethod = ImmutableMethod(
|
||||
getStoryVisibilityFingerprint.originalClassDef.type,
|
||||
getStoryVisibilityMethodMatch.immutableClassDef.type,
|
||||
"getSponsoredData",
|
||||
listOf(ImmutableMethodParameter(graphQlStoryClassDescriptor, null, null)),
|
||||
baseModelWithTreeType,
|
||||
|
|
@ -62,12 +59,12 @@ val hideSponsoredStoriesPatch = bytecodePatch(
|
|||
)
|
||||
}
|
||||
|
||||
getStoryVisibilityFingerprint.classDef.methods.add(getSponsoredDataHelperMethod)
|
||||
getStoryVisibilityMethodMatch.classDef.methods.add(getSponsoredDataHelperMethod)
|
||||
|
||||
// Check if the parameter type is GraphQLStory and if sponsoredDataModelGetter returns a non-null value.
|
||||
// If so, hide the story by setting the visibility to StoryVisibility.GONE.
|
||||
getStoryVisibilityFingerprint.method.addInstructionsWithLabels(
|
||||
getStoryVisibilityFingerprint.patternMatch!!.startIndex,
|
||||
getStoryVisibilityMethodMatch.method.addInstructionsWithLabels(
|
||||
getStoryVisibilityMethodMatch[0],
|
||||
"""
|
||||
instance-of v0, p0, $graphQlStoryClassDescriptor
|
||||
if-eqz v0, :resume_normal
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
package app.revanced.patches.facebook.ads.story
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.iface.value.StringEncodedValue
|
||||
|
||||
internal val adsInsertionFingerprint = fieldFingerprint(
|
||||
fieldValue = "AdBucketDataSourceUtil\$attemptAdsInsertion\$1",
|
||||
internal val BytecodePatchContext.adsInsertionMethod by runMethod(
|
||||
fieldValue = $$"AdBucketDataSourceUtil$attemptAdsInsertion$1",
|
||||
)
|
||||
|
||||
internal val fetchMoreAdsFingerprint = fieldFingerprint(
|
||||
fieldValue = "AdBucketDataSourceUtil\$attemptFetchMoreAds\$1",
|
||||
internal val BytecodePatchContext.fetchMoreAdsMethod by runMethod(
|
||||
fieldValue = $$"AdBucketDataSourceUtil$attemptFetchMoreAds$1",
|
||||
)
|
||||
|
||||
internal fun fieldFingerprint(fieldValue: String) = fingerprint {
|
||||
returns("V")
|
||||
parameters()
|
||||
custom { method, classDef ->
|
||||
method.name == "run" &&
|
||||
classDef.fields.any any@{ field ->
|
||||
if (field.name != "__redex_internal_original_name") return@any false
|
||||
(field.initialValue as? StringEncodedValue)?.value == fieldValue
|
||||
}
|
||||
internal fun runMethod(fieldValue: String) = gettingFirstMethodDeclaratively {
|
||||
name("run")
|
||||
returnType("V")
|
||||
parameterTypes()
|
||||
custom {
|
||||
immutableClassDef.anyField {
|
||||
name == "__redex_internal_original_name" && (initialValue as? StringEncodedValue)?.value == fieldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
package app.revanced.patches.facebook.ads.story
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val hideStoryAdsPatch = bytecodePatch(
|
||||
|
|
@ -10,12 +11,7 @@ val hideStoryAdsPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.facebook.katana")
|
||||
|
||||
execute {
|
||||
setOf(
|
||||
fetchMoreAdsFingerprint,
|
||||
adsInsertionFingerprint,
|
||||
).forEach { fingerprint ->
|
||||
fingerprint.method.replaceInstruction(0, "return-void")
|
||||
}
|
||||
apply {
|
||||
setOf(fetchMoreAdsMethod, adsInsertionMethod).forEach(MutableMethod::returnEarly)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,18 @@
|
|||
package app.revanced.patches.finanzonline.detection.bootloader
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val bootloaderDetectionPatch = bytecodePatch(
|
||||
val removeBootloaderDetectionPatch = bytecodePatch(
|
||||
name = "Remove bootloader detection",
|
||||
description = "Removes the check for an unlocked bootloader.",
|
||||
) {
|
||||
compatibleWith("at.gv.bmf.bmf2go")
|
||||
|
||||
execute {
|
||||
setOf(createKeyFingerprint, bootStateFingerprint).forEach { fingerprint ->
|
||||
fingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
""",
|
||||
)
|
||||
apply {
|
||||
setOf(createKeyMethod, bootStateMethod).forEach { method ->
|
||||
method.returnEarly(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
package app.revanced.patches.finanzonline.detection.bootloader
|
||||
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
// Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.AttestationHelper#isBootStateOk (3.0.1)
|
||||
internal val bootStateFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.bootStateMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returns("Z")
|
||||
returnType("Z")
|
||||
opcodes(
|
||||
Opcode.INVOKE_DIRECT,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
|
|
@ -25,13 +29,18 @@ internal val bootStateFingerprint = fingerprint {
|
|||
Opcode.IF_NE,
|
||||
Opcode.GOTO,
|
||||
Opcode.MOVE,
|
||||
Opcode.RETURN
|
||||
Opcode.RETURN,
|
||||
)
|
||||
}
|
||||
|
||||
// Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.AttestationHelper#createKey (3.0.1)
|
||||
internal val createKeyFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.createKeyMethod by gettingFirstMethodDeclaratively(
|
||||
"attestation",
|
||||
"SHA-256",
|
||||
"random",
|
||||
"EC",
|
||||
"AndroidKeyStore",
|
||||
) {
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returns("Z")
|
||||
strings("attestation", "SHA-256", "random", "EC", "AndroidKeyStore")
|
||||
}
|
||||
returnType("Z")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
package app.revanced.patches.finanzonline.detection.root
|
||||
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
// Located @ at.gv.bmf.bmf2go.taxequalization.tools.utils.RootDetection#isRooted (3.0.1)
|
||||
internal val rootDetectionFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.rootDetectionMethod by gettingFirstMethodDeclaratively {
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||
returns("L")
|
||||
parameters("L")
|
||||
returnType("L")
|
||||
parameterTypes("L")
|
||||
opcodes(
|
||||
Opcode.NEW_INSTANCE,
|
||||
Opcode.INVOKE_DIRECT,
|
||||
|
|
|
|||
|
|
@ -1,19 +1,17 @@
|
|||
package app.revanced.patches.finanzonline.detection.root
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.shared.PATCH_DESCRIPTION_REMOVE_ROOT_DETECTION
|
||||
import app.revanced.patches.shared.PATCH_NAME_REMOVE_ROOT_DETECTION
|
||||
|
||||
@Suppress("unused")
|
||||
val rootDetectionPatch = bytecodePatch(
|
||||
name = PATCH_NAME_REMOVE_ROOT_DETECTION,
|
||||
description = PATCH_DESCRIPTION_REMOVE_ROOT_DETECTION,
|
||||
val removeRootDetectionPatch = bytecodePatch(
|
||||
name = "Remove root detection",
|
||||
description = "Removes the check for root permissions and unlocked bootloader.",
|
||||
) {
|
||||
compatibleWith("at.gv.bmf.bmf2go")
|
||||
|
||||
execute {
|
||||
rootDetectionFingerprint.method.addInstructions(
|
||||
apply {
|
||||
rootDetectionMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
package app.revanced.patches.fotmob.ads
|
||||
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.definingClass
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val shouldDisplayAdsMethod = fingerprint {
|
||||
internal val BytecodePatchContext.shouldDisplayAdsMethod by gettingFirstMethodDeclaratively {
|
||||
name("shouldDisplayAds")
|
||||
definingClass("AdsService;")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||
returns("Z")
|
||||
custom { method, classDef ->
|
||||
method.name == "shouldDisplayAds" && classDef.type.endsWith("AdsService;")
|
||||
}
|
||||
returnType("Z")
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ val hideAdsPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.mobilefootie.wc2010")
|
||||
|
||||
execute {
|
||||
shouldDisplayAdsMethod.method.returnEarly(false)
|
||||
apply {
|
||||
shouldDisplayAdsMethod.returnEarly(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package app.revanced.patches.googlenews.customtabs
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
|
|
@ -12,9 +12,9 @@ val enableCustomTabsPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.google.android.apps.magazines")
|
||||
|
||||
execute {
|
||||
launchCustomTabFingerprint.method.apply {
|
||||
val checkIndex = launchCustomTabFingerprint.patternMatch!!.endIndex + 1
|
||||
apply {
|
||||
launchCustomTabMethodMatch.method.apply {
|
||||
val checkIndex = launchCustomTabMethodMatch[-1] + 1
|
||||
val register = getInstruction<OneRegisterInstruction>(checkIndex).registerA
|
||||
|
||||
replaceInstruction(checkIndex, "const/4 v$register, 0x1")
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
package app.revanced.patches.googlenews.customtabs
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.accessFlags
|
||||
import app.revanced.patcher.composingFirstMethod
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
|
||||
internal val launchCustomTabFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.launchCustomTabMethodMatch by composingFirstMethod {
|
||||
definingClass("CustomTabsArticleLauncher;")
|
||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||
opcodes(
|
||||
Opcode.IPUT_OBJECT,
|
||||
|
|
@ -13,5 +18,4 @@ internal val launchCustomTabFingerprint = fingerprint {
|
|||
Opcode.CONST_4,
|
||||
Opcode.IPUT_BOOLEAN,
|
||||
)
|
||||
custom { _, classDef -> classDef.endsWith("CustomTabsArticleLauncher;") }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
package app.revanced.patches.googlenews.misc.extension.hooks
|
||||
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
|
|
@ -10,19 +16,20 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|||
private var getApplicationContextIndex = -1
|
||||
|
||||
internal val startActivityInitHook = extensionHook(
|
||||
insertIndexResolver = { method ->
|
||||
getApplicationContextIndex = method.indexOfFirstInstructionOrThrow {
|
||||
getInsertIndex = {
|
||||
getApplicationContextIndex = indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "getApplicationContext"
|
||||
}
|
||||
|
||||
getApplicationContextIndex + 2 // Below the move-result-object instruction.
|
||||
},
|
||||
contextRegisterResolver = { method ->
|
||||
val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1)
|
||||
as OneRegisterInstruction
|
||||
getContextRegister = {
|
||||
val moveResultInstruction = instructions.elementAt(getApplicationContextIndex + 1) as OneRegisterInstruction
|
||||
"v${moveResultInstruction.registerA}"
|
||||
},
|
||||
) {
|
||||
name("onCreate")
|
||||
definingClass("/StartActivity;")
|
||||
opcodes(
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT,
|
||||
|
|
@ -35,7 +42,4 @@ internal val startActivityInitHook = extensionHook(
|
|||
Opcode.INVOKE_VIRTUAL, // Calls startActivity.getApplicationContext().
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
)
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package app.revanced.patches.googlenews.misc.gms
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val magazinesActivityOnCreateFingerprint = fingerprint {
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/StartActivity;")
|
||||
}
|
||||
internal val BytecodePatchContext.magazinesActivityOnCreateMethod by gettingFirstMethodDeclaratively {
|
||||
name("onCreate")
|
||||
definingClass("/StartActivity;")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
package app.revanced.patches.googlenews.misc.gms
|
||||
|
||||
import app.revanced.patcher.extensions.methodReference
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.Option
|
||||
import app.revanced.patches.googlenews.misc.extension.extensionPatch
|
||||
import app.revanced.patches.googlenews.misc.gms.Constants.MAGAZINES_PACKAGE_NAME
|
||||
import app.revanced.patches.googlenews.misc.gms.Constants.REVANCED_MAGAZINES_PACKAGE_NAME
|
||||
import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
||||
import app.revanced.patches.shared.misc.gms.gmsCoreSupportResourcePatch
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
|
||||
@Suppress("unused")
|
||||
val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
fromPackageName = MAGAZINES_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_MAGAZINES_PACKAGE_NAME,
|
||||
mainActivityOnCreateFingerprintToInsertIndex = magazinesActivityOnCreateFingerprint to {
|
||||
getMainActivityOnCreateMethodToGetInsertIndex = BytecodePatchContext::magazinesActivityOnCreateMethod::get to {
|
||||
val getApplicationContextIndex =
|
||||
magazinesActivityOnCreateFingerprint.method.indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "getApplicationContext"
|
||||
magazinesActivityOnCreateMethod.indexOfFirstInstructionOrThrow {
|
||||
methodReference?.name == "getApplicationContext"
|
||||
}
|
||||
|
||||
getApplicationContextIndex + 2 // Below the move-result-object instruction.
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ import app.revanced.util.returnEarly
|
|||
val enableDCIMFoldersBackupControlPatch = bytecodePatch(
|
||||
name = "Enable DCIM folders backup control",
|
||||
description = "Disables always on backup for the Camera and other DCIM folders, allowing you to control backup " +
|
||||
"for each folder individually. This will make the app default to having no folders backed up.",
|
||||
"for each folder individually. This will make the app default to having no folders backed up.",
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.photos")
|
||||
|
||||
execute {
|
||||
isDCIMFolderBackupControlDisabled.method.returnEarly(false)
|
||||
apply {
|
||||
isDCIMFolderBackupControlMethod.returnEarly(false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
package app.revanced.patches.googlephotos.misc.backup
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val isDCIMFolderBackupControlDisabled = fingerprint {
|
||||
returns("Z")
|
||||
strings("/dcim", "/mars_files/")
|
||||
internal val BytecodePatchContext.isDCIMFolderBackupControlMethod by gettingFirstMethodDeclaratively("/dcim", "/mars_files/") {
|
||||
returnType("Z")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
package app.revanced.patches.googlephotos.misc.extension
|
||||
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.opcodes
|
||||
import app.revanced.patches.shared.misc.extension.extensionHook
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
|
|
@ -10,19 +16,20 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
|||
private var getApplicationContextIndex = -1
|
||||
|
||||
internal val homeActivityInitHook = extensionHook(
|
||||
insertIndexResolver = { method ->
|
||||
getApplicationContextIndex = method.indexOfFirstInstructionOrThrow {
|
||||
getInsertIndex = {
|
||||
getApplicationContextIndex = indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "getApplicationContext"
|
||||
}
|
||||
|
||||
getApplicationContextIndex + 2 // Below the move-result-object instruction.
|
||||
},
|
||||
contextRegisterResolver = { method ->
|
||||
val moveResultInstruction = method.implementation!!.instructions.elementAt(getApplicationContextIndex + 1)
|
||||
as OneRegisterInstruction
|
||||
getContextRegister = {
|
||||
val moveResultInstruction = instructions.elementAt(getApplicationContextIndex + 1) as OneRegisterInstruction
|
||||
"v${moveResultInstruction.registerA}"
|
||||
},
|
||||
) {
|
||||
name("onCreate")
|
||||
definingClass("/HomeActivity;")
|
||||
opcodes(
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.INVOKE_STATIC,
|
||||
|
|
@ -31,7 +38,4 @@ internal val homeActivityInitHook = extensionHook(
|
|||
Opcode.INVOKE_VIRTUAL, // Calls getApplicationContext().
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
)
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package app.revanced.patches.googlephotos.misc.features
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val initializeFeaturesEnumFingerprint = fingerprint {
|
||||
strings("com.google.android.apps.photos.NEXUS_PRELOAD")
|
||||
}
|
||||
internal val BytecodePatchContext.initializeFeaturesEnumMethod by gettingFirstMethodDeclaratively("com.google.android.apps.photos.NEXUS_PRELOAD")
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package app.revanced.patches.googlephotos.misc.features
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.instructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.instructions
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.patch.stringsOption
|
||||
import app.revanced.util.getReference
|
||||
|
|
@ -19,18 +19,16 @@ val spoofFeaturesPatch = bytecodePatch(
|
|||
dependsOn(spoofBuildInfoPatch)
|
||||
|
||||
val featuresToEnable by stringsOption(
|
||||
key = "featuresToEnable",
|
||||
default = listOf(
|
||||
"com.google.android.apps.photos.NEXUS_PRELOAD",
|
||||
"com.google.android.apps.photos.nexus_preload",
|
||||
),
|
||||
title = "Features to enable",
|
||||
name = "Features to enable",
|
||||
description = "Google Pixel exclusive features to enable. Features up to Pixel XL enable the unlimited storage feature.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
val featuresToDisable by stringsOption(
|
||||
key = "featuresToDisable",
|
||||
default = listOf(
|
||||
"com.google.android.apps.photos.PIXEL_2017_PRELOAD",
|
||||
"com.google.android.apps.photos.PIXEL_2018_PRELOAD",
|
||||
|
|
@ -49,20 +47,20 @@ val spoofFeaturesPatch = bytecodePatch(
|
|||
"com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE",
|
||||
"com.google.android.feature.PIXEL_2025_EXPERIENCE",
|
||||
),
|
||||
title = "Features to disable",
|
||||
name = "Features to disable",
|
||||
description = "Google Pixel exclusive features to disable." +
|
||||
"Features after Pixel XL may have to be disabled for unlimited storage depending on the device.",
|
||||
required = true,
|
||||
)
|
||||
|
||||
execute {
|
||||
apply {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val featuresToEnable = featuresToEnable!!.toSet()
|
||||
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val featuresToDisable = featuresToDisable!!.toSet()
|
||||
|
||||
initializeFeaturesEnumFingerprint.method.apply {
|
||||
initializeFeaturesEnumMethod.apply {
|
||||
instructions.filter { it.opcode == Opcode.CONST_STRING }.forEach {
|
||||
val feature = it.getReference<StringReference>()!!.string
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package app.revanced.patches.googlephotos.misc.gms
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val homeActivityOnCreateFingerprint = fingerprint {
|
||||
custom { methodDef, classDef ->
|
||||
methodDef.name == "onCreate" && classDef.endsWith("/HomeActivity;")
|
||||
}
|
||||
internal val BytecodePatchContext.homeActivityOnCreateMethod by gettingFirstMethodDeclaratively {
|
||||
name("onCreate")
|
||||
definingClass("/HomeActivity;")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package app.revanced.patches.googlephotos.misc.gms
|
||||
|
||||
import app.revanced.patcher.extensions.methodReference
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.patch.Option
|
||||
import app.revanced.patches.googlephotos.misc.extension.extensionPatch
|
||||
import app.revanced.patches.googlephotos.misc.gms.Constants.PHOTOS_PACKAGE_NAME
|
||||
|
|
@ -8,14 +10,16 @@ import app.revanced.patches.shared.misc.gms.gmsCoreSupportPatch
|
|||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
|
||||
@Suppress("unused")
|
||||
val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||
fromPackageName = PHOTOS_PACKAGE_NAME,
|
||||
toPackageName = REVANCED_PHOTOS_PACKAGE_NAME,
|
||||
mainActivityOnCreateFingerprintToInsertIndex = homeActivityOnCreateFingerprint to {
|
||||
val index = homeActivityOnCreateFingerprint.method.indexOfFirstInstructionOrThrow {
|
||||
getReference<MethodReference>()?.name == "getApplicationContext"
|
||||
getMainActivityOnCreateMethodToGetInsertIndex = BytecodePatchContext::homeActivityOnCreateMethod::get to {
|
||||
val index = homeActivityOnCreateMethod.indexOfFirstInstructionOrThrow {
|
||||
methodReference?.name == "getApplicationContext"
|
||||
}
|
||||
|
||||
// Below the move-result-object instruction,
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
package app.revanced.patches.googlephotos.misc.preferences
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
|
||||
internal val backupPreferencesFingerprint = fingerprint {
|
||||
returns("Lcom/google/android/apps/photos/backup/data/BackupPreferences;")
|
||||
strings("backup_prefs_had_backup_only_when_charging_enabled")
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package app.revanced.patches.googlephotos.misc.preferences
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import com.android.tools.smali.dexlib2.Opcode
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Deprecated("This patch no longer works and this code will soon be deleted")
|
||||
@Suppress("unused")
|
||||
val restoreHiddenBackUpWhileChargingTogglePatch = bytecodePatch(
|
||||
description = "Restores a hidden toggle to only run backups when the device is charging."
|
||||
) {
|
||||
compatibleWith("com.google.android.apps.photos"("7.11.0.705590205"))
|
||||
|
||||
execute {
|
||||
// Patches 'backup_prefs_had_backup_only_when_charging_enabled' to always be true.
|
||||
backupPreferencesFingerprint.let {
|
||||
it.method.apply {
|
||||
val index = indexOfFirstInstructionOrThrow(
|
||||
it.stringMatches!!.first().index,
|
||||
Opcode.MOVE_RESULT
|
||||
)
|
||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||
addInstruction(index + 1, "const/4 v$register, 0x1")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,10 @@
|
|||
package app.revanced.patches.googlerecorder.restrictions
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val onApplicationCreateFingerprint = fingerprint {
|
||||
strings("com.google.android.feature.PIXEL_2017_EXPERIENCE")
|
||||
custom { method, classDef ->
|
||||
if (method.name != "onCreate") return@custom false
|
||||
|
||||
classDef.endsWith("RecorderApplication;")
|
||||
}
|
||||
internal val BytecodePatchContext.onApplicationCreateMethodMatch by composingFirstMethod {
|
||||
name("onCreate")
|
||||
definingClass("RecorderApplication;")
|
||||
instructions("com.google.android.feature.PIXEL_2017_EXPERIENCE"())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package app.revanced.patches.googlerecorder.restrictions
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.removeInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
|
|
@ -13,10 +13,10 @@ val removeDeviceRestrictionsPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.google.android.apps.recorder")
|
||||
|
||||
execute {
|
||||
val featureStringIndex = onApplicationCreateFingerprint.stringMatches!!.first().index
|
||||
apply {
|
||||
val featureStringIndex = onApplicationCreateMethodMatch[0]
|
||||
|
||||
onApplicationCreateFingerprint.method.apply {
|
||||
onApplicationCreateMethodMatch.method.apply {
|
||||
// Remove check for device restrictions.
|
||||
removeInstructions(featureStringIndex - 2, 5)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,13 @@
|
|||
package app.revanced.patches.hexeditor.ad
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val disableAdsPatch = bytecodePatch(
|
||||
name = "Disable ads",
|
||||
) {
|
||||
val disableAdsPatch = bytecodePatch("Disable ads") {
|
||||
compatibleWith("com.myprog.hexedit")
|
||||
|
||||
execute {
|
||||
primaryAdsFingerprint.method.replaceInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
""",
|
||||
)
|
||||
apply {
|
||||
primaryAdsMethod.returnEarly(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package app.revanced.patches.hexeditor.ad
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val primaryAdsFingerprint = fingerprint {
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("PreferencesHelper;") && method.name == "isAdsDisabled"
|
||||
}
|
||||
internal val BytecodePatchContext.primaryAdsMethod by gettingFirstMethodDeclaratively {
|
||||
name("isAdsDisabled")
|
||||
definingClass("PreferencesHelper;")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package app.revanced.patches.iconpackstudio.misc.pro
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.definingClass
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val checkProFingerprint = fingerprint {
|
||||
returns("Z")
|
||||
custom { _, classDef -> classDef.endsWith("IPSPurchaseRepository;") }
|
||||
}
|
||||
internal val BytecodePatchContext.checkProMethod by gettingFirstMethodDeclaratively {
|
||||
definingClass("IPSPurchaseRepository;")
|
||||
returnType("Z")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,13 @@
|
|||
package app.revanced.patches.iconpackstudio.misc.pro
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val unlockProPatch = bytecodePatch(
|
||||
name = "Unlock pro",
|
||||
) {
|
||||
val unlockProPatch = bytecodePatch("Unlock pro") {
|
||||
compatibleWith("ginlemon.iconpackstudio"("2.2 build 016"))
|
||||
|
||||
execute {
|
||||
checkProFingerprint.method.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
""",
|
||||
)
|
||||
apply {
|
||||
checkProMethod.returnEarly(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,19 @@
|
|||
package app.revanced.patches.idaustria.detection.deviceintegrity
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val isDeviceBootloaderOpenFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.isDeviceBootloaderOpenMethod by gettingFirstMethodDeclaratively {
|
||||
name("isDeviceBootloaderOpen")
|
||||
definingClass("/DeviceIntegrityCheckProviderImpl;")
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returns("Ljava/lang/Object;")
|
||||
custom { method, classDef ->
|
||||
method.name == "isDeviceBootloaderOpen" &&
|
||||
classDef.endsWith("/DeviceIntegrityCheckProviderImpl;")
|
||||
}
|
||||
returnType("Ljava/lang/Object;")
|
||||
}
|
||||
|
||||
internal val isDeviceRootedFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.isDeviceRootedMethod by gettingFirstMethodDeclaratively {
|
||||
name("isDeviceRooted")
|
||||
definingClass("/DeviceIntegrityCheckProviderImpl;")
|
||||
accessFlags(AccessFlags.PUBLIC)
|
||||
returns("Z")
|
||||
custom { method, classDef ->
|
||||
method.name == "isDeviceRooted" &&
|
||||
classDef.endsWith("/DeviceIntegrityCheckProviderImpl;")
|
||||
}
|
||||
returnType("Z")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package app.revanced.patches.idaustria.detection.deviceintegrity
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
|
||||
@Suppress("unused")
|
||||
val removeDeviceIntegrityChecksPatch = bytecodePatch(
|
||||
name = "Remove device integrity checks",
|
||||
|
|
@ -12,19 +11,17 @@ val removeDeviceIntegrityChecksPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("at.gv.oe.app")
|
||||
|
||||
execute {
|
||||
isDeviceRootedFingerprint.method.returnEarly(false)
|
||||
apply {
|
||||
isDeviceRootedMethod.returnEarly(false)
|
||||
|
||||
isDeviceBootloaderOpenFingerprint.method.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
invoke-static { v0 }, Lkotlin/coroutines/jvm/internal/Boxing;->boxBoolean(Z)Ljava/lang/Boolean;
|
||||
move-result-object v0
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
}
|
||||
isDeviceBootloaderOpenMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x0
|
||||
invoke-static { v0 }, Lkotlin/coroutines/jvm/internal/Boxing;->boxBoolean(Z)Ljava/lang/Boolean;
|
||||
move-result-object v0
|
||||
return-object v0
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
package app.revanced.patches.idaustria.detection.root
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.idaustria.detection.deviceintegrity.removeDeviceIntegrityChecksPatch
|
||||
|
||||
@Deprecated("Patch was superseded", ReplaceWith("removeDeviceIntegrityChecksPatch"))
|
||||
@Suppress("unused")
|
||||
val rootDetectionPatch = bytecodePatch {
|
||||
dependsOn(removeDeviceIntegrityChecksPatch)
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
package app.revanced.patches.idaustria.detection.signature
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.*
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import com.android.tools.smali.dexlib2.AccessFlags
|
||||
|
||||
internal val spoofSignatureFingerprint = fingerprint {
|
||||
internal val BytecodePatchContext.spoofSignatureMethod by gettingFirstMethodDeclaratively {
|
||||
name("getPubKey")
|
||||
definingClass("/SL2Step1Task;")
|
||||
accessFlags(AccessFlags.PRIVATE)
|
||||
returns("L")
|
||||
parameters("L")
|
||||
custom { method, classDef ->
|
||||
classDef.endsWith("/SL2Step1Task;") && method.name == "getPubKey"
|
||||
}
|
||||
returnType("L")
|
||||
parameterTypes("L")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ val spoofSignaturePatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("at.gv.oe.app")
|
||||
|
||||
execute {
|
||||
apply {
|
||||
val expectedSignature =
|
||||
"OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" +
|
||||
"067c149768320026e10b24799a1339e414605e448e3f264444a327b9ae292be2b62ad567dd1800dbed4a88f718a33dc6db6b" +
|
||||
|
|
@ -24,6 +24,6 @@ val spoofSignaturePatch = bytecodePatch(
|
|||
"77ef1be61b2c01ebdabddcbf53cc4b6fd9a3c445606ee77b3758162c80ad8f8137b3c6864e92db904807dcb2be9d7717dd21" +
|
||||
"bf42c121d620ddfb7914f7a95c713d9e1c1b7bdb4a03d618e40cf7e9e235c0b5687e03b7ab3,publicExponent=10001}"
|
||||
|
||||
spoofSignatureFingerprint.method.returnEarly(expectedSignature)
|
||||
spoofSignatureMethod.returnEarly(expectedSignature)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
package app.revanced.patches.inshorts.ad
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val inshortsAdsFingerprint = fingerprint {
|
||||
returns("V")
|
||||
strings("GoogleAdLoader", "exception in requestAd")
|
||||
internal val BytecodePatchContext.inshortsAdsMethod by gettingFirstMethodDeclaratively(
|
||||
"GoogleAdLoader", "exception in requestAd"
|
||||
) {
|
||||
returnType("V")
|
||||
}
|
||||
|
|
@ -1,20 +1,13 @@
|
|||
package app.revanced.patches.inshorts.ad
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide ads",
|
||||
) {
|
||||
val hideAdsPatch = bytecodePatch("Hide ads") {
|
||||
compatibleWith("com.nis.app")
|
||||
|
||||
execute {
|
||||
inshortsAdsFingerprint.method.addInstruction(
|
||||
0,
|
||||
"""
|
||||
return-void
|
||||
""",
|
||||
)
|
||||
apply {
|
||||
inshortsAdsMethod.returnEarly()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
package app.revanced.patches.instagram.ads
|
||||
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.meta.ads.adInjectorFingerprint
|
||||
import app.revanced.patches.meta.ads.adInjectorMethod
|
||||
import app.revanced.util.returnEarly
|
||||
|
||||
@Suppress("unused")
|
||||
val hideAdsPatch = bytecodePatch(
|
||||
name = "Hide ads",
|
||||
) {
|
||||
val hideAdsPatch = bytecodePatch("Hide ads") {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
adInjectorFingerprint.method.returnEarly(false)
|
||||
apply {
|
||||
adInjectorMethod.returnEarly(false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,12 @@
|
|||
package app.revanced.patches.instagram.feed
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal val mainFeedRequestClassFingerprint = fingerprint {
|
||||
strings("Request{mReason=", ", mInstanceNumber=")
|
||||
}
|
||||
internal val BytecodePatchContext.mainFeedRequestClassMethod by gettingFirstMethodDeclaratively(
|
||||
"Request{mReason=", ", mInstanceNumber="
|
||||
)
|
||||
|
||||
context(BytecodePatchContext)
|
||||
internal val initMainFeedRequestFingerprint get() = fingerprint {
|
||||
custom { method, classDef ->
|
||||
method.name == "<init>" &&
|
||||
classDef == mainFeedRequestClassFingerprint.classDef
|
||||
}
|
||||
}
|
||||
|
||||
internal val mainFeedHeaderMapFinderFingerprint = fingerprint {
|
||||
strings("pagination_source", "FEED_REQUEST_SENT")
|
||||
}
|
||||
internal val BytecodePatchContext.mainFeedHeaderMapFinderMethod by gettingFirstMethodDeclaratively(
|
||||
"pagination_source", "FEED_REQUEST_SENT"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
package app.revanced.patches.instagram.feed
|
||||
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.classDef
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.fieldReference
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.firstMethodDeclaratively
|
||||
import app.revanced.patcher.immutableClassDef
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||
import app.revanced.util.getReference
|
||||
|
|
@ -12,16 +17,16 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
|
|||
internal const val EXTENSION_CLASS_DESCRIPTOR = "Lapp/revanced/extension/instagram/feed/LimitFeedToFollowedProfiles;"
|
||||
|
||||
@Suppress("unused")
|
||||
val limitFeedToFollowedProfiles = bytecodePatch(
|
||||
val limitFeedToFollowedProfilesPatch = bytecodePatch(
|
||||
name = "Limit feed to followed profiles",
|
||||
description = "Filters the home feed to display only content from profiles you follow.",
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
dependsOn(sharedExtensionPatch)
|
||||
|
||||
execute {
|
||||
apply {
|
||||
/**
|
||||
* Since the header field is obfuscated and there is no easy way to identify it among all the class fields,
|
||||
* an additional method is fingerprinted.
|
||||
|
|
@ -29,19 +34,19 @@ val limitFeedToFollowedProfiles = bytecodePatch(
|
|||
*/
|
||||
val mainFeedRequestHeaderFieldName: String
|
||||
|
||||
with(mainFeedHeaderMapFinderFingerprint.method) {
|
||||
mainFeedHeaderMapFinderMethod.apply {
|
||||
mainFeedRequestHeaderFieldName = indexOfFirstInstructionOrThrow {
|
||||
getReference<FieldReference>().let { ref ->
|
||||
ref?.type == "Ljava/util/Map;" &&
|
||||
ref.definingClass == mainFeedRequestClassFingerprint.classDef.toString()
|
||||
|
||||
}
|
||||
val reference = fieldReference
|
||||
reference?.type == "Ljava/util/Map;" &&
|
||||
reference.definingClass == mainFeedRequestClassMethod.classDef.type
|
||||
}.let { instructionIndex ->
|
||||
getInstruction(instructionIndex).getReference<FieldReference>()!!.name
|
||||
}
|
||||
}
|
||||
|
||||
initMainFeedRequestFingerprint.method.apply {
|
||||
mainFeedRequestClassMethod.immutableClassDef.firstMethodDeclaratively {
|
||||
name("<init>")
|
||||
}.apply {
|
||||
// Finds the instruction where the map is being initialized in the constructor
|
||||
val getHeaderIndex = indexOfFirstInstructionOrThrow {
|
||||
getReference<FieldReference>().let {
|
||||
|
|
@ -57,7 +62,7 @@ val limitFeedToFollowedProfiles = bytecodePatch(
|
|||
"""
|
||||
invoke-static { v$paramHeaderRegister }, $EXTENSION_CLASS_DESCRIPTOR->setFollowingHeader(Ljava/util/Map;)Ljava/util/Map;
|
||||
move-result-object v$paramHeaderRegister
|
||||
"""
|
||||
""",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ val anonymousStoryViewingPatch = bytecodePatch(
|
|||
Your view will not appear in the story viewers list.
|
||||
Note: Since no data is sent, a story you have already viewed may appear as new on another device.
|
||||
""".trimIndentMultiline(),
|
||||
use = false
|
||||
use = false,
|
||||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
apply {
|
||||
// Prevent the hashmap of the seen media to be filled
|
||||
setMediaSeenHashmapFingerprint.method.returnEarly()
|
||||
setMediaSeenHashmapMethod.returnEarly()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
package app.revanced.patches.instagram.ghost.story
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||
import app.revanced.patcher.parameterTypes
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
import app.revanced.patcher.returnType
|
||||
|
||||
internal val setMediaSeenHashmapFingerprint = fingerprint {
|
||||
parameters()
|
||||
returns("V")
|
||||
strings("media/seen/")
|
||||
internal val BytecodePatchContext.setMediaSeenHashmapMethod by gettingFirstMethodDeclaratively("media/seen/") {
|
||||
parameterTypes()
|
||||
returnType("V")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
|
||||
package app.revanced.patches.instagram.hide.explore
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.composingFirstMethod
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.name
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal const val EXPLORE_KEY_TO_BE_HIDDEN = "sectional_items"
|
||||
|
||||
internal val exploreResponseJsonParserFingerprint = fingerprint {
|
||||
strings(EXPLORE_KEY_TO_BE_HIDDEN, "ExploreTopicalFeedResponse")
|
||||
custom { method, _ -> method.name == "parseFromJson" }
|
||||
internal val BytecodePatchContext.exploreResponseJsonParserMethodMatch by composingFirstMethod("ExploreTopicalFeedResponse") {
|
||||
name("parseFromJson")
|
||||
instructions("sectional_items"())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package app.revanced.patches.instagram.hide.explore
|
||||
|
||||
import app.revanced.patcher.extensions.getInstruction
|
||||
import app.revanced.patcher.extensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patches.instagram.shared.replaceStringWithBogus
|
||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@Suppress("unused")
|
||||
val hideExploreFeedPatch = bytecodePatch(
|
||||
|
|
@ -11,7 +13,12 @@ val hideExploreFeedPatch = bytecodePatch(
|
|||
) {
|
||||
compatibleWith("com.instagram.android")
|
||||
|
||||
execute {
|
||||
exploreResponseJsonParserFingerprint.replaceStringWithBogus(EXPLORE_KEY_TO_BE_HIDDEN)
|
||||
apply {
|
||||
exploreResponseJsonParserMethodMatch.method.apply {
|
||||
val targetStringIndex = exploreResponseJsonParserMethodMatch[0]
|
||||
val targetStringRegister = getInstruction<OneRegisterInstruction>(targetStringIndex).registerA
|
||||
|
||||
replaceInstruction(targetStringIndex, "const-string v$targetStringRegister, \"BOGUS\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
package app.revanced.patches.instagram.hide.highlightsTray
|
||||
|
||||
import app.revanced.patcher.fingerprint
|
||||
import app.revanced.patcher.composingFirstMethod
|
||||
import app.revanced.patcher.instructions
|
||||
import app.revanced.patcher.invoke
|
||||
import app.revanced.patcher.patch.BytecodePatchContext
|
||||
|
||||
internal const val TARGET_STRING = "highlights_tray"
|
||||
|
||||
internal val highlightsUrlBuilderFingerprint = fingerprint {
|
||||
strings(TARGET_STRING,"X-IG-Accept-Hint")
|
||||
internal val BytecodePatchContext.highlightsUrlBuilderMethodMatch by composingFirstMethod("X-IG-Accept-Hint") {
|
||||
instructions(TARGET_STRING())
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue