feat(Tiktok): Bump compatibility to 32.5.3 (#3389)

BREAKING CHANGE: This removes a patch but consolidates it into another.
This commit is contained in:
d4rkk3y 2023-12-12 07:07:01 +07:00 committed by GitHub
parent b7e53fb170
commit 96cdc102dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 170 additions and 245 deletions

View File

@ -814,12 +814,6 @@ public final class app/revanced/patches/ticktick/misc/themeunlock/UnlockProPatch
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
} }
public final class app/revanced/patches/tiktok/ad/HideAdsPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/tiktok/ad/HideAdsPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V
public synthetic fun execute (Lapp/revanced/patcher/data/Context;)V
}
public final class app/revanced/patches/tiktok/feedfilter/FeedFilterPatch : app/revanced/patcher/patch/BytecodePatch { public final class app/revanced/patches/tiktok/feedfilter/FeedFilterPatch : app/revanced/patcher/patch/BytecodePatch {
public static final field INSTANCE Lapp/revanced/patches/tiktok/feedfilter/FeedFilterPatch; public static final field INSTANCE Lapp/revanced/patches/tiktok/feedfilter/FeedFilterPatch;
public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V public fun execute (Lapp/revanced/patcher/data/BytecodeContext;)V

View File

@ -1,51 +0,0 @@
package app.revanced.patches.tiktok.ad
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.tiktok.ad.fingerprints.ConvertHelpFeedItemListFingerprint
import app.revanced.patches.tiktok.ad.fingerprints.FeedItemListCloneFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch(
name = "Hide ads",
compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["30.8.4"]),
CompatiblePackage("com.zhiliaoapp.musically", ["30.8.4"])
]
)
@Suppress("unused")
object HideAdsPatch : BytecodePatch(
setOf(FeedItemListCloneFingerprint, ConvertHelpFeedItemListFingerprint)
) {
override fun execute(context: BytecodeContext) {
listOf(
FeedItemListCloneFingerprint,
ConvertHelpFeedItemListFingerprint
).forEach { fingerprint ->
val method = fingerprint.result!!.mutableMethod
// iterate all instructions in the clone method
for ((index, instruction) in method.implementation!!.instructions.withIndex()) {
// conditions for the instruction we need
if (instruction.opcode.ordinal != Opcode.IPUT_OBJECT.ordinal) continue
val preloadAdsFieldInstruction = (instruction as? ReferenceInstruction)
if ((preloadAdsFieldInstruction?.reference as? FieldReference)?.name != "preloadAds") continue
// set null instead of the field "preloadAds"
val overrideRegister = (preloadAdsFieldInstruction as TwoRegisterInstruction).registerA
method.addInstruction(
index,
"const/4 v$overrideRegister, 0x0"
)
return@forEach
}
throw PatchException("Can not find required instruction.")
}
}
}

View File

@ -1,10 +0,0 @@
package app.revanced.patches.tiktok.ad.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object ConvertHelpFeedItemListFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/ConvertHelp;") &&
methodDef.name.endsWith("${'$'}FeedItemList")
}
)

View File

@ -1,9 +0,0 @@
package app.revanced.patches.tiktok.ad.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
internal object FeedItemListCloneFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/FeedItemList;") && methodDef.name == "clone"
}
)

View File

@ -1,8 +1,8 @@
package app.revanced.patches.tiktok.feedfilter package app.revanced.patches.tiktok.feedfilter
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstructions
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
@ -10,31 +10,35 @@ import app.revanced.patches.tiktok.feedfilter.fingerprints.FeedApiServiceLIZFing
import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.SettingsPatch import app.revanced.patches.tiktok.misc.settings.SettingsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch( @Patch(
name = "Feed filter", name = "Feed filter",
description = "Filters tiktok videos: removing ads, removing livestreams.", description = "Removes ads, livestreams, stories, image videos " +
"and videos with a specific amount of views or likes from the feed.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class], dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill"), CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically") CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
] ]
) )
@Suppress("unused") @Suppress("unused")
object FeedFilterPatch : BytecodePatch(setOf(FeedApiServiceLIZFingerprint, SettingsStatusLoadFingerprint)) { object FeedFilterPatch : BytecodePatch(
setOf(FeedApiServiceLIZFingerprint, SettingsStatusLoadFingerprint)
) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val method = FeedApiServiceLIZFingerprint.result!!.mutableMethod FeedApiServiceLIZFingerprint.result?.mutableMethod?.apply {
for ((index, instruction) in method.implementation!!.instructions.withIndex()) { val returnFeedItemInstruction = getInstructions().first { it.opcode == Opcode.RETURN_OBJECT }
if (instruction.opcode != Opcode.RETURN_OBJECT) continue val feedItemsRegister = (returnFeedItemInstruction as OneRegisterInstruction).registerA
val feedItemsRegister = (instruction as OneRegisterInstruction).registerA
method.addInstruction( addInstruction(
index, returnFeedItemInstruction.location.index,
"invoke-static {v$feedItemsRegister}, Lapp/revanced/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V" "invoke-static { v$feedItemsRegister }, " +
"Lapp/revanced/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V"
) )
break } ?: throw FeedApiServiceLIZFingerprint.exception
}
SettingsStatusLoadFingerprint.result?.mutableMethod?.addInstruction( SettingsStatusLoadFingerprint.result?.mutableMethod?.addInstruction(
0, 0,

View File

@ -1,12 +1,9 @@
package app.revanced.patches.tiktok.feedfilter.fingerprints package app.revanced.patches.tiktok.feedfilter.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags
internal object FeedApiServiceLIZFingerprint : MethodFingerprint( internal object FeedApiServiceLIZFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.SYNTHETIC,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/FeedApiService;") && methodDef.name == "LIZ" methodDef.definingClass.endsWith("/FeedApiService;") && methodDef.name == "fetchFeedList"
} }
) )

View File

@ -4,10 +4,9 @@ import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions import app.revanced.patcher.extensions.InstructionExtensions.replaceInstructions
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
@ -18,18 +17,19 @@ import app.revanced.patches.tiktok.interaction.downloads.fingerprints.DownloadPa
import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.SettingsPatch import app.revanced.patches.tiktok.misc.settings.SettingsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
import app.revanced.util.exception
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.iface.reference.StringReference
@Patch( @Patch(
name = "Downloads", name = "Downloads",
description = "Removes download restrictions and changes the default path to download to.", description = "Removes download restrictions and changes the default path to download to.",
dependencies = [IntegrationsPatch::class, SettingsPatch::class], dependencies = [IntegrationsPatch::class, SettingsPatch::class],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["30.8.4"]), CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["30.8.4"]) CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
] ]
) )
@Suppress("unused") @Suppress("unused")
@ -43,25 +43,30 @@ object DownloadsPatch : BytecodePatch(
) )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val method1 = ACLCommonShareFingerprint.result!!.mutableMethod fun MethodFingerprint.getMethod() = result?.mutableMethod ?: throw exception
method1.replaceInstructions(
mapOf<MethodFingerprint, MutableMethod.() -> Unit>(
ACLCommonShareFingerprint to {
replaceInstructions(
0, 0,
""" """
const/4 v0, 0x0 const/4 v0, 0x0
return v0 return v0
""" """
) )
val method2 = ACLCommonShareFingerprint2.result!!.mutableMethod },
method2.replaceInstructions( ACLCommonShareFingerprint2 to {
replaceInstructions(
0, 0,
""" """
const/4 v0, 0x2 const/4 v0, 0x2
return v0 return v0
""" """
) )
},
// Download videos without watermark. // Download videos without watermark.
val method3 = ACLCommonShareFingerprint3.result!!.mutableMethod ACLCommonShareFingerprint3 to {
method3.addInstructionsWithLabels( addInstructionsWithLabels(
0, 0,
""" """
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z
@ -73,56 +78,48 @@ object DownloadsPatch : BytecodePatch(
nop nop
""" """
) )
//Change the download path patch },
val method4 = DownloadPathParentFingerprint.result!!.mutableMethod // Change the download path patch.
val implementation4 = method4.implementation DownloadPathParentFingerprint to {
val instructions = implementation4!!.instructions val targetIndex = indexOfFirstInstruction { opcode == Opcode.INVOKE_STATIC }
var targetOffset = -1
//Search for the target method called instruction offset.
for ((index, instruction) in instructions.withIndex()) {
if (instruction.opcode != Opcode.CONST_STRING) continue
val reference = (instruction as ReferenceInstruction).reference as StringReference
if (reference.string != "video/mp4") continue
val targetInstruction = instructions[index + 1]
if (targetInstruction.opcode != Opcode.INVOKE_STATIC) continue
targetOffset = index + 1
break
}
if (targetOffset == -1) throw PatchException("Can not find download path uri method.")
//Change videos' download path.
val downloadUriMethod = context val downloadUriMethod = context
.toMethodWalker(DownloadPathParentFingerprint.result!!.method) .toMethodWalker(this)
.nextMethod(targetOffset, true) .nextMethod(targetIndex, true)
.getMethod() as MutableMethod .getMethod() as MutableMethod
downloadUriMethod.implementation!!.instructions.forEachIndexed { index, instruction ->
if (instruction.opcode == Opcode.SGET_OBJECT) { val firstIndex = downloadUriMethod.indexOfFirstInstruction {
val overrideRegister = (instruction as OneRegisterInstruction).registerA opcode == Opcode.INVOKE_DIRECT && ((this as Instruction35c).reference as MethodReference).name == "<init>"
}
val secondIndex = downloadUriMethod.indexOfFirstInstruction {
opcode == Opcode.INVOKE_STATIC && ((this as Instruction35c).reference as MethodReference).returnType.contains(
"Uri"
)
}
downloadUriMethod.addInstructions( downloadUriMethod.addInstructions(
index + 1, secondIndex,
""" """
invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String; invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
move-result-object v$overrideRegister move-result-object v0
""" """
) )
}
if (instruction.opcode == Opcode.CONST_STRING) { downloadUriMethod.addInstructions(
val string = ((instruction as ReferenceInstruction).reference as StringReference).string firstIndex,
if (string.contains("/Camera")) {
val overrideRegister = (instruction as OneRegisterInstruction).registerA
val overrideString = string.replace("/Camera", "")
downloadUriMethod.replaceInstruction(
index,
""" """
const-string v$overrideRegister, "$overrideString" invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String;
move-result-object v0
""" """
) )
} },
} SettingsStatusLoadFingerprint to {
} addInstruction(
val method5 = SettingsStatusLoadFingerprint.result!!.mutableMethod
method5.addInstruction(
0, 0,
"invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableDownload()V" "invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableDownload()V"
) )
} }
).forEach { (fingerprint, patch) ->
fingerprint.getMethod().patch()
}
}
} }

View File

@ -3,13 +3,22 @@ package app.revanced.patches.tiktok.interaction.downloads.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
internal object DownloadPathParentFingerprint : MethodFingerprint( internal object DownloadPathParentFingerprint : MethodFingerprint(
"V", "L",
AccessFlags.PUBLIC or AccessFlags.FINAL, AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf( strings = listOf(
"code", "video/mp4"
"reason", ),
"params insufficient" parameters = listOf(
"L",
"L"
),
opcodes = listOf(
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT
) )
) )

View File

@ -7,27 +7,36 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint
import app.revanced.util.exception
import app.revanced.util.indexOfFirstInstruction
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch( @Patch(
name = "Playback speed", name = "Playback speed",
description = "Enables the playback speed option for all videos.", description = "Enables the playback speed option for all videos.",
compatiblePackages = [ compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill"), CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically") CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
] ]
) )
@Suppress("unused") @Suppress("unused")
object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint)) { object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint)) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val parentMethod = SpeedControlParentFingerprint.result!!.mutableMethod SpeedControlParentFingerprint.result?.mutableMethod?.apply {
val parentMethodInstructions = parentMethod.implementation!!.instructions val targetMethodCallIndex = indexOfFirstInstruction {
for ((index, instruction) in parentMethodInstructions.withIndex()) { if (opcode == Opcode.INVOKE_STATIC) {
if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue val paramsTypes = ((this as Instruction35c).reference as MethodReference).parameterTypes
paramsTypes.size == 1 && paramsTypes[0].contains("/Aweme;")
} else false
}
val isSpeedEnableMethod = context val isSpeedEnableMethod = context
.toMethodWalker(parentMethod) .toMethodWalker(this)
.nextMethod(index, true) .nextMethod(targetMethodCallIndex, true)
.getMethod() as MutableMethod .getMethod() as MutableMethod
isSpeedEnableMethod.addInstructions( isSpeedEnableMethod.addInstructions(
0, 0,
""" """
@ -35,7 +44,6 @@ object PlaybackSpeedPatch : BytecodePatch(setOf(SpeedControlParentFingerprint))
return v0 return v0
""" """
) )
break } ?: throw SpeedControlParentFingerprint.exception
}
} }
} }

View File

@ -5,12 +5,9 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.AccessFlags
internal object SpeedControlParentFingerprint : MethodFingerprint( internal object SpeedControlParentFingerprint : MethodFingerprint(
returnType = "L",
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
parameters = listOf(
"L"
),
strings = listOf( strings = listOf(
"playback_speed" "onStopTrackingTouch, hasTouchMove=",
", isCurVideoPaused: ",
"already_shown_edge_speed_guide"
) )
) )

View File

@ -1,6 +1,5 @@
package app.revanced.patches.tiktok.misc.settings package app.revanced.patches.tiktok.misc.settings
import app.revanced.util.exception
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
@ -14,17 +13,19 @@ import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationA
import app.revanced.patches.tiktok.misc.settings.fingerprints.AddSettingsEntryFingerprint import app.revanced.patches.tiktok.misc.settings.fingerprints.AddSettingsEntryFingerprint
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsEntryFingerprint import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsEntryFingerprint
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsEntryInfoFingerprint import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsEntryInfoFingerprint
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction35c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction22c
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch( @Patch(
name = "Settings", name = "Settings",
description = "Adds ReVanced settings to TikTok.", description = "Adds ReVanced settings to TikTok.",
dependencies = [IntegrationsPatch::class], dependencies = [IntegrationsPatch::class],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage("com.ss.android.ugc.trill", ["30.8.4"]), CompatiblePackage("com.ss.android.ugc.trill", ["32.5.3"]),
CompatiblePackage("com.zhiliaoapp.musically", ["30.8.4"]) CompatiblePackage("com.zhiliaoapp.musically", ["32.5.3"])
] ]
) )
object SettingsPatch : BytecodePatch( object SettingsPatch : BytecodePatch(
@ -57,31 +58,31 @@ object SettingsPatch : BytecodePatch(
?: throw SettingsEntryInfoFingerprint.exception ?: throw SettingsEntryInfoFingerprint.exception
// Create a settings entry for 'revanced settings' and add it to settings fragment // Create a settings entry for 'revanced settings' and add it to settings fragment
AddSettingsEntryFingerprint.result?.apply { AddSettingsEntryFingerprint.result?.mutableMethod?.apply {
scanResult.patternScanResult?.startIndex?.let { val markIndex = implementation!!.instructions.indexOfFirst {
val settingsEntries = mutableMethod.getInstruction(it + 3) it.opcode == Opcode.IGET_OBJECT && ((it as Instruction22c).reference as FieldReference).name == "headerUnit"
val addEntry = mutableMethod.getInstruction<BuilderInstruction35c>(it + 5) }
val register1 = addEntry.registerC
val register2 = addEntry.registerD val getUnitManager = getInstruction(markIndex + 2)
// Add the settings entry created to the settings fragment val addEntry = getInstruction(markIndex + 1)
mutableMethod.addInstructions(
it + 6, addInstructions(
markIndex + 2,
listOf( listOf(
settingsEntries, getUnitManager,
addEntry addEntry
) )
) )
// These instructions call a method that create a settings entry use reflection base on the class name of classes that construct settings entry
mutableMethod.addInstructions( addInstructions(
it + 6, markIndex + 2,
""" """
const-string v$register1, "$settingsButtonClass" const-string v0, "$settingsButtonClass"
const-string v$register2, "$settingsButtonInfoClass" const-string v1, "$settingsButtonInfoClass"
invoke-static {v$register1, v$register2}, $CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR invoke-static {v0, v1}, $CREATE_SETTINGS_ENTRY_METHOD_DESCRIPTOR
move-result-object v$register2 move-result-object v0
""" """
) )
}
} ?: throw AddSettingsEntryFingerprint.exception } ?: throw AddSettingsEntryFingerprint.exception
// Initialize the settings menu once the replaced setting entry is clicked. // Initialize the settings menu once the replaced setting entry is clicked.
@ -98,10 +99,10 @@ object SettingsPatch : BytecodePatch(
""" """
invoke-static {v$thisRegister}, $INITIALIZE_SETTINGS_METHOD_DESCRIPTOR invoke-static {v$thisRegister}, $INITIALIZE_SETTINGS_METHOD_DESCRIPTOR
move-result v$usableRegister move-result v$usableRegister
if-eqz v$usableRegister, :notrevanced if-eqz v$usableRegister, :do_not_open
return-void return-void
""", """,
ExternalLabel("notrevanced", getInstruction(initializeSettingsIndex)) ExternalLabel("do_not_open", getInstruction(initializeSettingsIndex))
) )
} ?: throw AdPersonalizationActivityOnCreateFingerprint.exception } ?: throw AdPersonalizationActivityOnCreateFingerprint.exception
} }

View File

@ -1,22 +1,10 @@
package app.revanced.patches.tiktok.misc.settings.fingerprints package app.revanced.patches.tiktok.misc.settings.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
internal object AddSettingsEntryFingerprint : MethodFingerprint( internal object AddSettingsEntryFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.CONST_CLASS,
Opcode.APUT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SettingNewVersionFragment;") && methodDef.definingClass.endsWith("/SettingNewVersionFragment;") &&
methodDef.name == "onViewCreated" methodDef.name == "initUnitManger"
} }
) )

View File

@ -1,6 +1,5 @@
package app.revanced.patches.tiktok.misc.spoof.sim package app.revanced.patches.tiktok.misc.spoof.sim
import app.revanced.util.findMutableMethodOf
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
@ -10,8 +9,9 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch import app.revanced.patches.tiktok.misc.integrations.IntegrationsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
import app.revanced.patches.tiktok.misc.settings.SettingsPatch import app.revanced.patches.tiktok.misc.settings.SettingsPatch
import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint
import app.revanced.util.findMutableMethodOf
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
@ -39,7 +39,7 @@ object SpoofSimPatch : BytecodePatch() {
) )
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// Find all api call to check sim information // Find all api call to check sim information.
buildMap { buildMap {
context.classes.forEach { classDef -> context.classes.forEach { classDef ->
classDef.methods.let { methods -> classDef.methods.let { methods ->
@ -81,7 +81,7 @@ object SpoofSimPatch : BytecodePatch() {
} }
} }
// Enable patch in settings // Enable patch in settings.
with(SettingsStatusLoadFingerprint.result!!.mutableMethod) { with(SettingsStatusLoadFingerprint.result!!.mutableMethod) {
addInstruction( addInstruction(
0, 0,
@ -90,7 +90,7 @@ object SpoofSimPatch : BytecodePatch() {
} }
} }
// Patch Android API and return fake sim information // Patch Android API and return fake sim information.
private fun MutableMethod.replaceReference(index: Int, replacement: String) { private fun MutableMethod.replaceReference(index: Int, replacement: String) {
val resultReg = getInstruction<OneRegisterInstruction>(index + 1).registerA val resultReg = getInstruction<OneRegisterInstruction>(index + 1).registerA