Skip to content

Commit

Permalink
1.5.5 [Fixed bug & Shuffle]
Browse files Browse the repository at this point in the history
  • Loading branch information
SpartanB312 committed Nov 28, 2022
1 parent 78c3c32 commit 460ed7b
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 28 deletions.
11 changes: 7 additions & 4 deletions src/main/kotlin/net/spartanb312/grunt/Grunt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import net.spartanb312.grunt.process.resource.ResourceCache
import net.spartanb312.grunt.utils.logging.Logger

const val VERSION = "1.5.5"
const val TYPE = "Beta"
const val AUTHOR = "B_312"
const val GITHUB = "https://github.com/SpartanB312/Grunt"

fun main(args: Array<String>) {

Expand All @@ -19,8 +22,8 @@ fun main(args: Array<String>) {
""".trimIndent()
)
println("==========================================================")
println(" Grunt Klass Master (Version: $VERSION, Author: B_312)")
println(" Lightweight obfuscator for jvm programs")
println(" Grunt Klass Master (Version: $VERSION[$TYPE], Author: $AUTHOR)")
println(" Github: $GITHUB")
println("==========================================================")

Logger.info("Initializing Grunt...")
Expand All @@ -30,14 +33,14 @@ fun main(args: Array<String>) {
Configs.loadConfig(configName)
Configs.saveConfig(configName)
} catch (ignore: Exception) {
Logger.info("Failed to read config $configName!")
Logger.info("Failed to read config $configName!But we generated a new one.")
Logger.info("Type (Y/N) if you want to continue")
if (readLine()?.lowercase() == "n") return
}

ResourceCache(Configs.Settings.input, Configs.Settings.libraries).apply {
readJar()
Logger.info("Obfuscating...")
Logger.info("Processing...")
Transformers.forEach {
if (it.enabled) with(it) { transform() }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ object Transformers : Collection<Transformer> by mutableListOf(
MethodRenameTransformer,
FieldRenameTransformer,
ClassRenameTransformer,
ShuffleMembersTransformer,
WatermarkTransformer
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ package net.spartanb312.grunt.process.transformers
import net.spartanb312.grunt.config.value
import net.spartanb312.grunt.process.Transformer
import net.spartanb312.grunt.process.resource.ResourceCache
import net.spartanb312.grunt.utils.isAbstract
import net.spartanb312.grunt.utils.isAnnotation
import net.spartanb312.grunt.utils.isEnum
import net.spartanb312.grunt.utils.isInterface
import net.spartanb312.grunt.utils.*
import net.spartanb312.grunt.utils.logging.Logger
import org.objectweb.asm.tree.FieldInsnNode
import org.objectweb.asm.tree.InvokeDynamicInsnNode
Expand All @@ -17,13 +14,16 @@ object NativeCandidateTransformer : Transformer("NativeCandidate") {

val nativeAnnotation by value("NativeAnnotation", "Lnet/spartanb312/example/Native;")
private val upCallLimit by value("UpCallLimit", 0)
private val exclusions by value("Exclusions", listOf())

override fun ResourceCache.transform() {
Logger.info(" - Adding annotations on native transformable methods...")
val candidateMethod = mutableListOf<MethodNode>()
nonExcluded.asSequence()
.filter { !it.isInterface && !it.isAnnotation && !it.isEnum && !it.isAbstract }
.forEach { classNode ->
.filter {
!it.isInterface && !it.isAnnotation && !it.isEnum && !it.isAbstract
&& it.name.isNotExcludedIn(exclusions)
}.forEach { classNode ->
classNode.methods.forEach { methodNode ->
if (!ScrambleTransformer.appendedMethods.contains(methodNode)) {
var count = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,30 @@ import java.util.concurrent.ThreadLocalRandom

object NumberEncryptTransformer : Transformer("NumberEncrypt") {

private val encryptFloatingPoint by value("FloatingPoint", true)
private val times by value("Intensity", 1)
private val exclusion by value("Exclusions", listOf())

override fun ResourceCache.transform() {
Logger.info(" - Encrypting numbers...")
val floatCount = count {
if (encryptFloatingPoint) {
Logger.info(" Encrypting floating point numbers")
nonExcluded.asSequence()
.filter { c -> exclusion.none { c.name.startsWith(it) } }
.forEach { classNode ->
classNode.methods.asSequence()
.filter { !it.isAbstract && !it.isNative }
.forEach { methodNode: MethodNode ->
encryptFloatingPoint(methodNode)
}
}
}
}.get()
val count = count {
add(floatCount)
repeat(times) { t ->
if (times > 1) Logger.info(" Encrypting numbers ${t + 1} of $times times")
if (times > 1) Logger.info(" Encrypting integers ${t + 1} of $times times")
nonExcluded.asSequence()
.filter { c -> exclusion.none { c.name.startsWith(it) } }
.forEach { classNode ->
Expand Down Expand Up @@ -53,6 +69,56 @@ object NumberEncryptTransformer : Transformer("NumberEncrypt") {
Logger.info(" Encrypted $count numbers")
}

private fun Counter.encryptFloatingPoint(methodNode: MethodNode) {
methodNode.instructions.toList().forEach {
fun encryptFloat(cst: Float) {
val intBits = cst.asInt()
val key = kotlin.random.Random.nextInt()
val encryptedIntBits = intBits xor key
val insnList = InsnList().apply {
add(encryptedIntBits.toInsnNode())
add(key.toInsnNode())
add(InsnNode(Opcodes.IXOR))
add(MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Float", "intBitsToFloat", "(I)F"))
}
methodNode.instructions.insertBefore(it, insnList)
methodNode.instructions.remove(it)
add(1)
}

fun encryptDouble(cst: Double) {
val longBits = cst.asLong()
val key = kotlin.random.Random.nextLong()
val encryptedLongBits = longBits xor key
val insnList = InsnList().apply {
add(LdcInsnNode(encryptedLongBits))
add(LdcInsnNode(key))
add(InsnNode(Opcodes.LXOR))
add(MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Double", "longBitsToDouble", "(J)D"))
}
methodNode.instructions.insertBefore(it, insnList)
methodNode.instructions.remove(it)
add(1)
}
when {
it is LdcInsnNode -> when (val cst = it.cst) {
is Float -> encryptFloat(cst)
is Double -> encryptDouble(cst)
}

it.opcode == Opcodes.FCONST_0 -> encryptFloat(0.0f)
it.opcode == Opcodes.FCONST_1 -> encryptFloat(1.0f)
it.opcode == Opcodes.FCONST_2 -> encryptFloat(2.0f)
it.opcode == Opcodes.DCONST_0 -> encryptDouble(0.0)
it.opcode == Opcodes.DCONST_1 -> encryptDouble(1.0)
}
}
}

private fun Double.asLong(): Long = java.lang.Double.doubleToRawLongBits(this)

private fun Float.asInt(): Int = java.lang.Float.floatToRawIntBits(this)

private fun xor(value: Int) = InsnList().apply {
val first = Random(ThreadLocalRandom.current().nextInt().toLong()).nextInt(Short.MAX_VALUE.toInt()) + value
val second = -Random(ThreadLocalRandom.current().nextInt().toLong()).nextInt(Short.MAX_VALUE.toInt()) + value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,21 @@ import net.spartanb312.grunt.config.value
import net.spartanb312.grunt.process.Transformer
import net.spartanb312.grunt.process.resource.ResourceCache
import net.spartanb312.grunt.utils.count
import net.spartanb312.grunt.utils.isNotExcludedIn
import net.spartanb312.grunt.utils.logging.Logger
import org.objectweb.asm.Opcodes
import org.objectweb.asm.tree.*

object ShrinkingTransformer : Transformer("Shrinking") {

private val removeNOP by value("RemoveNOP", true)
private val removeInnerClass by value("RemoveInnerClass", true)
private val removeUnusedLabel by value("RemoveUnusedLabel", true)

private val exclusions by value("Exclusions", listOf())

override fun ResourceCache.transform() {
Logger.info(" - Shrinking classes...")
if (removeNOP) {
val nopCount = count {
nonExcluded.forEach { classNode ->
classNode.methods.forEach { methodNode ->
methodNode.instructions.toList().asSequence()
.filter { insnNode -> insnNode.opcode == Opcodes.NOP }
.forEach { insnNode ->
methodNode.instructions.remove(insnNode)
add(1)
}
}
}
}.get()
Logger.info(" Removed $nopCount NOPs")
}
val nonExcluded = nonExcluded.filter { it.name.isNotExcludedIn(exclusions) }
if (removeInnerClass) {
val innerClassCount = count {
nonExcluded.forEach { classNode ->
Expand All @@ -40,9 +28,24 @@ object ShrinkingTransformer : Transformer("Shrinking") {
add(classNode.innerClasses.size)
classNode.innerClasses.clear()
}
}
}.get()
Logger.info(" Removed $innerClassCount inner classes")
}
//if (removeNOP) {
// val nopCount = count {
// nonExcluded.forEach { classNode ->
// classNode.methods.forEach { methodNode ->
// methodNode.instructions.toList().asSequence()
// .filter { insnNode -> insnNode.opcode == Opcodes.NOP && insnNode is InsnNode }
// .forEach { insnNode ->
// methodNode.instructions.remove(insnNode)
// add(1)
// }
// }
// }
// }.get()
// Logger.info(" Removed $nopCount NOPs")
//}
if (removeUnusedLabel) {
val labelCount = count {
nonExcluded.forEach { classNode ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package net.spartanb312.grunt.process.transformers

import net.spartanb312.grunt.config.value
import net.spartanb312.grunt.process.Transformer
import net.spartanb312.grunt.process.resource.ResourceCache
import net.spartanb312.grunt.utils.count
import net.spartanb312.grunt.utils.logging.Logger

object ShuffleMembersTransformer : Transformer("ShuffleMembers") {

private val methods by value("Methods", true)
private val fields by value("Fields", true)
private val annotations by value("Annotations", true)

override fun ResourceCache.transform() {
Logger.info(" - Shuffling members...")
val count = count {
nonExcluded.forEach { classNode ->
if (methods) classNode.methods?.let {
classNode.methods = it.shuffled()
add(it.size)
}
if (fields) classNode.fields?.let {
classNode.fields = it.shuffled()
add(it.size)
}
if (annotations) {
classNode.visibleAnnotations?.let {
classNode.visibleAnnotations = it.shuffled()
add(it.size)
}
classNode.invisibleAnnotations?.let {
classNode.invisibleAnnotations = it.shuffled()
add(it.size)
}
classNode.methods?.forEach { methodNode ->
methodNode.visibleAnnotations?.let {
methodNode.visibleAnnotations = it.shuffled()
add(it.size)
}
methodNode.invisibleAnnotations?.let {
methodNode.invisibleAnnotations = it.shuffled()
add(it.size)
}
}
}
}
}.get()
Logger.info(" Shuffled $count members")
}

}

0 comments on commit 460ed7b

Please sign in to comment.