This is the regenny wiki.
What is regenny?
regenny is a reverse engineering tool to interactively reconstruct structures and generate usable C++ header files. Header file generation is done by the sister project sdkgenny.
For those familiar with other tools, it is similar to ReClass.NET. It is written in C++.
Structures are defined in a plaintext .genny
file rather than manually inserting types into a tree view. This allows for the structures to be version controlled, shared between users, and are human readable from a normal text editor.
It has a Lua scripting interface to easily read and manipulate the structures externally without compiling a separate program. This allows for easy testing, quick prototyping, or even writing a full blown tool in Lua. The Lua bindings can be used in a separate Lua installation/embedding, they are not tied to regenny.
Precompiled builds can currently be downloaded from the Actions page.
Getting started
To get started using ReGenny, create a project by clicking File->New
on the top menu bar and entering a name in the dialog box. This will create a .json
project file and a .genny
file.
After that, you can click Action->Attach
to attach to a running process and then you can edit the .genny
file created earlier to start reverse engineering structures.
Once you're finished, you can click Action->Generate SDK
to generate corresponding C++ files.
ReGenny is a very powerful tool has many other features, but this should give you a good idea on how to get started with reverse engineering using ReGenny.
What is a .genny
file?
.genny
files are defined in a C/C++-like syntax. They provide the definitions of the types to be viewed in the GUI, generated, and/or reflected upon by the scripting API.
Structures can be given an explicit size, and fields within the structures can be given explicit offsets without manual padding, and out of order.
Simple C structures can sometimes be directly pasted into a .genny
file.
Example
// Explicitly defined types.
// Format is type {type_name} {type_size} [[{metadata}]]
// the metadata determines how the type is displayed in the GUI and read by the Lua API.
type int 4 [[i32]]
type float 4 [[f32]]
type char 1
// Forward declared structure.
struct Bar{};
// Simple structure. Size is explicitly defined. It doesn't need to be, though.
struct Foo 0x100 {
int a @ 4 // Explicit offset
char* b @ 8 [[utf8*]]
int c // implicit offset, it's 0x10, inferred from the previous member
int d @ 0x70
float e @ 0x80
Bar* bar @ 0x90 // Pointer to a forward declared structure
};
struct Bar {
Foo* parent
int b
int c
};
The above image is slightly out of date. There is no longer a text editor inside ReGenny itself. .genny
files must be opened within ReGenny and edited with an external text editor now. Reason being ImGui's text editor functionality was not that great and caused frustrating issues.
The corresponding generated C++ structure
Foo.hpp
#pragma once
struct Bar;
#pragma pack(push, 1)
struct Foo {
char pad_0[0x4];
int a; // 0x4
// Metadata: utf8*
char* b; // 0x8
int c; // 0x10
char pad_14[0x5c];
int d; // 0x70
char pad_74[0xc];
float e; // 0x80
char pad_84[0xc];
Bar* bar; // 0x90
char pad_98[0x68];
}; // Size: 0x100
#pragma pack(pop)
Bar.hpp
#pragma once
struct Foo;
#pragma pack(push, 1)
struct Bar {
Foo* parent; // 0x0
int b; // 0x8
int c; // 0xc
}; // Size: 0x10
#pragma pack(pop)
Accessing this structure from Lua
Before using this script, the structure in the GUI has to be set to Foo
, regenny must be attached to a process, and the address of the structure must be set in the GUI.
-- An overlay is a special Lua type that allows access to the memory of a structure.
-- It has index and newindex metamethods that access to the members of the structure
-- seamlessly, with no magic numbers/offsets, completely externally.
local foo = regenny:overlay()
if not foo or foo:type():name() ~= "Foo" then
print("Overlay is not a Foo, cannot use this script.")
return
end
-- Dynamically read the structure memory from the target process.
print(foo.a) -- prints the value of foo.a
print(foo.b) -- prints the value of foo.b, will be a string
-- Setter demonstrations
-- These actually set the values within the target process's structure behind the scenes.
foo.c = 0x12345 -- sets foo.c to 0x12345
foo.e = 3.14159 -- sets foo.e to 3.14159
local bar = foo.bar -- gets the value of foo.bar
-- Because pointers can be null.
if bar ~= nil then
bar.b = 0x1337 -- sets bar.b to 0x1337
bar.c = bar.b + 0x100 -- sets bar.c to bar.b + 0x100
print(bar.parent:ptr() == foo:address()) -- prints true if bar.parent is equal to foo
if bar.parent:ptr() ~= foo:address() then
-- sets bar.parent to foo
-- pointers can be explicitly written to with a raw integer value
bar.parent = foo:address()
end
end
In addition to simply reading/modifying structures, the Lua API allows for more advanced features such as:
- Performing reflection on the structure types
- Reading and writing to the process memory
- Allocating memory in the process
- Parsing another
.genny
file separately - Generating C++ header files from a new
.genny
file or SDK instance