{"id":17845491,"url":"https://github.com/emd4600/cppreveng","last_synced_at":"2026-02-28T22:31:14.839Z","repository":{"id":134202072,"uuid":"193779105","full_name":"emd4600/CppRevEng","owner":"emd4600","description":"A library to help DLL injection and Detouring in C++","archived":false,"fork":false,"pushed_at":"2019-09-14T18:46:57.000Z","size":34,"stargazers_count":11,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-25T06:46:56.343Z","etag":null,"topics":["cpp","detours","dll-injection","reverse-engineering","x86"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emd4600.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-06-25T20:30:57.000Z","updated_at":"2024-07-14T20:38:07.000Z","dependencies_parsed_at":"2023-07-07T04:34:45.240Z","dependency_job_id":null,"html_url":"https://github.com/emd4600/CppRevEng","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/emd4600/CppRevEng","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emd4600%2FCppRevEng","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emd4600%2FCppRevEng/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emd4600%2FCppRevEng/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emd4600%2FCppRevEng/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emd4600","download_url":"https://codeload.github.com/emd4600/CppRevEng/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emd4600%2FCppRevEng/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29953280,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T18:42:55.706Z","status":"ssl_error","status_checked_at":"2026-02-28T18:42:48.811Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","detours","dll-injection","reverse-engineering","x86"],"created_at":"2024-10-27T21:36:05.324Z","updated_at":"2026-02-28T22:31:14.811Z","avatar_url":"https://github.com/emd4600.png","language":"C++","readme":"**CppRevEng** is a project aimed at making C++ reverse engineering and DLL injection easier. It's main focus is to provide an easier interface to use [Microsoft's Detours API](https://github.com/microsoft/Detours), which is used to alter the code of a running program.\n\nThis library (which is actually just two header files) was created for injecting and detouring Visual C++ x86 programs. If you want to use this library, just add the `inc` folder into your include path, and include the file `\u003cCppRevEng.h\u003e` . Even though one of its main focus is detouring, this does not include the `Detours` API; you must download it and include it in your project for `CppRevEng` to work correctly.\n\n## Projects that use CppRevEng\n\n - [Spore ModAPI](https://github.com/Emd4600/Spore-ModAPI) (uses slightly modified version)\n - [Spore ModCreatorKit](https://github.com/Emd4600/Spore-ModCreatorKit) (uses slightly modified version)\n\n## Addresses\n\nThe first thing `CppRevEng` helps you with is with organizing addresses. For small projects this is generally unnecessary, but if\nyou want to do a big project (like an API to mod a game) you will want to keep some order.\n\nThe most simple macro is `Address()`, which just takes an address you have found reverse engineering (with IDA, Ghidra or similars)\nand converts it into the correct address of the current executable running. `Address(0x4056d0)`, as simple as that.\n* Be warned, programs like Cheat Engine or OllyDBG treat base addresses differently, so you might need to add `0x400000` to the \naddresses you get from those programs.\n\nAnd then comes organization: it is recommended to store addresses in namespaces. Imagine you have reverse engineered a class, `cViewer`,\nwith two methods: `LoadTransformations` and `SetBackgroundColor`. You can then store their addresses in a list:\n\n```cpp\nclass cViewer { ... };\n\nnamespace Addresses(cViewer) {\n\tDeclareAddress(LoadTransformations, 0x7C5650);\n\tDeclareAddress(SetBackgroundColor, 0x7C42C0);\n}\n```\n\nNow you can use `GetAddress()` to get those addresses, e.g. `GetAddress(cViewer, LoadTransformations)`.\n\nIn your `dllmain.cpp`, you should add he following line just after the includes so that it can compile correctly:\n\n```cpp\nBaseAddressDeclare;\n```\n\nThen in your `DllMain` function, you should call the `InitCppRevEng()` function in order to correctly initialize the base address variable.\n\n## Method Redirecting\n\nWhen doing DLL injection, you will probably need to call a function of the executable, which is at a certain address. Normally, this would be done by making a function pointer type, casting the function address to that type and then call it. Since this is very counter-intuitive, `CppRevEng` includes several macros to help with that.\n\nOur preferred solution is declaring classes and methods in header files, as if it were an API. Then, do the implementation on a .cpp file (you can also do it in the .h, inlined). In order to generate the implementation for these kind of functions, we have the `Redirect...Method` macros. The macros are designed to work combined with the address lists we mentioned before.\n\nIn general, all the macros take:\n - The address namespace name (or class name if it's a member method).\n - The function name.\n - The return type.\n - The parameters.\n - The parameter names (they can be generic, don't need to match the header file).\n\nThere are three main macros:\n - `RedirectStaticMethod`: used for **static** and namespace functions.\n - `RedirectMethod`: used for non-virtual, **non-static** class methods.\n - `RedirectVirtualMethod`: used for **virtual**, non-static class methods. This one takes an extra parameter, the virtual class.\n\nThese macros have multiple variants (which can be combined):\n - `..._noargs`: if the method does not take any parameters.\n - `..._structret`: if the method returns a struct by value (exactly, if sizeof() \u003e 8)\n - `..._const`: if the method is declared as `const` (cannot be used in static functions).\n\nSome examples:\n\n```cpp\nnamespace Spore {\n    void DestroyObject(int index);\n}\nRedirectStaticMethod(Spore, DestroyObject, void, Args(int index), Args(index));\n\nclass  PhysicsEngine {\n    static float GetGravity();\n}\nRedirectStaticMethod_noargs(PhysicsEngine, GetGravity, float);\n\nnamespace Math {\n    Vector3 Normalize(const Vector3\u0026 v);\n    Vector3 GetZ();\n}\nRedirectStaticMethod_structret(Math, Normalize, Vector3, Args(const Vector3\u0026 v), Args(v));\nRedirectStaticMethod_structret(Math, GetZ, Vector3);\n\nclass Object {\n    uint32_t GetId();\n    uint32_t GetId() const;\n}\nRedirectMethod_noargs(Object, GetId, uint32_t);\nRedirectMethod_noargs_const(Object, GetId, uint32_t);\n\nclass Window {\n    void AddChild(int index);\n    virtual bool Paint(DrawSettings\u0026 drawer)\n}\nRedirectMethod(Window, AddChild, void, Args(int index), Args(index));\nRedirectVirtualMethod(Window, Paint, bool, Args(DrawSettings\u0026 drawer), Args(drawer));\n\nstruct Vector3 {\n    float Scale(float factor);\n}\nRedirectMethod_const(Vector3, Scale, float, Args(float factor), Args(factor));\n```\n\n## Detouring\n\nWhen using DLL injection, detouring is the most important technique: it allows you to hook the executable methods and override them with your own functionality. Generally, detouring a program is quite complicated. Not because it's hard, but because it requires many repeated code that could be avoided: that's what `CppRevEng` does.\n\nThis header file defines 3 macros:\n - `static_detour`: for static functions.\n - `member_detour`: for non-static, non-virtual methods.\n - `virtual_detour`: for non-static, virtual methods.\n\nThese macros are struct declarations, so you must follow them with a {};  - don't forget the final semicolon!\n\nAll macros take at least two parameters: \n - `name`: A unique name to identify the detour object. You will use it to attach the detour.\n - `declaration`: The type and parameter types of the function. Examples: `void(int)`, `bool()`, `const float\u0026(const vector\u003cint\u003e, int**)`\n\n### Detouring static functions\n\nImagine you want to detour a static function that returns a float, and takes a const char* as parameter. You would do it like this:\n```cpp\nstatic_detour(MyDetour1, float(const char*)) {\n\tfloat detoured(const char* pString) {\n\t\tif (pString[0] == '_') return -1.0f;\n\t\telse {\n\t\t\t// We call the original function; as you can see you can use any parameter you want\n\t\t\treturn original_function(pString) + original_function(\"object\");\n\t\t}\n\t}\n};\n```\n\n### Detouring a member method\n\nImagine you want to detour a method that is mebmer of a certain class. It returns void, and does not take any parameter. You would do it like this:\n```cpp\n// A class declaration, the method belongs to this class\nclass ClassManager {\nprotected:\n\tvector\u003cvoid*\u003e mObjects;\n}\n\nmember_detour(MyDetour2, ClassManager, void()) {\n\tvoid detoured() {\n\t\tMessageBox(\"Objects are being deleted\");\n\t\t// You can access the public and protected fields:\n\t\tmObjects.clear();\n\t}\n};\n```\n\n### Detouring a virtual member method\n\nImagine you want to detour a virtual method that is member of a certain class. It returns void, and takes 2 float parameters. You would do it like this:\n```cpp\n// A class declaration, the method belongs to this class\n// It's important to know in which class the method was declared. In this case, let's imagine it was declared in ICombatant\nclass cCreature : public IObject, public ICombatant {\nprotected:\n\tfloat mHealthPoints;\n}\n\nvirtual_detour(MyDetour3, cCreature, ICombatant, void(float, float)) {\n\tvoid detoured(float strength, float distance) {\n\t\t// I want to be immortal!\n\t\tif (mHealthPoints \u003c 10) mHealthPoints += 1000.0f;\n\t\toriginal_function(this, strength, distance);\n\t}\n};\n```\n\n### Attaching/detaching detours\n\nDetours must be attached/detached in the DllMain function. This header provides two functions:\n- `PrepareDetours(HANDLE)`: must be called before using any detours.\n- `CommitDetours()`: must be used after using detours\n\nAn example DllMain would look like this:\n```cpp\nswitch (dwReason) {\n\tcase DLL_PROCESS_ATTACH:\n\tPrepareDetours(hHandle);\n\tMyDetour1.attach(Address(0x405810));\n\t// You can also use address lists\n\tMyDetour2.attach(GetAddress(ClassManager, Create));\n\tCommitDetours();\n\tbreak;\n\ncase DLL_PROCESS_DETACH:\n\tPrepareDetours(hHandle);\n\tMyDetour1.detach();\n\tMyDetour2.detach();\n\tCommitDetours();\n\tbreak;\n}\n```\n\n### Separating header/cpp files\n\nIf you want, you can declare the detour in a header file, and specify the code in a cpp file. It would look like this:\n```cpp\n// In the header file:\nstatic_detour(MyDetour1, float(const char*)) {};\n\n// In the cpp file:\n// Use the macro DETOUR to access the method\nfloat MyDetour1::DETOUR(const char* pString) {\n\tif (pString[0] == '_') return -1.0f;\n\telse {\n\t\t// We call the original function; as you can see you can use any parameter you want\n\t\treturn original_function(pString) + original_function(\"object\");\n\t}\n}\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femd4600%2Fcppreveng","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femd4600%2Fcppreveng","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femd4600%2Fcppreveng/lists"}