Skip to content

Instantly share code, notes, and snippets.

@skeeto
Created February 13, 2024 15:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skeeto/43601c336a0cfdb0f33586148ae99bde to your computer and use it in GitHub Desktop.
Save skeeto/43601c336a0cfdb0f33586148ae99bde to your computer and use it in GitHub Desktop.
WriteProcessMemory demo
// WriteProcessMemory demo
// $ cc -nostartfiles -o demo.exe demo.c
// $ cl demo.c /link /subsystem:console kernel32.lib
// This is free and unencumbered software released into the public domain.
#include <stddef.h>
#define countof(a) (ptrdiff_t)(sizeof(a) / sizeof(*(a)))
typedef unsigned char u8;
typedef signed int b32;
typedef signed int i32;
typedef unsigned short char16_t;
typedef char16_t c16;
typedef ptrdiff_t size;
typedef ptrdiff_t iptr;
typedef size_t uptr;
typedef struct {
i32 cb;
uptr a, b, c;
i32 d, e, f, g, h, i, j, k, l;
uptr m, n, o, p;
} Si;
typedef struct {
iptr process;
iptr thread;
i32 pid;
i32 tid;
} Pi;
#define W32(r) __declspec(dllimport) r __stdcall
W32(iptr) CreateEventW(uptr, b32, b32, c16 *);
W32(b32) CreateProcessW(c16*,c16*,uptr,uptr,b32,i32,uptr,c16*,Si*,Pi*);
W32(void) ExitProcess(i32);
W32(c16 *) GetCommandLineW(void);
W32(i32) GetModuleFileNameW(iptr, c16 *, i32);
W32(iptr) GetStdHandle(i32);
W32(b32) SetEvent(iptr);
W32(void) Sleep(i32);
W32(u8 *) VirtualAlloc(uptr, size, i32, i32);
W32(i32) WaitForSingleObject(iptr, i32);
W32(iptr) WriteFile(iptr, u8 *, i32, i32 *, uptr);
W32(b32) WriteProcessMemory(iptr, uptr, u8 *, size, size *);
enum { BASEADDR = 1<<20 };
static i32 u8len(u8 *s, i32 max)
{
i32 len = 0;
for (; len<max && s[len]; len++) {}
return len;
}
static i32 child(iptr event)
{
i32 cap = 1<<12;
u8 *msg = VirtualAlloc(BASEADDR, cap, 0x3000, 4);
SetEvent(event); // tell parent that we're ready
if (!msg) return 1;
// Wait for parent to write a message
WaitForSingleObject(event, -1);
iptr stdout = GetStdHandle(-11);
i32 len = u8len(msg, cap);
b32 err = !WriteFile(stdout, msg, len, &len, 0);
return err;
}
static i32 parent(iptr event)
{
// Start the child process
c16 path[1<<15];
GetModuleFileNameW(0, path, countof(path));
Si si = {0};
si.cb = sizeof(si);
Pi pi;
b32 r = CreateProcessW(path, L"π", 0, 0, 0, 0, 0, 0, &si, &pi);
if (!r) {
return 1;
}
// Wait for child to map memory at a known address
WaitForSingleObject(event, -1);
// Write message into the child's memory
static u8 msg[] = "hello from parent\n";
size len = countof(msg) - 1;
r = WriteProcessMemory(pi.process, 1<<20, msg, len, &len);
SetEvent(event); // notify child that we're done
if (!r) return 1;
// Wait for child to exit
WaitForSingleObject(pi.process, -1);
return 0;
}
void mainCRTStartup(void)
{
b32 err = 0;
iptr event = CreateEventW(0, 0, 0, L"π");
if (*GetCommandLineW() == L'π') {
err = child(event);
} else {
err = parent(event);
}
ExitProcess(err);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment