Home

Awesome

masxinlingvonta

Compiles Java ByteCode to LLVM IR and native code (for obfuscation purposes). Contributions are welcome!

Prerequisites

Building from source

You can simply build this project with one simple command:

mvn -Djavacpp.platform=<HOST-PLATFORM> clean package

The HOST-PLATFORM is the platform you want to run this tool on, NOT the platform the compile code should run on. Supported host targets: windows-x86_64, linux-x86_64, macosx-x86_64

Features

This project is not production-safe. Please test if the code compiles correctly before publishing!

If you found bugs or missing features, feel free to open an issue.

Supported

Partially supported

Not supported

Planned features

Usage

Preparation

Before compiling, you have to add code to your program that loads the generated native libraries. Here is an example for a native loader that assumes that the natives are stored in META-INF/natives. To use it, just add NativeLoader.loadNatives() to the main-method of your program.

Applying NameObfuscation via ProGuard and another bytecode obfuscator for further obfuscation (e.g. ZKM (commercial) , obfuscator, Radon, etc.) is recommended.

Target selection

Before you think about target selection, you should first read about the limitations of this tool and the method it uses (see below).

By default, this tool does not compile every method in your program. You have to specify the methods you want to compile manually using either the annotation api or the config.

Compiling via CLI

If you want to compile shared libraries for your target OSes:

java -jar masxinlingvonta-cli.jar -i input.jar -o obfuscated.jar -compileFor windows,linux -llvmDir "C:\Program Files\LLVM\bin"

If you want to compile the generated IR yourself:

java -jar masxinlingvonta-cli.jar -i input.jar -o obfuscated.jar -ll output.ll

CLI Options:

OptionalOption NameShort aliasDescription
No--inputJar <FILE>-iInput JAR
No--outputJar <FILE>-iOutput JAR
Yes--config <FILE>-cAllows you to specify a config (see below)
Yes--irOutput <FILE>-llDumps the generated LLVM IR
Yes-compileFor <OS1,OS2,...>Compiles shared libraries for the specified targets
Yes-outputDirSelects a directory where the natives generated by -compileFor will be placed
Yes-llvmDirLLVM's bin folder
Yes-helpPrints a help page

Configuration

Here is an example configuration (should be self-explanatory)

{
  "additionalMethodsToCompile": [
    {
      "owner": "net/superblaubeere27/Main",
      "name": "superSophisticatedLicenseCheck",
      "desc": "(Ljava/lang/String;)Z"
    }
  ]
}

Annotations

To use annotations, include the masxinlingvonta-annotations JAR in your class path.

For now there is only one annotation:

AnnotationTargetDescription
@OutsourceMethodsMethods with this annotation will be compiled to native code

Limitations

Garbage Collection

Local references in a method are only freed when the method returns. For example function with loops like this could cause memory leaks:

@Outsource
private void foo(SocketServer server)throws Exception{
    while (true) {
        Socket sock = server.accept();
        // ...
    
        // The JVM would free the reference to sock which allows it to be garbage collected
    }
} // masxinlingvonta would free the references on return. 

To prevent a memory leak, you should consider extracting the inner part of loops that your program will be stuck in for a while:

@Outsource
private void foo(SocketServer server)throws Exception{
    while (true) {
        bar(server);
    }
}

@Outsource
private void foo(SocketServer server)throws Exception{
    Socket sock = server.accept();
    // ...
    // The local reference to sock will be freed here
  }

Performance

Every JVM-interop is handled via JNI-methods. Only primitive operations like arithmetics, branches etc. are independent.

This dramatically slows down the code, so only a few select methods should be compiled to native code