Remote Process Shellcode Injection - T1055
Shellcode Injection Inside A Remote Process
In this blog, we will take a look at how malwares utilizes a very well known technique called Process Injection - Shellcode Injection into a remote normal process inside a Windows Environment.
Source Code Repository
https://github.com/Faran-17/RemoteProcessInjector
Summary
Process Injection MITRE ID - T1055, is a technique in which and malicious shellcode is injected into the memory space of a remote process running on a target computer. This injection technique enables an attacker to assume control of the remote process's execution, potentially leading to unauthorized access, data exfiltration, or malicious activities.
This has been a popular technique that has been abused by malwares and ransomwares for a over a decade. Even though it's old and can now be easily be detected by AVs and EDRs still it is very crucial to learn in order to understand some advance evasion techniques.
In this blog, I will demonstrate how to perform a simple remote process injection via C++ and Win APIs.
Note - Keep in mind that evasion is not kept in mind while demonstrating this attack, so this exe is highly likely be caught by defender.
All the credits to @NULL, @Mr.Dox and @MaldevAcademy for the teaching me this concept in a simplistic way.
Here is the whole attack methodology -
A dropper file that has a embedded shellcode.
The shellcode is UUID obfuscated.
The shellcode is de-obfuscated and then injected into a remote process.
Win APIs are used to allocate a memory for the shellcode.
A new thread is created to began the execution of the shellcode.
The shellcode is executed and an connection is established to the attacker machine.
Here the whole attack scenario can be visualized in a diagram.
Code Walkthrough
In this section, we will walkthrough and understand the code logic of the process injector which is implemented in C++.
Note - I would love to explain each and every lines in the code but this will increase the length and complexity of the blog, will only be explaining the essentials parts of the code. I can do this in some future blogs.
Firstly, generating a bin file using msfvenom.
Now, I will be utilizing a in-build tool from Maldev Academy known as HellShell that will generated a UUID obfuscated shellcode of the bin file. UUID i.e Universally Unique IDentifier (UUID) is a bit complex and beyond the scope of this blog, so we'll skip it's explanation. You can use any obfuscation or encryption method of your choice.
Now all we have to do is copy and paste the payload inside the code.
On line 23, the NumberOfElements is 29 which is the character count of the shellcode variable uuid_payload[]
.
In the main() section of the code,
Parameters are initialized.
In line 211, a custom function
GetRemoteProcessHandle
is called which takes process id and pointer to the handle process.
Checking the GetRemoteProcessHandle
function.
On line 91, CreateToolhelp32Snapshot
is called to takes the snapshot of the processes running inside the environement. Here is structure of the API
In line 91, the dwFlags is set to TH32CS_SNAPPROCESS
which takes snapshot of all the processes.
Once the snapshot is taken, Process32First
API is used to get the information for the first process in the snapshot.
The Process32Next
is the name suggest, retrieves the information for the next process in the snapshot.
Both the APIs requires PROCESSENTRY32
structure to be passed in for their second parameter. After the struct is passed in, the functions will populate the struct with information about the process. Here is the structure,
After Process32First
or Process32Next
populate the struct, the data can be extracted from the struct by using the dot operator. For example, to extract the PID use PROCESSENTRY32.th32ProcessID
.
Moving on,
The UuidDeobfuscation
function on line 209 is where the shellcode is de-obfuscated, this is beyond the scope as of now so let's move on to the injection part.
Shellcode Injection.
Now, this is the main part of the attack where the shellcode is injected into the target's process and a new thread is created to began it's execution.
The InjectShellcodeToRemoteProcess
takes three parameters - the handle to the process, shellcode and the size of the shellcode.
The process injection techniques utilizes these infamous Win APIs
VirtualAllocEx
WriteProcessMemory
VirtualProtectEx
CreateRemoteThread
The VirtualAllocEx API is used to allocate the memory in the remote process, here is the structure of the API.
Understanding it's parameters,
hProcess parameter is handle to a process.
lpAdress is a pointer that specifies a desired starting address for the region of pages that you want to allocate. This is set to NULL so that the function determines where to allocate in the memory.
dwSize is the size of the memory region where the shellcode will be allocates. This is set to the
sSizeOfShellcode
parameterflAllocationType is a type of memory allocation. We can set more than one allocation type as well. Here is the full list. The parameter here is set to
MEM_COMMIT - Allocates a memory.
MEM_RESERVE - Reserves a range of the process's virtual address space without allocating any actual physical storage in memory or in the paging file on disk.
flProtect is used to set the memory protection of the regions of the pages to be allocated. Here is the full list of the memory protections. This parameter is set to PAGE_READWRITE(0x04) which enables read and write permissions to the commited memory region.
After the memory is successfully allocated in the remote process, the WriteProcessMemory is used to write to the allocated buffer. Here is the structure.
Understanding it's parameters,
hProcess parameter is handle to a process.
lpBaseAddress is the pointer to the base address inside the target's process which is
pShellcodeAddress
in this case.lpbuffer is a pointer to the buffer that contains data to be written in the address space of the specified process, in this case
pShellcode
.nSize is number of bytes to be written to the specified process, in this case
sSizeOfShellcode
.lpNumberOfBytesWritten is a pointer to a variable that receives the number of bytes transferred into the specified process.
After the shellcode is written, cleaning the shellcode via memset function.
Before the payload is executed the memory protection should be changed. VirtualProtect is used to modify the memory protections. Here is the structure,
All the parameters are similar from before. The flNewProtect is the parameter where the perismissions is set. Here is the full list of the permssion, in this case it is set to PAGE_EXECUTE_READWRITE(0x40).
After allocating the shellcode inside the target's process memory, creating a new remote thread via the API CreateRemoteThread to avoid crashing of the target process to crash after we close the connection and also maintain each thread's intergrity. Here is the structure of the API.
After this, build the code in "Release" mode.
Reverse Shell
Now to get a reverse shell, first start a notepad.exe process and give the argument of the process name while running the generated executable.
Checking back the listener.
Here is the video representation of the attack.
More clean quality below.
Detection
Writing a simple YARA rule to detect this attack.
In the above rule, I've flagged the three malicious APIs as ascii strings.
And here is the detection.
Thank You For Reading ☺️
Last updated