made by AI
This commit is contained in:
parent
bae293e3dd
commit
7302d29383
30 changed files with 256 additions and 302 deletions
|
|
@ -1,8 +1,9 @@
|
||||||
package app.revanced.patches.instagram.feed
|
package app.revanced.patches.instagram.feed
|
||||||
|
|
||||||
import app.revanced.patcher.classDef
|
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
|
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||||
|
import app.revanced.patcher.name
|
||||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
|
|
@ -33,20 +34,16 @@ val `Limit feed to followed profiles` by creatingBytecodePatch(
|
||||||
mainFeedRequestHeaderFieldName = indexOfFirstInstructionOrThrow {
|
mainFeedRequestHeaderFieldName = indexOfFirstInstructionOrThrow {
|
||||||
getReference<FieldReference>().let { ref ->
|
getReference<FieldReference>().let { ref ->
|
||||||
ref?.type == "Ljava/util/Map;" &&
|
ref?.type == "Ljava/util/Map;" &&
|
||||||
ref.definingClass == mainFeedRequestClassMethod.classDef.toString()
|
ref.definingClass == mainFeedRequestClassMethod.immutableClassDef.toString()
|
||||||
}
|
}
|
||||||
}.let { instructionIndex ->
|
}.let { instructionIndex ->
|
||||||
getInstruction(instructionIndex).getReference<FieldReference>()!!.name
|
getInstruction(instructionIndex).getReference<FieldReference>()!!.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val initMainFeedRequestMethod = fingerprint {
|
mainFeedRequestClassMethod.immutableClassDef.firstMutableMethodDeclaratively {
|
||||||
custom { method, classDef ->
|
name("<init>")
|
||||||
method.name == "<init>" &&
|
}.apply {
|
||||||
classDef == mainFeedRequestClassMethod.classDef
|
|
||||||
}
|
|
||||||
}
|
|
||||||
initMainFeedRequestMethod.apply {
|
|
||||||
// Finds the instruction where the map is being initialized in the constructor
|
// Finds the instruction where the map is being initialized in the constructor
|
||||||
val getHeaderIndex = indexOfFirstInstructionOrThrow {
|
val getHeaderIndex = indexOfFirstInstructionOrThrow {
|
||||||
getReference<FieldReference>().let {
|
getReference<FieldReference>().let {
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
|
|
||||||
package app.revanced.patches.instagram.hide.navigation
|
package app.revanced.patches.instagram.hide.navigation
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
internal val BytecodePatchContext.initializeNavigationButtonsListMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.initializeNavigationButtonsListMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
parameterTypes("Lcom/instagram/common/session/UserSession;", "Z")
|
parameterTypes("Lcom/instagram/common/session/UserSession;", "Z")
|
||||||
returnType("Ljava/util/List;")
|
returnType("Ljava/util/List;")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val navigationButtonsEnumClassDef = fingerprint {
|
internal val navigationButtonsEnumClassDefMatch = firstMethodComposite(
|
||||||
strings("FEED", "fragment_feed", "SEARCH", "fragment_search")
|
"FEED", "fragment_feed", "SEARCH", "fragment_search",
|
||||||
}
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package app.revanced.patches.instagram.hide.navigation
|
package app.revanced.patches.instagram.hide.navigation
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
|
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||||
|
import app.revanced.patcher.name
|
||||||
import app.revanced.patcher.patch.booleanOption
|
import app.revanced.patcher.patch.booleanOption
|
||||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||||
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.instagram.misc.extension.sharedExtensionPatch
|
||||||
|
|
@ -71,20 +73,14 @@ val `Hide navigation buttons` by creatingBytecodePatch(
|
||||||
|
|
||||||
// Get the field name which contains the name of the enum for the navigation button
|
// Get the field name which contains the name of the enum for the navigation button
|
||||||
// ("fragment_clips", "fragment_share", ...)
|
// ("fragment_clips", "fragment_share", ...)
|
||||||
val navigationButtonsEnumInitFingerprint = fingerprint {
|
val enumNameField = navigationButtonsEnumClassDefMatch.classDef.firstMutableMethodDeclaratively {
|
||||||
custom { method, classDef ->
|
name("<init>")
|
||||||
method.name == "<init>" &&
|
}.let { method ->
|
||||||
classDef == navigationButtonsEnumClassDef.classDef
|
method.indexOfFirstInstructionOrThrow {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val enumNameField: String
|
|
||||||
with(navigationButtonsEnumInitFingerprint.method) {
|
|
||||||
enumNameField = indexOfFirstInstructionOrThrow {
|
|
||||||
opcode == Opcode.IPUT_OBJECT &&
|
opcode == Opcode.IPUT_OBJECT &&
|
||||||
(this as TwoRegisterInstruction).registerA == 2 // p2 register.
|
(this as TwoRegisterInstruction).registerA == 2 // p2 register.
|
||||||
}.let {
|
}.let {
|
||||||
getInstruction(it).getReference<FieldReference>()!!.name
|
method.getInstruction(it).getReference<FieldReference>()!!.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package app.revanced.patches.instagram.hide.stories
|
||||||
import app.revanced.patcher.*
|
import app.revanced.patcher.*
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val getOrCreateAvatarViewMethod = firstMethodComposite {
|
internal val getOrCreateAvatarViewMethodMatch = firstMethodComposite {
|
||||||
definingClass("Lcom/instagram/reels/ui/views/reelavatar/RecyclerReelAvatarView;")
|
definingClass("Lcom/instagram/reels/ui/views/reelavatar/RecyclerReelAvatarView;")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
returnType("L")
|
returnType("L")
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,11 @@ val `Hide Stories from Home` by creatingBytecodePatch(
|
||||||
compatibleWith("com.instagram.android")
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
val addStoryEndIndex = getOrCreateAvatarViewMethod.indices.last()
|
getOrCreateAvatarViewMethodMatch.let {
|
||||||
|
val addStoryEndIndex = it.indices.last()
|
||||||
|
|
||||||
// Remove addView of Story.
|
// Remove addView of Story.
|
||||||
getOrCreateAvatarViewMethod.removeInstruction(addStoryEndIndex)
|
it.method.removeInstruction(addStoryEndIndex)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import app.revanced.patcher.patch.creatingBytecodePatch
|
||||||
import app.revanced.util.Utils.trimIndentMultiline
|
import app.revanced.util.Utils.trimIndentMultiline
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||||
|
import app.revanced.util.indexOfFirstStringInstruction
|
||||||
import app.revanced.util.returnEarly
|
import app.revanced.util.returnEarly
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
@ -20,8 +21,9 @@ val `Enable developer menu` by creatingBytecodePatch(
|
||||||
compatibleWith("com.instagram.android")
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
with(clearNotificationReceiverMethod) {
|
clearNotificationReceiverMethod.apply {
|
||||||
indexOfFirstInstructionReversedOrThrow(clearNotificationReceiverMethod.stringMatches.first().index) {
|
val stringIndex = indexOfFirstStringInstruction("NOTIFICATION_DISMISSED")
|
||||||
|
indexOfFirstInstructionReversedOrThrow(stringIndex) {
|
||||||
val reference = getReference<MethodReference>()
|
val reference = getReference<MethodReference>()
|
||||||
opcode in listOf(Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC_RANGE) &&
|
opcode in listOf(Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC_RANGE) &&
|
||||||
reference?.parameterTypes?.size == 1 &&
|
reference?.parameterTypes?.size == 1 &&
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
|
|
||||||
package app.revanced.patches.instagram.misc.devmenu
|
package app.revanced.patches.instagram.misc.devmenu
|
||||||
|
|
||||||
internal val BytecodePatchContext.clearNotificationReceiverMethod by gettingFirstMethodDeclaratively {
|
import app.revanced.patcher.*
|
||||||
custom { method, classDef ->
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
method.name == "onReceive" &&
|
|
||||||
classDef.type == "Lcom/instagram/notifications/push/ClearNotificationReceiver;"
|
internal val BytecodePatchContext.clearNotificationReceiverMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
}
|
"NOTIFICATION_DISMISSED",
|
||||||
strings("NOTIFICATION_DISMISSED")
|
) {
|
||||||
|
name("onReceive")
|
||||||
|
definingClass("Lcom/instagram/notifications/push/ClearNotificationReceiver;")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,27 +21,25 @@ val `Open links externally` by creatingBytecodePatch(
|
||||||
compatibleWith("com.instagram.android")
|
compatibleWith("com.instagram.android")
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
inAppBrowserFunctionMethodMatch.let {
|
inAppBrowserFunctionMethodMatch.method.apply {
|
||||||
val stringMatchIndex = it.stringMatches?.first { match -> match.string == TARGET_STRING }!!.index
|
val stringMatchIndex = inAppBrowserFunctionMethodMatch.indices.first()
|
||||||
|
|
||||||
it.method.apply {
|
val urlResultObjIndex = indexOfFirstInstructionOrThrow(
|
||||||
val urlResultObjIndex = indexOfFirstInstructionOrThrow(
|
stringMatchIndex,
|
||||||
stringMatchIndex,
|
Opcode.MOVE_OBJECT_FROM16,
|
||||||
Opcode.MOVE_OBJECT_FROM16,
|
)
|
||||||
)
|
|
||||||
|
|
||||||
// Register that contains the url after moving from a higher register.
|
// Register that contains the url after moving from a higher register.
|
||||||
val urlRegister = getInstruction<TwoRegisterInstruction>(urlResultObjIndex).registerA
|
val urlRegister = getInstruction<TwoRegisterInstruction>(urlResultObjIndex).registerA
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
urlResultObjIndex + 1,
|
urlResultObjIndex + 1,
|
||||||
"""
|
"""
|
||||||
invoke-static { v$urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->openExternally(Ljava/lang/String;)Z
|
invoke-static { v$urlRegister }, $EXTENSION_CLASS_DESCRIPTOR->openExternally(Ljava/lang/String;)Z
|
||||||
move-result v$urlRegister
|
move-result v$urlRegister
|
||||||
return v$urlRegister
|
return v$urlRegister
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,24 @@ package app.revanced.patches.instagram.misc.share
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
|
import app.revanced.util.indexOfFirstStringInstruction
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||||
|
|
||||||
context(BytecodePatchContext)
|
context(_: BytecodePatchContext)
|
||||||
internal fun editShareLinksPatch(block: MutableMethod.(index: Int, register: Int) -> Unit) {
|
internal fun editShareLinksPatch(block: MutableMethod.(index: Int, register: Int) -> Unit) {
|
||||||
val fingerprintsToPatch = arrayOf(
|
val methodsToPatch = arrayOf(
|
||||||
permalinkResponseJsonParserMethod,
|
permalinkResponseJsonParserMethod,
|
||||||
storyUrlResponseJsonParserMethod,
|
storyUrlResponseJsonParserMethod,
|
||||||
profileUrlResponseJsonParserMethod,
|
profileUrlResponseJsonParserMethod,
|
||||||
liveUrlResponseJsonParserMethod,
|
liveUrlResponseJsonParserMethod,
|
||||||
)
|
)
|
||||||
|
|
||||||
for (fingerprint in fingerprintsToPatch) {
|
for (method in methodsToPatch) {
|
||||||
fingerprint.method.apply {
|
method.apply {
|
||||||
val putSharingUrlIndex = indexOfFirstInstruction(
|
val putSharingUrlIndex = indexOfFirstInstruction(
|
||||||
permalinkResponseJsonParserMethod.stringMatches.first().index,
|
indexOfFirstStringInstruction("permalink"),
|
||||||
Opcode.IPUT_OBJECT,
|
Opcode.IPUT_OBJECT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,28 @@
|
||||||
package app.revanced.patches.instagram.misc.share
|
package app.revanced.patches.instagram.misc.share
|
||||||
|
|
||||||
import com.google.common.util.concurrent.Striped.custom
|
import app.revanced.patcher.*
|
||||||
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
|
|
||||||
internal val BytecodePatchContext.permalinkResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.permalinkResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
strings("permalink", "PermalinkResponse")
|
"permalink", "PermalinkResponse",
|
||||||
custom { method, _ -> method.name == "parseFromJson" }
|
) {
|
||||||
|
name("parseFromJson")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.storyUrlResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.storyUrlResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
strings("story_item_to_share_url", "StoryItemUrlResponse")
|
"story_item_to_share_url", "StoryItemUrlResponse",
|
||||||
custom { method, _ -> method.name == "parseFromJson" }
|
) {
|
||||||
|
name("parseFromJson")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.profileUrlResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.profileUrlResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
strings("profile_to_share_url", "ProfileUrlResponse")
|
"profile_to_share_url", "ProfileUrlResponse",
|
||||||
custom { method, _ -> method.name == "parseFromJson" }
|
) {
|
||||||
|
name("parseFromJson")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.liveUrlResponseJsonParserMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.liveUrlResponseJsonParserMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
strings("live_to_share_url", "LiveItemLinkUrlResponse")
|
"live_to_share_url", "LiveItemLinkUrlResponse",
|
||||||
custom { method, _ -> method.name == "parseFromJson" }
|
) {
|
||||||
|
name("parseFromJson")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,13 @@
|
||||||
package app.revanced.patches.instagram.misc.share.domain
|
package app.revanced.patches.instagram.misc.share.domain
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
internal val BytecodePatchContext.getCustomShareDomainMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.getCustomShareDomainMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||||
returnType("Ljava/lang/String;")
|
returnType("Ljava/lang/String;")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
custom { method, classDef ->
|
name("getCustomShareDomain")
|
||||||
method.name == "getCustomShareDomain" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
package app.revanced.patches.instagram.misc.signature
|
package app.revanced.patches.instagram.misc.signature
|
||||||
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import app.revanced.util.getReference
|
import app.revanced.util.getReference
|
||||||
import app.revanced.util.indexOfFirstInstruction
|
import app.revanced.util.indexOfFirstInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||||
|
|
||||||
internal val BytecodePatchContext.isValidSignatureClassMethod by gettingFirstMethodDeclaratively {
|
internal val isValidSignatureClassMethodMatch = firstMethodComposite(
|
||||||
strings("The provider for uri '", "' is not trusted: ")
|
"The provider for uri '", "' is not trusted: ",
|
||||||
}
|
)
|
||||||
|
|
||||||
internal val BytecodePatchContext.isValidSignatureMethodMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.isValidSignatureMethodMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
parameterTypes("L", "Z")
|
parameterTypes("L", "Z")
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
custom { method, _ ->
|
custom {
|
||||||
method.indexOfFirstInstruction {
|
indexOfFirstInstruction {
|
||||||
getReference<MethodReference>()?.name == "keySet"
|
getReference<MethodReference>()?.name == "keySet"
|
||||||
} >= 0
|
} >= 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ val `Disable signature check` by creatingBytecodePatch(
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
isValidSignatureMethodMethod
|
isValidSignatureMethodMethod
|
||||||
.match(isValidSignatureClassMethod.classDef)
|
.match(isValidSignatureClassMethodMatch.classDef)
|
||||||
.method
|
.method
|
||||||
.returnEarly(true)
|
.returnEarly(true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
package app.revanced.patches.messenger.metaai
|
package app.revanced.patches.messenger.metaai
|
||||||
|
|
||||||
import app.revanced.patcher.*
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val BytecodePatchContext.getMobileConfigBoolMethod by gettingFirstMutableMethodDeclaratively {
|
internal val getMobileConfigBoolMethodMatch = firstMethodComposite {
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
opcodes(Opcode.RETURN)
|
opcodes(Opcode.RETURN)
|
||||||
custom { "Lcom/facebook/mobileconfig/factory/MobileConfigUnsafeContext;" in immutableClassDef.interfaces }
|
custom { "Lcom/facebook/mobileconfig/factory/MobileConfigUnsafeContext;" in immutableClassDef.interfaces }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.metaAIKillSwitchCheckMethod by gettingFirstMutableMethodDeclaratively("SearchAiagentImplementationsKillSwitch") {
|
internal val metaAIKillSwitchCheckMethodMatch = firstMethodComposite("SearchAiagentImplementationsKillSwitch") {
|
||||||
opcodes(Opcode.CONST_WIDE)
|
opcodes(Opcode.CONST_WIDE)
|
||||||
}
|
}
|
||||||
internal val BytecodePatchContext.extensionMethodMethod by gettingFirstMutableMethodDeclaratively("REPLACED_BY_PATCH") {
|
|
||||||
|
internal val extensionMethodMethodMatch = firstMethodComposite("REPLACED_BY_PATCH") {
|
||||||
name(EXTENSION_METHOD_NAME)
|
name(EXTENSION_METHOD_NAME)
|
||||||
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package app.revanced.patches.messenger.metaai
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
import app.revanced.patcher.extensions.replaceInstruction
|
||||||
import app.revanced.patcher.method
|
|
||||||
import app.revanced.patcher.patch.creatingBytecodePatch
|
import app.revanced.patcher.patch.creatingBytecodePatch
|
||||||
import app.revanced.patches.messenger.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.messenger.misc.extension.sharedExtensionPatch
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
|
|
@ -21,11 +20,11 @@ val `Remove Meta AI` by creatingBytecodePatch(
|
||||||
dependsOn(sharedExtensionPatch)
|
dependsOn(sharedExtensionPatch)
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
getMobileConfigBoolMethod.apply {
|
getMobileConfigBoolMethodMatch.let {
|
||||||
val returnIndex = getMobileConfigBoolMethod.patternMatch.startIndex // TODO
|
val returnIndex = it.indices.first()
|
||||||
val returnRegister = getInstruction<OneRegisterInstruction>(returnIndex).registerA
|
val returnRegister = it.method.getInstruction<OneRegisterInstruction>(returnIndex).registerA
|
||||||
|
|
||||||
addInstructions(
|
it.method.addInstructions(
|
||||||
returnIndex,
|
returnIndex,
|
||||||
"""
|
"""
|
||||||
invoke-static { p1, p2, v$returnRegister }, $EXTENSION_CLASS_DESCRIPTOR->$EXTENSION_METHOD_NAME(JZ)Z
|
invoke-static { p1, p2, v$returnRegister }, $EXTENSION_CLASS_DESCRIPTOR->$EXTENSION_METHOD_NAME(JZ)Z
|
||||||
|
|
@ -35,16 +34,18 @@ val `Remove Meta AI` by creatingBytecodePatch(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the common starting digits of Meta AI flag IDs from a flag found in code.
|
// Extract the common starting digits of Meta AI flag IDs from a flag found in code.
|
||||||
val relevantDigits = with(metaAIKillSwitchCheckMethod) {
|
val relevantDigits = metaAIKillSwitchCheckMethodMatch.let {
|
||||||
method.getInstruction<WideLiteralInstruction>(patternMatch.startIndex).wideLiteral // TODO
|
it.method.getInstruction<WideLiteralInstruction>(it.indices.first()).wideLiteral
|
||||||
}.toString().substring(0, 7)
|
}.toString().substring(0, 7)
|
||||||
|
|
||||||
// Replace placeholder in the extension method.
|
// Replace placeholder in the extension method.
|
||||||
extensionMethodMethod.replaceInstruction(
|
extensionMethodMethodMatch.let {
|
||||||
stringM.first().index, // TODO
|
it.method.replaceInstruction(
|
||||||
"""
|
it.indices.first(),
|
||||||
|
"""
|
||||||
const-string v1, "$relevantDigits"
|
const-string v1, "$relevantDigits"
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,22 @@
|
||||||
package app.revanced.patches.youtube.layout.startpage
|
package app.revanced.patches.youtube.layout.startpage
|
||||||
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.invoke
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val BytecodePatchContext.intentActionMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.intentActionMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"has_handled_intent",
|
||||||
|
) {
|
||||||
parameterTypes("Landroid/content/Intent;")
|
parameterTypes("Landroid/content/Intent;")
|
||||||
instructions(
|
|
||||||
"has_handled_intent"(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.browseIdMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.browseIdMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"FEwhat_to_watch",
|
||||||
|
) {
|
||||||
returnType("Lcom/google/android/apps/youtube/app/common/ui/navigation/PaneDescriptor;")
|
returnType("Lcom/google/android/apps/youtube/app/common/ui/navigation/PaneDescriptor;")
|
||||||
|
|
||||||
// parameterTypes() // 20.30 and earlier is no parameters. 20.31+ parameter is L.
|
// parameterTypes() // 20.30 and earlier is no parameters. 20.31+ parameter is L.
|
||||||
instructions(
|
instructions(
|
||||||
"FEwhat_to_watch"(),
|
512L(),
|
||||||
512(),
|
allOf(Opcode.IPUT_OBJECT(), field { type == "Ljava/lang/String;" }),
|
||||||
fieldAccess(opcode = Opcode.IPUT_OBJECT, type = "Ljava/lang/String;"),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,16 @@
|
||||||
package app.revanced.patches.youtube.layout.theme
|
package app.revanced.patches.youtube.layout.theme
|
||||||
|
|
||||||
import app.revanced.patcher.anyInstruction
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.invoke
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
import app.revanced.patches.youtube.shared.YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
||||||
|
|
||||||
internal val BytecodePatchContext.useGradientLoadingScreenMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.useGradientLoadingScreenMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
instructions(
|
instructions(
|
||||||
45412406L(),
|
45412406L(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.splashScreenStyleMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.splashScreenStyleMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Landroid/os/Bundle;")
|
parameterTypes("Landroid/os/Bundle;")
|
||||||
instructions(
|
instructions(
|
||||||
|
|
@ -24,7 +19,6 @@ internal val BytecodePatchContext.splashScreenStyleMethod by gettingFirstMethodD
|
||||||
269032877L(), // 20.29 and lower.
|
269032877L(), // 20.29 and lower.
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
custom { method, classDef ->
|
definingClass(YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE)
|
||||||
method.name == "onCreate" && classDef.type == YOUTUBE_MAIN_ACTIVITY_CLASS_TYPE
|
name("onCreate")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -200,21 +200,17 @@ val themePatch = baseThemePatch(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
useGradientLoadingScreenMethod.let {
|
useGradientLoadingScreenMethod.insertLiteralOverride(
|
||||||
it.method.insertLiteralOverride(
|
45412406L,
|
||||||
it.instructionMatches.first().index,
|
"$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z",
|
||||||
"$EXTENSION_CLASS_DESCRIPTOR->gradientLoadingScreenEnabled(Z)Z",
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_19_47_or_greater) {
|
if (is_19_47_or_greater) {
|
||||||
// Lottie splash screen exists in earlier versions, but it may not be always on.
|
// Lottie splash screen exists in earlier versions, but it may not be always on.
|
||||||
splashScreenStyleMethod.let {
|
splashScreenStyleMethod.insertLiteralOverride(
|
||||||
it.method.insertLiteralOverride(
|
1074339245L,
|
||||||
it.instructionMatches.first().index,
|
"$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I",
|
||||||
"$EXTENSION_CLASS_DESCRIPTOR->getLoadingScreenType(I)I",
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
package app.revanced.patches.youtube.misc.dimensions.spoof
|
package app.revanced.patches.youtube.misc.dimensions.spoof
|
||||||
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
|
|
||||||
internal val BytecodePatchContext.deviceDimensionsModelToStringMethod by gettingFirstMethodDeclaratively {
|
// Strings are partial matches (format delimiters), so keep in instructions block.
|
||||||
|
internal val deviceDimensionsModelToStringMethodMatch = firstMethodComposite {
|
||||||
returnType("L")
|
returnType("L")
|
||||||
instructions(
|
strings {
|
||||||
"minh."(),
|
+"minh."
|
||||||
";maxh."(),
|
+";maxh."
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ val `Spoof device dimensions` by creatingBytecodePatch(
|
||||||
SwitchPreference("revanced_spoof_device_dimensions"),
|
SwitchPreference("revanced_spoof_device_dimensions"),
|
||||||
)
|
)
|
||||||
|
|
||||||
deviceDimensionsModelToStringMethod
|
deviceDimensionsModelToStringMethodMatch.classDef.methods.first { method -> method.name == "<init>" }
|
||||||
.classDef.methods.first { method -> method.name == "<init>" }
|
|
||||||
// Override the parameters containing the dimensions.
|
// Override the parameters containing the dimensions.
|
||||||
.addInstructions(
|
.addInstructions(
|
||||||
1, // Add after super call.
|
1, // Add after super call.
|
||||||
|
|
|
||||||
|
|
@ -30,21 +30,19 @@ internal val accountCredentialsInvalidTextPatch = bytecodePatch {
|
||||||
// MicroG accounts look almost identical to Google device accounts
|
// MicroG accounts look almost identical to Google device accounts
|
||||||
// and it's more foolproof to instead uninstall/reinstall.
|
// and it's more foolproof to instead uninstall/reinstall.
|
||||||
arrayOf(
|
arrayOf(
|
||||||
specificNetworkErrorViewControllerMethod,
|
specificNetworkErrorViewControllerMethodMatch,
|
||||||
loadingFrameLayoutControllerMethod,
|
loadingFrameLayoutControllerMethodMatch,
|
||||||
).forEach { fingerprint ->
|
).forEach { match ->
|
||||||
fingerprint.apply {
|
val index = match.indices.last()
|
||||||
val index = indices.last()
|
val register = match.method.getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
val register = method.getInstruction<OneRegisterInstruction>(index).registerA
|
|
||||||
|
|
||||||
method.addInstructions(
|
match.method.addInstructions(
|
||||||
index + 1,
|
index + 1,
|
||||||
"""
|
"""
|
||||||
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getOfflineNetworkErrorString(Ljava/lang/String;)Ljava/lang/String;
|
invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->getOfflineNetworkErrorString(Ljava/lang/String;)Ljava/lang/String;
|
||||||
move-result-object v$register
|
move-result-object v$register
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,33 @@
|
||||||
package app.revanced.patches.youtube.misc.gms
|
package app.revanced.patches.youtube.misc.gms
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val BytecodePatchContext.specificNetworkErrorViewControllerMethod by gettingFirstMethodDeclaratively {
|
internal val specificNetworkErrorViewControllerMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(
|
||||||
ResourceType.DRAWABLE("ic_offline_no_content_upside_down"),
|
ResourceType.DRAWABLE("ic_offline_no_content_upside_down"),
|
||||||
ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"),
|
ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"),
|
||||||
methodCall(name = "getString", returnType = "Ljava/lang/String;"),
|
method { name == "getString" && returnType == "Ljava/lang/String;" },
|
||||||
after(Opcode.MOVE_RESULT_OBJECT()),
|
Opcode.MOVE_RESULT_OBJECT(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// It's not clear if this second class is ever used and it may be dead code,
|
// It's not clear if this second class is ever used and it may be dead code,
|
||||||
// but it the layout image/text is identical to the network error fingerprint above.
|
// but it the layout image/text is identical to the network error fingerprint above.
|
||||||
internal val BytecodePatchContext.loadingFrameLayoutControllerMethod by gettingFirstMethodDeclaratively {
|
internal val loadingFrameLayoutControllerMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("L")
|
parameterTypes("L")
|
||||||
instructions(
|
instructions(
|
||||||
ResourceType.DRAWABLE("ic_offline_no_content_upside_down"),
|
ResourceType.DRAWABLE("ic_offline_no_content_upside_down"),
|
||||||
ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"),
|
ResourceType.STRING("offline_no_content_body_text_not_offline_eligible"),
|
||||||
methodCall(name = "getString", returnType = "Ljava/lang/String;"),
|
method { name == "getString" && returnType == "Ljava/lang/String;" },
|
||||||
after(Opcode.MOVE_RESULT_OBJECT()),
|
Opcode.MOVE_RESULT_OBJECT(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,19 +52,17 @@ val `Disable haptic feedback` by creatingBytecodePatch(
|
||||||
scrubbingHapticsMethod to "disablePreciseSeekingVibrate",
|
scrubbingHapticsMethod to "disablePreciseSeekingVibrate",
|
||||||
seekUndoHapticsMethod to "disableSeekUndoVibrate",
|
seekUndoHapticsMethod to "disableSeekUndoVibrate",
|
||||||
zoomHapticsMethod to "disableZoomVibrate",
|
zoomHapticsMethod to "disableZoomVibrate",
|
||||||
).forEach { (fingerprint, methodName) ->
|
).forEach { (method, methodName) ->
|
||||||
fingerprint.method.apply {
|
method.addInstructionsWithLabels(
|
||||||
addInstructionsWithLabels(
|
0,
|
||||||
0,
|
"""
|
||||||
"""
|
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->$methodName()Z
|
||||||
invoke-static {}, $EXTENSION_CLASS_DESCRIPTOR->$methodName()Z
|
move-result v0
|
||||||
move-result v0
|
if-eqz v0, :vibrate
|
||||||
if-eqz v0, :vibrate
|
return-void
|
||||||
return-void
|
""",
|
||||||
""",
|
ExternalLabel("vibrate", method.getInstruction(0)),
|
||||||
ExternalLabel("vibrate", getInstruction(0)),
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,28 @@
|
||||||
package app.revanced.patches.youtube.misc.hapticfeedback
|
package app.revanced.patches.youtube.misc.hapticfeedback
|
||||||
|
|
||||||
internal val BytecodePatchContext.markerHapticsMethod by gettingFirstMethodDeclaratively {
|
import app.revanced.patcher.*
|
||||||
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
|
|
||||||
|
internal val BytecodePatchContext.markerHapticsMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"Failed to execute markers haptics vibrate.",
|
||||||
|
) {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
strings("Failed to execute markers haptics vibrate.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.scrubbingHapticsMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.scrubbingHapticsMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"Failed to haptics vibrate for fine scrubbing.",
|
||||||
|
) {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
strings("Failed to haptics vibrate for fine scrubbing.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.seekUndoHapticsMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.seekUndoHapticsMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"Failed to execute seek undo haptics vibrate.",
|
||||||
|
) {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
strings("Failed to execute seek undo haptics vibrate.")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.zoomHapticsMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.zoomHapticsMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"Failed to haptics vibrate for video zoom",
|
||||||
|
) {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
strings("Failed to haptics vibrate for video zoom")
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ val cronetImageUrlHookPatch = bytecodePatch(
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
loadImageUrlMethod = messageDigestImageUrlMethod
|
loadImageUrlMethod = messageDigestImageUrlMethod
|
||||||
.match(messageDigestImageUrlParentMethod.immutableClassDef).method
|
.match(messageDigestImageUrlParentMethodMatch.classDef)
|
||||||
|
|
||||||
loadImageSuccessCallbackMethod = onSucceededMethod
|
loadImageSuccessCallbackMethod = onSucceededMethod
|
||||||
.match(onResponseStartedMethod.immutableClassDef).method
|
.match(onResponseStartedMethodMatch.classDef)
|
||||||
|
|
||||||
loadImageErrorCallbackMethod = onFailureMethod
|
loadImageErrorCallbackMethod = onFailureMethod
|
||||||
.match(onResponseStartedMethod.immutableClassDef).method
|
.match(onResponseStartedMethodMatch.classDef)
|
||||||
|
|
||||||
// The URL is required for the failure callback hook, but the URL field is obfuscated.
|
// The URL is required for the failure callback hook, but the URL field is obfuscated.
|
||||||
// Add a helper get method that returns the URL field.
|
// Add a helper get method that returns the URL field.
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,10 @@
|
||||||
package app.revanced.patches.youtube.misc.imageurlhook
|
package app.revanced.patches.youtube.misc.imageurlhook
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.anyInstruction
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
internal val BytecodePatchContext.onFailureMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.onFailureMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes(
|
parameterTypes(
|
||||||
|
|
@ -17,58 +12,49 @@ internal val BytecodePatchContext.onFailureMethod by gettingFirstMethodDeclarati
|
||||||
"Lorg/chromium/net/UrlResponseInfo;",
|
"Lorg/chromium/net/UrlResponseInfo;",
|
||||||
"Lorg/chromium/net/CronetException;",
|
"Lorg/chromium/net/CronetException;",
|
||||||
)
|
)
|
||||||
custom { method, _ ->
|
name("onFailed")
|
||||||
method.name == "onFailed"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acts as a parent fingerprint.
|
// Acts as a parent fingerprint.
|
||||||
internal val BytecodePatchContext.onResponseStartedMethod by gettingFirstMethodDeclaratively {
|
internal val onResponseStartedMethodMatch = firstMethodComposite(
|
||||||
|
"Content-Length",
|
||||||
|
"Content-Type",
|
||||||
|
"identity",
|
||||||
|
"application/x-protobuf",
|
||||||
|
) {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;")
|
parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;")
|
||||||
strings(
|
name("onResponseStarted")
|
||||||
"Content-Length",
|
|
||||||
"Content-Type",
|
|
||||||
"identity",
|
|
||||||
"application/x-protobuf",
|
|
||||||
)
|
|
||||||
custom { method, _ ->
|
|
||||||
method.name == "onResponseStarted"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.onSucceededMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.onSucceededMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;")
|
parameterTypes("Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;")
|
||||||
custom { method, _ ->
|
name("onSucceeded")
|
||||||
method.name == "onSucceeded"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal const val CRONET_URL_REQUEST_CLASS_DESCRIPTOR = "Lorg/chromium/net/impl/CronetUrlRequest;"
|
internal const val CRONET_URL_REQUEST_CLASS_DESCRIPTOR = "Lorg/chromium/net/impl/CronetUrlRequest;"
|
||||||
|
|
||||||
internal val BytecodePatchContext.requestMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.requestMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||||
custom { _, classDef ->
|
definingClass(CRONET_URL_REQUEST_CLASS_DESCRIPTOR)
|
||||||
classDef.type == CRONET_URL_REQUEST_CLASS_DESCRIPTOR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.messageDigestImageUrlMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.messageDigestImageUrlMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||||
parameterTypes("Ljava/lang/String;", "L")
|
parameterTypes("Ljava/lang/String;", "L")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.messageDigestImageUrlParentMethod by gettingFirstMethodDeclaratively {
|
internal val messageDigestImageUrlParentMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Ljava/lang/String;")
|
returnType("Ljava/lang/String;")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
strings {
|
||||||
anyInstruction(
|
anyOf(
|
||||||
"@#&=*+-_.,:!?()/~'%;\$"(),
|
"@#&=*+-_.,:!?()/~'%;\$",
|
||||||
"@#&=*+-_.,:!?()/~'%;\$[]"(), // 20.38+
|
"@#&=*+-_.,:!?()/~'%;\$[]", // 20.38+
|
||||||
),
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,6 @@
|
||||||
package app.revanced.patches.youtube.misc.links
|
package app.revanced.patches.youtube.misc.links
|
||||||
|
|
||||||
import app.revanced.patcher.StringComparisonType
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.accessFlags
|
|
||||||
import app.revanced.patcher.firstMethodComposite
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,10 +10,13 @@ internal val abUriParserLegacyMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Ljava/lang/Object;")
|
returnType("Ljava/lang/Object;")
|
||||||
parameterTypes("Ljava/lang/Object;")
|
parameterTypes("Ljava/lang/Object;")
|
||||||
|
strings {
|
||||||
|
// Partial string match - keep in instructions block
|
||||||
|
+"Found entityKey=`"
|
||||||
|
// "that does not contain a PlaylistVideoEntityId" - partial, skipped
|
||||||
|
}
|
||||||
instructions(
|
instructions(
|
||||||
"Found entityKey=`"(),
|
method { smali == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" },
|
||||||
addString("that does not contain a PlaylistVideoEntityId", comparison = StringComparisonType.CONTAINS),
|
|
||||||
methodCall(smali = "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -33,10 +30,10 @@ internal val abUriParserMethodMatch = firstMethodComposite {
|
||||||
instructions(
|
instructions(
|
||||||
// Method is a switch statement of unrelated code,
|
// Method is a switch statement of unrelated code,
|
||||||
// and there's no strings or anything unique to fingerprint.
|
// and there's no strings or anything unique to fingerprint.
|
||||||
methodCall(smali = "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;"),
|
method { smali == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" },
|
||||||
methodCall(smali = "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;"),
|
method { smali == "Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;" },
|
||||||
methodCall(smali = "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"),
|
method { smali == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" },
|
||||||
methodCall(smali = "Ljava/util/List;->get(I)Ljava/lang/Object;"),
|
method { smali == "Ljava/util/List;->get(I)Ljava/lang/Object;" },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,9 +42,11 @@ internal val httpUriParserMethodMatch = firstMethodComposite {
|
||||||
returnType("Landroid/net/Uri;")
|
returnType("Landroid/net/Uri;")
|
||||||
parameterTypes("Ljava/lang/String;")
|
parameterTypes("Ljava/lang/String;")
|
||||||
instructions(
|
instructions(
|
||||||
methodCall(smali = "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;"),
|
method { smali == "Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;" },
|
||||||
"https"(),
|
|
||||||
"://"(),
|
|
||||||
"https:"(),
|
|
||||||
)
|
)
|
||||||
|
strings {
|
||||||
|
+"https"
|
||||||
|
+"://"
|
||||||
|
+"https:"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
package app.revanced.patches.youtube.video.speed.remember
|
package app.revanced.patches.youtube.video.speed.remember
|
||||||
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
|
|
||||||
internal val BytecodePatchContext.initializePlaybackSpeedValuesMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.initializePlaybackSpeedValuesMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"menu_item_playback_speed",
|
||||||
|
) {
|
||||||
parameterTypes("[L", "I")
|
parameterTypes("[L", "I")
|
||||||
instructions(
|
|
||||||
"menu_item_playback_speed"(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,37 @@
|
||||||
package app.revanced.patches.youtube.video.videoid
|
package app.revanced.patches.youtube.video.videoid
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.invoke
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||||
|
|
||||||
internal val BytecodePatchContext.videoIdMethod by gettingFirstMethodDeclaratively {
|
/**
|
||||||
|
* Matches using the class found in [videoIdParentMethodMatch].
|
||||||
|
*/
|
||||||
|
context(_: BytecodePatchContext)
|
||||||
|
internal fun ClassDef.getVideoIdMethodMatch() = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("L")
|
parameterTypes("L")
|
||||||
instructions(
|
instructions(
|
||||||
methodCall(
|
method {
|
||||||
definingClass = "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;",
|
definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||||
returnType = "Ljava/lang/String;",
|
&& returnType == "Ljava/lang/String;"
|
||||||
),
|
},
|
||||||
Opcode.MOVE_RESULT_OBJECT(),
|
Opcode.MOVE_RESULT_OBJECT(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.videoIdBackgroundPlayMethod by gettingFirstMethodDeclaratively {
|
internal val videoIdBackgroundPlayMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.DECLARED_SYNCHRONIZED, AccessFlags.FINAL, AccessFlags.PUBLIC)
|
accessFlags(AccessFlags.DECLARED_SYNCHRONIZED, AccessFlags.FINAL, AccessFlags.PUBLIC)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("L")
|
parameterTypes("L")
|
||||||
instructions(
|
instructions(
|
||||||
methodCall(
|
method {
|
||||||
definingClass = "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;",
|
definingClass == "Lcom/google/android/libraries/youtube/innertube/model/player/PlayerResponseModel;"
|
||||||
returnType = "Ljava/lang/String;",
|
&& returnType == "Ljava/lang/String;"
|
||||||
),
|
},
|
||||||
Opcode.MOVE_RESULT_OBJECT(),
|
Opcode.MOVE_RESULT_OBJECT(),
|
||||||
Opcode.IPUT_OBJECT(),
|
Opcode.IPUT_OBJECT(),
|
||||||
Opcode.MONITOR_EXIT(),
|
Opcode.MONITOR_EXIT(),
|
||||||
|
|
@ -39,16 +39,16 @@ internal val BytecodePatchContext.videoIdBackgroundPlayMethod by gettingFirstMet
|
||||||
Opcode.MONITOR_EXIT(),
|
Opcode.MONITOR_EXIT(),
|
||||||
Opcode.RETURN_VOID(),
|
Opcode.RETURN_VOID(),
|
||||||
)
|
)
|
||||||
custom { method, classDef ->
|
custom {
|
||||||
method.implementation != null &&
|
implementation != null &&
|
||||||
(
|
(
|
||||||
classDef.methods.count() == 17 || // 20.39 and lower.
|
definingClass.methods.count() == 17 || // 20.39 and lower.
|
||||||
classDef.methods.count() == 16
|
definingClass.methods.count() == 16
|
||||||
) // 20.40+
|
) // 20.40+
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val videoIdParentFingerprint = fingerprint {
|
internal val videoIdParentMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("[L")
|
returnType("[L")
|
||||||
parameterTypes("L")
|
parameterTypes("L")
|
||||||
|
|
|
||||||
|
|
@ -92,22 +92,18 @@ val videoIdPatch = bytecodePatch(
|
||||||
)
|
)
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
videoIdMethod.match(videoIdParentFingerprint.immutableClassDef).let {
|
videoIdParentMethodMatch.classDef.getVideoIdMethodMatch().let {
|
||||||
it.method.apply {
|
videoIdMethod = it.method
|
||||||
videoIdMethod = this
|
val index = it.indices.first()
|
||||||
val index = it.instructionMatches.first().index
|
videoIdRegister = videoIdMethod.getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||||
videoIdRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
videoIdInsertIndex = index + 2
|
||||||
videoIdInsertIndex = index + 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
videoIdBackgroundPlayMethod.let {
|
videoIdBackgroundPlayMethodMatch.let {
|
||||||
it.method.apply {
|
backgroundPlaybackMethod = it.method
|
||||||
backgroundPlaybackMethod = this
|
val index = it.indices.first()
|
||||||
val index = it.instructionMatches.first().index
|
backgroundPlaybackVideoIdRegister = backgroundPlaybackMethod.getInstruction<OneRegisterInstruction>(index + 1).registerA
|
||||||
backgroundPlaybackVideoIdRegister = getInstruction<OneRegisterInstruction>(index + 1).registerA
|
backgroundPlaybackInsertIndex = index + 2
|
||||||
backgroundPlaybackInsertIndex = index + 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue