Gimme Shellter

binary code under a magnifying glass with the word polymorphic code

Red team penetration testers very often add tools to their arsenal that borrow techniques originating in malicious software. Shellter is such a tool. It was inspired by the EPO and polymorphic file-infector viruses, became established as a tool for pen testers and then crossed back to being leveraged by cybercriminals. If you are not familiar with these concepts, here are the definitions:

  • EPO stands for “entry point obscuring.” The most common types of file infections occur at the entry point, making the infected code easily detectable, so in order to circumvent that, the EPO infection takes place in an arbitrary location in the execution flow of the host application.
  • Polymorphic code is code that changes its appearance and instructions from one infection to another but maintains the same functionality.
  • File infectors add malicious code to originally benign executables.

Shellter acts like a file infector on demand, producing a functioning Windows executable file that contains hostile code executing along with the original code, using a benign application as input. The result is a harmless-looking application acting as a decoy for a malicious payload (usually a reverse shell to allow access to a victim’s machine) that tricks the unsuspecting user into executing the infected executable via social engineering. This is not the only feature that makes Shellter a very dangerous tool in the hands of an attacker. Combining EPO with polymorphic code allows the infected executable to bypass many security products, increasing the chances of compromising the targeted systems.

We have stopped a number of attacks in which Shellter-infected executables were utilized, so we decided to look more deeply into the mechanisms that Shellter leverages to evade antivirus products.

Investigation

For the initial investigation, we chose a Shellter-infected version of DebugView. DebugView is a legitimate application made by Microsoft that lets its users monitor system debug output.

During the dynamic analysis of the infected version of this application, the executable behaves as expected and functions normally like the original Microsoft version, but it also starts listening for incoming network connections on a non-standard port. Since this behavior does not match any of DebugView’s features, it is a clear indication that we are dealing with a modified version.

To see what happens behind the curtain, we fired up a debugger and started to delve into the live code. Examining the entry point revealed that it is a standard one for an application written in the Microsoft Visual C programming language, and therefore the altered part must be hidden somewhere else. After setting a few breakpoints, we were able to pinpoint the infection code.

Picture with different colored code

Figure 1. EPO infection code in a Shellter-infected version of DebugView

As can be seen, there are a lot of instructions without any real purpose. These are used to obfuscate the code and complicate the analysis. This is an example of the aforementioned EPO technique, which hides its entry point in randomly selected host code paths, as opposed to overwriting the host’s entry point.

Soon after in the control flow, a new memory zone is allocated. The malicious code copies its next stage there. Then, it jumps to this zone to execute.

Picture with different colored code

Figure 2. Malicious code copying its next stage in a newly allocated memory zone

The second-stage code uses the same obfuscation technique to complicate the analysis. The sole purpose of this stage is to decrypt the payload and transfer the execution to it.

This is what the beginning of the payload looks like:

picture with different colored code

Figure 3. Beginning of the payload in a Shellter-infected version of DebugView

You might already recognize the Meterpreter code. This stage will be almost the same for each infected executable — the only part that can change is the type of the payload. The most popular by far is the reverse shell.

By now, we’ve confirmed that the executable is infected by an EPO tool and that it executes a Meterpreter payload.

In order to demonstrate the polymorphic abilities, we analyzed another infected file. This one exhibited the same behavior and has the same structure (two stages and payload), but the code differs while maintaining the same functionality.

picture of code using different colors and highlights

Figure 4. A different file with the same Shellter infection, showing the code’s polymorphic ability

Hunting

Once we knew how Shellter looks and works, we wanted to test our findings by hunting for infected files in the wild. To do so, we developed a YARA rule based on our observations, and we used it with our MalQuery product, which allows complex searches over a vast body of malware samples.

Detection of polymorphic code with signature-based scanners is usually difficult, but the flexibility of YARA syntax gave us the possibility to create rules, which yielded a satisfactory grade of accuracy.

During our analysis, we found some weaknesses in the polymorphic generation routine that helped the creation of the rule. For example, for each xor [32bit_reg], big_constant instruction, there is a corresponding add [32bit_reg], big_constant instruction.

Another sequence of code remains almost the same:

sub     32bit_reg, 4
jnz     address

We also observed that each sample contains a Call $+5 instruction, which actually means “call the next instruction” — it is commonly used along with a POP instruction in order to get the current address of code execution.

The analysis of the infected files’ PE header and structure revealed some new characteristics: The digital signatures of the original samples are always removed, DLL Characteristics and Security Directory are always 0, and only 32-bit applications can be infected.

After putting together all of this information, we came up with the following YARA rule:

import "pe"
rule CrowdStrike_Shellter
{
 strings:
// call $+5
   $call_EIP = {E800000000}
// not     dword ptr [eax|ecx|edx|ebx|esi|edi]
   $not = {F7 (10|11|12|13|16|17)}
// xor     dword ptr [eax|ecx|edx|ebx|esi|edi], big_constant
   $xor = {81 (30|31|32|33|36|37)}
// add     dword ptr [eax|ecx|edx|ebx|esi|edi], big_constant
   $add = {81 (00|01|02|03|06|07)}
// sub     eax|ecx|edx|ebx|esi|edi|esp|ebp, 4
// jnz     decyption_loop
   $sub_jnz1 = {83 E8 04 0F 85 ?? F? FF FF}
   $sub_jnz2 = {83 E9 04 0F 85 ?? F? FF FF}
   $sub_jnz3 = {83 EA 04 0F 85 ?? F? FF FF}
   $sub_jnz4 = {83 EB 04 0F 85 ?? F? FF FF}
   $sub_jnz5 = {83 EC 04 0F 85 ?? F? FF FF}
   $sub_jnz6 = {83 ED 04 0F 85 ?? F? FF FF}
   $sub_jnz7 = {83 EE 04 0F 85 ?? F? FF FF}
   $sub_jnz8 = {83 EF 04 0F 85 ?? F? FF FF}
 condition:
   $call_EIP
   and $not and $xor and $add
// the not, xor and add instructions to detect should occur at least two times each
   and #not >= 2 and #xor >= 2 and #add >= 2
// check that the xor and the add have the same second operand
   and (uint32(@xor[1] + 2) == uint32(@add[1] + 2)
       or uint32(@xor[1] + 2) == uint32(@add[2] + 2)
       or uint32(@xor[2] + 2) == uint32(@add[1] + 2)
       or uint32(@xor[2] + 2) == uint32(@add[2] + 2))
// check if any $sub_jnz matches
   and any of ($sub_jnz*)
   and filesize < 1000KB
// we observed that any byte at offset $sub_jnz + 25 is equal to any byte at the offset $sub_jnz + 53
   and for any of ($sub_jnz*)  : (uint8(@ + 25) == uint8(@ + 53))
   and pe.number_of_signatures == 0
   and pe.dll_characteristics == 0
   and pe.machine == pe.MACHINE_I386
   and pe.characteristics & pe.EXECUTABLE_IMAGE
}

Here is a screenshot of the YARA rule being used in CrowdStrike Falcon® MalQuery:

Screenshot of CrowdStrike MalQuery interface

Figure 5. Our YARA rule in action

Outcome

Part of our motivation was to stop Shellter-based threats not only by using various indicators of attacks (IOAs) but also statically, just by analyzing files on disk. To accomplish these goals, we used the outcome of our research to hunt for Shellter files and added them to our machine learning (ML) training corpus. As a first step, this ensures that ML can learn from these malicious specimens. 

The next step, after building a collection of infected samples, was to extend our ML feature space by extracting specific Shellter features. 

With the new features, our model is able to dramatically increase the coverage of Shellter samples currently in our collection. This ability gives us an additional means of spotting this highly obfuscated attack vector to fortify our defense-in-depth approach.

Conclusion

Even though it was not created for malicious deeds, Shellter is a dangerous tool in the hands of attackers because of its effectiveness in bypassing the detection of antivirus programs. However, due to continuous research work like this combined with a powerful next-generation antivirus, CrowdStrike®solutions are able to detect and prevent such threats.

Are you an expert in designing large-scale distributed systems? The CrowdStrike Engineering team wants to hear from you! Check out the openings on our career page.

Additional Resources

Related Content