Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(YouTube - ReturnYouTubeDislike): Revert support for 18.37.36 #3041

Merged
merged 1 commit into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
PlayerTypeHookPatch::class,
],
compatiblePackages = [
CompatiblePackage("com.google.android.youtube", ["18.37.36"])
CompatiblePackage("com.google.android.youtube", ["18.32.39"])
]
)
@Suppress("unused")
Expand Down Expand Up @@ -91,40 +91,49 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
throw TextComponentAtomicReferenceFingerprint.exception
}?.let { textComponentContextFingerprintResult ->
val conversionContextIndex = textComponentContextFingerprintResult
.scanResult.patternScanResult!!.endIndex
.scanResult.patternScanResult!!.startIndex
val atomicReferenceStartIndex = TextComponentAtomicReferenceFingerprint.result!!
.scanResult.patternScanResult!!.startIndex

val insertIndex = atomicReferenceStartIndex + 9
val insertIndex = atomicReferenceStartIndex + 6

textComponentContextFingerprintResult.mutableMethod.apply {
// Get the conversion context obfuscated field name
// Get the conversion context obfuscated field name, and the registers for the AtomicReference and CharSequence
val conversionContextFieldReference =
getInstruction<ReferenceInstruction>(conversionContextIndex).reference

// Free register to hold the conversion context
// Reuse the free register to make room for the atomic reference register.
val freeRegister =
getInstruction<TwoRegisterInstruction>(atomicReferenceStartIndex).registerB

val atomicReferenceRegister =
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 6).registerC
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex + 1).registerC

// Instruction that is replaced, and also has the CharacterSequence register.
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex)
val moveCharSequenceInstruction = getInstruction<TwoRegisterInstruction>(insertIndex - 1)
val charSequenceSourceRegister = moveCharSequenceInstruction.registerB
val charSequenceTargetRegister = moveCharSequenceInstruction.registerA

// In order to preserve the atomic reference register, because it is overwritten,
// use another free register to store it.
replaceInstruction(
atomicReferenceStartIndex + 2,
"move-result-object v$freeRegister"
)
replaceInstruction(
atomicReferenceStartIndex + 3,
"move-object v$charSequenceSourceRegister, v$freeRegister"
)

// Move the current instance to the free register, and get the conversion context from it.
// Must replace the instruction to preserve the control flow label.
replaceInstruction(insertIndex, "move-object/from16 v$freeRegister, p0")
replaceInstruction(insertIndex - 1, "move-object/from16 v$freeRegister, p0")
addInstructions(
insertIndex + 1,
insertIndex,
"""
# Move context to free register
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
invoke-static {v$freeRegister, v$atomicReferenceRegister, v$charSequenceSourceRegister}, $INTEGRATIONS_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
move-result-object v$freeRegister
# Replace the original instruction
# Replace the original char sequence with the modified one.
move-object v${charSequenceTargetRegister}, v${freeRegister}
"""
)
Expand All @@ -143,7 +152,7 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
val isDisLikesBooleanReference = getInstruction<ReferenceInstruction>(patternResult.endIndex).reference

val textViewFieldReference = // Like/Dislike button TextView field
getInstruction<ReferenceInstruction>(patternResult.endIndex - 1).reference
getInstruction<ReferenceInstruction>(patternResult.endIndex - 2).reference

// Check if the hooked TextView object is that of the dislike button.
// If RYD is disabled, or the TextView object is not that of the dislike button, the execution flow is not interrupted.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ object ShortsTextViewFingerprint : MethodFingerprint(
Opcode.IF_EQ,
Opcode.RETURN_VOID,
Opcode.IGET_OBJECT, // TextView field
Opcode.CHECK_CAST,
Opcode.IGET_BOOLEAN, // boolean field
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,13 @@ object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.MOVE_OBJECT, // Register B is free register
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT, // Register A and B is context, use B as context, reuse A as free register
Opcode.INVOKE_VIRTUAL, // Register C is atomic reference
Opcode.MOVE_RESULT_OBJECT, // Register A is char sequence
Opcode.MOVE_OBJECT,
Opcode.CHECK_CAST,
Opcode.MOVE_OBJECT, // Replace this instruction with patch code
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_OBJECT,
Opcode.INVOKE_INTERFACE, // Insert hook here
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ object TextComponentContextFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
parameters = listOf("L"),
opcodes = listOf(
Opcode.MOVE_OBJECT_FROM16,
Opcode.MOVE_OBJECT_FROM16,
Opcode.INVOKE_STATIC_RANGE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT, // conversion context field name
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT, // conversion context field name
Opcode.IGET_BOOLEAN,
Opcode.IGET,
Opcode.IGET,
Opcode.IGET,
)
)