Code Injection

Table of Contents

1. Code Injection

Code Injection is an evasion technique used to hide code from dynamic analysis, it works be relaying on a victim process to execute the payload, hiding the flow of the malware; the attacker wants to hide the behavior of the malware from the analyst and from other softwares. From an analyst perspective we want to identify the victim process and then grab the payload when it’s deployed. The most succesfull way to do covert launching is to write instruciton in the memory of another process, it can be done in different ways:

  • process hollowing
  • DLL injeciton
  • PE Injeciton
  • Thread execution hijacking
  • Reflective DLL injection
  • Hook Injection

2. Process Hollowing

It is still a very popular methodology. It consists in launching a legal software in a suspended state, then replace all it’s code with the payload. This technique is pretty consistent because the launcher has complete control over the process: if the code hasn’t started yet the code to replace is not a lot.

The launcher will:

  • deallocate currently mapped sections of the process
  • allocate memory to accomodate for the malicious payload
  • write the payload contents to the address space of the victim
  • update the context of the suspended main thread, and finally
  • resume the supended main thread

There are primitives in Windows that allow in which memory location to write, from the analyst perspective there are tools capable of identifying processes in a suspended state. Of course the malware has to have read and write permissions to modify the memory suspended software.

There is some code in which the malware creates a process in suspended state.

code-injection-1.png

Then we have to unmap view of the section, then VirtualAllocEx is used to allocate a section and then the payload is written via WriteProcessMemory, and finally resume the thread.

code-injection-2.png

Process hollowing works best with position-independent code.

3. DLL Injection

Instead of writing in the memory of the process, with this technique it’s possible to inject a DLL into a running process, Windows will do the dirty work. It is possible to leverage the permissions granted to the victim process, but this method is cospicous and it can be easily spotted. The general idea is that the attacker writes a DLL, put it on the victim machine, then dire up a remote thread that invokes LoadLibrary to obtain a handle to suitable victim process, allocate memory for the string containing the DLL path and write to it. That’s possible thanks to the fact that windows allows to create a remote thread in another process.

code-injection-3.png

DLL injection may be detected easily when debugging thanks to the fact that the address of LoadLibrary can be looked up at any time, memory allocation, write operation and thread creation must go in this exact same order, and also the DLL must be deployed on disk.

4. PE Injection

It is similar to DLL injection trying to mimic the loader of windows without the need of deploying a DLL on disk. It requires careful code crafting to avoid crashing the victim, this method is good to inject shell code, otherwise special care is required. It works by performing multiple write operation, relocation operations and a creation of a remote thread, and before the thread starts it’s possible to dump the contents of write operations to analyze them separately.

When inspecting code that performs PE Injection commonly it is composed by two nested loops, and an and 0x0FFF is used to take 12 bits representing the offset of relocation. If it is shellcode this code is not necessarly.

code-injection-4.png

5. Thread Execution Hijacking

This technique works by Hijacking the thread of another process. Instead of starting a remote thread, it hijack an existing thread, looking for one with CreateToolHelp32Snapshot, Thread32First, Thread32Next and OpenThread. The victim thread will be suspended, and then it’s memory is overwritten, the EIP is modified and at last the thread is resumed. When a thread is suspended the victim program can crash, it can happen if the suspended thread called a system call breaking the system. To solve this problem the attacker may check if the EIP is within the range of ntdll.dll.

code-injection-5.png

6. Reflective DLL Injection

A weakness of DLL injection is the DLL presence on disk. The attacker may try to load a DLL from memory and not from disk, the problem is that no LoadLibrary from memory exists. The idea is to replicate what the windows loader does, so the attacker will compile the payload as a DLL that contains a function that acts as ReflectiveLoader. So from the launcher process we have to allocate a huge buffer, copy the DLL into the buffer, get the relative virtual address of ReflectiveLoader and create a remote thread into the victim to run reflective loader. The reflective Loader works by locating the PEB (process entry block), parse it to locate kernel32.dll to loacate LoadLibrary and GetProcAddress to fill the IAT and apply relocaiton. After this process the DLLMain function will be executes as entry point.

7. Hook Injection

Windows allow processes to register thooks to intercept messages destined for the current ptocess or for a remote one. Remote hooks can be used for keylogging, but also to load a DLL. A remote hook can be of two types:

  1. High-level. It uses a DLL export as hook procedure. In a simple terms it is like: to handle this message you need a function that is in this evil DLL 👿.
  2. Low-level. It uses a function that runs in the process that installed the hook.

SetWindowsHookEx is the key API used to implement this approach. It takes 4 arguments, the id of the hook, the address of the hooking function, the handle of the DLL and the thread ID to associate to the hook.

code-injection-6.png

code-injection-7.png

8. APC Injection

In Windows it is possible to ask a process to make something when it is waiting for something. An APC can replace thread creation hijacking for injection. Each thread has an APC queue that the system polls periodically. For example it can be used for a LoadLibrary operation, or to start a shell code. The system call QueueUserAPC takes three arguments:

  1. The user supplied function to be called by the thread
  2. the handle to the thread
  3. and a pointer value that is passed to the function

code-injection-8.png

This scheme has been abused a lot, so now there are policies in the OS that puts some security measures in place. For this reason the AtomBombing attacks are used, they exploit a feature of windows that enables processes to shares strings via atom tables. The attack consist in placing something in to the atom tables, to trigger an APC code to starts from there. GlobalGetAtomName is the function to call, the problem is that this function takes three arguments but QueueUserApc takes only one pointer value, so a ROP chain is needed to get around DEP.

AtomBombing is an elegant injection vector as it exploits design vulnerabilities to look legitimate.

9. Phantom DLL Hollowing

It abuses the transactional NTFS, a DLL file can be treated as a DB transaction, so the modifications on the file will be seen only by the process that edits that file. This technique allows to hollow a DLL without altering memory permission while other processes on the system will view the original DLL. Then the victim process will forced to see the modified contents via a copy of the handle of the transactional DLL. Now this technique no longer works thanks to Code Integrity Guard. But it is possible to beat it via a ROP chain. The edited DLL will not be commited.

10. Other ways

Another way to inject component is to abuse the TLS callbacks to inject a DLL into child processes before they start.

Author: Andrea Ercolino

Created: 2022-12-12 lun 12:10