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 CreateToolhelp32Snapshotwhich 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