The former post ended with the unusual CVE 2017-11882 exploitation shellcode running an executable.
That executable is used solely to run advanced staged payloads later on, as it drops jdcmaxm.cs and jdcmaxm.cmdline (random names) files in the temp directory and uses “csc.exe” to compile the C# file with cmdline parameter (see figure 1)
Once “csc.exe” finishes, the program executes the newly compiled exe.
The executable is .NET based, which made it possible to decompile. Judging by the level of ‘carefulness’, obfuscation and infection chain, it’s safe to say that the assemblies linked to that attack were made by people who knew what they were doing.
In my opinion, the attackers made the unusual choice of working with C# to create the malware due to several reasons; It’s easier to dynamically load assemblies while working in memory, it’s faster to code that way and it’s pretty safe to say that it’s highly unlikely for a windows computer not to have .NET installed.
Note: along some of the code samples in this document you will find comments. All of those comments were added by me to clarify things related to the code.
Decompiling the program has certainly made it easier to reverse. While looking at that executable, we see a relatively straight forward main as shown in Figure 2
The executable contains a lot of code, most of it is unused. The main function loads a BMP resource, decrypts it into an array of bytes, loads it as an assembly and invokes it in a new thread.
We were able to extract the invoked assembly and look into it as well.
A quick glance at the assembly reveals interesting techniques. No strings were present in the code. All of the strings that the assembly needs existed as base64 encoded strings that it read from a resource whenever needed. Each call had an index that marked the beginning of the base64 string in the resource stream. See an example for that in Figure 3.
I was able to extract the strings from the resource and noticed that the obfuscation was made using a tool called ‘Dot wall’.
The attackers did their best to write the code as complex as possible. Most of the code is made with While(True) loops with an integer used as some sort of instruction pointer that navigates through the code with ‘Switch – case’ statements, “go to” and labels.
After a lot of deceiving code, irritating loops and decryption strings, we finally get to an interesting point; A base64 string inside the resource that holds the string, returns a name of another resource in the assembly.
That resource is loaded into a stream and contains an encrypted assembly (Figure 4).
Then the encrypted assembly is sent to the decryption function shown in Figure 5.
“num” is initialized with 2. That makes the function start with retrieving the decryption key. Using that key the function decrypts every byte of the assembly using XOR with the next byte in the key (cyclic to length of 16). When ‘index’ equals the length of the assembly, num is set to 0, the code jumps to label_6 that returns the decrypted assembly.
The loaded assembly contains exported types. After loading the assembly into the current assembly, the line shown in Figure 6 returns an exported type from the recently loaded assembly.
Once case6 is finished, num is 0 and the instruction pointer is at case4.
Figure 7 shows the code executed next.
“num2” is our instruction pointer for this loop. Starting from case 4, instance is created using reflection out of the type loaded from the assembly and the string containing the path of “vbc.exe” which is a legitimate .NET executable is created.
After making sure the executable exists, the program goes to ‘case 0’, invokes a method in the exported type, the counter for ‘invoked types’ is increased and in the next step ‘break’ will exit the loop.
So far, the current assembly has done what it was supposed to do, invoking the exported type, sending vbc’s path as parameters.
That type is part of an assembly that has two interesting components I’d like to focus on;
The first one is what seems to be the persistency method which is made through scheduled tasks.
I took some time to beautify some of the code, so the variable names and strings you’re about to see are there to make the code a bit more clear.
The attackers used the same obfuscation method we seen before; all of the strings were encapsulated as base64 and hidden in a resource.
Figure 8 show that the malware queries the currently existing scheduled tasks.
Once that finished, it reads the standard output, searching for the executable’s name. If it does not exist, creates a task for it as shown in Figure 9.
In addition to that, the attackers created some obfuscated delegates. After beautifying the code it looks as shown in Figure 10.
If the first thing that pops to your mind when seeing those functions is injection, you are absolutely right.
Remember vbc.exe that was sent when invoking the type? That very same executable path is being launched.
After that, the attackers are checking if the system is 32 or 64 bit in order to know if GetThreadContext or Wow64GetThreadContext should be used (see Figure 11)
After that, the malware does some calculations, setting thread context and writing some reserved code in specific offsets from the very same DLL sent to the type upon invoke to the new process.
After the injection, I noticed that vbc.exe reaches the internet. I sniffed the traffic to see the request shown in Figure 12.
Vbc.exe sends a post request to what seems to be the CNC server for this malware which is the same server from which we initially fetched po.doc.
In the request’s content, vbc.exe sent some information about the machine. Although the server is up, it returned ERROR 404 (file not found). It seems as if the server didn’t find the information sent to it interesting enough.
Our personal view regarding this attack is that someone worked hard to protect the well-designed payload. This threat should be taken seriously and we advise to take necessary actions if the mail was viewed by an end user.
Roy Rashti and Leon Berlin,