feat: migrate to dalvik patches

This commit is contained in:
oSumAtrIX 2022-04-07 22:41:55 +02:00
parent dc4ec57441
commit e088c67108
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
8 changed files with 175 additions and 150 deletions

View File

@ -24,12 +24,8 @@ repositories {
dependencies { dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10") implementation("org.jetbrains.kotlin:kotlin-stdlib:1.6.10")
implementation("org.ow2.asm:asm:9.2")
implementation("org.ow2.asm:asm-util:9.2")
implementation("org.ow2.asm:asm-tree:9.2")
implementation("org.ow2.asm:asm-commons:9.2")
implementation("app.revanced:revanced-patcher:1.+") // use latest version. implementation("app.revanced:revanced-patcher:1.+") // use latest version.
implementation("org.smali:dexlib2:2.5.2")
} }
java { java {

View File

@ -1,36 +1,35 @@
package app.revanced.patches.ad package app.revanced.patches.ad
import app.revanced.patcher.cache.Cache import app.revanced.patcher.cache.Cache
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.signature.Signature import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.writer.ASMWriter.insertAt import app.revanced.patcher.smali.asInstructions
import org.objectweb.asm.Opcodes import org.jf.dexlib2.AccessFlags
import org.objectweb.asm.Type
import org.objectweb.asm.tree.MethodInsnNode
class VideoAds : Patch("VideoAds") { class VideoAds : Patch("VideoAds") {
override fun execute(cache: Cache): PatchResult { override fun execute(cache: Cache): PatchResult {
val showVideoAdsMethodData = cache.methods["show-video-ads"].findParentMethod( val map = cache.methodMap["show-video-ads-constructor"].findParentMethod(
Signature( MethodSignature(
"method", "show-video-ads-method",
Type.VOID_TYPE, "V",
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL, AccessFlags.PUBLIC or AccessFlags.FINAL,
arrayOf(Type.BOOLEAN_TYPE), setOf("Z"),
null null
) )
) ?: return PatchResultError("Could not find required method to patch") ) ?: return PatchResultError("Could not find required method to patch")
showVideoAdsMethodData.method.instructions.insertAt( // Override the parameter by calling shouldShowAds and setting the parameter to the result
map.resolveAndGetMethod().implementation!!.addInstructions(
0, 0,
MethodInsnNode( """
Opcodes.INVOKESTATIC, invoke-static { }, Lfi/vanced/libraries/youtube/whitelisting/Whitelist;->shouldShowAds()Z
"fi/vanced/libraries/youtube/whitelisting/Whitelist", move-result v0
"shouldShowAds", """.trimIndent().asInstructions()
Type.getMethodDescriptor(Type.BOOLEAN_TYPE)
)
) )
return PatchResultSuccess() return PatchResultSuccess()

View File

@ -1,49 +1,95 @@
package app.revanced.patches.interaction package app.revanced.patches.interaction
import app.revanced.patcher.cache.Cache import app.revanced.patcher.cache.Cache
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.writer.ASMWriter.insertAt import app.revanced.patcher.smali.asInstructions
import org.objectweb.asm.Opcodes import org.jf.dexlib2.Opcode
import org.objectweb.asm.tree.* import org.jf.dexlib2.builder.instruction.BuilderInstruction11n
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.builder.instruction.BuilderInstruction35c
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.immutable.reference.ImmutableMethodReference
class EnableSeekbarTapping : Patch("enable-seekbar-tapping") { class EnableSeekbarTapping : Patch("enable-seekbar-tapping") {
override fun execute(cache: Cache): PatchResult { override fun execute(cache: Cache): PatchResult {
val patchData = cache.methods["enable-seekbar-tapping"] val map = cache.methodMap["tap-seekbar-parent-method"]
val methodOPatchData = cache.methods["enable-seekbar-tapping-method-o"]
val methodPPatchData = cache.methods["enable-seekbar-tapping-method-p"]
val elseLabel = LabelNode() val tapSeekMethods = mutableMapOf<String, Method>()
patchData.method.instructions.insertAt(
patchData.scanData.endIndex, // find the methods which tap the seekbar
InsnNode(Opcodes.ACONST_NULL), map.definingClassProxy.immutableClass.methods.forEach {
MethodInsnNode( val instructions = it.implementation!!.instructions
Opcodes.INVOKESTATIC, // here we make sure we actually find the method because it has more then 7 instructions
"fi/razerman/youtube/preferences/BooleanPreferences", if (instructions.count() < 7) return@forEach
"isTapSeekingEnabled",
"()Z" // we know that the 7th instruction has the opcode CONST_4
val instruction = instructions.elementAt(6)
if (instruction.opcode != Opcode.CONST_4) return@forEach
// the literal for this instruction has to be either 1 or 2
val literal = (instruction as BuilderInstruction11n).narrowLiteral
// method founds
if (literal == 1) tapSeekMethods["P"] = it
if (literal == 2) tapSeekMethods["O"] = it
}
val implementation = cache.methodMap["enable-seekbar-tapping"].resolveAndGetMethod().implementation!!
// if tap-seeking is enabled, do not invoke the two methods below
val pMethod = tapSeekMethods["P"]!!
val oMethod = tapSeekMethods["O"]!!
implementation.addInstructions(
map.scanData.endIndex,
listOf(
BuilderInstruction35c(
Opcode.INVOKE_VIRTUAL,
0,
3,
0,
0,
0,
0,
ImmutableMethodReference(
oMethod.definingClass,
oMethod.name,
setOf("I"),
"V"
)
), ),
JumpInsnNode(Opcodes.IFEQ, elseLabel), BuilderInstruction35c(
VarInsnNode(Opcodes.ALOAD, 0), Opcode.INVOKE_VIRTUAL,
VarInsnNode(Opcodes.ILOAD, 6), 0,
MethodInsnNode( 3,
Opcodes.INVOKEVIRTUAL, 0,
methodOPatchData.declaringClass.name, 0,
methodOPatchData.method.name, 0,
"(I)V" 0,
), ImmutableMethodReference(
VarInsnNode(Opcodes.ALOAD, 0), pMethod.definingClass,
VarInsnNode(Opcodes.ILOAD, 6), pMethod.name,
MethodInsnNode( setOf("I"),
Opcodes.INVOKEVIRTUAL, "V"
methodPPatchData.declaringClass.name, )
methodPPatchData.method.name, )
"(I)V" )
),
elseLabel
) )
// if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
val elseLabel = implementation.instructions[7].location.labels.first()
implementation.addInstruction(
map.scanData.endIndex,
BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
)
implementation.addInstructions(
map.scanData.endIndex,
"""
invoke-static { }, Lfi/razerman/youtube/preferences/BooleanPreferences;->isTapSeekingEnabled()Z
move-result v0
""".trimIndent().asInstructions()
)
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@ -4,27 +4,16 @@ import app.revanced.patcher.cache.Cache
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.writer.ASMWriter.insertAt import app.revanced.patcher.smali.asInstruction
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.VarInsnNode
class CreateButtonRemover : Patch("create-button-remover") { class CreateButtonRemover : Patch("create-button-remover") {
override fun execute(cache: Cache): PatchResult { override fun execute(cache: Cache): PatchResult {
val patchData = cache.methods["create-button-patch"] val map = cache.methodMap["create-button-patch"]
patchData.method.instructions.insertAt( // Hide the button view via proxy by passing it to the hideCreateButton method
patchData.scanData.endIndex - 1, map.resolveAndGetMethod().implementation!!.addInstruction(
VarInsnNode( map.scanData.endIndex,
Opcodes.ALOAD, "invoke-static { v6 }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".asInstruction()
6
),
MethodInsnNode(
Opcodes.INVOKESTATIC,
"fi/razerman/youtube/XAdRemover",
"hideCreateButton",
"(Landroid/view/View;)V"
)
) )
return PatchResultSuccess() return PatchResultSuccess()

View File

@ -4,24 +4,17 @@ import app.revanced.patcher.cache.Cache
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.writer.ASMWriter.insertAt import app.revanced.patcher.smali.asInstruction
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.VarInsnNode
class HideReels : Patch("hide-reels") { class HideReels : Patch("hide-reels") {
override fun execute(cache: Cache): PatchResult { override fun execute(cache: Cache): PatchResult {
val patchData = cache.methods["hide-reel-patch"] val implementation = cache.methodMap["hide-reel-patch"].resolveAndGetMethod().implementation!!
patchData.method.instructions.insertAt( // HideReel will hide the reel view before it is being used,
patchData.scanData.endIndex + 1, // so we pass the view to the HideReel method
VarInsnNode(Opcodes.ALOAD, 18), implementation.addInstruction(
MethodInsnNode( 22,
Opcodes.INVOKESTATIC, "invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->HideReel(Landroid/view/View;)V".asInstruction()
"fi/razerman/youtube/XAdRemover",
"HideReels",
"(Landroid/view/View;)V"
)
) )
return PatchResultSuccess() return PatchResultSuccess()

View File

@ -1,52 +1,47 @@
package app.revanced.patches.layout package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache import app.revanced.patcher.cache.Cache
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.signature.Signature import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.writer.ASMWriter.insertAt import app.revanced.patcher.smali.asInstructions
import org.objectweb.asm.Opcodes import org.jf.dexlib2.AccessFlags
import org.objectweb.asm.Type import org.jf.dexlib2.Opcode
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.VarInsnNode
class HideSuggestions : Patch("hide-suggestions") { class HideSuggestions : Patch("hide-suggestions") {
override fun execute(cache: Cache): PatchResult { override fun execute(cache: Cache): PatchResult {
val method = cache.methods["hide-suggestions-patch"].findParentMethod( val map = cache.methodMap["hide-suggestions-patch"].findParentMethod(
Signature( MethodSignature(
"hide-suggestions-method", "hide-suggestions-method",
Type.VOID_TYPE, "V",
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL, AccessFlags.PUBLIC or AccessFlags.PUBLIC,
arrayOf(Type.BOOLEAN_TYPE), setOf("Z"),
arrayOf( arrayOf(
Opcodes.ALOAD, Opcode.IPUT_BOOLEAN,
Opcodes.ILOAD, Opcode.IGET_OBJECT,
Opcodes.PUTFIELD, Opcode.IPUT_BOOLEAN,
Opcodes.ALOAD, Opcode.INVOKE_VIRTUAL,
Opcodes.GETFIELD Opcode.RETURN_VOID
) )
) )
) ?: return PatchResultError("Parent method hide-suggestions-method has not been found") ) ?: return PatchResultError("Parent method hide-suggestions-method has not been found")
method.method.instructions.insertAt( // Proxy the first parameter by passing it to the RemoveSuggestions method
map.resolveAndGetMethod().implementation!!.addInstructions(
0, 0,
VarInsnNode(Opcodes.ILOAD, 1), """
MethodInsnNode( invoke-static { p1 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
Opcodes.INVOKESTATIC, move-result-object v0
"java/lang/Boolean", invoke-static { v0 }, Lfi/razerman/youtube/XAdRemover;->RemoveSuggestions(Ljava/lang/Boolean;)Ljava/lang/Boolean;
"valueOf", move-result-object v0
"(Z)Ljava/lang/Boolean" invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z
), move-result v0
MethodInsnNode( """.trimIndent().asInstructions()
Opcodes.INVOKESTATIC,
"fi/razerman/youtube/XAdRemover",
"HideReels",
"(Landroid/view/View;)V"
) )
)
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@ -4,10 +4,20 @@ import app.revanced.patcher.cache.Cache
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction10x
class MinimizedPlayback : Patch("minimized-playback") { class MinimizedPlayback : Patch("minimized-playback") {
override fun execute(cache: Cache): PatchResult { override fun execute(cache: Cache): PatchResult {
cache.methods["minimized-playback-manager"].method.instructions.clear() // Instead of removing all instructions like Vanced,
// we return the method at the beginning instead
cache.methodMap["minimized-playback-manager"]
.resolveAndGetMethod()
.implementation!!
.addInstruction(
0,
BuilderInstruction10x(Opcode.RETURN_VOID)
)
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@ -1,50 +1,47 @@
package app.revanced.patches.layout package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache import app.revanced.patcher.cache.Cache
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.signature.Signature import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.util.ExtraTypes import app.revanced.patcher.smali.asInstruction
import app.revanced.patcher.writer.ASMWriter.insertAt import org.jf.dexlib2.AccessFlags
import org.objectweb.asm.Opcodes import org.jf.dexlib2.Opcode
import org.objectweb.asm.tree.JumpInsnNode import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.VarInsnNode
class OldQualityLayout : Patch("old-quality-restore") { class OldQualityLayout : Patch("old-quality-restore") {
override fun execute(cache: Cache): PatchResult { override fun execute(cache: Cache): PatchResult {
val method = cache.methods["old-quality-patch"].findParentMethod( val map = cache.methodMap["old-quality-patch"].findParentMethod(
Signature( MethodSignature(
"old-quality-patch-method", "old-quality-patch-method",
ExtraTypes.Any, "L",
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL, AccessFlags.FINAL or AccessFlags.PUBLIC,
arrayOf(), emptySet(),
arrayOf( arrayOf(
Opcodes.ALOAD, Opcode.IF_NEZ,
Opcodes.GETFIELD, Opcode.IGET,
Opcodes.ISTORE, Opcode.CONST_4,
Opcodes.ICONST_3, Opcode.IF_NE
Opcodes.ISTORE
) )
) )
) ?: return PatchResultError("Parent method old-quality-patch-method has not been found") ) ?: return PatchResultError("Parent method old-quality-patch-method has not been found")
method.method.instructions.insertAt(
val implementation = map.resolveAndGetMethod().implementation!!
// if useOldStyleQualitySettings == true, jump over all instructions and return the field at the end
val jmpInstruction =
BuilderInstruction21t(Opcode.IF_NEZ, 0, implementation.instructions[5].location.labels.first())
implementation.addInstruction(0, jmpInstruction)
implementation.addInstruction(
0, 0,
MethodInsnNode( """
Opcodes.INVOKESTATIC, invoke-static { }, Lfi/razerman/youtube/XGlobals;->useOldStyleQualitySettings()Z
"fi/razerman/youtube/XGlobals", move-result v0
"useOldStyleQualitySettings", """.trimIndent().asInstruction()
"()Z"
),
VarInsnNode(Opcodes.ISTORE, 1),
VarInsnNode(Opcodes.ILOAD, 1),
JumpInsnNode(
Opcodes.IFNE,
(method.method.instructions[method.scanData.endIndex + 3] as JumpInsnNode).label
),
) )
return PatchResultSuccess() return PatchResultSuccess()