问题
I found an article which introduces the concept of randomizing the dictionary entries instead of using the standard "a, b, c, ..." for class names and variables when obfuscating. He explains that tasks can be run in gradle on build to generate a randomized text file which can replace the one provided by default:
tasks.whenTaskAdded { currentTask ->
//Android Gradle plugin may change this task name in the future
def prefix = 'transformClassesAndResourcesWithProguardFor'
if (currentTask.name.startsWith(prefix)) {
def taskName = currentTask.name.replace(prefix,
'createProguardDictionariesFor')
task "$taskName" {
doLast {
createRandomizedDictonaries()
}
}
//append scramble task to proguard task
currentTask.dependsOn "$taskName"
}
}
However, I don't know how he runs createRandomizedDictonaries()
in gradle and how he creates a text file which contains a random list of letters/integers/symbols. The logic could be something like:
- Run a function in a class from gradle.
- Read strings within a master text file (within the app) and adds them one by one into a string Arraylist with a loop? Potentially combine this with some randomization logic to add only X strings from text file?
- If all the strings were added to an Arraylist, use some randomization logic to add X number of strings into another string Arraylist which is to be used for ProGuard's obfuscation.
- Create a new text file with the randomized strings from the Arraylist.
- Direct ProGuard to use newly generated text file for obfuscation.
Solutions for both kotlin and java are welcome.
回答1:
I found a web which is talk about use gradle to build a obfuscationdictionary. https://yrom.net/blog/2019/06/19/simple-codes-to-generate-obfuscation-dictionary/
I run the code in my gradle task, but it needs to modify a little bit. The following is my gradle code:
task genDict{
outputs.file('D:/ProjectName/build/tmp/builddict.txt')
doLast{
def r =new Random()
println(r)
def begin = r.nextInt(1000) + 0x0100
def end = begin + 0x40000
println("end: "+end)
def chars = (begin..end)
.findAll { Character.isValidCodePoint(it) && Character.isJavaIdentifierPart(it) }
.collect { String.valueOf(Character.toChars(it)) }
println("chars: "+chars)
int max = chars.size()
println(max)
def start = []
def dict = []
for (int i = 0; i < max; i++) {
char c = chars.get(i).charAt(0)
if (Character.isJavaIdentifierStart(c)) {
start << String.valueOf(c)
}
}
println(start.size())
def f = outputs.files.getSingleFile()
f.getParentFile().mkdirs()
f.withWriter("UTF-8") {
it.write(start.join(System.lineSeparator()))
it.write()
}
}
I think you can set your dictionary rule. This is an example. Don't forget to add the obfuscation rule in your proguard-rules.pro file
-obfuscationdictionary 'D:\ProjectName\build\tmp\builddict.txt'
-classobfuscationdictionary 'D:\ProjectName\build\tmp\builddict.txt'
-packageobfuscationdictionary 'D:\ProjectName\build\tmp\builddict.txt'
来源:https://stackoverflow.com/questions/61015798/how-to-randomize-proguard-dictionaries-on-each-build