fix(NetWall - Unlock Premium): Add signature check bypass to avoid app crashes

Previously, this patch worked only on the app with pre-killed signature verification. Now, the patch itself will fix the signature check.
This commit is contained in:
Aaron Veil 2025-10-03 21:37:58 +03:00
parent 667d2230f7
commit decae2732d
3 changed files with 63 additions and 4 deletions

View file

@ -6,3 +6,11 @@ internal val premiumCheckFingerprint = legacyFingerprint(
parameters = listOf("I"),
strings = listOf("ODAz")
)
internal val integrityCheckFingerprint = legacyFingerprint(
name = "integrityCheckFingerprint",
returnType = "Ljava/lang/Object;",
strings = listOf(
"System.exit returned normally, while it was supposed to halt JVM."
)
)

View file

@ -3,19 +3,24 @@ package app.revanced.patches.netwall
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.patch.resourcePatch
import app.revanced.patcher.patch.*
import app.revanced.util.FilesCompat
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
import app.revanced.util.inputStreamFromBundledResourceOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.NarrowLiteralInstruction
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import integrityCheckFingerprint
import org.w3c.dom.Element
import org.w3c.dom.Node
import premiumCheckFingerprint
private lateinit var context: ResourcePatchContext
@Suppress("unused")
val unlockPremiumPatch = bytecodePatch {
execute {
@ -38,17 +43,40 @@ val unlockPremiumPatch = bytecodePatch {
}
replaceInstruction(constIndex, "const/16 p0, 0x1f4")
// Remove killProcess to avoid app crash
val targetMethod = integrityCheckFingerprint.methodOrThrow()
val killProcessIndex = targetMethod.indexOfFirstInstructionOrThrow {
opcode == Opcode.INVOKE_STATIC &&
getReference<MethodReference>()?.toString() == "Landroid/os/Process;->killProcess(I)V"
}
val conditionalJumpIndex = targetMethod.indexOfFirstInstructionReversedOrThrow(killProcessIndex) {
opcode == Opcode.IF_EQZ
}
targetMethod.replaceInstruction(conditionalJumpIndex, "nop")
}
}
}
@Suppress("unused")
private val unlockPremiumRawResourcePatch = rawResourcePatch(
description = "unlockPremiumRawResourcePatch"
) {
execute {
context = this
}
}
@Suppress("unused")
val unlockPremiumResourcePatch = resourcePatch(
name = "Unlock Premium",
description = "Unlocks NetWall Premium features once 'Unlock Premium Now' button is clicked.",
) {
compatibleWith("com.ysy.app.firewall")
dependsOn(unlockPremiumPatch)
dependsOn(unlockPremiumPatch, unlockPremiumRawResourcePatch)
execute {
document("AndroidManifest.xml").use { document ->
@ -86,5 +114,28 @@ val unlockPremiumResourcePatch = resourcePatch(
}
}
}
// Replace libnetwall.so with the patched one to avoid app crash.
with(context) {
setOf(
"arm64-v8a",
// "armeabi-v7a",
// "x86",
// "x86_64"
).forEach { arch ->
val architectureDirectory = get("lib/$arch")
if (architectureDirectory.exists()) {
val inputStream = inputStreamFromBundledResourceOrThrow(
"shared/netwall/lib",
"$arch/libnetwall.so"
)
FilesCompat.copy(
inputStream,
architectureDirectory.resolve("libnetwall.so"),
)
}
}
}
}
}