From e0f33468e6e96b9f10cf35ec67622d6488528c90 Mon Sep 17 00:00:00 2001 From: Sylvain Finot <25269226+SF73@users.noreply.github.com> Date: Mon, 22 Dec 2025 15:00:08 +0100 Subject: [PATCH] feat(ProtonVPN): Add `Unlock split tunneling` patch (#6353) Co-authored-by: oSumAtrIX --- patches/api/patches.api | 4 +++ .../protonvpn/splittunneling/Fingerprints.kt | 20 +++++++++++ .../splittunneling/UnlockSplitTunneling.kt | 34 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt create mode 100644 patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt diff --git a/patches/api/patches.api b/patches/api/patches.api index 9f779cbed..c8438af90 100644 --- a/patches/api/patches.api +++ b/patches/api/patches.api @@ -649,6 +649,10 @@ public final class app/revanced/patches/protonvpn/delay/RemoveDelayPatchKt { public static final fun getRemoveDelayPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } +public final class app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunnelingKt { + public static final fun getUnlockSplitTunnelingPatch ()Lapp/revanced/patcher/patch/BytecodePatch; +} + public final class app/revanced/patches/rar/misc/annoyances/purchasereminder/HidePurchaseReminderPatchKt { public static final fun getHidePurchaseReminderPatch ()Lapp/revanced/patcher/patch/BytecodePatch; } diff --git a/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt new file mode 100644 index 000000000..639141723 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/Fingerprints.kt @@ -0,0 +1,20 @@ +package app.revanced.patches.protonvpn.splittunneling + +import app.revanced.patcher.fingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +internal val enableSplitTunnelingUiFingerprint = fingerprint { + strings("currentModeAppNames") + opcodes( + Opcode.MOVE_OBJECT, + Opcode.MOVE_FROM16, + Opcode.INVOKE_DIRECT_RANGE + ) +} + +internal val initializeSplitTunnelingSettingsUIFingerprint = fingerprint { + custom { method, _ -> + method.name == "applyRestrictions" + } +} \ No newline at end of file diff --git a/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt new file mode 100644 index 000000000..f50a5f993 --- /dev/null +++ b/patches/src/main/kotlin/app/revanced/patches/protonvpn/splittunneling/UnlockSplitTunneling.kt @@ -0,0 +1,34 @@ +package app.revanced.patches.protonvpn.splittunneling + +import app.revanced.patcher.extensions.InstructionExtensions.getInstruction +import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction +import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction +import app.revanced.patcher.patch.bytecodePatch +import app.revanced.util.getReference +import app.revanced.util.indexOfFirstInstructionOrThrow +import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference + +@Suppress("unused") +val unlockSplitTunnelingPatch = + bytecodePatch( + name = "Unlock split tunneling", + ) { + compatibleWith("ch.protonvpn.android") + + execute { + val registerIndex = enableSplitTunnelingUiFingerprint.patternMatch!!.endIndex - 1 + + enableSplitTunnelingUiFingerprint.method.apply { + val register = getInstruction(registerIndex).registerA + replaceInstruction(registerIndex, "const/4 v$register, 0x0") + } + + initializeSplitTunnelingSettingsUIFingerprint.method.apply { + val initSettingsIndex = indexOfFirstInstructionOrThrow { + getReference()?.name == "getSplitTunneling" + } + removeInstruction(initSettingsIndex - 1) + } + } + }