Unpacking Pyrogenic/Qealler using Java agent -Part 0x2

We will learn how and when we can use Java agent to quickly unpack the Pyrogenic Infostealer. In the earlier post Pyrogenic Infostealer static analysis – Part 0x1 we statically analysed the Pyrogenic/Qealler Infostealer but this require more time and effort.  We will be using same sample PaymAdviceVend_LLCRep.jar from ANY.RUN (MD5: F0E21C7789CD57EEBF8ECDB9FADAB26B) used in Part 0x1. Let’s start with basic introduction to Java agent.

Introduction to Java agent

Java agent is used to instrument programs running on the JVM and it can modify the Java bytecode at runtime without source code. In this post we will be using Java agent to dump the classes during runtime without any bytecode modification but for more details please check this Java Agents Tutorial [1]. These are the minimum requirement for Java agent to work:

  1. Java agent class file should have a premain method which acts as the entry-point.This method is executed before the real java application main method, premain method it’s like TLS callback.
  2. MANIFEST.MF should be defined with Premain-Class attribute, which will point to class name with premain method. Another important point is there must be a new line at the end of the MANIFEST file. Otherwise, the last header is ignored.
  3. javaagent parameter should be specified to load java agent jar file with premain method e.g .java -javaagent:dumper.jar -jar malware.jar

Unpacking using Java agent

dumper.java & MANIFEST.mf are used to build Java agent dumper.jar. dumper.java code is copied from Reversing an obfuscated java malware pdf [2]  and I will highly recommend to go through the pdf[2] to understand the different method which can be used to analyse Java malware.


Note: All java, MANIFEST and jar files are uploaded to GitHub repo[3].


import java.io.*;
import java.lang.instrument.*;
import java.security.*;

// This code is copied from "Reversing an obfuscated java malware by Extreme Coders"
public class dumper {
    //A java agent must have a premain method which acts as the entry-point
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("agent loaded");
        // Register out trasnformer
        inst.addTransformer(new transformer());

class transformer implements ClassFileTransformer {
    // The transform method is called for each non-system class as they are being loaded
    public byte[] transform(ClassLoader loader, String className,
        Class < ? > classBeingRedefined, ProtectionDomain protectionDomain,
        byte[] classfileBuffer) throws IllegalClassFormatException {
        if (className != null) {
            // Skip all system classes
            if (!className.startsWith("java") &&
                !className.startsWith("sun") && !className.startsWith("javax") && !className.startsWith("com") && !className.startsWith("jdk") && !className.startsWith("org")) {
                System.out.println("Dumping: " + className);
                // Replace all separator characters with _
                String newName = className.replaceAll("/", "_") + ".class";
                try {
                    FileOutputStream fos = new FileOutputStream(newName);
                } catch (Exception ex) {
                    System.out.println("Exception while writing: " + newName);
        // We are not modifying the bytecode in anyway, so return it as-is
        return classfileBuffer;


Manifest-Version: 1.0
Premain-Class: dumper


Note: If you know the basic of Java or any other object oriented programming language then it will be much easier to understand this dumped unpacked code.

  1. Uploaded the jar file in GitHub repo[3]which is generated using following command: javac dumper.java
    jar cmf MANIFEST.MF dumper.jar dumper.class transformer.class
  2. Execute this cmd java -javaagent:dumper.jar -jar BankPaymAdviceVend_LLCRep.jar to run the malware with java agent and it will dump all the accessed classes at runtime to current working directory.
  3. Please decompile all the dumped class files which start with q0b4 and j/t/e package name files using ByteCodeViewer FernFlower Java decompiler. One of the easiest way is to zip all class and then use BCV. Then, import decompiled java source files from BCV into any Java IDE, this will help you in code navigation.
  4. Start from the bottom and go up in the above pic then you will find first proper package name q0b4/bootstrap/templates/Header which can be our starting point for unpacked code. We are Reverse engineer, we always start in reverser order :).
  5. Below pic shows all the unpacked classes dumped using Java agent dumper.jar. It starts from Header.java which uses decrypt function to AES decrypt the classes at runtime and invoke the main method. It invokes j.t.e.Main package main method.

Other approach is to dump all the classes present in obfuscatedEntryList using for loop and continue analysis

Dumped class file analysis

Malware authors are good coder 🙂 as they divided the source code in multiple sensible packages. They too have made our job easier by giving proper name to functions, variables and classes. We will go through some of the classes Main, Server, MainEx and one util IPAddress class, as it will take too much time to go through each one of them.

Main & Server class
    • Main class invoke the loadLibrary method which send the cmd to CC using sendCmd method.
    • Server class contain function loadLibrary which is used above and pushCredentials which is used send the stolen credential to CC.
    • Server class contain the following list of available library and cmds:
      public static final int PYTHON = 162144;
      public static final int SQLITE = 4353152;
      public static final int JNA = 224288;
      public static final int JNA_PLATFORM = 3048576;
      public static final int JNA_4 = 307200;
      public static final int JNA_PLATFORM_4 = 308224;
      public static final int BCPROV = 310272;
      public static final int INI4J = 311296;
      public static final int XML = 312320;
      public static final int JSON = 313344;
      public static final int W3DOM = 314368;
      public static final int Q4_PASS_LIB = 315392;
      public static final int JPOWERSHELL = 316416;
      private static final int LIBRARY_CMD = 16384;
      private static final int CREDENTIAL_CMD = 32768;
      private static final byte[] SEED = "uisdfysdgfbsdyufbsiybfsdyb733grfsudbfjh".getBytes();
      private static final int MAX_TRY_COUNT = 20;

Malware author didn’t packed all the required library in the jar but it is requested when needed at runtime. This significantly decrease the malware size to 153.27 Kb. Let’s discuss some of the library and cmds used:

      1. Server JNA, JNA_4, JNA_PLATFORM, JNA_PLATFORM_4  – JNA (Java Native Access ) provides simplified access to native library methods without requiring any additional JNI or native code.  For example you can call printf, GetSystemTime Windows API function directly from Java Code.
      2. INI4j – Java API for handling configuration files in Windows .ini format
      3. JPOWERSHELL – Simple Java API that allows to interact with PowerShell console. It may be used when malware invokes any PowerShell cmds.
      4. Q4_PASS_LIB – May be Qealler v4 Password Library loaded first using list.add(server.loadLibrary(315392));
      5. LIBRARY_CMD – May be used to load the clean dll used sqlitejdbc.dll and jnidispatch.dll
      6. CREDENTIAL_CMD – This cmd is used to pushCredentials to CC
MainEx class
    • j.t.e.Main main method invokes the j.t.e.MainEx main method as shown above in Main class.  It sent credential and system info in JSON format to CC. All the communication are AES encrypted using EncryptedCipherOutputStream and EncryptedCipherInputStream which extends CipherOutputStream & CipherInputStream respectively.
    • MainEx class contain two important method run() and getSysinfo() as shown below.
    •  Malware steal credential from list of software mentioned in the run() method
      this.add(new IExplorer());
      this.add(new UCBrowser());
      this.add(new Composer());
      this.add(new Credman());
      this.add(new Outlook());
      this.add(new Pidgin());
      this.add(new PostgreSQL());
      this.add(new Squirrel());
      this.add(new Tortoise());
    • getSysinfo() collect osName, osVersion, osArch, javaHome, userName, userHome, availableProcessor, freeMemory, totalMemory, localIpAddress & globalIpAddress in JSON format which is encrypted and sent to CC with other info.
IPAddress class
    • IPAddress class is one of the class present in package j.t.e.core.utils which get the IP address of the infected system and sent it to CC with other system info. It uses http://bot.whatismyipaddress.com for collecting the public IP of infected system.


When it will fail?

Unpacking using Java agent will be unable to dump all the classes at runtime due to following conditions:

  • When malware is unable to interact with CC then it will not able to exhibit it complete behaviour.
  • Malware is using some anti analysis technique e.g checking for vmware etc.
  • Malware is unable to run due to some supporting files, command line etc.


Unpacking using Java agent is quiet simple and can speed up your analysis, you can use the dumper.jar uploaded in Github [3]. This method can be used in any Java based malware. We have also gone through some of the dumped Pyrogenic/Qealler source code to understand the stealer functionality. In the last part 0x3 we find similarity between Qealler/Pyrogenic variants based on static code analysis.

Hope you enjoyed this post, please  me on Twitter to get the latest update about my malware analysis & DFIR journey. Happy reversing 🙂

Targeted Application list

This is the list of application collected from the dumped unpacked classes:

  1. ChromiumBased Browser
    • 7Star
    • amigo
    • brave
    • centbrowser
    • chedot
    • chrome canary
    • chromium
    • coccoc
    • comodo dragon
    • elements browser
    • epic privacy browser
    • google chrome
    • kometa
    • opera
    • orbitum
    • sputnik
    • torch
    • uran
    • vivaldi
    • yandexBrowser
  2. MozillaBased Browser
    • firefox
    • blackHawk
    • cyberfox
    • comodo IceDragon
    • k-Meleon
    • icecat
  3. IExplorer
  4. UCBrowser
  5. Composer
  6. Windows Credential
  7. Outlook
  8. Pidgin
  9. PostgreSQL
  10. Squirrel
  11. Tortoise


  1. Java Agents Tutorial
  2. Reversing an obfuscated java malware by Extreme Coders
  3. GitHub repo

Related Posts

2 Comments. Leave new

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.