add: resource patcher

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
oSumAtrIX
2022-05-04 23:46:04 +02:00
parent c459beb5f8
commit 99319e63da
17 changed files with 304 additions and 74 deletions

View File

@@ -1,7 +1,8 @@
package app.revanced.patcher
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.usage.ExamplePatch
import app.revanced.patcher.usage.ExampleBytecodePatch
import app.revanced.patcher.usage.ExampleResourcePatch
import org.junit.jupiter.api.Test
import java.io.File
import kotlin.test.assertTrue
@@ -9,8 +10,14 @@ import kotlin.test.assertTrue
internal class PatcherTest {
@Test
fun testPatcher() {
val patcher = Patcher(File(PatcherTest::class.java.getResource("/test1.dex")!!.toURI()))
patcher.addPatches(listOf(ExamplePatch()))
val patcher = Patcher(
File(PatcherTest::class.java.getResource("/test1.dex")!!.toURI()),
"exampleCacheDirectory",
patchResources = true
)
patcher.addPatches(listOf(ExampleBytecodePatch(), ExampleResourcePatch()))
for (signature in patcher.resolveSignatures()) {
if (!signature.resolved) {
throw Exception("Signature ${signature.metadata.name} was not resolved!")

View File

@@ -1,9 +1,13 @@
package app.revanced.patcher.usage
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.signature.MethodMetadata
@@ -35,7 +39,7 @@ val packageMetadata = listOf(
)
)
class ExamplePatch : Patch(
class ExampleBytecodePatch : BytecodePatch(
PatchMetadata(
"example-patch",
"ReVanced example patch",
@@ -71,7 +75,7 @@ class ExamplePatch : Patch(
) {
// This function will be executed by the patcher.
// You can treat it as a constructor
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
// Get the resolved method for the signature from the resolver cache
val result = signatures.first().result!!
@@ -86,7 +90,7 @@ class ExamplePatch : Patch(
implementation.replaceStringAt(startIndex, "Hello, ReVanced! Editing bytecode.")
// Get the class in which the method matching our signature is defined in.
val mainClass = patcherData.findClass {
val mainClass = data.findClass {
it.type == result.definingClassProxy.immutableClass.type
}!!.resolve()

View File

@@ -0,0 +1,50 @@
package app.revanced.patcher.usage
import app.revanced.patcher.data.implementation.ResourceData
import app.revanced.patcher.patch.implementation.ResourcePatch
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import com.sun.org.apache.xerces.internal.dom.ElementImpl
class ExampleResourcePatch : ResourcePatch(
PatchMetadata(
"example-patch",
"Example Resource Patch",
"Example demonstration of a resource patch.",
packageMetadata,
"0.0.1"
)
) {
override fun execute(data: ResourceData): PatchResult {
val editor = data.getXmlEditor("AndroidManifest.xml")
// regular DomFileEditor
val element = editor
.file
.getElementsByTagName("application")
.item(0) as ElementImpl
element
.setAttribute(
"exampleAttribute",
"exampleValue"
)
// close the editor to write changes
editor.close()
// iterate through all available resources
data.forEach {
if (it.extension.lowercase() != "xml") return@forEach
data.replace(
it.path,
"\\ddip", // regex supported
"0dip",
true
)
}
return PatchResultSuccess()
}
}