Repository: alpheratzteam/obfuscator
Branch: master
Commit: a03cc48293a7
Files: 42
Total size: 89.6 KB
Directory structure:
gitextract_o39oe31y/
├── .gitignore
├── .idea/
│ └── .gitignore
├── LICENSE
├── README.md
├── build.gradle.kts
├── gradle/
│ └── wrapper/
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src/
└── main/
└── kotlin/
└── pl/
└── alpheratzteam/
└── obfuscator/
├── Obfuscator.kt
├── api/
│ ├── number/
│ │ ├── NumberData.kt
│ │ └── NumberType.kt
│ └── transformer/
│ └── Transformer.kt
├── main.kt
├── transformer/
│ ├── AntiDebugTransformer.kt
│ ├── BadAnnotationTransformer.kt
│ ├── BooleanObfuscationTransformer.kt
│ ├── DebugInfoRemoverTransformer.kt
│ ├── FakeInstructionsTransformer.kt
│ ├── FlowTransformer.kt
│ ├── FullAccessTransformer.kt
│ ├── HideCodeTransformer.kt
│ ├── LocalVariableTransformer.kt
│ ├── MarkerTransformer.kt
│ ├── NumberTransformer.kt
│ ├── ShuffleMemberTransformer.kt
│ ├── SignatureTransformer.kt
│ ├── SourceFileTransformer.kt
│ ├── ThrowableTransformer.kt
│ ├── TrashCodeTransformer.kt
│ ├── TrashExceptionTransformer.kt
│ └── optimizer/
│ ├── FieldAccessTransformer.kt
│ ├── GotoInlinerTransformer.kt
│ └── NopRemoverTransformer.kt
└── util/
├── AsmUtil.kt
├── ConditionUtil.kt
├── InsnBuilder.kt
├── JarUtil.kt
├── RandomUtil.kt
├── StringUtil.kt
└── Util.kt
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
================================================
FILE: .idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../../:\Users\Unix\IdeaProjects\Obfuscator\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 AlpheratzTeam
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Java Obfuscator
Java Obfuscator for protecting your Java applications. You can find further instruction on compilation and usage below.
[](https://discord.gg/Teh8Sqb)
***
## Getting Started
todo
***
### TODO
- ~~boolean obf~~
- new string encryption
- ~~java -> kotlin~~
- ~~insn builder~~
- ~~number obf~~
- ~~crc32 error~~
- class/method/field renamer
- decompilators crasher
- website (?)
- gui (c++, jni)
- configuration toml/json
***
================================================
FILE: build.gradle.kts
================================================
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.4.10"
application
}
group = "pl.alpheratzteam"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
maven("http://oss.sonatype.org/content/groups/public/")
}
dependencies {
implementation("org.ow2.asm:asm:9.0")
implementation("org.ow2.asm:asm-tree:9.0")
implementation("org.ow2.asm:asm-commons:9.0")
implementation("org.ow2.asm:asm-util:9.0")
testImplementation(kotlin("test-junit"))
implementation(kotlin("reflect"))
}
tasks.test {
useJUnit()
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
application {
mainClassName = "pl.alpheratzteam.obfuscator.MainKt"
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: gradle.properties
================================================
kotlin.code.style=official
================================================
FILE: gradlew
================================================
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
================================================
FILE: gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: settings.gradle.kts
================================================
rootProject.name = "Obfuscator"
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/Obfuscator.kt
================================================
package pl.alpheratzteam.obfuscator
import org.objectweb.asm.tree.ClassNode
import pl.alpheratzteam.obfuscator.transformer.*
import pl.alpheratzteam.obfuscator.util.JarUtil
import java.io.File
/**
* @author Unix
* @since 16.12.2020
*/
class Obfuscator {
private val dataFolder = File("obfuscator") // base folder
val classes = mutableMapOf<String, ClassNode>() // classes from jar
val assets = mutableMapOf<String, ByteArray>() // assets from jar
/**
* The main startup method of the obfuscator.
*/
fun onStart() {
val jarFile = File(dataFolder, "jars").apply { // create files
dataFolder.mkdir()
mkdir()
}
JarUtil.loadJar(File(jarFile, "input.jar")).apply { // load classes, assets from jar
println("Loading jar...")
}.run {
println("Loaded jar!")
println("Starting transformers...")
classes.putAll(first)
assets.putAll(second)
}
val transformers = mutableListOf(ThrowableTransformer()) // modifiers
transformers.forEach {
val name = it.javaClass.simpleName
var time = System.currentTimeMillis()
println("Running $name transformer...")
it.transform(this) // modify classes
time = System.currentTimeMillis() - time
println("Finished running $name transformer. [$time ms]")
println("---------------------------------------")
}
JarUtil.saveJar(File(jarFile, "output.jar"), Pair(classes, assets)).apply { // save output
println("Saving jar...")
}.run {
println("Saved jar!")
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/api/number/NumberData.kt
================================================
package pl.alpheratzteam.obfuscator.api.number
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.tree.FieldNode
/**
* @author Unix
* @since 03.04.2021
*/
class NumberData<T : Number>(val fieldName: String, val numberType: NumberType) {
val numbers = mutableMapOf<Int, T>()
var size = 0
fun addNumber(id: Int, number: T) {
numbers[id] = number
}
fun getFieldNode() : FieldNode {
return FieldNode(ACC_STATIC + ACC_PRIVATE, fieldName, numberType.descriptor, null, null)
}
}
//class NumberData<T : Number>(val fieldName: String, val numberType: NumberType, val opcodes: Array<Int>) {
//
// val numbers = mutableMapOf<Int, T>()
// var size = 0
//
// fun addNumber(id: Int, number: Any) {
// numbers[id] = number as T
// }
//
// fun getFieldNode() : FieldNode {
// return FieldNode(ACC_STATIC + ACC_PRIVATE, fieldName, numberType.descriptor, null, null)
// }
//
// fun isNumber(abstractInsnNode: AbstractInsnNode) : Boolean {
// return when(numberType) {
// NumberType.INTEGER -> ASMUtil.isIntInsn(abstractInsnNode)
// NumberType.DOUBLE -> ASMUtil.isDoubleInsn(abstractInsnNode)
// NumberType.FLOAT -> ASMUtil.isFloatInsn(abstractInsnNode)
// NumberType.LONG -> ASMUtil.isLongInsn(abstractInsnNode)
// }
// }
//
// fun getNumber(abstractInsnNode: AbstractInsnNode) : Number {
// return when(numberType) {
// NumberType.INTEGER -> ASMUtil.getIntFromInsn(abstractInsnNode)
// NumberType.DOUBLE -> ASMUtil.getDoubleFromInsn(abstractInsnNode)
// NumberType.FLOAT -> ASMUtil.getFloatFromInsn(abstractInsnNode)
// NumberType.LONG -> ASMUtil.getLongFromInsn(abstractInsnNode)
// }
// }
//
//}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/api/number/NumberType.kt
================================================
package pl.alpheratzteam.obfuscator.api.number
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.tree.InsnNode
/**
* @author Unix
* @since 03.04.2021
*/
enum class NumberType(val store: Int, val opcode: Int, val descriptor: String) {
INTEGER(IASTORE, T_INT, "[I"),
DOUBLE(DASTORE, T_DOUBLE, "[D"),
FLOAT(FASTORE, T_FLOAT, "[F"),
LONG(LASTORE, T_LONG, "[J")
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/api/transformer/Transformer.kt
================================================
package pl.alpheratzteam.obfuscator.api.transformer
import pl.alpheratzteam.obfuscator.Obfuscator
/**
* @author Unix
* @since 16.12.2020
*/
interface Transformer {
/**
* This method transform some classes by obfuscator.
* @param obfuscator as instance of obfuscator.
* @see [ClassNode] class to transform.
*/
fun transform(obfuscator: Obfuscator)
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/main.kt
================================================
import pl.alpheratzteam.obfuscator.Obfuscator
/**
* @author Unix
* @since 16.12.2020
*/
/**
* This method starts the obfuscator.
* @see [Obfuscator] obfuscator class.
*/
fun main() {
Obfuscator().onStart() // start application
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/AntiDebugTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.insnBuilder
import org.objectweb.asm.tree.LabelNode
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MethodNode
import pl.alpheratzteam.obfuscator.util.StringUtil
/**
* @author Unix
* @since 17.12.2020
*/
class AntiDebugTransformer : Transformer {
private val debugTypes = arrayOf("-Xbootclasspath", "-Xdebug", "-agentlib", "-Xrunjdwp:", "-verbose")
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach { classNode ->
classNode.methods.find { it.name.equals("<clinit>") }.also {
val methodNode = makeMethod()
it?.instructions?.insertBefore(it.instructions.last, MethodInsnNode(INVOKESTATIC, classNode.name, methodNode.name, methodNode.desc, false))
classNode.methods.add(methodNode)
}
}
}
private fun makeMethod(): MethodNode {
val method = MethodNode()
with(method) {
access = ACC_PRIVATE or ACC_STATIC
name = StringUtil.generateString(8)
desc = "()V"
signature = null
exceptions = null
maxStack = 2
instructions = insnBuilder {
invokestatic("java/lang/management/ManagementFactory", "getRuntimeMXBean", "()Ljava/lang/management/RuntimeMXBean;", false)
invokeinterface("java/lang/management/RuntimeMXBean", "getInputArguments", "()Ljava/util/List;", true)
invokeinterface("java/util/List", "iterator", "()Ljava/util/Iterator;", true)
astore(1)
val label1 = LabelNode()
+label1
frame(F_APPEND, 1, arrayOf("java/util/Iterator"), 0, null)
aload(1)
invokeinterface("java/util/Iterator", "hasNext", "()Z", true)
val label2 = LabelNode()
ifeq(label2)
aload(1)
invokeinterface("java/util/Iterator", "next", "()Ljava/lang/Object;", true)
checkcast("java/lang/String")
astore(2)
+LabelNode()
aload(2)
ldc("-javaagent:")
invokevirtual("java/lang/String", "startsWith", "(Ljava/lang/String;)Z", false)
val label4 = LabelNode()
debugTypes.forEach {
ifne(label4)
aload(2)
ldc(it)
invokevirtual("java/lang/String", "startsWith", "(Ljava/lang/String;)Z", false)
}
val label5 = LabelNode()
ifeq(label5)
+label4
frame(F_APPEND, 1, arrayOf("java/lang/String"), 0, null)
insn(ICONST_0)
invokestatic("java/lang/System", "exit", "(I)V", false)
+label5
frame(F_CHOP, 1, null, 0, null)
goto(label1)
+label2
frame(F_CHOP, 1, null, 0, null)
_return()
}
}
return method
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/BadAnnotationTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.tree.AnnotationNode
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.RandomUtil
import pl.alpheratzteam.obfuscator.util.StringUtil
import java.util.Objects
/**
* @author Unix
* @since 17.12.2020
*/
class BadAnnotationTransformer : Transformer {
private val annotations: MutableList<AnnotationNode> = mutableListOf()
init {
val string = StringUtil.generateString(RandomUtil.int(10, 64))
repeat((0..RandomUtil.int(1, 10)).count()) { annotations.add(AnnotationNode("L$string;")) }
repeat((0..RandomUtil.int(1, 10)).count()) { annotations.add(AnnotationNode(string)) }
repeat((0..RandomUtil.int(1, 10)).count()) { annotations.add(AnnotationNode("@$string")) }
}
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
it.run {
if (Objects.isNull(visibleAnnotations)) {
visibleAnnotations = mutableListOf()
}
if (Objects.isNull(invisibleAnnotations)) {
invisibleAnnotations = mutableListOf()
}
val pair = change(visibleAnnotations, invisibleAnnotations)
visibleAnnotations = pair.first
invisibleAnnotations = pair.second
}
it.methods.forEach {
it.run {
if (Objects.isNull(visibleAnnotations)) {
visibleAnnotations = mutableListOf()
}
if (Objects.isNull(invisibleAnnotations)) {
invisibleAnnotations = mutableListOf()
}
val pair = change(visibleAnnotations, invisibleAnnotations)
visibleAnnotations = pair.first
invisibleAnnotations = pair.second
}
}
it.fields.forEach {
it.run {
if (Objects.isNull(visibleAnnotations)) {
visibleAnnotations = mutableListOf()
}
if (Objects.isNull(invisibleAnnotations)) {
invisibleAnnotations = mutableListOf()
}
val pair = change(visibleAnnotations, invisibleAnnotations)
visibleAnnotations = pair.first
invisibleAnnotations = pair.second
}
}
}
}
fun change(visibleAnnotations: MutableList<AnnotationNode>, invisibleAnnotations: MutableList<AnnotationNode>): Pair<List<AnnotationNode>, List<AnnotationNode>> {
visibleAnnotations.addAll(annotations)
invisibleAnnotations.addAll(annotations)
return Pair(visibleAnnotations, invisibleAnnotations)
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/BooleanObfuscationTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.tree.*
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.RandomUtil
import pl.alpheratzteam.obfuscator.util.StringUtil
import pl.alpheratzteam.obfuscator.util.insnBuilder
import java.util.concurrent.atomic.AtomicInteger
/**
* @author Unix
* @since 07.04.2021
*/
class BooleanObfuscationTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach { classNode ->
val fieldName = StringUtil.generateString(8)
val ints = mutableListOf<Int>()
classNode.fields.add(FieldNode(ACC_STATIC + ACC_PRIVATE, fieldName, "[I", null, null))
classNode.methods.forEach { methodNode ->
methodNode.instructions.forEach {
if (it.previous is InsnNode && it is VarInsnNode) {
val value = RandomUtil.int(10, 2000)
val insnNode = it.previous as InsnNode
if (insnNode.opcode == 4 || insnNode.opcode == 3) {
methodNode.instructions.insertBefore(it, makeInsn(classNode, fieldName, ints.size, ints.size + 1))
methodNode.instructions.remove(it.previous)
ints.add(value)
when (insnNode.opcode) {
4 -> ints.add(value)
3 -> ints.add(value + RandomUtil.int(10, 2000))
}
}
}
}
}
classNode.methods.filter { it.name.equals("<clinit>") }.forEach { it.instructions = makeClinit(it, classNode.name, fieldName, ints) }
}
}
private fun makeClinit(methodNode: MethodNode, className: String, fieldName: String, ints: List<Int>): InsnList {
val insnNode = methodNode.instructions
return insnBuilder {
ldc(ints.size)
newintarray()
putstatic(className, fieldName, "[I")
val size = AtomicInteger()
ints.forEach {
getstatic(className, fieldName, "[I")
ldc(size.getAndIncrement())
ldc(it)
iastore()
}
+insnNode
_return()
}
}
fun makeInsn(classNode: ClassNode, fieldName: String, first: Int, second: Int) : InsnList {
return insnBuilder {
getstatic(classNode.name, fieldName, "[I")
ldc(first)
iaload()
getstatic(classNode.name, fieldName, "[I")
ldc(second)
iaload()
val labelNode = LabelNode()
if_icmpne(labelNode)
insn(ICONST_1)
val labelNode2 = LabelNode()
goto(labelNode2)
+labelNode
frame(F_SAME, 0, null, 0, null)
insn(ICONST_0)
+labelNode2
frame(F_SAME1, 0, null, 1, arrayOf(INTEGER))
istore(0)
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/DebugInfoRemoverTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.tree.ClassNode
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
/**
* @author Unix
* @since 18.12.2020
*/
class DebugInfoRemoverTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
val classes = mutableMapOf<String, ClassNode>()
obfuscator.classes.values.forEach {
val classWriter = ClassWriter(ClassWriter.COMPUTE_MAXS or ClassWriter.COMPUTE_FRAMES)
it.accept(classWriter)
val newClassNode = ClassNode()
ClassReader(classWriter.toByteArray()).accept(newClassNode, ClassReader.SKIP_DEBUG)
classes[newClassNode.name] = newClassNode
}
obfuscator.classes.clear()
obfuscator.classes.putAll(classes)
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/FakeInstructionsTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.ASMUtil
import org.objectweb.asm.tree.InsnNode
import org.objectweb.asm.tree.IntInsnNode
import org.objectweb.asm.tree.LdcInsnNode
import pl.alpheratzteam.obfuscator.util.RandomUtil
import java.util.concurrent.atomic.AtomicInteger
/**
* @author Unix
* @since 16.04.2021
*/
class FakeInstructionsTransformer : Transformer {
// https://github.com/sim0n/Caesium/blob/master/src/main/java/dev/sim0n/caesium/mutator/impl/PolymorphMutator.java
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
it.methods.filter { ASMUtil.hasInstructions(it) }.forEach {
val index = AtomicInteger()
val instructions = it.instructions
it.instructions.forEach {
if (it is LdcInsnNode) {
if (RandomUtil.boolean()) {
instructions.insertBefore(
it,
IntInsnNode(BIPUSH, RandomUtil.int(-64, 64))
)
instructions.insertBefore(it, InsnNode(POP))
}
} else if (index.getAndIncrement() % 6 == 0) {
if (RandomUtil.float() > 0.6) {
instructions.insertBefore(
it,
IntInsnNode(BIPUSH, RandomUtil.int(-27, 37))
)
instructions.insertBefore(it, InsnNode(POP))
} else {
instructions.insertBefore(it, InsnNode(NOP))
}
}
}
}
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/FlowTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.tree.FieldInsnNode
import org.objectweb.asm.tree.FieldNode
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.StringUtil
import org.objectweb.asm.tree.InsnNode
import org.objectweb.asm.tree.JumpInsnNode
import pl.alpheratzteam.obfuscator.util.ConditionUtil
/**
* @author Unix
* @since 18.12.2020
*/
class FlowTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach { classNode ->
var hasField = false
val fieldName = StringUtil.generateString(8)
classNode.methods.forEach { methodNode ->
methodNode.instructions.filter { it.opcode == GOTO }.forEach {
hasField = true
with(methodNode) {
instructions.insertBefore(it, FieldInsnNode(GETSTATIC, classNode.name, fieldName, "Z"))
instructions.insert(it, InsnNode(ATHROW))
instructions.insert(it, InsnNode(ACONST_NULL))
instructions.set(it, JumpInsnNode(IFEQ, (it as JumpInsnNode).label))
}
}
}
ConditionUtil.checkCondition(hasField) {
classNode.fields.add(FieldNode(ACC_PUBLIC + ACC_STATIC + ACC_FINAL, fieldName, "Z", null, null))
}
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/FullAccessTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
/**
* @author Unix
* @since 18.12.2020
*/
class FullAccessTransformer : Transformer {
private val accesses = intArrayOf(ACC_ANNOTATION, ACC_FINAL, ACC_ENUM, ACC_INTERFACE, ACC_MANDATED,
ACC_MODULE, ACC_OPEN, ACC_STRICT, ACC_SYNCHRONIZED, ACC_SYNTHETIC, ACC_TRANSIENT, ACC_TRANSITIVE, ACC_VARARGS, ACC_DEPRECATED
) // separate (enum): class, method, field
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
with (it) {
// access = changeAccess(access) // change classNode
methods.filter { !it.name.startsWith("<") }.forEach { it.access = changeAccess(it.access) } // change methodNode
fields.forEach { it.access = changeAccess(it.access) } // change fieldNode
}
}
}
private fun changeAccess(access: Int): Int {
var newAccess: Int = access
accesses.filter { access and it == 0 }.forEach { newAccess = newAccess or it }
return newAccess
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/HideCodeTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.ASMUtil
import pl.alpheratzteam.obfuscator.util.ConditionUtil
import java.util.Objects
/**
* @author Unix
* @since 18.12.2020
*/
class HideCodeTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
ConditionUtil.checkCondition(!(ASMUtil.isSynthetic(it.access) && Objects.isNull(it.visibleAnnotations))) {
it.access = it.access or ACC_SYNTHETIC
}
it.methods.forEach {
ConditionUtil.checkCondition(!ASMUtil.isSynthetic(it.access)) {
it.access = it.access or ACC_SYNTHETIC
}
ConditionUtil.checkCondition(!it.name.startsWith("<") && ASMUtil.isBridge(it.access)) {
it.access = it.access or ACC_BRIDGE
}
}
it.fields.filter { ASMUtil.isStatic(it.access) }.forEach {
it.access = it.access or ACC_SYNTHETIC
}
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/LocalVariableTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.StringUtil
import java.util.*
/**
* @author Unix
* @since 18.12.2020
*/
class LocalVariableTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.flatMap { it.value.methods }
.filter { Objects.nonNull(it.localVariables) }
.flatMap { it.localVariables }
.forEach { it.name = StringUtil.generateString(16) }
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/MarkerTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.tree.MethodNode
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.insnBuilder
/**
* @author Unix
* @since 18.12.2020
*/
class MarkerTransformer : Transformer {
private val methodName = "hello"
private val text = "your text here"
override fun transform(obfuscator: Obfuscator) {
val methodNode = makeMethod()
obfuscator.classes.values.forEach { it.methods.add(methodNode) }
}
private fun makeMethod(): MethodNode {
val method = MethodNode()
with(method) {
access = ACC_PRIVATE or ACC_STATIC
name = methodName
desc = "()V"
signature = null
exceptions = null
instructions = insnBuilder {
getstatic("java/lang/System", "out", "Ljava/io/PrintStream;")
ldc(text)
invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V", false)
_return()
}
}
return method
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/NumberTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.tree.InsnList
import org.objectweb.asm.tree.MethodNode
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.number.NumberData
import pl.alpheratzteam.obfuscator.api.number.NumberType.DOUBLE
import pl.alpheratzteam.obfuscator.api.number.NumberType.FLOAT
import pl.alpheratzteam.obfuscator.api.number.NumberType.LONG
import pl.alpheratzteam.obfuscator.api.number.NumberType.INTEGER
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.*
/**
* @author Unix
* @since 17.12.2020
*/
class NumberTransformer : Transformer {
// TODO: 04.04.2021 cleanup code, static initialization
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach { classNode ->
val intNumbers = NumberData<Int>(StringUtil.generateString(8), INTEGER)
val doubleNumbers = NumberData<Double>(StringUtil.generateString(8), DOUBLE)
val floatNumbers = NumberData<Float>(StringUtil.generateString(8), FLOAT)
val longNumbers = NumberData<Long>(StringUtil.generateString(8), LONG)
classNode.fields.add(intNumbers.getFieldNode())
classNode.fields.add(doubleNumbers.getFieldNode())
classNode.fields.add(floatNumbers.getFieldNode())
classNode.fields.add(longNumbers.getFieldNode())
classNode.methods.forEach { methodNode ->
methodNode.instructions.forEach {
ConditionUtil.checkCondition(ASMUtil.isIntInsn(it)) { // int
val fieldNumber = RandomUtil.int(10, 3000)
val originalNumber = ASMUtil.getIntFromInsn(it)
val fakeNumber = RandomUtil.int(10, 3000)
val calcNumber = originalNumber xor fakeNumber * fieldNumber
intNumbers.addNumber(intNumbers.size, fieldNumber)
methodNode.instructions.insertBefore(it, insnBuilder {
ldc(calcNumber)
ldc(fakeNumber)
getstatic(classNode.name, intNumbers.fieldName, intNumbers.numberType.descriptor)
ldc(intNumbers.size)
iaload()
imul()
ixor()
})
methodNode.instructions.remove(it)
++intNumbers.size
}
ConditionUtil.checkCondition(ASMUtil.isDoubleInsn(it)) { // double
val fieldNumber = RandomUtil.int(10, 3000).toDouble()
val originalNumber = ASMUtil.getDoubleFromInsn(it)
val fakeNumber = RandomUtil.int(10, 3000).toDouble()
val calcNumber = originalNumber * fakeNumber * fieldNumber
doubleNumbers.addNumber(doubleNumbers.size, fieldNumber)
methodNode.instructions.insertBefore(it, insnBuilder {
ldc(calcNumber)
ldc(fakeNumber)
getstatic(classNode.name, doubleNumbers.fieldName, doubleNumbers.numberType.descriptor)
ldc(doubleNumbers.size)
daload()
dmul()
ddiv()
})
methodNode.instructions.remove(it)
++doubleNumbers.size
}
ConditionUtil.checkCondition(ASMUtil.isFloatInsn(it)) { // float
val fieldNumber = RandomUtil.int(10, 3000).toFloat()
val originalNumber = ASMUtil.getFloatFromInsn(it)
val fakeNumber = RandomUtil.int(10, 3000).toFloat()
val calcNumber = originalNumber * fakeNumber * fieldNumber
floatNumbers.addNumber(floatNumbers.size, fieldNumber)
methodNode.instructions.insertBefore(it, insnBuilder {
ldc(calcNumber)
ldc(fakeNumber)
getstatic(classNode.name, floatNumbers.fieldName, floatNumbers.numberType.descriptor)
ldc(floatNumbers.size)
faload()
fmul()
fdiv()
})
methodNode.instructions.remove(it)
++floatNumbers.size
}
ConditionUtil.checkCondition(ASMUtil.isLongInsn(it)) { // long
val fieldNumber = RandomUtil.int(10, 3000).toLong()
val originalNumber = ASMUtil.getLongFromInsn(it)
val fakeNumber = RandomUtil.int(10, 3000).toLong()
val calcNumber = originalNumber xor fakeNumber * fieldNumber
longNumbers.addNumber(longNumbers.size, fieldNumber)
methodNode.instructions.insertBefore(it, insnBuilder {
ldc(calcNumber)
ldc(fakeNumber)
getstatic(classNode.name, longNumbers.fieldName, longNumbers.numberType.descriptor)
ldc(longNumbers.size)
laload()
lmul()
lxor()
})
methodNode.instructions.remove(it)
++longNumbers.size
}
}
}
with (classNode) {
methods.filter { it.name.equals("<clinit>") }.forEach {
it.instructions = makeClinit(it, classNode.name, intNumbers)
it.instructions = makeClinit(it, classNode.name, doubleNumbers)
it.instructions = makeClinit(it, classNode.name, floatNumbers)
it.instructions = makeClinit(it, classNode.name, longNumbers)
}
}
}
}
private fun <T : Number> makeClinit(methodNode: MethodNode, className: String, numberData: NumberData<T>): InsnList {
val insnNode = methodNode.instructions
return insnBuilder {
ldc(numberData.size)
newarray(numberData.numberType.opcode)
putstatic(className, numberData.fieldName, numberData.numberType.descriptor)
numberData.numbers.forEach { (key, value) ->
getstatic(className, numberData.fieldName, numberData.numberType.descriptor)
ldc(key)
when (numberData.numberType) {
INTEGER -> ldc(value as Int)
LONG -> ldc(value as Long)
DOUBLE -> ldc(value as Double)
FLOAT -> ldc(value as Float)
}
insn(numberData.numberType.store)
}
+insnNode
_return()
}
}
}
// FIXME: 07.04.2021 V error - Exception in thread "main" java.lang.NegativeArraySizeException: -1
//class NumberTransformer : Transformer {
//
// // TODO: 04.04.2021 static initialization, unique string generator
//
// override fun transform(obfuscator: Obfuscator) {
// obfuscator.classes.values.forEach { classNode ->
// val numberDatas = listOf(NumberData<Int>(StringUtil.generateString(8), INTEGER, arrayOf(IALOAD, IMUL, IXOR)), NumberData<Long>(StringUtil.generateString(8), LONG, arrayOf(LALOAD, LMUL, LXOR)),
// NumberData<Double>(StringUtil.generateString(8), DOUBLE, arrayOf(DALOAD, DMUL, DDIV)), NumberData<Float>(StringUtil.generateString(8), FLOAT, arrayOf(FALOAD, FMUL, FDIV)))
//
// numberDatas.forEach { classNode.fields.add(it.getFieldNode()) }
//
// classNode.methods.forEach { methodNode ->
// numberDatas.forEach { numberData ->
// methodNode.instructions.forEach { abstractInsnNode ->
// ConditionUtil.checkCondition(numberData.isNumber(abstractInsnNode)) {
// val fieldNumber = RandomUtil.int(10, 3000)
// val originalNumber = numberData.getNumber(abstractInsnNode)
// val fakeNumber = RandomUtil.int(10, 3000)
// methodNode.instructions.insertBefore(abstractInsnNode, insnBuilder {
// when (numberData.numberType) {
// INTEGER -> {
// numberData.addNumber(numberData.size, fieldNumber)
// ldc((originalNumber.toInt() xor fakeNumber * fieldNumber))
// }
// DOUBLE -> {
// numberData.addNumber(numberData.size, fieldNumber.toDouble())
// ldc((originalNumber.toDouble() * fakeNumber * fieldNumber))
// }
// FLOAT -> {
// numberData.addNumber(numberData.size, fieldNumber.toFloat())
// ldc((originalNumber.toFloat() * fakeNumber * fieldNumber))
// }
// LONG -> {
// numberData.addNumber(numberData.size, fieldNumber.toLong())
// ldc((originalNumber.toLong() xor fakeNumber.toLong() * fieldNumber))
// }
// }
//
// ldc(fakeNumber)
// getstatic(classNode.name, numberData.fieldName, numberData.numberType.descriptor)
// ldc(numberData.size)
// numberData.opcodes.forEach { insn(it) }
// })
//
// methodNode.instructions.remove(abstractInsnNode)
// ++numberData.size
// }
// }
// }
// }
//
// with (classNode) {
// methods.filter { it.name.equals("<clinit>") }.forEach { methodNode ->
// val insnList = InsnList()
// numberDatas.forEach { insnList.add(makeClinit(classNode.name, it)) }
//
// if (Objects.isNull(methodNode.instructions)) {
// methodNode.instructions = InsnList()
// }
//
// val cachedInsnNode = methodNode.instructions
// methodNode.instructions.clear()
// methodNode.instructions.add(insnBuilder {
// +insnList
// +cachedInsnNode
// _return()
// })
// }
// }
// }
// }
//
// private fun <T : Number> makeClinit(className: String, numberData: NumberData<T>): InsnList {
// return insnBuilder {
// ldc(numberData.size)
// newarray(numberData.numberType.opcode)
// putstatic(className, numberData.fieldName, numberData.numberType.descriptor)
// numberData.numbers.forEach { (key, value) ->
// getstatic(className, numberData.fieldName, numberData.numberType.descriptor)
// ldc(key)
// when (numberData.numberType) {
// INTEGER -> ldc(value as Int)
// LONG -> ldc(value as Long)
// DOUBLE -> ldc(value as Double)
// FLOAT -> ldc(value as Float)
// }
// insn(numberData.numberType.store)
// }
// }
// }
//
//}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/ShuffleMemberTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
/**
* @author Unix
* @since 18.12.2020
*/
class ShuffleMemberTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
it.attrs?.shuffle()
it.methods?.shuffle()
it.methods?.forEach {
it.localVariables?.shuffle()
it.parameters?.shuffle()
it.attrs?.shuffle()
}
it.fields?.shuffle()
it.fields?.forEach { it.attrs?.shuffle() }
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/SignatureTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.StringUtil
/**
* @author Unix
* @since 16.12.2020
*/
class SignatureTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) = obfuscator.classes.values.forEach { it.signature = StringUtil.makeUnreadable(StringUtil.generateString(4)) }
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/SourceFileTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.StringUtil
/**
* @author Unix
* @since 18.12.2020
*/
class SourceFileTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) = obfuscator.classes.values.forEach { it.sourceFile = StringUtil.generateString(Byte.MAX_VALUE.toInt()) }
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/ThrowableTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.F_SAME
import org.objectweb.asm.tree.*
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.ASMUtil
import pl.alpheratzteam.obfuscator.util.RandomUtil
import pl.alpheratzteam.obfuscator.util.StringUtil
import pl.alpheratzteam.obfuscator.util.insnBuilder
import java.io.IOException
import java.lang.annotation.AnnotationTypeMismatchException
import java.nio.BufferUnderflowException
import java.util.*
import kotlin.reflect.KClass
/**
* @author Unix
* @since 03.04.2021
*/
class ThrowableTransformer : Transformer {
private val exceptions = listOf(get(Exception::class), get(IOException::class), get(BufferUnderflowException::class), get(ExceptionInInitializerError::class),
get(ArrayIndexOutOfBoundsException::class), get(ArrayStoreException::class), get(AnnotationTypeMismatchException::class))
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
it.methods.filter { !it.name.startsWith("<") }.forEach { methodNode ->
methodNode.instructions
.asSequence()
.filter { ASMUtil.isInstruction(it) && !Objects.isNull(it.next) }
.forEach { methodNode.instructions.insertBefore(it.next, makeInsn()) }
}
}
}
fun makeInsn() : InsnList {
return insnBuilder {
+LabelNode()
val bool = RandomUtil.boolean()
val type = RandomUtil.int(1, 3)
when (type) {
1 -> {
val string = StringUtil.generateString(2)
ldc(string)
when {
bool -> {
ldc(string + StringUtil.generateString(2))
}
else -> {
ldc(string)
}
}
invokevirtual("java/lang/String", "equals", "(Ljava/lang/Object;)Z", false)
}
2 -> {
when (RandomUtil.int(1, 3)) {
1 -> {
ldc(RandomUtil.float(1.0, 200.0))
when (RandomUtil.int(1, 3)) {
1 -> invokestatic("java/lang/Float", "isInfinite", "(F)Z", false)
2 -> invokestatic("java/lang/Float", "isNaN", "(F)Z", false)
}
}
2 -> {
ldc(RandomUtil.double(1.0, 200.0))
when (RandomUtil.int(1, 3)) {
1 -> invokestatic("java/lang/Double", "isInfinite", "(D)Z", false)
2 -> invokestatic("java/lang/Double", "isNaN", "(D)Z", false)
}
}
}
}
}
// val string = StringUtil.generateString(2)
// ldc(string)
// ldc(string + StringUtil.generateString(2))
// invokevirtual("java/lang/String", "equals", "(Ljava/lang/Object;)Z", false)
val labelNode = LabelNode()
when (type) {
1 -> {
when {
bool -> {
ifeq(labelNode)
}
else -> {
ifne(labelNode)
}
}
}
else -> ifeq(labelNode)
}
val labelNode1 = LabelNode()
+labelNode1
when (RandomUtil.int(1, 3)) {
1 -> {
val exception: String? = exceptions[RandomUtil.int(exceptions.size)]
exception?.let {
new(it)
dup()
invokespecial(it, "<init>", "()V", false)
}
}
else -> aconst_null()
}
athrow()
+labelNode
frame(F_SAME, 0, null, 0, null)
+LabelNode()
}
}
fun <T : Any> get(any: KClass<T>) = any.qualifiedName?.replace(".", "/")
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/TrashCodeTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.tree.LabelNode
import org.objectweb.asm.tree.MethodInsnNode
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.StringUtil
import pl.alpheratzteam.obfuscator.util.insnBuilder
import pl.alpheratzteam.obfuscator.util.RandomUtil
import pl.alpheratzteam.obfuscator.util.printlnAsm
/**
* @author Unix
* @since 18.12.2020
*/
class TrashCodeTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
it.methods.filter { !it.name.startsWith("<") }.forEach { methodNode ->
methodNode.instructions.filter { it is MethodInsnNode }.map { it as MethodInsnNode }
.filter { !it.owner.startsWith("\u0000") }.forEach {
methodNode.instructions.insertBefore(it.next, insnBuilder {
val bool = RandomUtil.boolean()
+LabelNode()
// TODO: 17.04.2021 code cleanup.
val type = RandomUtil.int(1, 3)
when (type) {
1 -> {
val string = StringUtil.generateString(2)
ldc(string)
when {
bool -> {
ldc(string + StringUtil.generateString(2))
}
else -> {
ldc(string)
}
}
invokevirtual("java/lang/String", "equals", "(Ljava/lang/Object;)Z", false)
}
2 -> {
when (RandomUtil.int(1, 3)) {
1 -> {
ldc(RandomUtil.float(1.0, 200.0))
when (RandomUtil.int(1, 3)) {
1 -> invokestatic("java/lang/Float", "isInfinite", "(F)Z", false)
2 -> invokestatic("java/lang/Float", "isNaN", "(F)Z", false)
}
}
2 -> {
ldc(RandomUtil.double(1.0, 200.0))
when (RandomUtil.int(1, 3)) {
1 -> invokestatic("java/lang/Double", "isInfinite", "(D)Z", false)
2 -> invokestatic("java/lang/Double", "isNaN", "(D)Z", false)
}
}
}
}
3 -> {
}
}
val labelNode = LabelNode()
when (type) {
1 -> {
when {
bool -> {
ifeq(labelNode)
}
else -> {
ifne(labelNode)
}
}
}
else -> ifeq(labelNode)
}
val labelNode1 = LabelNode()
+labelNode1
// start
// todo make switch with shit code.
when(RandomUtil.int(1, 3)) {
1 -> {
val size = RandomUtil.int(1, 30)
val stringBuilder = StringBuilder()
stringBuilder.append("(")
repeat((1..size).count()) { stringBuilder.append("Ljava/lang/String;") }
stringBuilder.append(")V")
repeat((1..RandomUtil.int(3, 10)).count()) {
+LabelNode()
val className = '\u0000' + StringUtil.getStringWithJavaKeywords(6)
new(className)
repeat((1..size).count()) { ldc(StringUtil.generateString(6)) }
invokespecial(
className,
"<init>",
stringBuilder.toString(),
false
)
+LabelNode()
}
}
2 -> {
val list = mutableListOf<Pair<LabelNode, Int>>()
repeat((0..RandomUtil.int(10, 30)).count()) { list.add(Pair(LabelNode(), it))}
val label3 = LabelNode()
val labels = mutableListOf<LabelNode>()
val ints = mutableListOf<Int>()
list.forEach {
labels.add(it.first)
ints.add(it.second)
}
labels.add(label3)
ints.add(100)
+LabelNode()
ldc(RandomUtil.int(10, 2000))
ldc(RandomUtil.int(10, 2000))
ixor()
lookupswitch(label3, Pair(ints.toIntArray(), labels.toTypedArray()))
+label3
frame(F_SAME, 0, null, 0, null)
goto(label3)
labels.remove(label3)
labels.forEach {
+it
frame(F_SAME, 0, null, 0, null)
when(RandomUtil.int(1, 6)) {
1 -> {
new("java/lang/NullPointerException")
dup()
ldc("AlpheratzObfuscator")
invokespecial(
"java/lang/NullPointerException",
"<init>",
"(Ljava/lang/String;)V",
false
)
athrow()
}
2 -> {
val size = RandomUtil.int(1, 30)
val stringBuilder = StringBuilder()
stringBuilder.append("(")
repeat((1..size).count()) { stringBuilder.append("Ljava/lang/String;") }
stringBuilder.append(")V")
repeat((1..RandomUtil.int(3, 10)).count()) {
+LabelNode()
val className = '\u0000' + StringUtil.getStringWithJavaKeywords(6)
new(className)
repeat((1..size).count()) { ldc(StringUtil.generateString(6)) }
invokespecial(
className,
"<init>",
stringBuilder.toString(),
false
)
+LabelNode()
}
}
3 -> {
ldc("AlpheratzObfuscator - https://github.com/alpheratzteam/obfuscator")
printlnAsm()
}
4 -> {
aconst_null()
athrow()
}
else -> goto(label3)
}
}
+LabelNode()
}
}
// shit code
// end
+labelNode
frame(F_SAME, 0, null, 0, null)
// +LabelNode()
})
}
}
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/TrashExceptionTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import java.io.IOException
import java.lang.annotation.AnnotationTypeMismatchException
import java.nio.BufferUnderflowException
import kotlin.reflect.KClass
/**
* @author Unix
* @since 04.04.2021
*/
class TrashExceptionTransformer : Transformer {
// TODO: 04.04.2021 get automatic all exceptions from package java/util
private val exceptions = listOf(get(Exception::class), get(IOException::class), get(BufferUnderflowException::class), get(ExceptionInInitializerError::class),
get(ArrayIndexOutOfBoundsException::class), get(ArrayStoreException::class), get(AnnotationTypeMismatchException::class))
override fun transform(obfuscator: Obfuscator) = obfuscator.classes.values.forEach { it.methods.forEach { it.exceptions.addAll(exceptions) } }
fun <T : Any> get(any: KClass<T>) = any.qualifiedName?.replace(".", "/")
// fun <T : Any> gets(classes: List<KClass<T>>) : List<String> {
// val list = mutableListOf<String>()
// classes.forEach { get(it)?.let { list.add(it) } }
//
// return list
// }
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/optimizer/FieldAccessTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer.optimizer
import org.objectweb.asm.Opcodes.ACC_FINAL
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.ASMUtil
/**
* @author Unix
* @since 07.04.2021
*/
class FieldAccessTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.stream()
.flatMap { it.fields.stream() }
.filter { ASMUtil.isFinal(it.access) }
.forEach { it.access -= ACC_FINAL }
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/optimizer/GotoInlinerTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer.optimizer
import org.objectweb.asm.Opcodes.GOTO
import org.objectweb.asm.tree.JumpInsnNode
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
import pl.alpheratzteam.obfuscator.util.ConditionUtil
import java.util.*
/**
* @author Unix
* @since 18.12.2020
*/
class GotoInlinerTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) {
obfuscator.classes.values.forEach {
it.methods.forEach {
it.instructions.filter { it.opcode == GOTO }.forEach {
val gotoJump = it as JumpInsnNode
val insnAfterTarget = gotoJump.label.next
ConditionUtil.checkCondition(Objects.nonNull(insnAfterTarget)) {
when (insnAfterTarget.opcode) {
GOTO -> gotoJump.label = (insnAfterTarget as JumpInsnNode).label
}
}
}
}
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/optimizer/NopRemoverTransformer.kt
================================================
package pl.alpheratzteam.obfuscator.transformer.optimizer
import org.objectweb.asm.Opcodes.NOP
import pl.alpheratzteam.obfuscator.Obfuscator
import pl.alpheratzteam.obfuscator.api.transformer.Transformer
/**
* @author Unix
* @since 18.12.2020
*/
class NopRemoverTransformer : Transformer {
override fun transform(obfuscator: Obfuscator) = obfuscator.classes.values.forEach { it.methods.forEach { methodNode -> methodNode.instructions.filter { it.opcode == NOP }.forEach { methodNode.instructions.remove(it) } } }
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/util/AsmUtil.kt
================================================
package pl.alpheratzteam.obfuscator.util
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.commons.CodeSizeEvaluator
import org.objectweb.asm.tree.*
import java.util.*
import kotlin.collections.HashMap
import kotlin.collections.any
import kotlin.collections.filterIndexed
import kotlin.collections.forEachIndexed
import kotlin.collections.set
// https://github.com/ByteZ1337/Vetric/blob/master/src/main/kotlin/xyz/xenondevs/obfuscator/utils/asm/ASMUtils.kt
object ASMUtil {
/* ------------------ Constants ------------------ */
const val OBJECT_TYPE = "java/lang/Object"
/* ------------------ Access Checks ------------------ */
fun isPublic(access: Int) = access and ACC_PUBLIC != 0
fun isPrivate(access: Int) = access and ACC_PRIVATE != 0
fun isProtected(access: Int) = access and ACC_PROTECTED != 0
fun isStatic(access: Int) = access and ACC_STATIC != 0
fun isFinal(access: Int) = access and ACC_FINAL != 0
fun isAbstract(access: Int) = access and ACC_ABSTRACT != 0
fun isNative(access: Int) = access and ACC_NATIVE != 0
fun isEnum(access: Int) = access and ACC_ENUM != 0
fun isInterface(access: Int) = access and ACC_INTERFACE != 0
fun isAnnotation(access: Int) = access and ACC_ANNOTATION != 0
fun isBridge(access: Int) = access and ACC_BRIDGE != 0
fun isMandated(access: Int) = access and ACC_MANDATED != 0
fun isModule(access: Int) = access and ACC_MODULE != 0
fun isOpen(access: Int) = access and ACC_OPEN != 0
fun isStaticPhase(access: Int) = access and ACC_STATIC_PHASE != 0
fun isSuper(access: Int) = access and ACC_SUPER != 0
fun isSynchronized(access: Int) = access and ACC_SYNCHRONIZED != 0
fun isSynthetic(access: Int) = access and ACC_SYNTHETIC != 0
fun isTransient(access: Int) = access and ACC_TRANSIENT != 0
fun isTransitive(access: Int) = access and ACC_TRANSITIVE != 0
fun isVolatile(access: Int) = access and ACC_VOLATILE != 0
fun isVarargs(access: Int) = access and ACC_VARARGS != 0
fun isDeprecated(access: Int) = access and ACC_DEPRECATED != 0
fun isStrict(access: Int) = access and ACC_STRICT != 0
fun AnnotationNode.toHashMap(): HashMap<String, Any?> {
val map = HashMap<String, Any?>()
values.filterIndexed { index, _ -> index % 2 == 0 }.forEachIndexed { index, any ->
map[any.toString()] = values[index * 2 + 1]
}
return map
}
fun hasMethod(name: String, desc: String, clazz: ClassNode) =
clazz.methods != null && clazz.methods.any { it.desc == desc && it.name == name }
fun getIntInsn(value: Int) =
when (value) {
in -1..5 -> InsnNode(value + 3)
in Byte.MIN_VALUE..Byte.MAX_VALUE -> IntInsnNode(BIPUSH, value)
in Short.MIN_VALUE..Short.MAX_VALUE -> IntInsnNode(SIPUSH, value)
else -> LdcInsnNode(value)
}
fun getLongInsn(value: Long) =
when (value) {
in 0..1 -> InsnNode((value + 9).toInt())
else -> LdcInsnNode(value)
}
fun getFloatInsn(value: Float) =
when {
value % 1 == 0f && value in 0f..2f -> InsnNode((value + 11).toInt())
else -> LdcInsnNode(value)
}
fun getDoubleInsn(value: Double) =
when {
value % 1 == 0.0 && value in 0.0..1.0 -> InsnNode((value + 14).toInt())
else -> LdcInsnNode(value)
}
fun isIntInsn(insn: AbstractInsnNode): Boolean {
return when {
Objects.isNull(insn) -> false
else -> {
val opcode = insn.opcode
(opcode in ICONST_M1..ICONST_5 || opcode == BIPUSH || opcode == SIPUSH || (insn is LdcInsnNode && insn.cst is Int))
}
}
}
fun isLongInsn(insn: AbstractInsnNode): Boolean = insn.opcode == LCONST_0 || insn.opcode == LCONST_1 || (insn is LdcInsnNode && insn.cst is Long)
fun isFloatInsn(insn: AbstractInsnNode): Boolean = (insn.opcode in FCONST_0..FCONST_2 || insn is LdcInsnNode && insn.cst is Float)
fun isDoubleInsn(insn: AbstractInsnNode): Boolean = (insn.opcode in DCONST_0..DCONST_1 || insn is LdcInsnNode && insn.cst is Double)
// https://github.com/ItzSomebody/radon/blob/master/src/main/java/me/itzsomebody/radon/utils/ASMUtils.java
fun getIntFromInsn(insn: AbstractInsnNode): Int {
val opcode = insn.opcode
return when {
opcode in ICONST_M1..ICONST_5 -> opcode - 3
insn is IntInsnNode && insn.opcode !== NEWARRAY -> insn.operand
insn is LdcInsnNode && insn.cst is Int -> insn.cst as Int
else -> throw UnsupportedOperationException()
}
}
fun getLongFromInsn(insn: AbstractInsnNode): Long {
val opcode = insn.opcode
return when {
opcode in LCONST_0..LCONST_1 -> (opcode - 9).toLong()
insn is LdcInsnNode && insn.cst is Long -> insn.cst as Long
else -> 0L
}
}
fun getFloatFromInsn(insn: AbstractInsnNode): Float {
val opcode = insn.opcode
return when {
opcode in FCONST_0..FCONST_2 -> (opcode - 11).toFloat()
insn is LdcInsnNode && insn.cst is Float -> insn.cst as Float
else -> .0f
}
}
fun getDoubleFromInsn(insn: AbstractInsnNode): Double {
val opcode = insn.opcode
return when {
opcode in DCONST_0..DCONST_1 -> (opcode - 14).toDouble()
insn is LdcInsnNode && insn.cst is Double -> insn.cst as Double
else -> .0
}
}
fun isInstruction(insn: AbstractInsnNode?) = insn !is FrameNode && insn !is LineNumberNode && insn !is LabelNode
fun getMaxSize(methodNode: MethodNode): Int {
val codeSizeEvaluator = CodeSizeEvaluator(null)
methodNode.accept(codeSizeEvaluator)
return codeSizeEvaluator.getMaxSize()
}
fun hasInstructions(methodNode: MethodNode) = Objects.nonNull(methodNode.instructions) && methodNode.instructions.size() > 0
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/util/ConditionUtil.kt
================================================
package pl.alpheratzteam.obfuscator.util
/**
* @author Unix
* @since 30.03.2021
*/
object ConditionUtil {
/**
* Checks some conditions.
* if **true**, runs [Runnable].
* @param condition as conditions to check.
* @param runnable as runnable to run.
* @see [Runnable]
*/
fun checkCondition(condition: Boolean, runnable: Runnable) {
if (!condition) {
return
}
runnable.run()
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/util/InsnBuilder.kt
================================================
package pl.alpheratzteam.obfuscator.util
import org.objectweb.asm.Handle
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.Type
import org.objectweb.asm.tree.*
/**
* @author cookiedragon234, ByteZ
*/
class InsnBuilder {
val list = InsnList()
operator fun InsnList.unaryPlus() = list.add(this)
operator fun AbstractInsnNode.unaryPlus() = list.add(this)
fun Int.insn() = InsnNode(this)
fun insn(opcode: Int) = +InsnNode(opcode)
fun nop() = insn(NOP)
/* Loading constant values */
fun aconst_null() = insn(ACONST_NULL)
fun ldc(int: Int) = +ASMUtil.getIntInsn(int)
fun ldc(long: Long) = +ASMUtil.getLongInsn(long)
fun ldc(float: Float) = +ASMUtil.getFloatInsn(float)
fun ldc(double: Double) = +ASMUtil.getDoubleInsn(double)
fun ldc(string: String) = +LdcInsnNode(string)
fun ldc(type: Type) = +LdcInsnNode(type)
fun ldc(handle: Handle) = +LdcInsnNode(handle)
/* Locals */
fun istore(`var`: Int) = +VarInsnNode(ISTORE, `var`)
fun iload(`var`: Int) = +VarInsnNode(ILOAD, `var`)
fun lstore(`var`: Int) = +VarInsnNode(LSTORE, `var`)
fun lload(`var`: Int) = +VarInsnNode(LLOAD, `var`)
fun fstore(`var`: Int) = +VarInsnNode(FSTORE, `var`)
fun fload(`var`: Int) = +VarInsnNode(FLOAD, `var`)
fun dstore(`var`: Int) = +VarInsnNode(DSTORE, `var`)
fun dload(`var`: Int) = +VarInsnNode(DLOAD, `var`)
fun astore(`var`: Int) = +VarInsnNode(ASTORE, `var`)
fun aload(`var`: Int) = +VarInsnNode(ALOAD, `var`)
/* Array storing & loading */
fun iastore() = insn(IASTORE)
fun iaload() = insn(IALOAD)
fun lastore() = insn(LASTORE)
fun laload() = insn(LALOAD)
fun fastore() = insn(FASTORE)
fun faload() = insn(FALOAD)
fun dastore() = insn(DASTORE)
fun daload() = insn(DALOAD)
fun aastore() = insn(AASTORE)
fun aaload() = insn(AALOAD)
fun bastore() = insn(BASTORE)
fun baload() = insn(BALOAD)
fun castore() = insn(CASTORE)
fun caload() = insn(CALOAD)
fun sastore() = insn(SASTORE)
fun saload() = insn(SALOAD)
/* Stack manipulation */
fun pop() = insn(POP)
fun pop2() = insn(POP2)
fun dup() = insn(DUP)
fun dup_x1() = insn(DUP_X1)
fun dup_x2() = insn(DUP_X2)
fun dup2() = insn(DUP2)
fun dup2_x1() = insn(DUP2_X1)
fun dup2_x2() = insn(DUP2_X2)
fun swap() = insn(SWAP)
/* Arithmetic & Bitwise */
fun iadd() = insn(IADD)
fun isub() = insn(ISUB)
fun imul() = insn(IMUL)
fun idiv() = insn(IDIV)
fun irem() = insn(IREM)
fun ineg() = insn(INEG)
fun ishl() = insn(ISHL)
fun ishr() = insn(ISHR)
fun iushr() = insn(IUSHR)
fun iand() = insn(IAND)
fun ior() = insn(IOR)
fun ixor() = insn(IXOR)
fun iinc(`var`: Int, incr: Int) = +IincInsnNode(`var`, incr)
fun ladd() = insn(LADD)
fun lsub() = insn(LSUB)
fun lmul() = insn(LMUL)
fun ldiv() = insn(LDIV)
fun lrem() = insn(LREM)
fun lneg() = insn(LNEG)
fun lshl() = insn(LSHL)
fun lshr() = insn(LSHR)
fun lushr() = insn(LUSHR)
fun lor() = insn(LOR)
fun land() = insn(LAND)
fun lxor() = insn(LXOR)
fun fadd() = insn(FADD)
fun fsub() = insn(FSUB)
fun fmul() = insn(FMUL)
fun fdiv() = insn(FDIV)
fun frem() = insn(FREM)
fun fneg() = insn(FNEG)
fun dadd() = insn(DADD)
fun dsub() = insn(DSUB)
fun dmul() = insn(DMUL)
fun ddiv() = insn(DDIV)
fun drem() = insn(DREM)
fun dneg() = insn(DNEG)
/* Primitive type conversion */
fun i2l() = insn(I2L)
fun i2f() = insn(I2F)
fun i2d() = insn(I2D)
fun i2b() = insn(I2B)
fun i2c() = insn(I2C)
fun i2s() = insn(I2S)
fun l2i() = insn(L2I)
fun l2f() = insn(L2F)
fun l2d() = insn(L2D)
fun f2i() = insn(F2I)
fun f2l() = insn(F2L)
fun f2d() = insn(F2D)
fun d2i() = insn(D2I)
fun d2l() = insn(D2L)
fun d2f() = insn(D2F)
/* Number comparisons */
fun lcmp() = insn(LCMP)
fun fcmpl() = insn(FCMPL)
fun fcmpg() = insn(FCMPG)
fun dcmpl() = insn(DCMPL)
fun dcmpg() = insn(DCMPG)
/* Jumping */
fun goto(label: LabelNode) = +JumpInsnNode(GOTO, label)
fun jsr(label: LabelNode) = +JumpInsnNode(JSR, label)
fun ifeq(label: LabelNode) = +JumpInsnNode(IFEQ, label)
fun ifne(label: LabelNode) = +JumpInsnNode(IFNE, label)
fun iflt(label: LabelNode) = +JumpInsnNode(IFLT, label)
fun ifle(label: LabelNode) = +JumpInsnNode(IFLE, label)
fun ifge(label: LabelNode) = +JumpInsnNode(IFGE, label)
fun ifgt(label: LabelNode) = +JumpInsnNode(IFGT, label)
fun if_icmplt(label: LabelNode) = +JumpInsnNode(IF_ICMPLT, label)
fun if_icmple(label: LabelNode) = +JumpInsnNode(IF_ICMPLE, label)
fun if_icmpge(label: LabelNode) = +JumpInsnNode(IF_ICMPGE, label)
fun if_icmpgt(label: LabelNode) = +JumpInsnNode(IF_ICMPGT, label)
fun if_icmpeq(label: LabelNode) = +JumpInsnNode(IF_ICMPEQ, label)
fun if_icmpne(label: LabelNode) = +JumpInsnNode(IF_ICMPNE, label)
fun if_acmpeq(label: LabelNode) = +JumpInsnNode(IF_ACMPEQ, label)
fun ifnull(label: LabelNode) = +JumpInsnNode(IFNULL, label)
fun ifnonnull(label: LabelNode) = +JumpInsnNode(IFNONNULL, label)
// fun tableswitch(baseNumber: Int, dflt: LabelNode, vararg targets: LabelNode) = +constructTableSwitch(baseNumber, dflt, *targets)
fun lookupswitch(defaultLabel: LabelNode, lookup: Pair<IntArray, Array<LabelNode>>) = +LookupSwitchInsnNode(defaultLabel, lookup.first, lookup.second)
/* Fields */
fun getstatic(owner: String, name: String, desc: String) = +FieldInsnNode(GETSTATIC, owner, name, desc)
fun putstatic(owner: String, name: String, desc: String) = +FieldInsnNode(PUTSTATIC, owner, name, desc)
fun getfield(owner: String, name: String, desc: String) = +FieldInsnNode(GETFIELD, owner, name, desc)
fun putfield(owner: String, name: String, desc: String) = +FieldInsnNode(PUTFIELD, owner, name, desc)
/* Method invocation */
fun invokevirtual(owner: String, name: String, desc: String, `interface`: Boolean = false) = +MethodInsnNode(INVOKEVIRTUAL, owner, name, desc, `interface`)
fun invokespecial(owner: String, name: String, desc: String, `interface`: Boolean = false) = +MethodInsnNode(INVOKESPECIAL, owner, name, desc, `interface`)
fun invokestatic(owner: String, name: String, desc: String, `interface`: Boolean = false) = +MethodInsnNode(INVOKESTATIC, owner, name, desc, `interface`)
fun invokeinterface(owner: String, name: String, desc: String, `interface`: Boolean = false) = +MethodInsnNode(INVOKEINTERFACE, owner, name, desc, `interface`)
/* Creating new instances */
fun new(type: String) = +TypeInsnNode(NEW, type)
fun newarray(type: Int) = +IntInsnNode(NEWARRAY, type)
fun anewarray(desc: String) = +TypeInsnNode(ANEWARRAY, desc)
fun newboolarray() = newarray(T_BOOLEAN)
fun newchararray() = newarray(T_CHAR)
fun newbytearray() = newarray(T_BYTE)
fun newshortarray() = newarray(T_SHORT)
fun newintarray() = newarray(T_INT)
fun newlongarray() = newarray(T_LONG)
fun newfloatarray() = newarray(T_FLOAT)
fun newdoublearray() = newarray(T_DOUBLE)
/* Array information */
fun arraylength() = insn(ARRAYLENGTH)
/* Throwing exceptions */
fun athrow() = insn(ATHROW)
/* Type checks and casts */
fun checkcast(descriptor: String) = +TypeInsnNode(CHECKCAST, descriptor)
fun instanceof(descriptor: String) = +TypeInsnNode(INSTANCEOF, descriptor)
/* Returns */
fun ireturn() = insn(IRETURN)
fun lreturn() = insn(LRETURN)
fun freturn() = insn(FRETURN)
fun dreturn() = insn(DRETURN)
fun areturn() = insn(ARETURN)
fun _return() = insn(RETURN)
/* Frames */
fun frame(type: Int, numLocal: Int, local: Array<Any>?, numStack: Int, stack: Array<Any>?) = +FrameNode(type, numLocal, local, numStack, stack)
}
fun insnBuilder(builder: InsnBuilder.() -> Unit) = InsnBuilder().also(builder).list
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/util/JarUtil.kt
================================================
package pl.alpheratzteam.obfuscator.util
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassWriter
import org.objectweb.asm.tree.ClassNode
import java.io.*
import java.lang.Exception
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.jar.JarOutputStream
import java.util.zip.CRC32
import java.util.zip.ZipOutputStream
/**
* @author Unix
* @since 16.12.2020
*/
object JarUtil {
/**
* Loads jar file as [Pair].
* @param file input file.
* @return [Pair] as readed content from the file.
*/
fun loadJar(file: File): Pair<MutableMap<String, ClassNode>, MutableMap<String, ByteArray>> {
val classes = mutableMapOf<String, ClassNode>()
val assets = mutableMapOf<String, ByteArray>()
JarFile(file).use {
val entries = it.entries()
while (entries.hasMoreElements()) {
val jarEntry = entries.nextElement()
try {
val bytes = asByteArray(it.getInputStream(jarEntry))
if (!jarEntry.name.endsWith(".class")) {
assets[jarEntry.name] = bytes
continue
}
val classNode = ClassNode()
val classReader = ClassReader(bytes)
classReader.accept(classNode, ClassReader.EXPAND_FRAMES)
classes[classNode.name] = classNode
} catch (ex: Exception) {
ex.printStackTrace()
}
}
}
return Pair(classes, assets)
}
/**
* Saves contents to jar file.
* @param file output file.
* @param pair content to save.
* @throws [IOException] thrown when error is occurred.
*/
@Throws(IOException::class)
fun saveJar(file: File, pair: Pair<MutableMap<String, ClassNode>, MutableMap<String, ByteArray>>) {
JarOutputStream(FileOutputStream(file)).use {
corrupt(it) // TODO: 04.04.2021 add this to configuration
pair.first.values.forEach { classNode ->
val classWriter = ClassWriter(ClassWriter.COMPUTE_MAXS or ClassWriter.COMPUTE_FRAMES)
it.putNextEntry(JarEntry(classNode.name + ".class"))
classNode.accept(classWriter)
it.write(classWriter.toByteArray())
it.closeEntry()
}
pair.second.forEach { (key, value) ->
run {
it.putNextEntry(JarEntry(key))
it.write(value)
it.closeEntry()
}
}
}
}
/**
* This methods reads content from [InputStream] to [ByteArray].
* @param inputStream stream to read.
* @return [ByteArray] readed data.
*/
private fun asByteArray(inputStream: InputStream): ByteArray {
return try {
val out = ByteArrayOutputStream()
var readed: Int
while (inputStream.read().also { readed = it } != -1) {
out.write(readed)
}
inputStream.close()
out.toByteArray()
} catch (ex: Exception) {
ex.printStackTrace()
ByteArray(0)
}
}
/**
* Corrupts the contents of the zip file.
* @param outputStream stream to corrupt
* @see [ZipOutputStream]
*/
private fun corrupt(outputStream: ZipOutputStream) {
val field = ZipOutputStream::class.java.getDeclaredField("crc")
field.isAccessible = true
field[outputStream] = object : CRC32() {
override fun getValue() = RandomUtil.int(Int.MAX_VALUE).toLong()
}
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/util/RandomUtil.kt
================================================
package pl.alpheratzteam.obfuscator.util
import java.util.concurrent.ThreadLocalRandom
/**
* @author Unix
* @since 17.12.2020
*/
object RandomUtil {
private val random = ThreadLocalRandom.current()
/**
* Randomizes a number.
* @param max as max int range.
* @return [Int] randomized int value.
*/
fun int(max: Int) = random.nextInt(max)
/**
* Randomizes a number.
* @return [Int] randomized int value.
*/
fun int() = random.nextInt()
/**
* Randomizes a number.
* @return [Double] randomized double value.
*/
fun double() = random.nextDouble()
/**
* Randomizes a number.
* @return [Float] randomized float value.
*/
fun float() = random.nextFloat()
/**
* Randomizes a number.
* @param min as min value to randomize.
* @param max as max value to randomize.
* @return [Int] randomized int value.
*/
fun int(min: Int, max: Int) = random.nextInt(min, max)
/**
* Randomizes a number.
* @param [min] as min value to randomize.
* @param [max] as max value to randomize.
* @return [Double] randomized double value.
*/
fun double(min: Double, max: Double) = random.nextDouble(min, max)
/**
* Randomizes a number.
* @param [min] as min value to randomize.
* @param [max] as max value to randomize.
* @return [Float] randomized float value.
*/
fun float(min: Double, max: Double) = double(min, max).toFloat()
/**
* Randomizes the chance.
* @param chance as chance to check.
* @return [Boolean], if `true` chance is right.
*/
fun chance(chance: Double) = Math.random() * 100.0 <= chance
/**
* Randomizes a boolean.
* @return [Boolean] randomized boolean value.
*/
fun boolean() = random.nextBoolean()
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/util/StringUtil.kt
================================================
package pl.alpheratzteam.obfuscator.util
import java.lang.StringBuilder
import java.util.stream.Collectors
import java.util.stream.IntStream
import java.util.concurrent.ThreadLocalRandom
/**
* @author Unix
* @since 17.12.2020
*/
object StringUtil {
private val chars = "abcdefghijklmnopqrstuvwxyz1234567890".toCharArray()
private val javaKeywords = mutableListOf(
"abstract", "boolean", "break", "byte", "case", "catch", "char", "class",
"continue", "default", "do", "while", "for", "if",
"\u0000", "\u0001", "\u0002", "\u0004",
"double", "else", "new", "null", "return", "short",
"super", "static", "switch", "try", "void",
"while", "volatile"
)
/**
* Generates custom string.
* @param length length of the generated string.
* @return [String] as generated string.
*/
fun generateString(length: Int): String {
return IntStream.range(0, length)
.mapToObj {
Character.toString(
chars[RandomUtil.int(chars.size)]
)
}.collect(Collectors.joining())
}
/**
* Generates unreadable string.
* @param string string to be encoded.
* @return [String] as unreadable generated string.
*/
fun makeUnreadable(string: String): String { // generate unreadable string
val stringBuilder = StringBuilder()
string.toCharArray().forEach { stringBuilder.append((it + '\u7159'.toInt())) }
return stringBuilder.toString()
}
/**
* Generates java keyword string.
* @param length length of the generated string.
* @return [String] as java keyword generated string.
*/
fun getStringWithJavaKeywords(length: Int): String {
val stringBuilder = StringBuilder()
for (index in 0..length) {
val keyword = javaKeywords[ThreadLocalRandom.current().nextInt(0, javaKeywords.size)]
when {
index != 24 -> {
stringBuilder.append(keyword).append(" ")
} else -> {
stringBuilder.append(keyword)
}
}
}
return stringBuilder.toString()
}
}
================================================
FILE: src/main/kotlin/pl/alpheratzteam/obfuscator/util/Util.kt
================================================
package pl.alpheratzteam.obfuscator.util
import org.objectweb.asm.Type
import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.tree.*
import java.io.PrintStream
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
/**
* @author cookiedragon234 23/Apr/2020
*/
inline fun <reified T: Any> Any?.cast(type: KClass<T>): T = this as T
inline fun <reified T: Any> Any?.cast(type: Class<T>): T = this as T
val <T: Any> KClass<T>.internalName: String
get() = Type.getInternalName(this.java)
inline val KFunction<*>.descriptor: String
inline get() {
val params = parameters.map { Type.getType(it.type.classifier.cast(KClass::class).java) }
val returnType = Type.getType(returnType.classifier.cast(KClass::class).java)
return Type.getMethodDescriptor(returnType, *params.toTypedArray())
}
fun InsnList.add(opcode: Int) = add(InsnNode(opcode))
fun ldcInt(int: Int): AbstractInsnNode {
return if (int == -1) {
InsnNode(ICONST_M1)
} else if (int == 0) {
InsnNode(ICONST_0)
} else if (int == 1) {
InsnNode(ICONST_1)
} else if (int == 2) {
InsnNode(ICONST_2)
} else if (int == 3) {
InsnNode(ICONST_3)
} else if (int == 4) {
InsnNode(ICONST_4)
} else if (int == 5) {
InsnNode(ICONST_5)
} else if (int >= -128 && int <= 127) {
IntInsnNode(BIPUSH, int)
} else if (int >= -32768 && int <= 32767) {
IntInsnNode(SIPUSH, int)
} else {
LdcInsnNode(int)
}
}
fun ldcLong(long: Long): AbstractInsnNode {
return when (long) {
0L -> InsnNode(LCONST_0)
1L -> InsnNode(LCONST_1)
else -> LdcInsnNode(long)
}
}
fun ldcDouble(double: Double): AbstractInsnNode {
return when (double) {
0.0 -> InsnNode(DCONST_0)
1.0 -> InsnNode(DCONST_1)
else -> LdcInsnNode(double)
}
}
fun ldcFloat(float: Float): AbstractInsnNode {
return when (float) {
0f -> InsnNode(FCONST_0)
1f -> InsnNode(FCONST_1)
2f -> InsnNode(FCONST_2)
else -> LdcInsnNode(float)
}
}
inline fun constructTableSwitch(
baseNumber: Int,
defaultLabel: LabelNode,
vararg targetLabels: LabelNode
): TableSwitchInsnNode {
return TableSwitchInsnNode(
baseNumber,
baseNumber + targetLabels.size - 1,
defaultLabel,
*targetLabels
)
}
inline fun constructLookupSwitch(
defaultLabel: LabelNode,
lookup: Array<Pair<Int, LabelNode>>
): LookupSwitchInsnNode {
lookup.sortWith { a, b -> a.first.compareTo(b.first) }
val keys = lookup.map {
it.first
}.toIntArray()
val values = lookup.map {
it.second
}.toTypedArray()
return LookupSwitchInsnNode(
defaultLabel,
keys,
values
)
}
fun InsnList.printlnAsm() {
add(FieldInsnNode(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"))
add(SWAP)
add(MethodInsnNode(INVOKEVIRTUAL, PrintStream::class.internalName, "println", "(Ljava/lang/Object;)V", false))
}
fun InsnBuilder.printlnAsm() {
+FieldInsnNode(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;")
+SWAP.insn()
+MethodInsnNode(INVOKEVIRTUAL, PrintStream::class.internalName, "println", "(Ljava/lang/Object;)V", false)
}
fun InsnList.printlnIntAsm() {
add(FieldInsnNode(GETSTATIC, System::class.internalName, "out", "Ljava/io/PrintStream;"))
add(InsnNode(SWAP))
add(MethodInsnNode(INVOKEVIRTUAL, PrintStream::class.internalName, "println", "(I)V", false))
}
fun InsnBuilder.printlnIntAsm() {
+FieldInsnNode(GETSTATIC, System::class.internalName, "out", "Ljava/io/PrintStream;")
+SWAP.insn()
+MethodInsnNode(INVOKEVIRTUAL, PrintStream::class.internalName, "println", "(I)V", false)
}
inline fun InsnList.forEach(op: (insn: AbstractInsnNode) -> Unit) = this.iterator().forEach(op)
gitextract_o39oe31y/
├── .gitignore
├── .idea/
│ └── .gitignore
├── LICENSE
├── README.md
├── build.gradle.kts
├── gradle/
│ └── wrapper/
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src/
└── main/
└── kotlin/
└── pl/
└── alpheratzteam/
└── obfuscator/
├── Obfuscator.kt
├── api/
│ ├── number/
│ │ ├── NumberData.kt
│ │ └── NumberType.kt
│ └── transformer/
│ └── Transformer.kt
├── main.kt
├── transformer/
│ ├── AntiDebugTransformer.kt
│ ├── BadAnnotationTransformer.kt
│ ├── BooleanObfuscationTransformer.kt
│ ├── DebugInfoRemoverTransformer.kt
│ ├── FakeInstructionsTransformer.kt
│ ├── FlowTransformer.kt
│ ├── FullAccessTransformer.kt
│ ├── HideCodeTransformer.kt
│ ├── LocalVariableTransformer.kt
│ ├── MarkerTransformer.kt
│ ├── NumberTransformer.kt
│ ├── ShuffleMemberTransformer.kt
│ ├── SignatureTransformer.kt
│ ├── SourceFileTransformer.kt
│ ├── ThrowableTransformer.kt
│ ├── TrashCodeTransformer.kt
│ ├── TrashExceptionTransformer.kt
│ └── optimizer/
│ ├── FieldAccessTransformer.kt
│ ├── GotoInlinerTransformer.kt
│ └── NopRemoverTransformer.kt
└── util/
├── AsmUtil.kt
├── ConditionUtil.kt
├── InsnBuilder.kt
├── JarUtil.kt
├── RandomUtil.kt
├── StringUtil.kt
└── Util.kt
Condensed preview — 42 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (99K chars).
[
{
"path": ".gitignore",
"chars": 278,
"preview": "# Compiled class file\n*.class\n\n# Log file\n*.log\n\n# BlueJ files\n*.ctxt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Packa"
},
{
"path": ".idea/.gitignore",
"chars": 237,
"preview": "# Default ignored files\n/shelf/\n/workspace.xml\n# Datasource local storage ignored files\n/../../../../../../:\\Users\\Unix\\"
},
{
"path": "LICENSE",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2019 AlpheratzTeam\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "README.md",
"chars": 531,
"preview": "# Java Obfuscator\n\nJava Obfuscator for protecting your Java applications. You can find further instruction on compilatio"
},
{
"path": "build.gradle.kts",
"chars": 731,
"preview": "import org.jetbrains.kotlin.gradle.tasks.KotlinCompile\n\nplugins {\n kotlin(\"jvm\") version \"1.4.10\"\n application\n}\n\n"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 202,
"preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributi"
},
{
"path": "gradle.properties",
"chars": 27,
"preview": "kotlin.code.style=official\n"
},
{
"path": "gradlew",
"chars": 5766,
"preview": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\n#\n# Licensed under the Apache License, Version 2.0"
},
{
"path": "gradlew.bat",
"chars": 2674,
"preview": "@rem\n@rem Copyright 2015 the original author or authors.\n@rem\n@rem Licensed under the Apache License, Version 2.0 (the \""
},
{
"path": "settings.gradle.kts",
"chars": 34,
"preview": "\nrootProject.name = \"Obfuscator\"\n\n"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/Obfuscator.kt",
"chars": 1708,
"preview": "package pl.alpheratzteam.obfuscator\n\nimport org.objectweb.asm.tree.ClassNode\nimport pl.alpheratzteam.obfuscator.transfor"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/api/number/NumberData.kt",
"chars": 1800,
"preview": "package pl.alpheratzteam.obfuscator.api.number\n\nimport org.objectweb.asm.Opcodes.*\nimport org.objectweb.asm.tree.FieldNo"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/api/number/NumberType.kt",
"chars": 392,
"preview": "package pl.alpheratzteam.obfuscator.api.number\n\nimport org.objectweb.asm.Opcodes.*\nimport org.objectweb.asm.tree.InsnNod"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/api/transformer/Transformer.kt",
"chars": 384,
"preview": "package pl.alpheratzteam.obfuscator.api.transformer\n\nimport pl.alpheratzteam.obfuscator.Obfuscator\n\n/**\n * @author Unix\n"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/main.kt",
"chars": 240,
"preview": "import pl.alpheratzteam.obfuscator.Obfuscator\n\n/**\n * @author Unix\n * @since 16.12.2020\n */\n\n/**\n * This method starts t"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/AntiDebugTransformer.kt",
"chars": 3306,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport pl.alpheratzteam.obfuscator.O"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/BadAnnotationTransformer.kt",
"chars": 2960,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.tree.AnnotationNode\nimport pl.alpheratzteam.ob"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/BooleanObfuscationTransformer.kt",
"chars": 3215,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport org.objectweb.asm.tree.*\nimpo"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/DebugInfoRemoverTransformer.kt",
"chars": 947,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.ClassReader\nimport org.objectweb.asm.ClassWrit"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/FakeInstructionsTransformer.kt",
"chars": 1982,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport pl.alpheratzteam.obfuscator.O"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/FlowTransformer.kt",
"chars": 1553,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport org.objectweb.asm.tree.FieldI"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/FullAccessTransformer.kt",
"chars": 1216,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport pl.alpheratzteam.obfuscator.O"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/HideCodeTransformer.kt",
"chars": 1238,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport pl.alpheratzteam.obfuscator.O"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/LocalVariableTransformer.kt",
"chars": 607,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport pl.alpheratzteam.obfuscator.Obfuscator\nimport pl.alpheratzteam.o"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/MarkerTransformer.kt",
"chars": 1205,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport org.objectweb.asm.tree.Method"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/NumberTransformer.kt",
"chars": 12150,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.tree.InsnList\nimport org.objectweb.asm.tree.Me"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/ShuffleMemberTransformer.kt",
"chars": 692,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport pl.alpheratzteam.obfuscator.Obfuscator\nimport pl.alpheratzteam.o"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/SignatureTransformer.kt",
"chars": 462,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport pl.alpheratzteam.obfuscator.Obfuscator\nimport pl.alpheratzteam.o"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/SourceFileTransformer.kt",
"chars": 458,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport pl.alpheratzteam.obfuscator.Obfuscator\nimport pl.alpheratzteam.o"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/ThrowableTransformer.kt",
"chars": 4426,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.F_SAME\nimport org.objectweb.asm.tree.*"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/TrashCodeTransformer.kt",
"chars": 9715,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport org.objectweb.asm.Opcodes.*\nimport org.objectweb.asm.tree.LabelN"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/TrashExceptionTransformer.kt",
"chars": 1216,
"preview": "package pl.alpheratzteam.obfuscator.transformer\n\nimport pl.alpheratzteam.obfuscator.Obfuscator\nimport pl.alpheratzteam.o"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/optimizer/FieldAccessTransformer.kt",
"chars": 599,
"preview": "package pl.alpheratzteam.obfuscator.transformer.optimizer\n\nimport org.objectweb.asm.Opcodes.ACC_FINAL\nimport pl.alpherat"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/optimizer/GotoInlinerTransformer.kt",
"chars": 1064,
"preview": "package pl.alpheratzteam.obfuscator.transformer.optimizer\n\nimport org.objectweb.asm.Opcodes.GOTO\nimport org.objectweb.as"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/transformer/optimizer/NopRemoverTransformer.kt",
"chars": 524,
"preview": "package pl.alpheratzteam.obfuscator.transformer.optimizer\n\nimport org.objectweb.asm.Opcodes.NOP\nimport pl.alpheratzteam."
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/util/AsmUtil.kt",
"chars": 6055,
"preview": "package pl.alpheratzteam.obfuscator.util\n\nimport org.objectweb.asm.Opcodes.*\nimport org.objectweb.asm.commons.CodeSizeEv"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/util/ConditionUtil.kt",
"chars": 462,
"preview": "package pl.alpheratzteam.obfuscator.util\n\n/**\n * @author Unix\n * @since 30.03.2021\n */\n\nobject ConditionUtil {\n\n /**\n"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/util/InsnBuilder.kt",
"chars": 7988,
"preview": "package pl.alpheratzteam.obfuscator.util\n\nimport org.objectweb.asm.Handle\nimport org.objectweb.asm.Opcodes.*\nimport org."
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/util/JarUtil.kt",
"chars": 3727,
"preview": "package pl.alpheratzteam.obfuscator.util\n\nimport org.objectweb.asm.ClassReader\nimport org.objectweb.asm.ClassWriter\nimpo"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/util/RandomUtil.kt",
"chars": 1857,
"preview": "package pl.alpheratzteam.obfuscator.util\n\nimport java.util.concurrent.ThreadLocalRandom\n\n/**\n * @author Unix\n * @since 1"
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/util/StringUtil.kt",
"chars": 2223,
"preview": "package pl.alpheratzteam.obfuscator.util\n\nimport java.lang.StringBuilder\nimport java.util.stream.Collectors\nimport java."
},
{
"path": "src/main/kotlin/pl/alpheratzteam/obfuscator/util/Util.kt",
"chars": 3879,
"preview": "package pl.alpheratzteam.obfuscator.util\n\nimport org.objectweb.asm.Type\nimport org.objectweb.asm.Opcodes.*\nimport org.ob"
}
]
About this extraction
This page contains the full source code of the alpheratzteam/obfuscator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 42 files (89.6 KB), approximately 22.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.