VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Infecting PE files with Java Bytecode

Valhalla #4
August 2013

[Back to index] [Comments]

About Sojourner

This is my first Java Bytecode virus. It is a direct action file infector of PE32 exe files in the current directory. The virus inserts a loader code and the Sojourner virus class at the end of the last section. It is the world's first Java Bytecode virus to infect PE32 exe files.

What is it?

Java Bytecode is the instruction set from the Java Virtual Machine. We all know that Java is primary language to compile its source code to Java Bytecode. But there are other languages that also produce Java Bytecode (for example, Scala, Clojure, Groovy) and use the Java Virtual Machine.

The binary file produced that contains the code that is run by the virtual machine is the Class file. Recently I learned how can you use the virtual machine from native programs (in Java they call "native" those files that belong to a operating system). Since there is no Java virus to infect PE32 executable files, I thought to make a low-level one. ;)

How can we do that

Firstly, we need to have a loader code that can run our class file in the infected file. Java introduced the Java Native Interface in the 90s. It allows native programs to execute Java classes. We have to create an instance of the Java Virtual Machine using JNI_CreateJavaVM(). If successful, it returns an interface from which we can load our class.

We use DefineClass() method to load our class from memory, so we don't need to drop any file. Then we use GetMethodID() to get the ID of the method we want to call.

My class uses just one method "S". The class does not contains any other method (that is, no main(), no constructors such as init()). But before we can call our method we must initialize the class object. Since we have no constructor we can use AllocObject() that does not call the constructor method, then we can proceed to call using CallVoidMethod().

However, there is an advantage to have a constructor. Typically, you will see the use of NewObject() instead of AllocObject(), this is because the former does calls a constructor method (typically init()) that they must first get using Get****MethodID(). What we will do is to call our method instead using NewObject() as if it was the constructor.

The code I wrote for this can be used for different projects, but requires the Java Virtual Machine DLL to be in the same directory. There is one way to locate it using the registry but I did not include such functionality in this code.

Now that we know what the loader must do in an infected files, we need to work in the payload.

Java Bytecode

I wrote the code in Java Bytecode instead of Java programming language. For that I used Jasmin. With Jasmin we can code Java Bytecode at a source level and also decide some details of the class file. I didn't optimize the code too much, but instead decided to make very specific optimizations.

Instead of using methods I used subroutines that are rare and might confuse some decompilers. For example:

aload_3 iload_2 ;IMAGE_NT_HEADERS i2l invokevirtual java/io/ jsr file_read4 sipush 0x4550 ;IMAGE_NT_SIGNATURE if_icmpne close_fileobj

Some subroutines return the value via stack, this is to optimize and add further confusion since it's not explicitly pushed (or loaded). In order to save a couple of bytes (instead of saving a value in a temporary register) I used a branch directly to what would be the "catch" code:

jsr file_read2 dup ;one to store, one to compare sipush 0xe0 if_icmpne catch_begin iload_2 ;IMAGE_NT_HEADERS.FileHeader.NumberOfSections - 1 * sizeof IMAGE_SECTION_HEADER iadd ;IMAGE_NT_HEADERS.FileHeader.SizeOfOptionalHeader + (IMAGE_NT_HEADERS.FileHeader.NumberOfSections - 1) * sizeof IMAGE_SECTION_HEADER bipush 0x20 ;IMAGE_NT_HEADERS.OptionalHeader + sizeof IMAGE_SECTION_HEADER.Name iadd istore_2 catch_begin: pop close_fileobj: aload_3 invokevirtual java/io/RandomAccessFile.close()V

It might be possible to create a further confusion using jsr and ret instruction in subroutine, to create a fake "finally" block of code, since compilers implemented those instruction for that purpose in JSE6.

There are many more possibilities and approachs to the simple techniques I used in the code (maybe instead of reading the target file sequentially, it could be read entirely to a single buffer which could be an array).


It is funny that for quite some time Java viruses have been forgotten (but now instead you can see malware using Java code for nefarious purposes), in 1998 the virus writer Landing Camel, began his/her "Strange Brew" [1] research that became the world's fist Java viruses to infect class files. Recently, the virus writer R3s1stanc3 showed us a new technique to infect JAR (Java ARchive) files [2]. The virus was also written in Java.

An attractive possibility is to create polymorphic viruses. There are tools to obfuscate class files, but they do just that. They can still be detected without forcing the anti-virus to dynamically analyse the code.

R3sistanc3's work uses the JavaCompiler class that can be used to compile Java source code. Sufficiently good engine should be capable of generate source code that when compiled would use most of the instruction set. But to use the full potential, you must go low-level, and probably anti-viruses don't even support these techniques yet.

Our work should be enough to understand and attack the basics. Now we can only expect more complex Java viruses over time. :) But we need to explore further.

27 August 2013
  1. Strange Brew by Landing Camel
  2. Infecting JAR-Files using the JavaCompiler Class by R3s1stanc3
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! aka