Running Shellcode Through Windows Callbacks Using VBA Macro

87% of the ransomware found on the dark web has been delivered via malicious macros to infect targeted systems. Because of this reason, AV and Sandbox vendors try to extend their Macro detection capabilities. On the other hand, attackers have developed various methods to evade the AVs, EPPs, and Sandbox products.

The last strange method has been seen in the wild for a while. It is completely designed to bypass blacklisted functions controls such as shell, run, execute, etc. 

As seen below, only 8 out of 62 AVs can mark this sample as malicious.

Let’s deep dive into analyzing the sample. Firstly, I submitted the sample to DOCGuard. DOCGuard marked the sample as malicious because of obfuscation and blacklisted APIs observed.

If we jump into the IOCs tab, we can see that there are some suspicious functions (ZwAllocateVirtualMemory, MultiByteToWideChar, and document_open) called in one of the modules named “ThisDocument”. 

As far as we collected so far, there is no suspicious function that may be the indicator of process injection or an exploit. But, if an end user opens the document and executes the macro code, the activities and process tree look strange.

Firstly, a connection was initiated directly from “WORD.exe”  to “http[:]//worldoptions[.]buzz”  and a DLL file was downloaded. After that task scheduler runs one of the DLL’s functions (Rdwmnjioffws) using rundll32.exe. 

But, there is no function that can initiate the network connection.

So, let’s deep dive into the VBA Macro code.

Let’s resolve the function names to read the code.

Let’s read line by line.

  • if we take a closer look to ZwAllocateVirtualMemory from ntdll we have the following interface according to MSDN:
  • ZwAllocateVirtualMemory will allocate the 5000 bytes of memory from WORD.exe with Read, Write and Execute permissions.
  • MultiByteToWideChar maps a character string to a UTF-16 (wide character) string. 
  • MultiByteToWideChar converts the shellcode char string to Unicode and writes the converted output to the memory region which was allocated by ZwAllocateVirtualMemory.
  • Internal_EnumUILanguages is an undocumented API function imported from kernelbase.dll. This Internal functions can be potentially used as callbacks to run shellcodes, payload codes, etc. This can be abused to pass a shellcode instead of a function pointer. So, this function can be the reason of initial network connection originated from WORD.exe.


  • Now, let’s try to imagine what it could happen if we give a running Shellcode as a CallBack function.

In this case, the system will try to execute the Shellcode believing to run an implementation of UILANGUAGE_ENUMPROCW. Once the run has just happened (that is the system has run the injected Shellcode), the IP (Instruction Pointer) will get an out-of-bound value which will eventually result in an exception. But before the exception rise, the Shellcode has been executed. 

As summary, 

  1. the first step is to allocate the memory for the Shellcode using ZwAllocateVirtualMemory.
  2. The second step is to copy the shellcode to the prepared memory using MultiByteToWideChar.
  3. After that, it calls the Internal_EnumUILanguages, we give the pointer to the previously allocated memory: where it is supposed to be the UILANGUAGE_ENUMPROCW implementation function but it is the shellcode instead of the function pointer.
  4. Runs the shellcode.

Comments are closed.