Skip to content

Commit

Permalink
Generate a unique Deobfuscator class per project #14
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelRocks committed Feb 22, 2018
1 parent cffbb23 commit ad1e6e1
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 Michael Rozumyanskiy
* Copyright 2018 Michael Rozumyanskiy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -54,7 +54,8 @@ class ParanoidTransform(private val android: BaseExtension) : Transform() {
classpath = invocation.referencedInputs.flatMap {
it.jarInputs.map { it.file } + it.directoryInputs.map { it.file }
},
bootClasspath = android.bootClasspath
bootClasspath = android.bootClasspath,
projectName = invocation.context.path.replace(":transformClassesWithParanoidFor", ":").replace(':', '$')
)

try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 Michael Rozumyanskiy
* Copyright 2018 Michael Rozumyanskiy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@
package io.michaelrocks.paranoid.processor

import io.michaelrocks.paranoid.processor.logging.getLogger
import io.michaelrocks.paranoid.processor.model.Deobfuscator
import java.io.File
import java.util.Collections
import java.util.HashSet
Expand All @@ -25,7 +26,10 @@ import javax.tools.JavaFileObject
import javax.tools.StandardLocation
import javax.tools.ToolProvider

class Generator(private val stringRegistry: StringRegistry) {
class Generator(
private val deobfuscator: Deobfuscator,
private val stringRegistry: StringRegistry
) {
private val logger = getLogger()

fun generateDeobfuscator(
Expand All @@ -35,7 +39,7 @@ class Generator(private val stringRegistry: StringRegistry) {
bootClasspath: Collection<File>
) {
val sourceCode = generateDeobfuscatorSourceCode()
val sourceFile = File(sourcePath, "${DEOBFUSCATOR_TYPE.internalName}.java")
val sourceFile = File(sourcePath, "${deobfuscator.type.internalName}.java")

sourceFile.parentFile.mkdirs()
genPath.mkdirs()
Expand Down Expand Up @@ -107,7 +111,7 @@ class Generator(private val stringRegistry: StringRegistry) {
val locationChunkCount = (stringCount + chunkSize - 1) / chunkSize

return buildString {
val internalName = DEOBFUSCATOR_TYPE.internalName
val internalName = deobfuscator.type.internalName
val packageName = internalName.substringBeforeLast('/').replace('/', '.')
val className = internalName.substringAfterLast('/')
appendln("package $packageName;")
Expand Down Expand Up @@ -169,7 +173,7 @@ class Generator(private val stringRegistry: StringRegistry) {
}

appendln()
appendln(" public static String ${DEOBFUSCATION_METHOD.name}(final int id) {")
appendln(" public static String ${deobfuscator.deobfuscationMethod.name}(final int id) {")
appendln(" final int offset = locations[id * 2];")
appendln(" final int length = locations[id * 2 + 1];")
appendln(" final char[] stringChars = new char[length];")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 Michael Rozumyanskiy
* Copyright 2018 Michael Rozumyanskiy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,7 +18,11 @@ package io.michaelrocks.paranoid.processor

import io.michaelrocks.grip.Grip
import io.michaelrocks.grip.GripFactory
import io.michaelrocks.grip.mirrors.getObjectTypeByInternalName
import io.michaelrocks.paranoid.processor.logging.getLogger
import io.michaelrocks.paranoid.processor.model.Deobfuscator
import org.objectweb.asm.Type
import org.objectweb.asm.commons.Method
import java.io.File

class ParanoidProcessor(
Expand All @@ -27,7 +31,8 @@ class ParanoidProcessor(
private val sourcePath: File,
private val genPath: File,
private val classpath: Collection<File>,
private val bootClasspath: Collection<File>
private val bootClasspath: Collection<File>,
private val projectName: String
) {
private val logger = getLogger()

Expand All @@ -41,8 +46,11 @@ class ParanoidProcessor(

val analysisResult = Analyzer(grip).analyze(inputs)
analysisResult.dump()
Patcher(stringRegistry, grip.classRegistry).copyAndPatchClasses(inputs, outputs, analysisResult)
Generator(stringRegistry).generateDeobfuscator(sourcePath, genPath, outputs + classpath, bootClasspath)

val deobfuscator = createDeobfuscator()
logger.info("Prepare to generate {}", deobfuscator)
Patcher(deobfuscator, stringRegistry, grip.classRegistry).copyAndPatchClasses(inputs, outputs, analysisResult)
Generator(deobfuscator, stringRegistry).generateDeobfuscator(sourcePath, genPath, outputs + classpath, bootClasspath)
}

private fun AnalysisResult.dump() {
Expand All @@ -60,4 +68,20 @@ class ParanoidProcessor(
}
}
}

private fun createDeobfuscator(): Deobfuscator {
val deobfuscatorInternalName = "io/michaelrocks/paranoid/Deobfuscator${composeDeobfuscatorNameSuffix()}"
val deobfuscatorType = getObjectTypeByInternalName(deobfuscatorInternalName)
val deobfuscationMethod = Method("getString", Type.getType(String::class.java), arrayOf(Type.INT_TYPE))
return Deobfuscator(deobfuscatorType, deobfuscationMethod)
}

private fun composeDeobfuscatorNameSuffix(): String {
val normalizedProjectName = projectName.filter { it.isLetterOrDigit() || it == '_' || it == '$' }
return if (normalizedProjectName.isEmpty() || normalizedProjectName.startsWith('$')) {
normalizedProjectName
} else {
'$' + normalizedProjectName
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 Michael Rozumyanskiy
* Copyright 2018 Michael Rozumyanskiy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,11 +20,13 @@ import io.michaelrocks.grip.ClassRegistry
import io.michaelrocks.grip.mirrors.Type
import io.michaelrocks.grip.mirrors.getObjectTypeByInternalName
import io.michaelrocks.paranoid.processor.logging.getLogger
import io.michaelrocks.paranoid.processor.model.Deobfuscator
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassWriter
import java.io.File

class Patcher(
private val deobfuscator: Deobfuscator,
private val stringRegistry: StringRegistry,
private val classRegistry: ClassRegistry
) {
Expand Down Expand Up @@ -73,7 +75,7 @@ class Patcher(
logger.debug(" Target: {}", targetFile)
val reader = ClassReader(sourceFile.readBytes())
val writer = StandaloneClassWriter(reader, ClassWriter.COMPUTE_MAXS or ClassWriter.COMPUTE_FRAMES, classRegistry)
val stringLiteralsPatcher = StringLiteralsClassPatcher(stringRegistry, writer)
val stringLiteralsPatcher = StringLiteralsClassPatcher(deobfuscator, stringRegistry, writer)
val stringConstantsPatcher = StringConstantsClassPatcher(configuration, stringLiteralsPatcher)
reader.accept(stringConstantsPatcher, ClassReader.SKIP_FRAMES)
targetFile.parentFile.mkdirs()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 Michael Rozumyanskiy
* Copyright 2018 Michael Rozumyanskiy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,13 +16,16 @@

package io.michaelrocks.paranoid.processor

import io.michaelrocks.grip.mirrors.toAsmType
import io.michaelrocks.paranoid.processor.logging.getLogger
import io.michaelrocks.paranoid.processor.model.Deobfuscator
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.MethodVisitor
import org.objectweb.asm.Opcodes.ASM5
import org.objectweb.asm.commons.GeneratorAdapter

class StringLiteralsClassPatcher(
private val deobfuscator: Deobfuscator,
private val stringRegistry: StringRegistry,
delegate: ClassVisitor
) : ClassVisitor(ASM5, delegate) {
Expand Down Expand Up @@ -65,7 +68,7 @@ class StringLiteralsClassPatcher(
logger.info(" Obfuscating string literal: \"{}\"", string)
val stringId = stringRegistry.registerString(string)
push(stringId)
invokeStatic(DEOBFUSCATOR_TYPE, DEOBFUSCATION_METHOD)
invokeStatic(deobfuscator.type.toAsmType(), deobfuscator.deobfuscationMethod)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017 Michael Rozumyanskiy
* Copyright 2018 Michael Rozumyanskiy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,13 +16,8 @@

package io.michaelrocks.paranoid.processor

import org.objectweb.asm.Type
import org.objectweb.asm.commons.Method
import java.util.HashMap

val DEOBFUSCATOR_TYPE = Type.getObjectType("io/michaelrocks/paranoid/Deobfuscator")
val DEOBFUSCATION_METHOD: Method = Method("getString", Type.getType(String::class.java), arrayOf(Type.INT_TYPE))

interface StringRegistry {
fun registerString(string: String): Int
fun getAllIds(): Collection<Int>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2018 Michael Rozumyanskiy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.michaelrocks.paranoid.processor.model

import io.michaelrocks.grip.mirrors.Type
import org.objectweb.asm.commons.Method

data class Deobfuscator(
val type: Type.Object,
val deobfuscationMethod: Method
)

0 comments on commit ad1e6e1

Please sign in to comment.