Files
archived-Reclass/plugins/RemoteProcessMemory/rcx_rpc_protocol.h
IChooseYou 5e11ff5496 feat: Remote Process Memory plugin, source menu icons, base address fix
- Remote Process Memory plugin: shared-memory IPC payload injected into
  target process (CreateRemoteThread on Win, ptrace+dlopen on Linux),
  VirtualQuery-based memory safety, PEB-based image base, batch reads
- Source dropdown: SVG icons per provider type, DLL filename shown
- Fix base address not updating when switching to a new source provider
- ProviderRegistry carries DLL filename from PluginManager

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 07:29:56 -07:00

130 lines
4.3 KiB
C

/*
* RCX RPC Protocol -- shared between plugin DLL and payload DLL/SO.
* No dependencies beyond standard C headers.
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/* ── constants ─────────────────────────────────────────────────────── */
#define RCX_RPC_VERSION 1
#define RCX_RPC_MAX_BATCH 256
#define RCX_RPC_SHM_SIZE (1024 * 1024) /* 1 MB */
#define RCX_RPC_HEADER_SIZE 4096
#define RCX_RPC_DATA_OFFSET RCX_RPC_HEADER_SIZE
#define RCX_RPC_DATA_SIZE (RCX_RPC_SHM_SIZE - RCX_RPC_DATA_OFFSET)
#define RCX_RPC_BOOT_SIZE 64
/* status codes */
#define RCX_RPC_STATUS_OK 0
#define RCX_RPC_STATUS_ERROR 1
#define RCX_RPC_STATUS_PARTIAL 2
/* ── commands ──────────────────────────────────────────────────────── */
#ifdef __cplusplus
enum RcxRpcCommand : uint32_t {
#else
typedef uint32_t RcxRpcCommand;
enum {
#endif
RPC_CMD_NONE = 0,
RPC_CMD_READ_BATCH = 1, /* batch read: N {address, length} pairs */
RPC_CMD_WRITE = 2, /* single write */
RPC_CMD_ENUM_MODULES = 3, /* enumerate loaded modules */
RPC_CMD_PING = 4, /* heartbeat */
RPC_CMD_SHUTDOWN = 5, /* graceful teardown */
};
/* ── wire structs (natural alignment, verified by static_assert) ─── */
struct RcxRpcReadEntry {
uint64_t address;
uint32_t length;
uint32_t dataOffset; /* offset into data region for response bytes */
};
struct RcxRpcModuleEntry {
uint64_t base;
uint64_t size;
uint32_t nameOffset; /* offset into data region, UTF-16 on Win, UTF-8 on Linux */
uint32_t nameLength; /* in bytes */
};
/*
* Header -- lives at shared-memory offset 0, padded to 4096 bytes.
*
* offset field
* ------ -----
* 0 version (4)
* 4 payloadReady (4)
* 8 command (4)
* 12 requestCount (4)
* 16 writeAddress (8)
* 24 writeLength (4)
* 28 status (4)
* 32 responseCount (4)
* 36 totalDataUsed (4)
* 40 imageBase (8) -- main module base from PEB / procfs
* 48 _pad[4048]
*/
struct RcxRpcHeader {
uint32_t version;
uint32_t payloadReady; /* payload sets to 1 after init */
uint32_t command; /* RcxRpcCommand */
uint32_t requestCount;
uint64_t writeAddress;
uint32_t writeLength;
uint32_t status; /* RCX_RPC_STATUS_* */
uint32_t responseCount;
uint32_t totalDataUsed;
uint64_t imageBase; /* main module base (PEB on Win, /proc on Linux) */
uint8_t _pad[RCX_RPC_HEADER_SIZE - 48];
};
/* Bootstrap shm -- 64 bytes, carries the nonce from plugin to payload */
struct RcxRpcBootHeader {
uint32_t nonceLength;
char nonce[60];
};
/* ── name formatting helpers ───────────────────────────────────────── */
static inline void rcx_rpc_boot_name(char* buf, int n, uint32_t pid) {
#ifdef _WIN32
snprintf(buf, n, "Local\\RCX_BOOT_%u", pid);
#else
snprintf(buf, n, "/rcx_boot_%u", pid);
#endif
}
static inline void rcx_rpc_shm_name(char* buf, int n, uint32_t pid, const char* nonce) {
#ifdef _WIN32
snprintf(buf, n, "Local\\RCX_SHM_%u_%s", pid, nonce);
#else
snprintf(buf, n, "/rcx_shm_%u_%s", pid, nonce);
#endif
}
static inline void rcx_rpc_req_name(char* buf, int n, uint32_t pid, const char* nonce) {
#ifdef _WIN32
snprintf(buf, n, "Local\\RCX_REQ_%u_%s", pid, nonce);
#else
snprintf(buf, n, "/rcx_req_%u_%s", pid, nonce);
#endif
}
static inline void rcx_rpc_rsp_name(char* buf, int n, uint32_t pid, const char* nonce) {
#ifdef _WIN32
snprintf(buf, n, "Local\\RCX_RSP_%u_%s", pid, nonce);
#else
snprintf(buf, n, "/rcx_rsp_%u_%s", pid, nonce);
#endif
}
#ifdef __cplusplus
static_assert(sizeof(RcxRpcHeader) == RCX_RPC_HEADER_SIZE, "Header must be 4096 bytes");
static_assert(sizeof(RcxRpcBootHeader) <= RCX_RPC_BOOT_SIZE, "Boot header must fit 64 bytes");
#endif