mirror of
https://github.com/revanced/revanced-patches.git
synced 2025-12-15 21:52:27 +01:00
Compare commits
40 Commits
v2.187.0-d
...
v2.188.0-d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5deaa6476f | ||
|
|
78d831fc63 | ||
|
|
46809c3819 | ||
|
|
8f559ca170 | ||
|
|
48ea11f571 | ||
|
|
2ff3400ef1 | ||
|
|
bc8ce81bbc | ||
|
|
7c131bfe1b | ||
|
|
f1e063ee76 | ||
|
|
3cd5f573b1 | ||
|
|
9eaf98e4a1 | ||
|
|
d56308539b | ||
|
|
68c4d965cd | ||
|
|
d10b5cf56e | ||
|
|
92223607fe | ||
|
|
21beefa7e6 | ||
|
|
fec613eb13 | ||
|
|
b007aa3827 | ||
|
|
8cd293310a | ||
|
|
9e8c4e61a5 | ||
|
|
9725870e6a | ||
|
|
204284f5d3 | ||
|
|
70cffa4466 | ||
|
|
4f885b15c0 | ||
|
|
28c541078b | ||
|
|
4d031cb029 | ||
|
|
1ea6f27d7d | ||
|
|
636e9dc446 | ||
|
|
dbcff623c8 | ||
|
|
e93adc15c2 | ||
|
|
244473cd4f | ||
|
|
efe7cbc78c | ||
|
|
9ac0ed477a | ||
|
|
9426b28dcc | ||
|
|
146b213b4a | ||
|
|
557a9f7418 | ||
|
|
e7b2bfbde3 | ||
|
|
d442acaac8 | ||
|
|
a00eab6744 | ||
|
|
87f2f90fc5 |
141
CHANGELOG.md
141
CHANGELOG.md
@@ -1,3 +1,144 @@
|
||||
# [2.188.0-dev.12](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.11...v2.188.0-dev.12) (2023-08-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `Override certificate pinning` patch ([#2781](https://github.com/ReVanced/revanced-patches/issues/2781)) ([94ed738](https://github.com/ReVanced/revanced-patches/commit/94ed738515aa6e1a1d346b85b54805e68e36f94c))
|
||||
|
||||
# [2.188.0-dev.11](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.10...v2.188.0-dev.11) (2023-08-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Client spoof:** Remove exception from option ([9c69f87](https://github.com/ReVanced/revanced-patches/commit/9c69f876902496c101eac295e581c15e02bfaf29))
|
||||
|
||||
# [2.188.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.9...v2.188.0-dev.10) (2023-08-09)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Tasker:** Remove `Unlock trial` patch ([8354a87](https://github.com/ReVanced/revanced-patches/commit/8354a879cfc6028820e2bb0e01d6f607e145c0f6))
|
||||
|
||||
# [2.188.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.8...v2.188.0-dev.9) (2023-08-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide video action buttons:** Hide individual action buttons ([#2723](https://github.com/ReVanced/revanced-patches/issues/2723)) ([220f694](https://github.com/ReVanced/revanced-patches/commit/220f694b12e7ed013753c8215d181936ab2205c3))
|
||||
|
||||
# [2.188.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.7...v2.188.0-dev.8) (2023-08-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Change package name:** Append `.revanced` to package name by default ([#2750](https://github.com/ReVanced/revanced-patches/issues/2750)) ([e83e62f](https://github.com/ReVanced/revanced-patches/commit/e83e62fc2400caf1c5179d25e0ac4fbd51ddba00))
|
||||
|
||||
# [2.188.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.6...v2.188.0-dev.7) (2023-08-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Debug:** Logging of layout proto buffer strings ([#2759](https://github.com/ReVanced/revanced-patches/issues/2759)) ([189f719](https://github.com/ReVanced/revanced-patches/commit/189f719720551f36c6e006c45558fe5ae46ca4f8))
|
||||
|
||||
# [2.188.0-dev.6](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.5...v2.188.0-dev.6) (2023-08-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Client spoof:** Adjust spoof signature settings description ([#2760](https://github.com/ReVanced/revanced-patches/issues/2760)) ([f71d893](https://github.com/ReVanced/revanced-patches/commit/f71d8937663fdbfc93d8e3ce1cdb47e1667554f0))
|
||||
|
||||
# [2.188.0-dev.5](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.4...v2.188.0-dev.5) (2023-08-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube Music:** Add `Permanent repeat` patch ([#2722](https://github.com/ReVanced/revanced-patches/issues/2722)) ([506d49c](https://github.com/ReVanced/revanced-patches/commit/506d49c82a68faee25aede8194e7884191c0f271))
|
||||
|
||||
# [2.188.0-dev.4](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.3...v2.188.0-dev.4) (2023-08-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve wording ([26f9b05](https://github.com/ReVanced/revanced-patches/commit/26f9b0514fda9434b2a36d2f9e5ad6a4f5bb94bd))
|
||||
* **Tiktok - Show seekbar:** Bump compatibility ([#2737](https://github.com/ReVanced/revanced-patches/issues/2737)) ([08413bd](https://github.com/ReVanced/revanced-patches/commit/08413bdc97aef892f7372c585d1d792eb95e30f4))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Lightroom:** Add `Disable mandatory login` patch ([#2738](https://github.com/ReVanced/revanced-patches/issues/2738)) ([896a713](https://github.com/ReVanced/revanced-patches/commit/896a71308f1084d7f941c5b59610e40ea5d53009))
|
||||
* **Lightroom:** Add `Unlock premium` patch ([#2740](https://github.com/ReVanced/revanced-patches/issues/2740)) ([e18a9bc](https://github.com/ReVanced/revanced-patches/commit/e18a9bcb50705d374ccbf03cd6ab9a140a2f23ec))
|
||||
* **YouTube Music:** Add `Permanent Shuffle` patch ([#2730](https://github.com/ReVanced/revanced-patches/issues/2730)) ([86a271c](https://github.com/ReVanced/revanced-patches/commit/86a271cd7cc3d1d2a11ff9ebe962574368b93f4f))
|
||||
|
||||
# [2.188.0-dev.3](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.2...v2.188.0-dev.3) (2023-08-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove newline ([545388b](https://github.com/ReVanced/revanced-patches/commit/545388b3b21cabb485c4d2025756c48984548d6b))
|
||||
|
||||
# [2.188.0-dev.2](https://github.com/ReVanced/revanced-patches/compare/v2.188.0-dev.1...v2.188.0-dev.2) (2023-08-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Reddit is Fun - Spoof client:** Use a more convincing user agent ([236a18f](https://github.com/ReVanced/revanced-patches/commit/236a18f9356cede156417c0d55a876d25a98cd4d))
|
||||
|
||||
# [2.188.0-dev.1](https://github.com/ReVanced/revanced-patches/compare/v2.187.0...v2.188.0-dev.1) (2023-08-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Nova Launcher:** Remove `Unlock prime` patch ([bbde91c](https://github.com/ReVanced/revanced-patches/commit/bbde91cf9df4b410a34147bbe5f359e39a71ad4c))
|
||||
|
||||
# [2.187.0](https://github.com/ReVanced/revanced-patches/compare/v2.186.0...v2.187.0) (2023-08-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Remove version numbers from individual patches ([#2709](https://github.com/ReVanced/revanced-patches/issues/2709)) ([7a828ea](https://github.com/ReVanced/revanced-patches/commit/7a828ea8826864505fac9b2bdb3a1261d9f4dc35))
|
||||
* **Sync for Reddit - Change OAuth client id:** Disable piracy detection ([cd103dd](https://github.com/ReVanced/revanced-patches/commit/cd103dd9b8ff2667246d4abaf75577f28bf1a11b))
|
||||
* Use clearer descriptions ([8dbb0e2](https://github.com/ReVanced/revanced-patches/commit/8dbb0e212e8ceeb0381a3509e45afca095ddee53))
|
||||
* **YouTube - Spoof app version:** Fix grammar in description ([#2711](https://github.com/ReVanced/revanced-patches/issues/2711)) ([dd249e6](https://github.com/ReVanced/revanced-patches/commit/dd249e62243e57733a6ff4d3a17d30db0e08a84d))
|
||||
* **YouTube - Spoof App Version:** Remove 17.30.35 target (version no longer works correctly) ([#2703](https://github.com/ReVanced/revanced-patches/issues/2703)) ([210108b](https://github.com/ReVanced/revanced-patches/commit/210108bd8f86f583f5cd5d5538480b76d51d7776))
|
||||
* **YouTube - Theme:** only set splash screen color if background colors are set ([f058db4](https://github.com/ReVanced/revanced-patches/commit/f058db4ba4300400ac92b4a9790708eb8bde7092))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Joey for Reddit:** Add `Change OAuth client id` patch ([1bac47d](https://github.com/ReVanced/revanced-patches/commit/1bac47df889b5221bef1c03e652f894be8d39385))
|
||||
* **Joey for Reddit:** Add `Disable ads` patch ([ad7e147](https://github.com/ReVanced/revanced-patches/commit/ad7e14771208dcab08fd6dc29403b1a4cf602111))
|
||||
* **Reddit is Fun - Spoof client:** Spoof the user agent ([b9aaf61](https://github.com/ReVanced/revanced-patches/commit/b9aaf610ad9f1f45a72265a3782d2cf996020139))
|
||||
* **Sync for Reddit:** add `Disable Sync for Lemmy bottom sheet` patch ([56b535b](https://github.com/ReVanced/revanced-patches/commit/56b535b2a136d4b0afbddf2c8e251889c2555056))
|
||||
* **YouTube - Hide layout components:** Hide `chips shelf` ([#2699](https://github.com/ReVanced/revanced-patches/issues/2699)) ([8e6058b](https://github.com/ReVanced/revanced-patches/commit/8e6058b62350b3d14d79e6fe52b0ad781b66b5de))
|
||||
* **YouTube:** add `Player Flyout Menu` patch ([#2295](https://github.com/ReVanced/revanced-patches/issues/2295)) ([aea0af0](https://github.com/ReVanced/revanced-patches/commit/aea0af059784ae4820a0e73ff91f97bbc3ebc4c7))
|
||||
|
||||
# [2.187.0-dev.10](https://github.com/ReVanced/revanced-patches/compare/v2.187.0-dev.9...v2.187.0-dev.10) (2023-08-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Reddit is Fun - Spoof client:** Spoof the user agent ([b9aaf61](https://github.com/ReVanced/revanced-patches/commit/b9aaf610ad9f1f45a72265a3782d2cf996020139))
|
||||
|
||||
# [2.187.0-dev.9](https://github.com/ReVanced/revanced-patches/compare/v2.187.0-dev.8...v2.187.0-dev.9) (2023-07-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use clearer descriptions ([8dbb0e2](https://github.com/ReVanced/revanced-patches/commit/8dbb0e212e8ceeb0381a3509e45afca095ddee53))
|
||||
|
||||
# [2.187.0-dev.8](https://github.com/ReVanced/revanced-patches/compare/v2.187.0-dev.7...v2.187.0-dev.8) (2023-07-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Sync for Reddit - Change OAuth client id:** Disable piracy detection ([cd103dd](https://github.com/ReVanced/revanced-patches/commit/cd103dd9b8ff2667246d4abaf75577f28bf1a11b))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **Joey for Reddit:** Add `Change OAuth client id` patch ([1bac47d](https://github.com/ReVanced/revanced-patches/commit/1bac47df889b5221bef1c03e652f894be8d39385))
|
||||
* **Joey for Reddit:** Add `Disable ads` patch ([ad7e147](https://github.com/ReVanced/revanced-patches/commit/ad7e14771208dcab08fd6dc29403b1a4cf602111))
|
||||
|
||||
# [2.187.0-dev.7](https://github.com/ReVanced/revanced-patches/compare/v2.187.0-dev.6...v2.187.0-dev.7) (2023-07-30)
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("app.revanced:revanced-patcher:12.0.0")
|
||||
implementation("app.revanced:revanced-patcher:12.1.1")
|
||||
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
|
||||
// Required for meta
|
||||
implementation("com.google.code.gson:gson:2.10.1")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 2.187.0-dev.7
|
||||
version = 2.188.0-dev.12
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,79 @@
|
||||
package app.revanced.patches.all.misc.network.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.*
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.all.misc.debugging.patch.EnableAndroidDebuggingPatch
|
||||
import org.w3c.dom.Element
|
||||
import java.io.File
|
||||
|
||||
@Patch(false)
|
||||
@Name("Override certificate pinning")
|
||||
@Description("Overrides certificate pinning, allowing to inspect traffic via a proxy.")
|
||||
@DependsOn([EnableAndroidDebuggingPatch::class])
|
||||
class OverrideCertificatePinningPatch : ResourcePatch {
|
||||
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
val resXmlDirectory = context["res/xml"]
|
||||
|
||||
// Add android:networkSecurityConfig="@xml/network_security_config" and the "networkSecurityConfig" attribute if it does not exist.
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val document = editor.file
|
||||
val applicationNode = document.getElementsByTagName("application").item(0) as Element
|
||||
|
||||
if (!applicationNode.hasAttribute("networkSecurityConfig")) {
|
||||
document.createAttribute("android:networkSecurityConfig")
|
||||
.apply { value = "@xml/network_security_config" }.let(applicationNode.attributes::setNamedItem)
|
||||
}
|
||||
}
|
||||
|
||||
// In case the file does not exist create the "network_security_config.xml" file.
|
||||
File(resXmlDirectory, "network_security_config.xml").apply {
|
||||
if (!exists()) {
|
||||
createNewFile()
|
||||
writeText(
|
||||
"""
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates
|
||||
src="user"
|
||||
overridePins="true" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
<debug-overrides>
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates
|
||||
src="user"
|
||||
overridePins="true" />
|
||||
</trust-anchors>
|
||||
</debug-overrides>
|
||||
</network-security-config>
|
||||
"""
|
||||
)
|
||||
} else {
|
||||
// If the file already exists.
|
||||
readText().let { text ->
|
||||
if (!text.contains("<certificates src=\"user\" />")) {
|
||||
writeText(
|
||||
text.replace(
|
||||
"<trust-anchors>",
|
||||
"<trust-anchors>\n<certificates src=\"user\" overridePins=\"true\" />\n<certificates src=\"system\" />"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -9,39 +9,43 @@ import org.w3c.dom.Element
|
||||
|
||||
@Patch(false)
|
||||
@Name("Change package name")
|
||||
@Description("Changes the package name.")
|
||||
@Description("Changes the package name. Appends \".revanced\" to the package name by default.")
|
||||
class ChangePackageNamePatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
packageName?.let { packageName ->
|
||||
val packageNameRegex = Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")
|
||||
if (!packageName.matches(packageNameRegex))
|
||||
return PatchResultError("Invalid package name")
|
||||
val packageNameToUse = packageName ?: getDefaultPackageName(context)
|
||||
|
||||
var originalPackageName: String
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
|
||||
originalPackageName = manifest.getAttribute("package")
|
||||
}
|
||||
val packageNameRegex = Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")
|
||||
if (!packageNameToUse.matches(packageNameRegex))
|
||||
return PatchResultError("Invalid package name")
|
||||
|
||||
if (!originalPackageName.matches(packageNameRegex))
|
||||
return PatchResultError("Failed to get the original package name")
|
||||
val originalPackageName = getOriginalPackageName(context)
|
||||
|
||||
context["AndroidManifest.xml"].apply {
|
||||
readText().replace(originalPackageName, packageName).let(::writeText)
|
||||
}
|
||||
|
||||
} ?: return PatchResultError("No package name provided")
|
||||
context["AndroidManifest.xml"].apply {
|
||||
readText().replace(originalPackageName, packageNameToUse).let(::writeText)
|
||||
}
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
private fun getDefaultPackageName(context: ResourceContext): String {
|
||||
val originalPackageName = getOriginalPackageName(context)
|
||||
return "$originalPackageName.revanced"
|
||||
}
|
||||
|
||||
private fun getOriginalPackageName(context: ResourceContext): String {
|
||||
context.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||
val manifest = editor.file.getElementsByTagName("manifest").item(0) as Element
|
||||
return manifest.getAttribute("package")
|
||||
}
|
||||
}
|
||||
|
||||
companion object : OptionsContainer() {
|
||||
var packageName: String? by option(
|
||||
PatchOption.StringOption(
|
||||
key = "packageName",
|
||||
default = null,
|
||||
title = "Package name",
|
||||
description = "The name of the package to rename of the app.",
|
||||
description = "The name of the package to rename the app to.",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package app.revanced.patches.lightroom.misc.login.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.adobe.lrmobile",)])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class DisableMandatoryLoginCompatibility
|
||||
@@ -0,0 +1,19 @@
|
||||
package app.revanced.patches.lightroom.misc.login.fingerprint
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object IsLoggedInFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
|
||||
opcodes = listOf(
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IF_NE,
|
||||
Opcode.CONST_4,
|
||||
Opcode.GOTO
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package app.revanced.patches.lightroom.misc.login.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.lightroom.misc.login.annotations.DisableMandatoryLoginCompatibility
|
||||
import app.revanced.patches.lightroom.misc.login.fingerprint.IsLoggedInFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("Disable mandatory login")
|
||||
@DisableMandatoryLoginCompatibility
|
||||
class DisableMandatoryLoginPatch : BytecodePatch(listOf(IsLoggedInFingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
IsLoggedInFingerprint.result?.mutableMethod?.apply {
|
||||
val index = implementation!!.instructions.lastIndex - 1
|
||||
// Set isLoggedIn = true.
|
||||
replaceInstruction(index, "const/4 v0, 0x1")
|
||||
} ?: throw IsLoggedInFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package app.revanced.patches.lightroom.misc.premium.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("com.adobe.lrmobile")])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class UnlockPremiumCompatibility
|
||||
@@ -0,0 +1,18 @@
|
||||
package app.revanced.patches.lightroom.misc.premium.fingerprint
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object HasPurchasedFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
|
||||
strings = listOf("isPurchaseDoneRecently = true, access platform profile present? = "),
|
||||
opcodes = listOf(
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.CONST_4,
|
||||
Opcode.CONST_4,
|
||||
Opcode.CONST_4,
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package app.revanced.patches.lightroom.misc.premium.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.lightroom.misc.premium.annotations.UnlockPremiumCompatibility
|
||||
import app.revanced.patches.lightroom.misc.premium.fingerprint.HasPurchasedFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("Unlock premium")
|
||||
@Description("Unlocks premium features.")
|
||||
@UnlockPremiumCompatibility
|
||||
class UnlockPremiumPatch : BytecodePatch(listOf(HasPurchasedFingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
// Set hasPremium = true.
|
||||
HasPurchasedFingerprint.result?.mutableMethod?.replaceInstruction(2, "const/4 v2, 0x1")
|
||||
?: throw HasPurchasedFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.patches.music.interaction.permanentrepeat.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object RepeatTrackFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
listOf("L", "L"),
|
||||
listOf(
|
||||
Opcode.CHECK_CAST,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.MOVE_RESULT,
|
||||
Opcode.IF_NEZ
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,40 @@
|
||||
package app.revanced.patches.music.interaction.permanentrepeat.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.music.annotations.MusicCompatibility
|
||||
import app.revanced.patches.music.interaction.permanentrepeat.fingerprints.RepeatTrackFingerprint
|
||||
|
||||
@Patch(false)
|
||||
@Name("Permanent repeat")
|
||||
@Description("Permanently remember your repeating preference even if the playlist ends or another track is played.")
|
||||
@MusicCompatibility
|
||||
class PermanentRepeatPatch : BytecodePatch(
|
||||
listOf(RepeatTrackFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
RepeatTrackFingerprint.result?.let {
|
||||
val startIndex = it.scanResult.patternScanResult!!.endIndex
|
||||
val repeatIndex = startIndex + 3
|
||||
|
||||
it.mutableMethod.apply {
|
||||
addInstructionsWithLabels(
|
||||
startIndex,
|
||||
"goto :repeat",
|
||||
ExternalLabel("repeat", getInstruction(repeatIndex))
|
||||
)
|
||||
}
|
||||
} ?: return RepeatTrackFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.music.interaction.permanentshuffle.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object DisableShuffleFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
AccessFlags.PUBLIC or AccessFlags.FINAL,
|
||||
listOf(),
|
||||
listOf(
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL,
|
||||
Opcode.SGET_OBJECT,
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.IGET_OBJECT,
|
||||
Opcode.INVOKE_VIRTUAL
|
||||
)
|
||||
)
|
||||
@@ -0,0 +1,29 @@
|
||||
package app.revanced.patches.music.interaction.permanentshuffle.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.music.annotations.MusicCompatibility
|
||||
import app.revanced.patches.music.interaction.permanentshuffle.fingerprints.DisableShuffleFingerprint
|
||||
|
||||
@Patch(false)
|
||||
@Name("Permanent shuffle")
|
||||
@Description("Permanently remember your shuffle preference " +
|
||||
"even if the playlist ends or another track is played.")
|
||||
@MusicCompatibility
|
||||
class PermanentShuffleTogglePatch : BytecodePatch(
|
||||
listOf(DisableShuffleFingerprint)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
DisableShuffleFingerprint.result?.mutableMethod?.addInstruction(0, "return-void")
|
||||
?: return DisableShuffleFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package app.revanced.patches.nova.prime.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[
|
||||
Package("com.teslacoilsw.launcher")
|
||||
]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class UnlockPrimeCompatibility
|
||||
@@ -1,16 +0,0 @@
|
||||
package app.revanced.patches.nova.prime.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object UnlockPrimeFingerprint : MethodFingerprint(
|
||||
"V",
|
||||
opcodes = listOf(
|
||||
Opcode.IPUT_OBJECT,
|
||||
Opcode.CONST_STRING,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_INTERFACE,
|
||||
Opcode.MOVE_RESULT
|
||||
),
|
||||
strings = listOf("1")
|
||||
)
|
||||
@@ -1,48 +0,0 @@
|
||||
package app.revanced.patches.nova.prime.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.nova.prime.annotations.UnlockPrimeCompatibility
|
||||
import app.revanced.patches.nova.prime.fingerprints.UnlockPrimeFingerprint
|
||||
import org.jf.dexlib2.builder.instruction.BuilderInstruction11x
|
||||
|
||||
@Patch
|
||||
@Name("Unlock prime")
|
||||
@Description("Unlocks Nova Prime and all functions of the app.")
|
||||
@UnlockPrimeCompatibility
|
||||
class UnlockPrimePatch : BytecodePatch(
|
||||
listOf(
|
||||
UnlockPrimeFingerprint
|
||||
)
|
||||
) {
|
||||
private companion object {
|
||||
// Any value except 0 unlocks prime, but 512 is needed for a protection mechanism
|
||||
// which would reset the preferences if the value on disk had changed after a restart.
|
||||
const val PRIME_STATUS: Int = 512
|
||||
}
|
||||
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
UnlockPrimeFingerprint.result?.apply {
|
||||
val insertIndex = scanResult.patternScanResult!!.endIndex + 1
|
||||
|
||||
val primeStatusRegister =
|
||||
(mutableMethod.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA
|
||||
|
||||
mutableMethod.addInstruction(
|
||||
insertIndex,
|
||||
"""
|
||||
const/16 v$primeStatusRegister, $PRIME_STATUS
|
||||
"""
|
||||
)
|
||||
} ?: return UnlockPrimeFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,15 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.*
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractChangeOAuthClientIdPatch(
|
||||
abstract class AbstractSpoofClientPatch(
|
||||
private val redirectUri: String,
|
||||
private val options: ChangeOAuthClientIdOptionsContainer,
|
||||
private val fingerprints: List<MethodFingerprint>
|
||||
) : BytecodePatch(fingerprints) {
|
||||
private val options: SpoofClientOptionsContainer,
|
||||
private val clientIdFingerprints: List<MethodFingerprint>,
|
||||
private val userAgentFingerprints: List<MethodFingerprint>? = null,
|
||||
) : BytecodePatch(buildList {
|
||||
addAll(clientIdFingerprints)
|
||||
userAgentFingerprints?.let(::addAll)
|
||||
}) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
if (options.clientId == null) {
|
||||
// Ensure device runs Android.
|
||||
@@ -27,7 +31,7 @@ abstract class AbstractChangeOAuthClientIdPatch(
|
||||
|
||||
val error = """
|
||||
In order to use this patch, you need to provide a client ID.
|
||||
You can do this by creating a file at ${it.absolutePath} with the client ID as its content.
|
||||
You can do that by creating a file at ${it.absolutePath} with the client ID as its content.
|
||||
Alternatively, you can provide the client ID using patch options.
|
||||
|
||||
You can get your client ID from https://www.reddit.com/prefs/apps.
|
||||
@@ -38,13 +42,39 @@ abstract class AbstractChangeOAuthClientIdPatch(
|
||||
}.let { options.clientId = it.readText().trim() }
|
||||
}
|
||||
|
||||
return fingerprints.map { it.result ?: throw it.toErrorResult() }.patch(context)
|
||||
fun List<MethodFingerprint>?.executePatch(
|
||||
patch: List<MethodFingerprintResult>.(BytecodeContext) -> PatchResult
|
||||
) {
|
||||
when (val result = this?.map { it.result ?: throw it.toErrorResult() }?.patch(context)) {
|
||||
is PatchResultError -> throw result
|
||||
}
|
||||
}
|
||||
|
||||
clientIdFingerprints.executePatch { patchClientId(context) }
|
||||
userAgentFingerprints.executePatch { patchUserAgent(context) }
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
abstract fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult
|
||||
/**
|
||||
* Patch the client ID. The fingerprints are guaranteed to be in the same order as in [clientIdFingerprints].
|
||||
*
|
||||
* @param context The current [BytecodeContext].
|
||||
*
|
||||
*/
|
||||
abstract fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult
|
||||
|
||||
/**
|
||||
* Patch the user agent. The fingerprints are guaranteed to be in the same order as in [userAgentFingerprints].
|
||||
*
|
||||
* @param context The current [BytecodeContext].
|
||||
*/
|
||||
// Not every client needs to patch the user agent.
|
||||
open fun List<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext): PatchResult =
|
||||
PatchResultSuccess()
|
||||
|
||||
companion object Options {
|
||||
open class ChangeOAuthClientIdOptionsContainer : OptionsContainer() {
|
||||
open class SpoofClientOptionsContainer : OptionsContainer() {
|
||||
var clientId by option(
|
||||
PatchOption.StringOption(
|
||||
"client-id",
|
||||
@@ -5,5 +5,5 @@ import app.revanced.patcher.patch.annotations.Patch
|
||||
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Patch
|
||||
@Name("Change OAuth client id")
|
||||
annotation class ChangeOAuthClientIdPatchAnnotation
|
||||
@Name("Spoof client")
|
||||
annotation class SpoofClientAnnotation
|
||||
@@ -9,15 +9,15 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.baconreader.api.fingerprints.GetAuthorizationUrlFingerprint
|
||||
import app.revanced.patches.reddit.customclients.baconreader.api.fingerprints.RequestTokenFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
@SpoofClientAnnotation
|
||||
@Description("Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://baconreader.com/auth\".")
|
||||
@Compatibility(
|
||||
@@ -26,11 +26,11 @@ import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
Package("com.onelouder.baconreader.premium")
|
||||
]
|
||||
)
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"http://baconreader.com/auth", Options, listOf(GetAuthorizationUrlFingerprint, RequestTokenFingerprint)
|
||||
) {
|
||||
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
fun MethodFingerprintResult.patch(replacementString: String) {
|
||||
val clientIdIndex = scanResult.stringsScanResult!!.matches.first().index
|
||||
|
||||
@@ -52,5 +52,5 @@ class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -8,29 +8,29 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
@SpoofClientAnnotation
|
||||
@Description("Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://rubenmayayo.com\".")
|
||||
@Compatibility([Package("com.rubenmayayo.reddit")])
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"http://rubenmayayo.com", Options, listOf(GetClientIdFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
first().mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
"""
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -9,23 +9,23 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints.GetHttpBasicAuthHeaderFingerprint
|
||||
import app.revanced.patches.reddit.customclients.infinityforreddit.api.fingerprints.LoginActivityOnCreateFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
@SpoofClientAnnotation
|
||||
@Description("Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"infinity://localhost\".")
|
||||
@Compatibility([Package("ml.docilealligator.infinityforreddit")])
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"infinity://localhost",
|
||||
Options,
|
||||
listOf(GetHttpBasicAuthHeaderFingerprint, LoginActivityOnCreateFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
forEach {
|
||||
val clientIdIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
it.mutableMethod.apply {
|
||||
@@ -41,5 +41,5 @@ class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.ads.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
|
||||
object IsAdFreeUserFingerprint : MethodFingerprint(
|
||||
returnType = "Z",
|
||||
accessFlags = AccessFlags.PUBLIC.value,
|
||||
strings = listOf("AD_FREE_USER")
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.ads.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Package
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.reddit.customclients.joeyforreddit.ads.fingerprints.IsAdFreeUserFingerprint
|
||||
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
|
||||
|
||||
@Patch
|
||||
@Name("Disable ads")
|
||||
@DependsOn([DisablePiracyDetectionPatch::class])
|
||||
@Compatibility([Package("o.o.joey")])
|
||||
class DisableAdsPatch : BytecodePatch(listOf(IsAdFreeUserFingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
IsAdFreeUserFingerprint.result?.mutableMethod?.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
) ?: return IsAdFreeUserFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object GetClientIdFingerprint : MethodFingerprint(
|
||||
returnType = "L",
|
||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
opcodes = listOf(
|
||||
Opcode.CONST, // R.string.valuable_cid
|
||||
Opcode.INVOKE_STATIC, // StringMaster.decrypt
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.RETURN_OBJECT
|
||||
),
|
||||
customFingerprint = custom@{ _, classDef ->
|
||||
classDef.sourceFile == "AuthUtility.java"
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.api.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Package
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.joeyforreddit.api.fingerprints.GetClientIdFingerprint
|
||||
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
|
||||
|
||||
@SpoofClientAnnotation
|
||||
@Description(
|
||||
"Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"https://127.0.0.1:65023/authorize_callback\"."
|
||||
)
|
||||
@Compatibility(
|
||||
[
|
||||
Package("o.o.joey"),
|
||||
Package("o.o.joey.pro"),
|
||||
Package("o.o.joey.dev")
|
||||
]
|
||||
)
|
||||
@DependsOn([DisablePiracyDetectionPatch::class])
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"https://127.0.0.1:65023/authorize_callback", Options, listOf(GetClientIdFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
first().mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object PiracyDetectionFingerprint : MethodFingerprint(
|
||||
returnType = "V",
|
||||
accessFlags = AccessFlags.PRIVATE or AccessFlags.STATIC,
|
||||
opcodes = listOf(
|
||||
Opcode.NEW_INSTANCE, // new PiracyDetectionRunnable()
|
||||
Opcode.CONST_16,
|
||||
Opcode.CONST_WIDE_16,
|
||||
Opcode.INVOKE_DIRECT, // <init>(..)
|
||||
Opcode.INVOKE_VIRTUAL, // run()
|
||||
Opcode.RETURN_VOID
|
||||
),
|
||||
customFingerprint = custom@{ _, classDef ->
|
||||
classDef.type.endsWith("ProcessLifeCyleListener;")
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,22 @@
|
||||
package app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.joeyforreddit.detection.piracy.fingerprints.PiracyDetectionFingerprint
|
||||
|
||||
class DisablePiracyDetectionPatch : BytecodePatch(listOf(PiracyDetectionFingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
PiracyDetectionFingerprint.result?.mutableMethod?.addInstruction(
|
||||
0,
|
||||
"""
|
||||
return-void
|
||||
"""
|
||||
) ?: return PiracyDetectionFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints
|
||||
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
|
||||
object GetUserAgentFingerprint : MethodFingerprint(
|
||||
"Ljava/lang/String;",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
emptyList(),
|
||||
listOf(
|
||||
Opcode.NEW_ARRAY,
|
||||
Opcode.CONST_4,
|
||||
Opcode.INVOKE_STATIC,
|
||||
Opcode.MOVE_RESULT_OBJECT,
|
||||
Opcode.APUT_OBJECT,
|
||||
Opcode.CONST,
|
||||
)
|
||||
)
|
||||
@@ -4,32 +4,32 @@ import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Package
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult.StringMatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.BasicAuthorizationFingerprint
|
||||
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.BuildAuthorizationStringFingerprint
|
||||
import app.revanced.patches.reddit.customclients.redditisfun.api.fingerprints.GetUserAgentFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
@SpoofClientAnnotation
|
||||
@Description("Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"redditisfun://auth\".")
|
||||
@Compatibility([Package("com.andrewshu.android.reddit"), Package("com.andrewshu.android.redditdonation")])
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"redditisfun://auth",
|
||||
Options,
|
||||
listOf(
|
||||
BuildAuthorizationStringFingerprint,
|
||||
BasicAuthorizationFingerprint,
|
||||
)
|
||||
listOf(BuildAuthorizationStringFingerprint, BasicAuthorizationFingerprint),
|
||||
listOf(GetUserAgentFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
/**
|
||||
* Replaces a one register instruction with a const-string instruction
|
||||
* at the index returned by [getReplacementIndex].
|
||||
@@ -57,5 +57,21 @@ class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
override fun List<MethodFingerprintResult>.patchUserAgent(context: BytecodeContext): PatchResult {
|
||||
// Use a random user agent.
|
||||
val randomName = (0..100000).random()
|
||||
val userAgent = "android:app.revanced.$randomName:v1.0.0 (by /u/revanced)"
|
||||
|
||||
first().mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$userAgent"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -9,20 +9,20 @@ import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.GetLoggedInBearerTokenFingerprint
|
||||
import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.GetLoggedOutBearerTokenFingerprint
|
||||
import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.GetRefreshTokenFingerprint
|
||||
import app.revanced.patches.reddit.customclients.relayforreddit.api.fingerprints.LoginActivityClientIdFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
@SpoofClientAnnotation
|
||||
@Description("Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"dbrady://relay\".")
|
||||
@Compatibility([Package("free.reddit.news"), Package("reddit.news")])
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"dbrady://relay",
|
||||
Options,
|
||||
listOf(
|
||||
@@ -32,7 +32,7 @@ class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
GetRefreshTokenFingerprint
|
||||
)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
forEach {
|
||||
val clientIdIndex = it.scanResult.stringsScanResult!!.matches.first().index
|
||||
it.mutableMethod.apply {
|
||||
@@ -48,5 +48,5 @@ class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -1,36 +1,36 @@
|
||||
package app.revanced.patches.reddit.customclients.slide.api.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Package
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://www.ccrama.me\".")
|
||||
@Compatibility([Package("me.ccrama.redditslide")])
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
"http://www.ccrama.me", Options, listOf(GetClientIdFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
first().mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
}
|
||||
package app.revanced.patches.reddit.customclients.slide.api.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Package
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.boostforreddit.api.fingerprints.GetClientIdFingerprint
|
||||
|
||||
@SpoofClientAnnotation
|
||||
@Description("Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://www.ccrama.me\".")
|
||||
@Compatibility([Package("me.ccrama.redditslide")])
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"http://www.ccrama.me", Options, listOf(GetClientIdFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
first().mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
const-string v0, "$clientId"
|
||||
return-object v0
|
||||
"""
|
||||
)
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.
|
||||
@Patch
|
||||
@Name("Disable ads")
|
||||
@DependsOn([DisablePiracyDetectionPatch::class])
|
||||
@Description("Disables ads.")
|
||||
@Compatibility([Package("com.laurencedawson.reddit_sync")])
|
||||
class DisableAdsPatch : BytecodePatch(listOf(IsAdsEnabledFingerprint)) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
|
||||
@@ -12,17 +12,19 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patches.reddit.customclients.AbstractChangeOAuthClientIdPatch
|
||||
import app.revanced.patches.reddit.customclients.ChangeOAuthClientIdPatchAnnotation
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.reddit.customclients.AbstractSpoofClientPatch
|
||||
import app.revanced.patches.reddit.customclients.SpoofClientAnnotation
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetAuthorizationStringFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.api.fingerprints.GetBearerTokenFingerprint
|
||||
import app.revanced.patches.reddit.customclients.syncforreddit.detection.piracy.patch.DisablePiracyDetectionPatch
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.iface.reference.StringReference
|
||||
import java.util.*
|
||||
|
||||
@ChangeOAuthClientIdPatchAnnotation
|
||||
@Description("Changes the OAuth client ID. " +
|
||||
@SpoofClientAnnotation
|
||||
@Description("Spoofs the client in order to allow logging in. " +
|
||||
"The OAuth application type has to be \"Installed app\" " +
|
||||
"and the redirect URI has to be set to \"http://redditsync/auth\".")
|
||||
@Compatibility(
|
||||
@@ -32,10 +34,11 @@ import java.util.*
|
||||
Package("com.laurencedawson.reddit_sync.dev")
|
||||
]
|
||||
)
|
||||
class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
@DependsOn([DisablePiracyDetectionPatch::class])
|
||||
class SpoofClientPatch : AbstractSpoofClientPatch(
|
||||
"http://redditsync/auth", Options, listOf(GetAuthorizationStringFingerprint)
|
||||
) {
|
||||
override fun List<MethodFingerprintResult>.patch(context: BytecodeContext): PatchResult {
|
||||
override fun List<MethodFingerprintResult>.patchClientId(context: BytecodeContext): PatchResult {
|
||||
forEach { fingerprintResult ->
|
||||
fingerprintResult.also { result ->
|
||||
GetBearerTokenFingerprint.also { it.resolve(context, result.classDef) }.result?.mutableMethod?.apply {
|
||||
@@ -72,5 +75,5 @@ class ChangeOAuthClientIdPatch : AbstractChangeOAuthClientIdPatch(
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
companion object Options : AbstractChangeOAuthClientIdPatch.Options.ChangeOAuthClientIdOptionsContainer()
|
||||
companion object Options : AbstractSpoofClientPatch.Options.SpoofClientOptionsContainer()
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package app.revanced.patches.tasker.trial.unlock.annotations
|
||||
|
||||
import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility([Package("net.dinglisch.android.taskerm")])
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class UnlockTrialCompatibility
|
||||
@@ -1,7 +0,0 @@
|
||||
package app.revanced.patches.tasker.trial.unlock.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object CheckLicenseFingerprint : MethodFingerprint(
|
||||
strings = listOf("Can't check license")
|
||||
)
|
||||
@@ -1,30 +0,0 @@
|
||||
package app.revanced.patches.tasker.trial.unlock.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.tasker.trial.unlock.annotations.UnlockTrialCompatibility
|
||||
import app.revanced.patches.tasker.trial.unlock.fingerprints.CheckLicenseFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("Unlock trial")
|
||||
@Description("Unlocks the trial version.")
|
||||
@UnlockTrialCompatibility
|
||||
class UnlockLicensePatch : BytecodePatch(
|
||||
listOf(
|
||||
CheckLicenseFingerprint
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext) = CheckLicenseFingerprint
|
||||
.result
|
||||
?.mutableMethod
|
||||
// Return the method early, which prompts the user with a non dismissible dialog, when the trial period is over.
|
||||
?.addInstruction(0, "return-void")
|
||||
?.let { PatchResultSuccess() }
|
||||
?: CheckLicenseFingerprint.toErrorResult()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package app.revanced.patches.tiktok.interaction.seekbar.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
object ShouldShowSeekBarFingerprint : MethodFingerprint(
|
||||
strings = listOf(
|
||||
"can not show seekbar, state: 1, not in resume"
|
||||
),
|
||||
)
|
||||
@@ -5,14 +5,13 @@ import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.Patch
|
||||
import app.revanced.patches.tiktok.interaction.seekbar.annotations.ShowSeekbarCompatibility
|
||||
import app.revanced.patches.tiktok.interaction.seekbar.fingerprints.SetSeekBarShowTypeFingerprint
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction22t
|
||||
import app.revanced.patches.tiktok.interaction.seekbar.fingerprints.ShouldShowSeekBarFingerprint
|
||||
|
||||
@Patch
|
||||
@Name("Show seekbar")
|
||||
@@ -21,11 +20,21 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction22t
|
||||
class ShowSeekbarPatch : BytecodePatch(
|
||||
listOf(
|
||||
SetSeekBarShowTypeFingerprint,
|
||||
ShouldShowSeekBarFingerprint,
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
ShouldShowSeekBarFingerprint.result?.mutableMethod?.apply {
|
||||
addInstructions(
|
||||
0,
|
||||
"""
|
||||
const/4 v0, 0x1
|
||||
return v0
|
||||
"""
|
||||
)
|
||||
}
|
||||
SetSeekBarShowTypeFingerprint.result?.mutableMethod?.apply {
|
||||
val typeRegister = getInstruction<Instruction22t>(1).registerB
|
||||
val typeRegister = implementation!!.registerCount - 1
|
||||
|
||||
addInstructions(
|
||||
0,
|
||||
|
||||
@@ -34,6 +34,30 @@ class HideButtonsPatch : ResourcePatch {
|
||||
StringResource("revanced_hide_like_dislike_button_summary_on", "Like and dislike buttons are hidden"),
|
||||
StringResource("revanced_hide_like_dislike_button_summary_off", "Like and dislike buttons are shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_live_chat_button",
|
||||
StringResource("revanced_hide_live_chat_button_title", "Hide live chat button"),
|
||||
StringResource("revanced_hide_live_chat_button_summary_on", "Live chat button is hidden"),
|
||||
StringResource("revanced_hide_live_chat_button_summary_off", "Live chat button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_share_button",
|
||||
StringResource("revanced_hide_share_button_title", "Hide share button"),
|
||||
StringResource("revanced_hide_share_button_summary_on", "Share button is hidden"),
|
||||
StringResource("revanced_hide_share_button_summary_off", "Share button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_report_button",
|
||||
StringResource("revanced_hide_report_button_title", "Hide report button"),
|
||||
StringResource("revanced_hide_report_button_summary_on", "Report button is hidden"),
|
||||
StringResource("revanced_hide_report_button_summary_off", "Report button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_remix_button",
|
||||
StringResource("revanced_hide_remix_button_title", "Hide remix button"),
|
||||
StringResource("revanced_hide_remix_button_summary_on", "Remix button is hidden"),
|
||||
StringResource("revanced_hide_remix_button_summary_off", "Remix button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_download_button",
|
||||
StringResource("revanced_hide_download_button_title", "Hide download button"),
|
||||
@@ -41,24 +65,28 @@ class HideButtonsPatch : ResourcePatch {
|
||||
StringResource("revanced_hide_download_button_summary_off", "Download button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_playlist_button",
|
||||
StringResource("revanced_hide_playlist_button_title", "Hide playlist button"),
|
||||
StringResource("revanced_hide_playlist_button_summary_on", "Playlist button is hidden"),
|
||||
StringResource("revanced_hide_playlist_button_summary_off", "Playlist button is shown")
|
||||
"revanced_hide_thanks_button",
|
||||
StringResource("revanced_hide_thanks_button_title", "Hide thanks button"),
|
||||
StringResource("revanced_hide_thanks_button_summary_on", "Thanks button is hidden"),
|
||||
StringResource("revanced_hide_thanks_button_summary_off", "Thanks button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_clip_button",
|
||||
StringResource("revanced_hide_clip_button_title", "Hide clip button"),
|
||||
StringResource("revanced_hide_clip_button_summary_on", "Clip button is hidden"),
|
||||
StringResource("revanced_hide_clip_button_summary_off", "Clip button is shown"),
|
||||
StringResource("revanced_hide_clip_button_user_dialog_message",
|
||||
"Hiding the clip button might not work reliably. In the case it does not work, it can only be hidden by enabling \\'Hide all other action buttons\\'")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_action_buttons",
|
||||
StringResource("revanced_hide_action_buttons_title", "Hide all other action buttons"),
|
||||
StringResource("revanced_hide_action_buttons_summary_on", "Share, remix, thanks, shop, live chat buttons are hidden"),
|
||||
StringResource("revanced_hide_action_buttons_summary_off", "Share, remix, thanks, shop, live chat buttons are shown")
|
||||
"revanced_hide_playlist_button",
|
||||
StringResource("revanced_hide_playlist_button_title", "Hide save to playlist button"),
|
||||
StringResource("revanced_hide_playlist_button_summary_on", "Save button is hidden"),
|
||||
StringResource("revanced_hide_playlist_button_summary_off", "Save button is shown")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_hide_shop_button",
|
||||
StringResource("revanced_hide_shop_button_title", "Hide shop button"),
|
||||
StringResource("revanced_hide_shop_button_summary_on", "Shop button is hidden"),
|
||||
StringResource("revanced_hide_shop_button_summary_off", "Shop button is shown")
|
||||
)
|
||||
),
|
||||
StringResource("revanced_hide_buttons_preference_screen_summary", "Hide or show buttons under videos")
|
||||
|
||||
@@ -2,7 +2,6 @@ package app.revanced.patches.youtube.layout.hide.player.flyoutmenupanel.patch
|
||||
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.ResourceContext
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
@@ -21,7 +20,6 @@ import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
@Description("Hides player flyout menu items.")
|
||||
@DependsOn([LithoFilterPatch::class, SettingsPatch::class])
|
||||
@HidePlayerFlyoutMenuItemsCompatibility
|
||||
@Version("0.0.1")
|
||||
class HidePlayerFlyoutMenuPatch : ResourcePatch {
|
||||
override fun execute(context: ResourceContext): PatchResult {
|
||||
SettingsPatch.PreferenceScreen.LAYOUT.addPreferences(
|
||||
|
||||
@@ -32,6 +32,15 @@ class DebuggingPatch : ResourcePatch {
|
||||
StringResource("revanced_debug_summary_on", "Debug logs are enabled"),
|
||||
StringResource("revanced_debug_summary_off", "Debug logs are disabled")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_debug_protobuffer",
|
||||
StringResource(
|
||||
"revanced_debug_protobuffer_title",
|
||||
"Log protocol buffer"
|
||||
),
|
||||
StringResource("revanced_debug_protobuffer_summary_on", "Debug logs include proto buffer"),
|
||||
StringResource("revanced_debug_protobuffer_summary_off", "Debug logs do not include proto buffer")
|
||||
),
|
||||
SwitchPreference(
|
||||
"revanced_debug_stacktrace",
|
||||
StringResource(
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
|
||||
@Patch
|
||||
@Name("Client spoof")
|
||||
@Description("Spoofs a patched client to allow playback.")
|
||||
@Description("Spoofs the client to allow playback.")
|
||||
@ClientSpoofCompatibility
|
||||
@DependsOn([SpoofSignatureVerificationPatch::class])
|
||||
class ClientSpoofPatch : BytecodePatch(
|
||||
|
||||
@@ -14,13 +14,16 @@ import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ProtobufParameterBuilderFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.ScrubbedPreviewLayoutFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailFingerprint
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.StoryboardThumbnailParentFingerprint
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
|
||||
@Name("Spoof signature verification")
|
||||
@Description("Spoofs a patched client to prevent playback issues.")
|
||||
@Description("Spoofs the client to prevent playback issues.")
|
||||
@DependsOn([
|
||||
SpoofSignatureVerificationResourcePatch::class,
|
||||
IntegrationsPatch::class,
|
||||
|
||||
@@ -8,7 +8,6 @@ import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch
|
||||
import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.fix.playback.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
|
||||
@DependsOn([SettingsPatch::class, ResourceMappingPatch::class])
|
||||
@@ -23,11 +22,11 @@ class SpoofSignatureVerificationResourcePatch : ResourcePatch {
|
||||
"App signature spoofed\\n\\n"
|
||||
+ "Side effects include:\\n"
|
||||
+ "• Ambient mode may not work\\n"
|
||||
+ "• Seekbar thumbnails are hidden\\n"
|
||||
+ "• Downloading videos may not work"),
|
||||
StringResource("revanced_spoof_signature_verification_summary_off", "App signature not spoofed"),
|
||||
+ "• Downloading videos may not work\\n"
|
||||
+ "• Seekbar thumbnails are always hidden"),
|
||||
StringResource("revanced_spoof_signature_verification_summary_off", "App signature not spoofed\\n\\nVideo playback may not work"),
|
||||
StringResource("revanced_spoof_signature_verification_user_dialog_message",
|
||||
"Turning off this setting may cause playback issues.")
|
||||
"Turning off this setting will cause video playback issues.")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -9,23 +9,19 @@ import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWith
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstructions
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
||||
import app.revanced.patcher.extensions.or
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
|
||||
import app.revanced.patcher.patch.BytecodePatch
|
||||
import app.revanced.patcher.patch.PatchResult
|
||||
import app.revanced.patcher.patch.PatchResultSuccess
|
||||
import app.revanced.patcher.patch.annotations.DependsOn
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
|
||||
import app.revanced.patcher.util.smali.ExternalLabel
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.litho.filter.fingerprints.*
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.immutable.ImmutableField
|
||||
import java.io.Closeable
|
||||
|
||||
@DependsOn([IntegrationsPatch::class])
|
||||
@@ -41,32 +37,29 @@ class LithoFilterPatch : BytecodePatch(
|
||||
* Additionally, the method contains a reference to the components identifier.
|
||||
* The identifier is used to filter components by their identifier.
|
||||
*
|
||||
* In addition to that, a static field is added to the class of this method. (See protobufBufferField).
|
||||
* This field holds a reference to the protobuf buffer object.
|
||||
* The field is being set in another method that holds a reference to the protobuf buffer object.
|
||||
* The object contains a large byte array that represents the component tree.
|
||||
* The protobuf buffer is passed along from a different injection point before the filtering occurs.
|
||||
* The buffer is a large byte array that represents the component tree.
|
||||
* This byte array is searched for strings that indicate the current component.
|
||||
*
|
||||
* The following pseudo code shows how the patch works:
|
||||
*
|
||||
* class ComponentContextParser {
|
||||
* public static ByteBuffer buffer; // Inserted by this patch.
|
||||
*
|
||||
* public ComponentContext parseBytesToComponentContext(...) {
|
||||
* ...
|
||||
* if (filter(identifier, pathBuilder, buffer)); // Inserted by this patch.
|
||||
* return emptyComponent;
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class SomeOtherClass {
|
||||
* // Called before ComponentContextParser.parseBytesToComponentContext method.
|
||||
* public void someOtherMethod(ByteBuffer byteBuffer) {
|
||||
* ComponentContextParser.buffer = byteBuffer; // Inserted by this patch.
|
||||
* IntegrationsClass.setProtoBuffer(byteBuffer); // Inserted by this patch.
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* class ComponentContextParser {
|
||||
*
|
||||
* public ComponentContext parseBytesToComponentContext(...) {
|
||||
* ...
|
||||
* if (IntegrationsClass.filter(identifier, pathBuilder)); // Inserted by this patch.
|
||||
* return emptyComponent;
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
ComponentContextParserFingerprint.result?.also {
|
||||
@@ -78,21 +71,12 @@ class LithoFilterPatch : BytecodePatch(
|
||||
return fingerprint.toErrorResult()
|
||||
}
|
||||
}?.let { bytesToComponentContextMethod ->
|
||||
// region Add a static field that holds a reference to the protobuf buffer object.
|
||||
val protobufBufferField = ImmutableField(
|
||||
bytesToComponentContextMethod.mutableClass.type,
|
||||
"buffer",
|
||||
"Ljava/nio/ByteBuffer;",
|
||||
AccessFlags.PUBLIC or AccessFlags.STATIC,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
).toMutable()
|
||||
bytesToComponentContextMethod.mutableClass.staticFields.add(protobufBufferField)
|
||||
|
||||
// Set the field with the reference to the protobuf buffer object.
|
||||
// region Pass the buffer into Integrations.
|
||||
|
||||
ProtobufBufferReferenceFingerprint.result
|
||||
?.mutableMethod?.addInstruction(0, "sput-object p2, $protobufBufferField")
|
||||
?.mutableMethod?.addInstruction(0,
|
||||
" invoke-static { p2 }, $INTEGRATIONS_CLASS_DESCRIPTOR->setProtoBuffer(Ljava/nio/ByteBuffer;)V")
|
||||
?: return ProtobufBufferReferenceFingerprint.toErrorResult()
|
||||
|
||||
// endregion
|
||||
@@ -135,17 +119,13 @@ class LithoFilterPatch : BytecodePatch(
|
||||
// region Patch the method.
|
||||
|
||||
// Insert the instructions that are responsible
|
||||
// to return an EmptyComponent instead of the original component if the filter method returns false.
|
||||
// to return an EmptyComponent instead of the original component if the filter method returns true.
|
||||
addInstructionsWithLabels(
|
||||
insertHookIndex,
|
||||
"""
|
||||
# Register "free1" holds the protobuf buffer object
|
||||
|
||||
sget-object v$free1, $protobufBufferField
|
||||
|
||||
# Invoke the filter method.
|
||||
|
||||
invoke-static { v$stringBuilderRegister, v$identifierRegister, v$free1 }, $FILTER_METHOD_DESCRIPTOR
|
||||
invoke-static { v$identifierRegister, v$stringBuilderRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->filter(Ljava/lang/String;Ljava/lang/StringBuilder;)Z
|
||||
move-result v$free1
|
||||
|
||||
if-eqz v$free1, :unfiltered
|
||||
@@ -197,9 +177,7 @@ class LithoFilterPatch : BytecodePatch(
|
||||
private val Instruction.descriptor
|
||||
get() = (this as ReferenceInstruction).reference.toString()
|
||||
|
||||
private const val FILTER_METHOD_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/components/LithoFilterPatch;" +
|
||||
"->filter(Ljava/lang/StringBuilder;Ljava/lang/String;Ljava/nio/ByteBuffer;)Z"
|
||||
const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/components/LithoFilterPatch;"
|
||||
|
||||
internal lateinit var addFilter: (String) -> Unit
|
||||
private set
|
||||
|
||||
Reference in New Issue
Block a user