Skip to content

Commit

Permalink
build(Needs bump)!: Bump dependencies
Browse files Browse the repository at this point in the history
BREAKING CHANGE: This bump updates smali, a crucial dependency
  • Loading branch information
oSumAtrIX committed Aug 11, 2023
1 parent 496c224 commit d5f89a9
Show file tree
Hide file tree
Showing 44 changed files with 244 additions and 242 deletions.
19 changes: 11 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@ val githubPassword: String = project.findProperty("gpr.key") as? String ?: Syste

repositories {
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/revanced/multidexlib2")
credentials {
username = githubUsername
password = githubPassword
google()
listOf("multidexlib2", "apktool").forEach { repo ->
maven {
url = uri("https://maven.pkg.github.com/revanced/$repo")
credentials {
username = githubUsername
password = githubPassword
}
}
}
}

dependencies {
implementation("xpp3:xpp3:1.1.4c")
implementation("app.revanced:smali:2.5.3-a3836654")
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
implementation("app.revanced:apktool-lib:2.8.2-1")
implementation("com.android.tools.smali:smali:3.0.3")
implementation("app.revanced:multidexlib2:3.0.3.r2")
implementation("app.revanced:apktool-lib:2.8.2-2")

implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.22")
testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.20-RC")
Expand Down
188 changes: 88 additions & 100 deletions src/main/kotlin/app/revanced/patcher/Patcher.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,24 @@ import app.revanced.patcher.patch.*
import brut.androlib.AaptInvoker
import brut.androlib.ApkDecoder
import brut.androlib.Config
import brut.androlib.apk.ApkInfo
import brut.androlib.res.Framework
import brut.androlib.res.ResourcesDecoder
import brut.androlib.res.decoder.AndroidManifestResourceParser
import brut.androlib.res.decoder.ResAttrDecoder
import brut.androlib.res.decoder.XmlPullStreamDecoder
import brut.androlib.res.util.ExtMXSerializer
import brut.androlib.res.util.ExtXmlSerializer
import brut.androlib.res.xml.ResXmlPatcher
import brut.directory.ExtFile
import com.android.tools.smali.dexlib2.Opcodes
import com.android.tools.smali.dexlib2.iface.DexFile
import com.android.tools.smali.dexlib2.writer.io.MemoryDataStore
import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.DexIO
import lanchon.multidexlib2.MultiDexIO
import org.jf.dexlib2.Opcodes
import org.jf.dexlib2.iface.DexFile
import org.jf.dexlib2.writer.io.MemoryDataStore
import java.io.Closeable
import java.io.File
import java.io.OutputStream
import java.nio.file.Files
import java.util.logging.LogManager

internal val NAMER = BasicDexFileNamer()

Expand All @@ -37,18 +36,25 @@ internal val NAMER = BasicDexFileNamer()
* @param options The options for the patcher.
*/
class Patcher(private val options: PatcherOptions) {
val context: PatcherContext

private val logger = options.logger

private val opcodes: Opcodes

private var resourceDecodingMode = ResourceDecodingMode.MANIFEST_ONLY

private var mergeIntegrations = false
val context: PatcherContext

private val config = Config.getDefaultConfig().apply {
useAapt2 = true
aaptPath = options.aaptPath
frameworkDirectory = options.frameworkDirectory
}

init {
LogManager.getLogManager().getLogger("brut.*").useParentHandlers = false

logger.info("Reading dex files")
// read dex files
val dexFile = MultiDexIO.readDexFile(true, options.inputFile, NAMER, null, null)
Expand Down Expand Up @@ -84,61 +90,61 @@ class Patcher(private val options: PatcherOptions) {
fun save(): PatcherResult {
var resourceFile: File? = null

when (resourceDecodingMode) {
ResourceDecodingMode.FULL -> {
logger.info("Compiling resources")

val cacheDirectory = ExtFile(options.resourceCacheDirectory)
val aaptFile = cacheDirectory.resolve("aapt_temp_file").also {
Files.deleteIfExists(it.toPath())
}.also { resourceFile = it }

try {
AaptInvoker(
config,
context.packageMetadata.apkInfo
).invokeAapt(
aaptFile,
cacheDirectory.resolve("AndroidManifest.xml").also {
ResXmlPatcher.fixingPublicAttrsInProviderAttributes(it)
},
cacheDirectory.resolve("res"),
null,
null,
context.packageMetadata.apkInfo.usesFramework.let { usesFramework ->
usesFramework.ids.map { id ->
Framework(config).getFrameworkApk(id, usesFramework.tag)
}.toTypedArray()
}
)
} finally {
cacheDirectory.close()
}
if (resourceDecodingMode == ResourceDecodingMode.FULL) {
logger.info("Compiling resources")

val cacheDirectory = ExtFile(options.resourceCacheDirectory)
val aaptFile = cacheDirectory.resolve("aapt_temp_file").also {
Files.deleteIfExists(it.toPath())
}.also { resourceFile = it }

try {
AaptInvoker(
config,
context.packageMetadata.apkInfo
).invokeAapt(
aaptFile,
cacheDirectory.resolve("AndroidManifest.xml").also {
ResXmlPatcher.fixingPublicAttrsInProviderAttributes(it)
},
cacheDirectory.resolve("res"),
null,
null,
context.packageMetadata.apkInfo.usesFramework.let { usesFramework ->
usesFramework.ids.map { id ->
Framework(config).getFrameworkApk(id, usesFramework.tag)
}.toTypedArray()
}
)
} finally {
cacheDirectory.close()
}
else -> logger.info("Not compiling resources because resource patching is not required")
}

logger.trace("Creating new dex file")
val newDexFile = object : DexFile {
override fun getClasses() = context.bytecodeContext.classes.also { it.replaceClasses() }
override fun getOpcodes() = this@Patcher.opcodes
}

// write modified dex files
logger.info("Writing modified dex files")
val dexFiles = mutableMapOf<String, MemoryDataStore>()
MultiDexIO.writeDexFile(
true, -1, // core count
dexFiles, NAMER, newDexFile, DexIO.DEFAULT_MAX_DEX_POOL_SIZE, null
)

return PatcherResult(
dexFiles.map {
app.revanced.patcher.util.dex.DexFile(it.key, it.value.readAt(0))
},
context.packageMetadata.apkInfo.doNotCompress?.toList(),
resourceFile
)

return mutableMapOf<String, MemoryDataStore>().apply {
MultiDexIO.writeDexFile(
true,
-1, // Defaults to amount of available cores.
this,
NAMER,
object : DexFile {
override fun getClasses() = context.bytecodeContext.classes.also { it.replaceClasses() }
override fun getOpcodes() = this@Patcher.opcodes
},
DexIO.DEFAULT_MAX_DEX_POOL_SIZE,
null
)
}.let { dexFiles ->
PatcherResult(
dexFiles.map {
app.revanced.patcher.util.dex.DexFile(it.key, it.value.readAt(0))
},
context.packageMetadata.apkInfo.doNotCompress?.toList(),
resourceFile
)
}
}

/**
Expand Down Expand Up @@ -178,73 +184,55 @@ class Patcher(private val options: PatcherOptions) {
* @param mode The [ResourceDecodingMode] to use when decoding.
*/
private fun decodeResources(mode: ResourceDecodingMode) {
val extInputFile = ExtFile(options.inputFile)
try {
val resourcesDecoder = ResourcesDecoder(config, extInputFile)
val apkInfo = ApkInfo(ExtFile(options.inputFile)).also { context.packageMetadata.apkInfo = it }

// Needed to record uncompressed files.
val apkDecoder = ApkDecoder(config, apkInfo)

// Needed to decode resources.
val resourcesDecoder = ResourcesDecoder(config, apkInfo)

try {
when (mode) {
ResourceDecodingMode.FULL -> {
val outDir = File(options.resourceCacheDirectory)
if (outDir.exists()) {
logger.info("Deleting existing resource cache directory")
if (!outDir.deleteRecursively()) logger.error("Failed to delete existing resource cache directory")
}

outDir.mkdirs()
val outDir = options.recreateResourceCacheDirectory()

logger.info("Decoding resources")

resourcesDecoder.decodeManifest(outDir)
resourcesDecoder.decodeResources(outDir)

context.packageMetadata.also {
it.apkInfo = resourcesDecoder.apkInfo
}.apkInfo.doNotCompress = ApkDecoder(config, extInputFile).recordUncompressedFiles(
context.packageMetadata.apkInfo, resourcesDecoder.resFileMapping
)
apkDecoder.recordUncompressedFiles(resourcesDecoder.resFileMapping)
}
ResourceDecodingMode.MANIFEST_ONLY -> {
logger.info("Decoding AndroidManifest.xml only, because resources are not needed")

// Instead of using resourceDecoder.decodeManifest which decodes the whole file
// use the XmlPullStreamDecoder in order to get necessary information from the manifest
// used below.
XmlPullStreamDecoder(AndroidManifestResourceParser().apply {
attrDecoder = ResAttrDecoder().apply { this.resTable = resourcesDecoder.resTable }
}, ExtMXSerializer().apply {
setProperty(
ExtXmlSerializer.PROPERTY_SERIALIZER_INDENTATION, " "
)
setProperty(
ExtXmlSerializer.PROPERTY_SERIALIZER_LINE_SEPARATOR,
System.getProperty("line.separator")
)
setProperty(
ExtXmlSerializer.PROPERTY_DEFAULT_ENCODING,
"utf-8"
)
setDisabledAttrEscape(true)
}
logger.info("Decoding app manifest")

// Decode manually instead of using resourceDecoder.decodeManifest
// because it does not support decoding to an OutputStream.
XmlPullStreamDecoder(
AndroidManifestResourceParser(resourcesDecoder.resTable),
resourcesDecoder.resXmlSerializer
).decodeManifest(
extInputFile.directory.getFileInput("AndroidManifest.xml"),
apkInfo.apkFile.directory.getFileInput("AndroidManifest.xml"),
// Older Android versions do not support OutputStream.nullOutputStream()
object : OutputStream() { override fun write(b: Int) { /* do nothing */ } }
object : OutputStream() {
override fun write(b: Int) { /* do nothing */
}
}
)
}
}

// Get the package name and version from the manifest using the XmlPullStreamDecoder.
// XmlPullStreamDecoder.decodeManifest() sets metadata.apkInfo.
context.packageMetadata.let { metadata ->
metadata.apkInfo = resourcesDecoder.apkInfo

metadata.packageName = resourcesDecoder.resTable.currentResPackage.name
resourcesDecoder.apkInfo.versionInfo.let {
apkInfo.versionInfo.let {
metadata.packageVersion = it.versionName ?: it.versionCode
}
}
} finally {
extInputFile.close()
apkInfo.apkFile.close()
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/app/revanced/patcher/PatcherContext.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import app.revanced.patcher.data.*
import app.revanced.patcher.logging.Logger
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.util.ClassMerger.merge
import org.jf.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.ClassDef
import java.io.File

data class PatcherContext(
Expand Down
13 changes: 12 additions & 1 deletion src/main/kotlin/app/revanced/patcher/PatcherOptions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,15 @@ data class PatcherOptions(
internal val aaptPath: String? = null,
internal val frameworkDirectory: String? = null,
internal val logger: Logger = NopLogger
)
) {
fun recreateResourceCacheDirectory() = File(resourceCacheDirectory).also {
if (it.exists()) {
logger.info("Deleting existing resource cache directory")

if (!it.deleteRecursively())
logger.error("Failed to delete existing resource cache directory")
}

it.mkdirs()
}
}
4 changes: 2 additions & 2 deletions src/main/kotlin/app/revanced/patcher/data/Context.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package app.revanced.patcher.data

import app.revanced.patcher.util.ProxyBackedClassList
import app.revanced.patcher.util.method.MethodWalker
import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import org.w3c.dom.Document
import java.io.Closeable
import java.io.File
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package app.revanced.patcher.extensions

import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import org.jf.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.AccessFlags

/**
* Create a label for the instruction at given index.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patcher.util.smali.toInstruction
import app.revanced.patcher.util.smali.toInstructions
import org.jf.dexlib2.builder.BuilderInstruction
import org.jf.dexlib2.builder.BuilderOffsetInstruction
import org.jf.dexlib2.builder.Label
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.builder.instruction.*
import org.jf.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.builder.BuilderInstruction
import com.android.tools.smali.dexlib2.builder.BuilderOffsetInstruction
import com.android.tools.smali.dexlib2.builder.Label
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.builder.instruction.*
import com.android.tools.smali.dexlib2.iface.instruction.Instruction

object InstructionExtensions {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import app.revanced.patcher.fingerprint.Fingerprint
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.patch.PatchResultError
import app.revanced.patcher.util.proxy.ClassProxy
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.Instruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.util.MethodUtil
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.*

private typealias StringMatch = MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult.StringMatch
Expand Down
Loading

0 comments on commit d5f89a9

Please sign in to comment.