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 {
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("org.smali:dexlib2:2.5.2")
}
java {

View File

@ -1,36 +1,35 @@
package app.revanced.patches.ad
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.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.signature.Signature
import app.revanced.patcher.writer.ASMWriter.insertAt
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
import org.objectweb.asm.tree.MethodInsnNode
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.smali.asInstructions
import org.jf.dexlib2.AccessFlags
class VideoAds : Patch("VideoAds") {
override fun execute(cache: Cache): PatchResult {
val showVideoAdsMethodData = cache.methods["show-video-ads"].findParentMethod(
Signature(
"method",
Type.VOID_TYPE,
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
arrayOf(Type.BOOLEAN_TYPE),
val map = cache.methodMap["show-video-ads-constructor"].findParentMethod(
MethodSignature(
"show-video-ads-method",
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
setOf("Z"),
null
)
) ?: 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,
MethodInsnNode(
Opcodes.INVOKESTATIC,
"fi/vanced/libraries/youtube/whitelisting/Whitelist",
"shouldShowAds",
Type.getMethodDescriptor(Type.BOOLEAN_TYPE)
)
"""
invoke-static { }, Lfi/vanced/libraries/youtube/whitelisting/Whitelist;->shouldShowAds()Z
move-result v0
""".trimIndent().asInstructions()
)
return PatchResultSuccess()

View File

@ -1,49 +1,95 @@
package app.revanced.patches.interaction
import app.revanced.patcher.cache.Cache
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.writer.ASMWriter.insertAt
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.*
import app.revanced.patcher.smali.asInstructions
import org.jf.dexlib2.Opcode
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") {
override fun execute(cache: Cache): PatchResult {
val patchData = cache.methods["enable-seekbar-tapping"]
val methodOPatchData = cache.methods["enable-seekbar-tapping-method-o"]
val methodPPatchData = cache.methods["enable-seekbar-tapping-method-p"]
val map = cache.methodMap["tap-seekbar-parent-method"]
val elseLabel = LabelNode()
patchData.method.instructions.insertAt(
patchData.scanData.endIndex,
InsnNode(Opcodes.ACONST_NULL),
MethodInsnNode(
Opcodes.INVOKESTATIC,
"fi/razerman/youtube/preferences/BooleanPreferences",
"isTapSeekingEnabled",
"()Z"
),
JumpInsnNode(Opcodes.IFEQ, elseLabel),
VarInsnNode(Opcodes.ALOAD, 0),
VarInsnNode(Opcodes.ILOAD, 6),
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
methodOPatchData.declaringClass.name,
methodOPatchData.method.name,
"(I)V"
),
VarInsnNode(Opcodes.ALOAD, 0),
VarInsnNode(Opcodes.ILOAD, 6),
MethodInsnNode(
Opcodes.INVOKEVIRTUAL,
methodPPatchData.declaringClass.name,
methodPPatchData.method.name,
"(I)V"
),
elseLabel
val tapSeekMethods = mutableMapOf<String, Method>()
// find the methods which tap the seekbar
map.definingClassProxy.immutableClass.methods.forEach {
val instructions = it.implementation!!.instructions
// here we make sure we actually find the method because it has more then 7 instructions
if (instructions.count() < 7) return@forEach
// 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"
)
),
BuilderInstruction35c(
Opcode.INVOKE_VIRTUAL,
0,
3,
0,
0,
0,
0,
ImmutableMethodReference(
pMethod.definingClass,
pMethod.name,
setOf("I"),
"V"
)
)
)
)
// 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()
}
}

View File

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

View File

@ -1,52 +1,47 @@
package app.revanced.patches.layout
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.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.signature.Signature
import app.revanced.patcher.writer.ASMWriter.insertAt
import org.objectweb.asm.Opcodes
import org.objectweb.asm.Type
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.VarInsnNode
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.smali.asInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
class HideSuggestions : Patch("hide-suggestions") {
override fun execute(cache: Cache): PatchResult {
val method = cache.methods["hide-suggestions-patch"].findParentMethod(
Signature(
val map = cache.methodMap["hide-suggestions-patch"].findParentMethod(
MethodSignature(
"hide-suggestions-method",
Type.VOID_TYPE,
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
arrayOf(Type.BOOLEAN_TYPE),
"V",
AccessFlags.PUBLIC or AccessFlags.PUBLIC,
setOf("Z"),
arrayOf(
Opcodes.ALOAD,
Opcodes.ILOAD,
Opcodes.PUTFIELD,
Opcodes.ALOAD,
Opcodes.GETFIELD
Opcode.IPUT_BOOLEAN,
Opcode.IGET_OBJECT,
Opcode.IPUT_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_VOID
)
)
) ?: 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,
VarInsnNode(Opcodes.ILOAD, 1),
MethodInsnNode(
Opcodes.INVOKESTATIC,
"java/lang/Boolean",
"valueOf",
"(Z)Ljava/lang/Boolean"
),
MethodInsnNode(
Opcodes.INVOKESTATIC,
"fi/razerman/youtube/XAdRemover",
"HideReels",
"(Landroid/view/View;)V"
)
"""
invoke-static { p1 }, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
move-result-object v0
invoke-static { v0 }, Lfi/razerman/youtube/XAdRemover;->RemoveSuggestions(Ljava/lang/Boolean;)Ljava/lang/Boolean;
move-result-object v0
invoke-virtual { v0 }, Ljava/lang/Boolean;->booleanValue()Z
move-result v0
""".trimIndent().asInstructions()
)
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.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction10x
class MinimizedPlayback : Patch("minimized-playback") {
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()
}
}

View File

@ -1,50 +1,47 @@
package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.signature.Signature
import app.revanced.patcher.util.ExtraTypes
import app.revanced.patcher.writer.ASMWriter.insertAt
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.JumpInsnNode
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.VarInsnNode
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.smali.asInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
class OldQualityLayout : Patch("old-quality-restore") {
override fun execute(cache: Cache): PatchResult {
val method = cache.methods["old-quality-patch"].findParentMethod(
Signature(
val map = cache.methodMap["old-quality-patch"].findParentMethod(
MethodSignature(
"old-quality-patch-method",
ExtraTypes.Any,
Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL,
arrayOf(),
"L",
AccessFlags.FINAL or AccessFlags.PUBLIC,
emptySet(),
arrayOf(
Opcodes.ALOAD,
Opcodes.GETFIELD,
Opcodes.ISTORE,
Opcodes.ICONST_3,
Opcodes.ISTORE
Opcode.IF_NEZ,
Opcode.IGET,
Opcode.CONST_4,
Opcode.IF_NE
)
)
) ?: 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,
MethodInsnNode(
Opcodes.INVOKESTATIC,
"fi/razerman/youtube/XGlobals",
"useOldStyleQualitySettings",
"()Z"
),
VarInsnNode(Opcodes.ISTORE, 1),
VarInsnNode(Opcodes.ILOAD, 1),
JumpInsnNode(
Opcodes.IFNE,
(method.method.instructions[method.scanData.endIndex + 3] as JumpInsnNode).label
),
"""
invoke-static { }, Lfi/razerman/youtube/XGlobals;->useOldStyleQualitySettings()Z
move-result v0
""".trimIndent().asInstruction()
)
return PatchResultSuccess()