Created
February 13, 2024 15:12
-
-
Save skeeto/43601c336a0cfdb0f33586148ae99bde to your computer and use it in GitHub Desktop.
WriteProcessMemory demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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