Windows
A simple and safe-ish memory reading and writing utility made in pure c and a small portion of assembly for syscalls.
As said before the utility uses syscalls for:
Opening and Closing the handle
Reading and Writing memory
Allocating memory
Querying memory
Note: This does not mean it's "undetected" it still calls functions like CreateToolhelp32Snapshot
which can easily be detected
Getting started
This memory library revolves around one main struct called Process
. Now when creating a new process the process is manually allocated and returned as a pointer so you will also need to free it. The Process struct inherits the handle
, pid
, baseAddress
and baseSize
.
struct Process {
HANDLE handle;
DWORD pid;
uintptr_t baseAddress;
uintptr_t baseSize;
}
But with a specific macro you can as well choose if the functions that you are gonna use are inside the struct or just a global variable
#define FUNCS // remove if you don't want the functions in the Process struct
struct Process {
HANDLE handle;
DWORD pid;
uintptr_t baseAddress;
uintptr_t baseSize;
#ifdef FUNCS
bool (*ReadMemory)(Process* process, uintptr_t address, void* out_buffer, size_t size);
bool (*WriteMemory)(Process* process, uintptr_t address, void* data, size_t size);
uintptr_t (*Rebase)(Process* process, uintptr_t address);
uintptr_t (*PatternScan)(Process* proc, const char* pattern);
Module* (*Module)(Process* process, const char* name);
void* (*Allocate)(Process* process, SIZE_T size);
void (*Terminate)(Process* process);
#endif
};
#ifndef FUNCS
uintptr_t rebase(Process* proc, uintptr_t address);
bool write_memory(Process* proc, uintptr_t address, const void* data, size_t size);
bool read_memory(Process* proc, uintptr_t address, void* out_buffer, size_t size);
void terminate(Process* proc)
uintptr_t find_pattern(Process* process, const char* pattern);
Module* get_module(Process* process, const char* name);
void* allocate_memory(Process* process, SIZE_T size);
#endif
In this example I will be focusing on the option where it is within the struct and not just a normal function.
Creating a new process
Creating a new process only requires it's name and the library will do the rest of it itself
Note that the program will automatically close if the program is not found
Process* proc = new_process("RobloxPlayerBeta.exe");
Reading memory
Reading memory using this library is fairly simple as it requires 4 main variables, the process pointer, the address you want to read, the buffer you want to read into, and the size of the type that you want to read.
uintptr_t fake;
proc->ReadMemory(proc, (proc->Rebase(proc, 0x67633D8)), &fake, sizeof(uintptr_t));
Writing memory
Writing memory is just as easy as reading memory ans it also just requires the same 4 variables, but in this cause there is no out buffer there is a data "buffer" which need to hold a valid value.
uintptr_t newValue = 1;
proc->WriteMemory(proc, fake, &newValue, sizeof(uintptr_t));
Rebase
Now as you have seen in ReadMemory
there is also a function that lets you rebase a address.
uintptr_t rebased = proc->Rebase(proc, 0x67633D8);
Pattern scanning
Pattern scanning as well is pretty straight forward since you only need the process pointer and just the pattern you want to scan for
uintptr_t address = proc->PatternScan(proc, "48 8B C4 44 89 48 ? 4C 89 40 ? 48 89 50 ? 48 89 48 ? 53");
To get the offset from the output address just do it like this
uintptr_t offset = (address - proc->baseAddress);
printf("0x%llx\n", offset);
Getting a module
Getting a loaded (e.g RobloxPlayerBeta.dll) is really simple and it returns a Module
struct which contains the entry data itself (MODULEENTRY32) and the baseAddress of the loaded module directly.
typedef struct {
MODULEENTRY32 entry;
uintptr_t baseAddress;
} Module;
Module* player = proc->Module(proc, "RobloxPlayerBeta.dll");
Allocating memory
Allocating memory requires the size given in and that was about it
void* allocated = proc->Allocate(proc, 290);
Terminating the process
Terminating the process can be done using the Terminate method
proc->Terminate(proc);
Last updated