feat: Patches for YouTube Music

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
oSumAtrIX
2022-04-26 23:10:36 +02:00
parent 62f1801e9c
commit b60c9d33b6
14 changed files with 383 additions and 24 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
package app.revanced.patches.youtube.ad
import app.revanced.extensions.injectHideCall
import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.toMethodWalker
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction11x
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.youtube",
listOf("17.03.38", "17.14.35")
)
)
private val patchMetadata = PatchMetadata(
"home-promo-ads",
"Home Promo Ads Patch",
"Patch to remove promoted ads in YouTube",
compatiblePackages,
"0.0.1"
)
private val signatureDescription = "Required signature for ${patchMetadata.name}. Discovered in version 17.03.38."
class HomePromoPatch : Patch(
patchMetadata,
listOf(
MethodSignature(
MethodSignatureMetadata(
"promoted-discovery-app-parent-method",
MethodMetadata(
"Ljjl;",
"lG",
),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
signatureDescription,
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC,
listOf("L", "L"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.IGET_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.NEW_ARRAY,
Opcode.IPUT_OBJECT,
Opcode.CONST_4,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_GE,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.APUT_OBJECT,
Opcode.ADD_INT_LIT8,
Opcode.GOTO
)
),
MethodSignature(
MethodSignatureMetadata(
"promoted-discovery-action-parent-method",
MethodMetadata(
"Ljjc;",
"lG",
),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
signatureDescription,
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC,
listOf("L", "L"),
listOf(
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL_RANGE,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_BOOLEAN,
Opcode.CONST_4,
Opcode.XOR_INT_2ADDR,
Opcode.IGET_BOOLEAN,
Opcode.INVOKE_DIRECT,
Opcode.IGET_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.CONST_4,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT
)
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
for (signature in signatures) {
val result = signature.result!!
val methodMetadata = MethodMetadata(signature.metadata.methodMetadata!!.definingClass, "d")
val requiredMethod = result.findParentMethod(
MethodSignature(
MethodSignatureMetadata(
"promoted-discovery-action-parent-method",
methodMetadata,
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
signatureDescription,
"0.0.1"
),
"V",
AccessFlags.PRIVATE or AccessFlags.FINAL,
listOf("Z", "Z"),
null
)
)
?: return PatchResultError("Required parent method ${methodMetadata.name} could not be found in ${methodMetadata.definingClass}")
val toBePatchedInvokeOffset =
requiredMethod.immutableMethod.implementation!!.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_DIRECT }
val toBePatchedMethod = patcherData
.toMethodWalker(requiredMethod.immutableMethod)
.walk(toBePatchedInvokeOffset, true)
.getMethod() as MutableMethod
val implementation = toBePatchedMethod.implementation!!
val invokeVirtualOffset = implementation.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_VIRTUAL }
val moveResultInstruction = implementation.instructions[invokeVirtualOffset + 1]
if (moveResultInstruction.opcode != Opcode.MOVE_RESULT_OBJECT)
return PatchResultError("The toBePatchedInvokeOffset offset was wrong in ${metadata.name}")
val register = (moveResultInstruction as Instruction11x).registerA
implementation.injectHideCall(invokeVirtualOffset + 2, register)
}
return PatchResultSuccess()
}
}

View File

@ -0,0 +1,108 @@
package app.revanced.patches.youtube.ad
import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val packageMetadata = listOf(
PackageMetadata(
"com.google.android.youtube",
listOf("17.14.35")
)
)
private val patchMetadata = PatchMetadata(
"video-ads",
"YouTube Video Ads Patch",
"Patch to remove ads in the YouTube video player.",
packageMetadata,
"0.0.1"
)
class VideoAdsPatch : Patch(
patchMetadata,
listOf(
MethodSignature(
MethodSignatureMetadata(
"show-video-ads-constructor",
MethodMetadata(
"zai",
"<init>",
),
PatternScanMethod.Fuzzy(2),// FIXME: Test this threshold and find the best value.
packageMetadata,
"Required signature for ${patchMetadata.name}. Discovered in version 17.14.35.",
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "L", "L"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
null, // either CONST_4 or CONST_16
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.CONST_4,
Opcode.IPUT_BOOLEAN,
Opcode.RETURN_VOID
)
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
var result = signatures.first().result!!
val responsibleMethodSignature = MethodSignature(
MethodSignatureMetadata(
"show-video-ads-method",
MethodMetadata(
"zai",
null // unknown
),
PatternScanMethod.Direct(),
packageMetadata,
"Signature to find the method, which is responsible for showing the video ads. Discovered in version 17.14.35",
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("Z"),
null
)
result = result.findParentMethod(
responsibleMethodSignature
) ?: return PatchResultError(
"Could not find parent method with signature ${responsibleMethodSignature.metadata.name}"
)
// Override the parameter by calling shouldShowAds and setting the parameter to the result
result.method.implementation!!.addInstructions(
0,
"""
invoke-static { }, Lfi/vanced/libraries/youtube/whitelisting/Whitelist;->shouldShowAds()Z
move-result v1
""".trimIndent().toInstructions()
)
return PatchResultSuccess()
}
}