Dismiss Notice
Want to Shorten Your Long URL? Check out our sister website Tiniurl to solve your needs!

Tutorial Converting CE Lua to C++ (Mini-detour tut)

Discussion in 'C/C++' started by toxxic458, Feb 11, 2016.

  1. toxxic458

    toxxic458

    Messages:
    34
    Likes Received:
    6
    Joined:
    Jan 2, 2016
    So, since many people find this a hard part, I decided to write a tutorial on it describing how this exactly works.
    I am going to put an explaination on the detour technique (hooking) since that's the most common used.

    Requirements:
    Basic knowledge of Lua, C++ and assembly.
    Cheat Engine would be handy, but optional since the code will be provided.
    A C++ programming enviroment such as Visual Studio or Dev-C++. (this tutorial is using Visual Studio so some things might not work in Dev-C++.)

    A quick explaination on how CE lua works.
    The Cheat Engine's LUA has two parts. [ENABLE] and [DISABLE], which will be called to their corresponding action.
    Below [ENABLE], there's mostly a memory allocator, for example:
    alloc(newmem,2048)

    This will create 2048 bytes in the memory where code can be stored, labeled "newmem". Below it are registration of the labels that are used in your code (on default: returnhere and exit), where your assembly code can jump to.
    Mostly CE's Lua is created to hook assembly code inside of the executable, allowing code injection. This is called a detour.
    Upon disabling, mostly there's a deallocator block there.
    dealloc(newmem);
    This means that it is going to delete the allocated code block. This is done to prevent memory leaks. Below that is restoration of the original code without it being hooked.

    What exactly is a detour?
    A detour means that, when a code block is executed, it executes your code at the place where you've placed your detour. When you are completely finished with executing your code, you MUST jump back to the original code to retain a perfect codeflow.
    [​IMG]

    The bad part about placing a detour (or not) is that it destroys the original code. Depending on the action and instructions, you might have to restore the original code in order to keep it from crashing. Most external detours (such as MS Detours), restore this code for you.

    Information needed for this tutorial:
    Code:
    [ENABLE]
    //code from here to '[DISABLE]' will be used to enable the cheat
    alloc(newmem,2048)
    label(returnhere)
    label(exit)
    
    newmem: //this is allocated memory, you have read,write,execute access
    //place your code here
    mov ecx,[ebp+0c]#1000
    //NOTE: I left a label out here.
    
    exit:
    jmp returnhere
    
    "program.exe"+695AED:
    jmp newmem
    returnhere:
    
    [DISABLE]
    //code from here till the end of the code will be used to disable the cheat
    dealloc(newmem)
    "program.exe"+695AED:
    fstp dword ptr [eax]
    pop esi
    mov esp,ebp
    //Alt: db D9 18 5E 8B E5

    The code at "program.exe"+695AED:
    [​IMG]

    program.exe has a base address of 0x400000.

    Setting up the C++ code
    Basically what I've described in the Lua explaination, you need to allocate memory where code can be executed in. We do this by creating a function then flag it as naked. Naked means that it's a function without a calling conversion and no return value. It's plain code that can be jumped to, but not called.
    We will also call it "newmem", but we do not have to allocate space to it since it resizes with the amount of code you put in it. You also need a patch and a restore function. You call the patch function when you want to install it, and the restore to prevent your code from being executed.

    Code:
    DWORD returnhere = 0;
    
    __declspec(naked) void newmem(void) {
    
    }
    
    void patchmem() {
    
    }
    
    void restoremem() {
    
    }
    
    Creating the patch function
    What we wanna do in the code at "program.exe"+695AED is make it always set to 1000. The value we want to set is stored in ebp+0c.
    To create a detour, we need to place:
    jmp newmem
    In the original code at that address. the opcode for jmp is 0xE9. Because we cannot use "newmem", we have to get the address of the function newmem. We do this by casting it to a DWORD, which is 4 bytes. This makes our jump code 5 bytes long. Writing this will destroy the first three lines seen in the image above. (count the bytes, D9 18 5E 8B E5 = 5 bytes, the detour is 1 + 4 = 5).

    To calculate the address needed, we take the image base + 695AED (400000 + 965AED = A95AED). This is where we will write the first byte to, which is jmp.
    Code:
    void patchmem() {
    *(BYTE*)(0xA95AED)= 0xE9;
    }
    
    After that, we want the JMP to reference to our "newmem". Cast it to a DWORD will get it's address. To calculate the offset, we take the address of newmem, substract the address where we wrote our jump to and substract 5 since that's the size of our detour.
    The code will look as following:

    Code:
    void patchmem() {
    *(BYTE*)(0xA95AED)= 0xE9;
    *(DWORD*)(0xA95AED+ 1) = ((DWORD)newmem - 0xA95AED - 5);
    }
    
    Now we have successfully placed the hook and when calling patchmem, the code will now go to our code.

    Changing the code and restoring the original
    All the code we have in the lua label newmem:
    mov ecx,[ebp+0c]#1000

    is what we will place in our newmem function too.
    To get the return address of the retour, we'll just add 5 to the address where the detour is going to be placed at. (0xA95AED + 5)
    Code:
    DWORD returnhere = 0xA95AED + 5;
    __declspec(naked) void newmem(void) {
    __asm {
    mov ecx,[ebp+0c]#1000
    jmp returnhere
    }
    }
    
    But wait! we only wanted to overwrite the first instruction and keep everything else in tact!
    Below our overwritten instruction we will write the original code, which was
    pop esi
    mov esp,ebp

    It will now look like this:
    Code:
    __declspec(naked) void newmem(void) {
    __asm {
    mov ecx,[ebp+0c]#1000
    pop esi
    mov esp,ebp
    }
    }
    
    Restoring the code back to normal
    Restoring the original code is the easiest part. All you have to do is restore the original bytes you have overwritten to place the detour, back into the process.
    The original bytes are, if the lua is autogenerated, at the bottom of the script. it looks like:
    //Alt: db D9 18 5E 8B E5
    If it's not you can find it in cheat engine.

    The C++ code will look like this:
    Code:
    void restoremem() {
    *(BYTE*)(0xA95AED)= 0xD9;
    *(BYTE*)(0xA95AED+1)= 0x18;
    *(BYTE*)(0xA95AED+2)= 0x5E;
    *(BYTE*)(0xA95AED+3)= 0x8B;
    *(BYTE*)(0xA95AED+4)= 0xE5;
    }
    
    Final code:
    Code:
    DWORD returnhere = 0xA95AED + 5;
    
    __declspec(naked) void newmem(void) {
    __asm {
    mov ecx,[ebp+0c]#1000
    pop esi
    mov esp,ebp
    jmp returnhere
    }
    }
    
    void patchmem() {
    *(BYTE*)(0xA95AED)= 0xE9;
    *(DWORD*)(0xA95AED+ 1) = ((DWORD)newmem - 0xA95AED - 5);
    }
    
    void restoremem() {
    *(BYTE*)(0xA95AED)= 0xD9;
    *(BYTE*)(0xA95AED+1)= 0x18;
    *(BYTE*)(0xA95AED+2)= 0x5E;
    *(BYTE*)(0xA95AED+3)= 0x8B;
    *(BYTE*)(0xA95AED+4)= 0xE5;
    }
    

    Conclusion
    Depending on the resource you have and you can use, Lua to C++ can be pretty simple.
    If there's anything not clear, needs adds, things that need to be removed or invalid information, please post what and the replacement, so I can fix it.

    I hope this will make things more clear for some people.

    Greetings,

    Toxxic
     
    Last edited: Feb 11, 2016
    sopfox3 likes this.
  2. Uncle Sam

    Uncle Sam We want you!

    Messages:
    46
    Likes Received:
    3
    Joined:
    Jan 29, 2016
    Gender:
    Male
    Well done toxxic, If you ever want to, I'd love to see you make a thorough tutorial about calling functions. stdcall or cdecl. Something I'm still working on myself.

    hey also found a great debugger, which you might not have heard of but I really love it.

    Just in case you haven't heard of it!

    http://x64dbg.com/

    I know it's a little off topic but yeaXD
     
    toxxic458 likes this.

Share This Page