Table of Contents
- In the previous article we explored how we can write a simple stageless C++ dropper. In this article we build upon the capabilities of the dropper by implementing process injection.
- Process injection is a well-known defense evasion technique that is used to hide code within the address space of another process. This allows an attacker to mask malicious code as a legitimate process in the system. It can also be used as a persistence technique by migrating to stable processes during post-exploitation.
High-Level Overview #
- We begin by selecting a target process i.e notepad.exe. We can select any standard process in the system provided we have the necessary permissions
- Open the process found and obtain a handle to it
- Allocate memory within that process through the handle we have
- Write our shellcode into the memory
- Execute the injected code.
- We can summarize the above into 2 main parts:
- Find a target process
- Injecting into the target process
- The final project file can be located here for quick reference: https://github.com/trevorsaudi/Process-Injection-cpp
1. Finding a Target Process #
- We use this function to create a snapshot of the specified processes in the system. This includes components and activities of the processes.
- Since we will be enumerating the processes in the system to find our target, we will utilize the
TH32CS_SNAPPROCESSparameter that allows us to grab all processes in the system. The second parameter is ignored when we use
TH32CS_SNAPPROCESSso we place a
- It returns a handle to the snapshot that’s why we define a
HANDLEvariable for it
- This pre-defined windows data structure holds information about a single process when the snapshot was taken.
pe32is an instance of
pe32.dwSizeis a member of the PROCESSENTRY32 data structure. It represents the size of the structure in bytes. We grab the size of the structure using
- We will use these 2 APIs to enumerate through the running processes looking for a process with a specific name
- They both require the size of the structure to determine how much info to retrieve.
In line with the code block above, we get the first process from the snapshot we took, where,
hProcSnapis a handle to the snapshot of processes and
PROCESSENTRY32structure which will get filled with information about a process.
If the block of code fails to get a process for some reason, we close the handle.
We now proceed to find the target process below
- We use
Process32Next, to get the information about the next process. This allows us to cycle through the snapshot. We then compare the name of the current process which is stored in
pe32.szExeFilewith what we are looking for
2. Injecting into the target process #
- This process involves us allocating memory to our target process, writing to it, and executing the shellcode from the process calling it.
- We use this to allocate memory in the
- The difference between the VirtualAllocEx and VirtualAlloc is that VirtualAlloc allocates memory within the address space of the
calling process, while VirtualAllocEx lets you
specify a target processto allocate memory.
- We use this API to write into the memory in a specified address. We will utilize this to write our shellcode into the memory region we reserved in the target process.
- This API is used to create a thread that runs in the address space of a target process. Our target is notepad.exe, this API will help us run our shellcode in that context
- We specify
hProc, a handle to the process that we are injecting to.
- We then use
WaitForSingleObjectto specify a timeout for the process.
3. Final Implant #
- The final process injection implementation:
- You can compile with cl.exe using the following flags
cl.exe /Ox /MT /W0 /GS- /DNDEBUG /Tcprocessinjection.cpp /link /OUT:processinjection.exe /SUBSYSTEM:CONSOLE /MACHINE:x64
- We can verify the messagebox was spawned in the context of Notepad using Process Hacker.
- Process Hacker is a tool that can help you monitor resources, debug software and detect malware.
- It has a functionality called “Find Window and Threads”, demonstrated below, which you can click then drag to a window to show the kind of resources (processes, threads, handles, etc) it is associated with.
- We can also see the memory region we had allocated for our target process, marked as RX (Read Executable) as shown below.
- This brings us to the end of our blog, hope you learned a ton!