Skip to content
/ RELang Public

RELang is a domain-specific language that allows you to describe memory interfaces to binary executables and transpiles to C++.

License

Notifications You must be signed in to change notification settings

jushar/RELang

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RELang

Build Status

RELang is a domain-specific language that allows you to describe memory interfaces to binary executables and transpiles to C++17. The acronym RELang stands for Reverse Engineering Language.

Writing binary interfaces for existing applications you don't have the source of can be annoying with C++ only and either needs a lot of boilerplate code or more generic approaches tend to break auto-completion in IDEs.
Instead, this project follows a different approach: The required interfaces are all written in RELang, the RELang compiler is integrated in your project's toolchain and generates C++ code. This C++ code is then included in your project and you can continue as usual.

RELang is based upon the ANTLR4 parser generator, is written in Golang and its syntax looks very similar to C++. It was primilarily invented for and tested with code generated by and for the MSVC compiler. Support for other compilers may be added in the future.

Key Features

  • Function body generation for memory address-based function calls
  • Automatic pad generation for unknown memory regions in struct
  • Support for virtual methods
  • Strong type system with fixed-size types only

Examples

class Vehicle : Element
{
    void Fix() @ 0xBEAF;
    bool Attach(Element* element) @ 0x123456;

    float32 health @ 0x4;
    ModelInfo* model;
    bool engineOn;
    Vehicle* trailer;
    bool locked;
    int8 color @ 0x50;
};

...transpiles to something like...

class Vehicle : public Element
{
public:
    inline void Fix()
    {
        using Func_t = void(__thiscall *)(decltype(this));
        auto f = reinterpret_cast<Func_t>(0xBEAF);
        return f(this);
    }

    inline bool Attach(Element* element)
    {
        using Func_t = bool(__thiscall *)(decltype(this), Element*);
        auto f = reinterpret_cast<Func_t>(0x123456);
        return f(this, element);
    }

private:
    char _pad0[4];
public:
    // offset 4
    float32 health;
    // offset 8
    ModelInfo* model;
    // offset 12
    bool engineOn;
    // offset 13
    Vehicle* trailer;
    // offset 17
    bool locked;
private:
    char _pad1[62];
public:
    // offset 80
    int8 color;
};

Building

To be able to build the project, you need:

  • golang >= 1.11
  • Java runtime (only required if you intend to make changes to the grammar)
  • Node.js and globally installed gulp (only required for more convenience)

Compiling the examples

The following command will transpile examples/Vehicle.relang to examples/out/Vehicle.h.

go run cmd/relang.go -p examples/Vehicle.relang -o examples/out/Vehicle.h

Alternatively, if you have gulp installed, you can also compile all examples at once:

gulp run-examples

Language Documentation

Type System

On assembly level, we only need to distinguish between primitive types, pointers and embedded class types.

Primitive Types

Supported primitive types are:

signed unsigned other
int8 uint8 bool
int16 uint16 float32
int32 uint32 float64

Their meaning should be self-explanatory and matches C++'s fixed width integer types.

Pointers

Pointers are declared by appending an asterisk (*) to the type, just like in C++. Their size is always 32-bit for an x86 target and 64-bit for an x86_64 target.

Classes

Classes look very similar to C++, except for:

  • No access modifiers like public, protected or private
  • No modifiers like const
  • What else? (TODO)
// Declare class named 'Tree' and inherit from class named 'Plant'
class Tree : Plant {
    // Declare function named 'CountLeafs' that is located
    // at address 0x12345678 and returns an uint32
    uint32 CountLeafs() @ 0x12345678;

    // Arrays are pointers pointing to the first element
    // so just return a Leaf pointer here.
    // Uses the non-default __stdcall calling convention
    Leaf* __stdcall GetLeafs() @ 0x234;

    // Declare an attribute named 'color' at offset 0x50
    uint32 color @ 0x50;

    // Declare another attribute.
    // If an offset is not defined, it's automatically calculated
    // based on the previous attributes size. In this case,
    // it'll lay at offset 0x54 as sizeof(uint32) == 4
    bool needsWater;
};

Inheritance

You can inherit from one or more classes. The base classes are embedded into the declared class in the same order as they are listed.

Virtual Methods

Declaring virtual methods works similarly to declaring attributes. Their memory address is the offset in the vtable (virtual function table).

class Plant {
    virtual int8* GetName() @ 0x8;
}

Static Functions

You can also declare functions as static. They have a non-__thiscall calling convention and behave like static functions in C++.

Global Functions and Variables

Functions

// Declare global function at offset '0xBEAF'
// that returns a PlantFactory ptr and accepts an int32 as parameter
PlantFactory* GetPlantFactory(int32 flags) @ 0xBEAF;

Variables

TODO

Raw Blocks

Sometimes, it might not be possible to express something in RELang, but works well with C++ or you just want to add some logic to your class. In most cases, it might be better to inherit from or embed the generated class. If that doesn't work for you, you can use the raw-block instead.
The raw block just injects a piece of code into the generated C++ code without modifying it.

class PlantFactory {
    ```
        template<std::size_t N> 
        void AllocatePlants() {
            // Do some stuff
        }
    ```
};

Namespaces

Namespaces work exactly like C++ namespaces. C++17's nested namespaces are also supported and compile to pre-C++17 code as well.

About

RELang is a domain-specific language that allows you to describe memory interfaces to binary executables and transpiles to C++.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages