diff --git a/patches/api/patches.api b/patches/api/patches.api index be23caa1c9..0c4935b4a6 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -160,6 +160,10 @@ public final class app/revanced/patches/cieid/restrictions/root/BypassRootChecks public static final fun getBypassRootChecksPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/crunchyroll/ads/HideAdsPatchKt { + public static final fun getHideAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/duolingo/ad/DisableAdsPatchKt { public static final fun getDisableAdsPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt new file mode 100644 index 0000000000..0266e0344d --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/Fingerprints.kt @@ -0,0 +1,7 @@ +package app.revanced.patches.crunchyroll.ads + +import app.revanced.patcher.fingerprint + +internal val videoUrlReadyToStringFingerprint = fingerprint { + strings("VideoUrlReady(url=", ", enableAds=") +} diff --git a/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/HideAdsPatch.kt b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/HideAdsPatch.kt new file mode 100644 index 0000000000..5344175bcb --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/crunchyroll/ads/HideAdsPatch.kt @@ -0,0 +1,46 @@ +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.patch.bytecodePatch +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstruction +import app.revanced.util.removeFlags +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode +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" +) { + compatibleWith("com.crunchyroll.crunchyroid") + + execute { + // 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(fieldIndex).getReference()!! + } + + // Remove final access flag on field. + videoUrlReadyToStringFingerprint.classDef.fields + .first { it.name == enableAdsField.name } + .removeFlags(AccessFlags.FINAL) + + // Override enableAds field in non-default constructor. + val constructor = videoUrlReadyToStringFingerprint.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 + """) + } +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index 047f21cc43..017a998626 100644 --- a/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/patches/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -10,6 +10,7 @@ import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction import app.revanced.patcher.patch.BytecodePatchContext import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableClass +import app.revanced.patcher.util.proxy.mutableTypes.MutableField import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.smali.ExternalLabel @@ -1021,6 +1022,14 @@ private fun MutableMethod.overrideReturnValue(value: String, returnLate: Boolean } } +/** + * Remove the given AccessFlags from the field. + */ +internal fun MutableField.removeFlags(vararg flags: AccessFlags) { + val bitField = flags.map { it.value }.reduce { acc, flag -> acc and flag } + this.accessFlags = this.accessFlags and bitField.inv() +} + internal fun BytecodePatchContext.addStaticFieldToExtension( className: String, methodName: String,