Damion Brown's Blog

0x7F1F27C3C19D9B74

How the "atlassian-agent" keygen + crack works.


  • Tue 28 May 2019
  • Tech

A look at the "atlassian-agent", a keygen + crack for the Atlassian product suite published on GitHub by Neo Peng (@pengzhile).

The premise on which the crack operates is extremely simple. The Atlassian license manager uses a private/public keypair and PKI to validate licenses.

Included within an Atlassian product is the public key used to verify that a given license key is valid. License validation happens locally on a given instance and does not require an internet connection, that is to say the products do not phone home to validate licenses.

The "atlassian-agent" simply injects it's own public key in replacement of Atlassian's, and then providers the private key by way of the keygen.


Reverse Engineering

KeyTransformer.java

The implementation of this phenomenal.

The documentation instructs the user to include -javaagent:/path/to/atlassian-agent.jar in the Java Virtual Machine (JVM) options of the target application.

javaagent is part of the "Java Instrumentation" libraries which provides the premain(String args, Instrumentation inst) method, which is called prior to main(String[] args) and provides a mechmechanism to replace bytecode withing the JVM at runtime

"atlassian-agent" takes advantage of this to target EncodedKeySpec(byte[] encodedKey), a native library of the JRE used for handling private/public x509 keys.

Critically, three modifications are made to the runtime bytecode:

That if() statement is as follows: if(Arrays.equals($1,__h_ok)){$1=__h_nk;System.out.println(\"agent working");} and functionally executes like so:

EncodedKeySpec(byte[] encodedKey){
    if(encodedKey == __h_ok){
        encodedKey = __h_nk;
        System.out.println("agent working");
    }
    ...Original EncodedKeySpec() code...
}

It checks if the variable passed to the method ($1 / encodedKey) is Atlassian's key, and if so - replaces it with the new custom key.

That's it.

Now that custom key is returned to the Atlassian code, and everything continues executing.