remem
is a C++20/C++17 header-only library designed for safely reading and writing memory in Windows applications. It includes features like exception handling, pointer validation, and memory manipulation utilities, making it a useful tool for low-level memory operations.
- Memory Reading and Writing: Easily read and write memory at specified addresses with support for multiple offsets.
- Pointer Validation: Ensure that pointers are valid before accessing memory, preventing crashes or undefined behavior.
- Pattern Scanning: Find byte patterns in memory with support for both IDA-style signatures and code style signatures.
- Function Calling: Call functions with different calling conventions, including support for member functions (with
this
pointer). - Exception Handling: (Optional) Safeguard against exceptions during pointer dereferencing by using a vectored exception handler.
- Logging: (Optional) Log memory addresses and offsets during read/write operations for debugging purposes.
To use remem
in your project, simply include the remem.hpp
header file in your code. No additional dependencies are required.
If you want to enable exception handling, you should set up the exception handler at the beginning of your program:
remem::SetupExceptionHandler();
You can read memory using the ReadMemory function template. It supports reading from an address with multiple offsets:
uintptr_t baseAddress = remem::GetModuleBaseAddress<uintptr_t>("module_name.exe");
std::vector<DWORD> offsets = {0x10, 0x20, 0x30};
int value = remem::ReadMemory<int>(baseAddress, offsets);
If you want to read a string from memory:
std::string value = remem::ReadMemory<std::string>(baseAddress, offsets);
Similarly, you can write to memory using the WriteMemory function template:
int newValue = 12345;
remem::WriteMemory<int>(baseAddress, offsets, newValue);
Before performing any operations on a pointer, you can validate it:
void* ptr = reinterpret_cast<void*>(address);
if (remem::IsValidPtr(ptr)) {
// Safe to use the pointer
}
The CallFunction template allows you to call functions with different calling conventions in C++. Here’s how to use it:
Decide which calling convention your function uses (thiscall
, fastcall
, stdcall
, or cdecl
).
Specify the return type and parameters of the function you want to call.
For thiscall and fastcall conventions, you need to pass a this pointer as the first argument.
For stdcall and cdecl conventions, you do not need to pass a this pointer.
To call a thiscall or fastcall function, provide the address of the function, a this pointer, and the arguments:
auto result = CallFunction<CallingConvention::thiscall_, ReturnType>(funcAddress, thisPointer, arg1, arg2);
To call a stdcall or cdecl function, provide the address of the function and the arguments:
auto result = CallFunction<CallingConvention::cdecl_, ReturnType>(funcAddress, arg1, arg2);
In both cases, replace ReturnType
with the return type of the function and funcAddress
with the address of the function you are calling.
The pattern class allows for easy memory pattern scanning with support for both IDA-style signatures and code-style signatures.
pattern
Class
Constructor
pattern(std::string _pattern, const char* _module_name = nullptr)
: Constructs a pattern object by scanning for the specified pattern in the given module (or the current module if nullptr).
Member Functions
pattern add(uint32_t _value, bool _deref = false)
: Adds an offset to the current pointer. If _deref is true, it will also dereference the pointer before adding the offset.
pattern sub(uint32_t _value)
: Subtracts an offset from the current pointer.
pattern inst(uint32_t _offset)
: Adds an offset to the current pointer, with the offset value taken from a pointer located at _offset from the current pointer.
GetPointer()
: Returns the current pointer value.
For example we are pattern scanning mov ecx, [0xDEADBEEF]
auto PatternTest = remem::pattern("8B 0D ?? ?? ?? ??").add(2, true);
The add member will deref the pointer if we call auto insideofmovecx = PatternTest.GetPointer()
it will return 0xDEADBEEF.
Exception handling can be enabled or disabled by setting the _EXCEPTION_HANDLING macro:
#define _EXCEPTION_HANDLING 1 // Enable exception handling
Logging can be enabled or disabled by setting the _LOGS macro:
#define _LOGS 1
This library is designed specifically for Windows and utilizes Windows-specific APIs.
This library is provided as-is, with no warranties or guarantees. Use it at your own risk.
Created by 0xenia on 11.08.2024.