Forum > Coding >

C++ Intermediate Lessons EP: 4 : C++ Trampoline Hooks

Posts: 224

Threads: 43

Joined: May, 2022

Reputation: -5

Posted

In the past tutorials, we learned how memory works, how pointers work in C/C++ and how we can use them to our advantage. 

Now that you know how it works, I'm going to teach you what trampoline hooks are( note that this is one of multiple trampoline hooking methods. I've posted other methods of it on my github and here before. ), how they work, and why they're useful. Let's start off with the why:

Let's say you want to run your code each time the game calls a certain function or runs a certain piece of code, that's exactly what a trampoline hook lets you achieve.

How:

 It works by overwriting 5 or more bytes ( 5 is the amount of bytes required for a relative JMP instruction ) of the specific code or function we want to hook and using those overwritten bytes to jump to our code we want to execute, and after executing our code, execute the overwritten code ( so that the game works as normal ) and proceed to jump to the next instruction after the instructions we executed to continue execution.  

 

They get the name trampoline hook ( also known as a detour ) because you're jumping from code to code, sort of like a trampoline where you jump, go in the air, then go back down to where you originally were.

 

Here's my implementation of a basic trampoline hook:

 

std::uint32_t tramp_hook( void* hook_addr, void* new_func, std::uint32_t instr_size ) 

{

constexpr auto jmp_instr_size = 5; // minimum size required for a JMP instruction



DWORD vp_old_prot{ 0u };

VirtualProtect( hook_addr, instr_size, PAGE_EXECUTE_READWRITE, &vp_old_prot ); // In order to overwrite code, we need proper access.

std::memset( hook_addr, 0x90, instr_size ); // setting the bytes we will overwrite to 0x90 / nop ( no operation )



const auto rel_addr = ( reinterpret_cast< std::uint32_t>( new_func ) - reinterpret_cast< std::uint32_t >( hook_addr ) ) - jmp_instr_size; // relative address calculation. in a relative jmp / call, the result of this calculation will be used by the CPU to add to the EIP ( instruction pointer ).



*( static_cast< std::uint8_t* >( hook_addr ) ) = 0xE9; // overwriting a byte to the JMP opcode ( 0xE9 )

*( reinterpret_cast < std::uint32_t* >( reinterpret_cast< std::uint32_t >( hook_addr ) + 1) ) = rel_addr; // setting the result of our relative address calculation as the relative jmp operand.



VirtualProtect( hook_addr, instr_size, vp_old_prot, nullptr ); / resetting our access

return reinterpret_cast< std::uint32_t >( hook_addr ) + 5; // returning the address next instruction to be executed to be used later

}

 

  • 2

https://media.discordapp.net/attachments/1044764388546068510/1051935933836050482/Signature_4.png

Posts: 1210

Threads: 68

Joined: May, 2022

Reputation: 17

Replied

whoever named this must have been on some kind of drug

  • 0

Did I mention I use arch btw?

Skid_Destroyer

Self Taught (Pro)grammer

Posts: 10

Threads: 2

Joined: Jul, 2022

Reputation: 3

Replied

That's ugly code.

  • 0

Posts: 0

Threads: 0

Joined: ?

Reputation:

Replied

Nice lesson, the code looks simple and easy to read. Nice, I love how you implemented comments into your code to show/make a better understanding of how the code works.

  • 0

Posts: 224

Threads: 43

Joined: May, 2022

Reputation: -5

Replied

@Skid_Destroyer

 

let me know when your code is better :skull:

lets see your trampoline hook code

  • 0

https://media.discordapp.net/attachments/1044764388546068510/1051935933836050482/Signature_4.png

Skid_Destroyer

Self Taught (Pro)grammer

Posts: 10

Threads: 2

Joined: Jul, 2022

Reputation: 3

Replied

@luxiferrwoo How about I just modify your code? 

std::uintptr_t tramp_hook(void* target, void* new_func, std::size_t size)
{
    DWORD old {};
    VirtualProtect(target, size, PAGE_EXECUTE_READWRITE, &old);

    std::memset(target, 0x90, size);
    const auto rel_addr = (reinterpret_cast<std::uintptr_t>(new_func) - reinterpret_cast<std::uintptr_t>(target)) - 5;
    *static_cast<std::uint8_t*>(target) = 0xE9;
    *reinterpret_cast<std::uintptr_t*>(reinterpret_cast<std::uintptr_t>(target) + 1) = rel_addr;

    VirtualProtect(target, size, old, nullptr);

    return reinterpret_cast<std::uintptr_t>(target) + 5;
}

 

Also fix your .clang-format file lmfao

  • 0

Posts: 224

Threads: 43

Joined: May, 2022

Reputation: -5

Replied

@Skid_Destroyer

legit all you did was change formatting lol

also my formatting is fine, i love it :kiss.

  • 0

https://media.discordapp.net/attachments/1044764388546068510/1051935933836050482/Signature_4.png

Skid_Destroyer

Self Taught (Pro)grammer

Posts: 10

Threads: 2

Joined: Jul, 2022

Reputation: 3

Replied

@luxiferrwoo I removed your sh|tty practices and did what you do most of the time (modifying other peoples code)

 

Why?

https://cdn.discordapp.com/attachments/1014484696463323168/1020553806620131339/unknown.png

 

That 0u is ugly and unnecessary

https://cdn.discordapp.com/attachments/1014484696463323168/1020678778357305426/unknown.png

 

Using the Variable here but not on the return statement (lol)?

https://cdn.discordapp.com/attachments/1014484696463323168/1020553891726762004/unknown.png

https://cdn.discordapp.com/attachments/1014484696463323168/1020553994889859154/unknown.png

 

What the fu€k 

https://cdn.discordapp.com/attachments/1014484696463323168/1020679343787221063/unknown.png

 

std::uintptr_t exists

https://cdn.discordapp.com/attachments/1014484696463323168/1020679638416109640/unknown.png

https://cdn.discordapp.com/attachments/1014484696463323168/1020679590965948466/unknown.png

https://cdn.discordapp.com/attachments/1014484696463323168/1020679855718813738/unknown.png

https://cdn.discordapp.com/attachments/1014484696463323168/1020680977472831488/unknown.png

https://cdn.discordapp.com/attachments/1014484696463323168/1020681091574665286/unknown.png

 

  • 0

Posts: 224

Threads: 43

Joined: May, 2022

Reputation: -5

Replied

 

 

what do you mean most of the time I'm modifying other people's code??? what??

the only repositories I have asked for help on are the signature scanner ( which I have completely modified and rewritten but haven't yet released publicly and don't plan to ), which was just 0x90 showing me a better way of doing it and then I further improved it privately, from 1400ms to 300ms and a better way for checking for a function end ( 0x90 ). the rest is all written by me lol, not only that but every single piece of code that isn't mine, has been credited completely.

 

to answer your questions:

1. it's for clarity, this is a tutorial, why would I not explain the meaning of why I'm using 5 in code as well as in text?

2. the 0u is completely preference lol, nice one

it's funny how you call me out for using uint32_t yet in your "modified" version, you legit use it aswell?

https://media.discordapp.net/attachments/798043651309699122/1020686372136296508/unknown.png you forgot to change from uint32_t here to uintptr_t

 

In most if not all of my github repositories you'll see me using std::uint32_t which is a practice I have since changed to uintptr_t a while ago, way before you made this reply, but haven't updated any of the repositories to use std::uintptr_t so even if I do update one it'll probably remain the same anyways.

 

your only "valid" argument is using std::uintptr_t instead of std::uint32_t and that's fine since I have already quit that habit before I even made this thread

 

and your little comment about me modifying other people's code is weird, since not only have they been credited, the "modified code" you're talking about is the ret_function_bytes function and the signature scanner, both from 0x90 and one that has been thrown out and improved ( by me ) lol, you're acting like I completely copied code and changed formatting. 

 

  • 0

https://media.discordapp.net/attachments/1044764388546068510/1051935933836050482/Signature_4.png

Skid_Destroyer

Self Taught (Pro)grammer

Posts: 10

Threads: 2

Joined: Jul, 2022

Reputation: 3

Replied

@luxiferrwoo Not reading all of that but sorry about your loss

  • 0

Posts: 224

Threads: 43

Joined: May, 2022

Reputation: -5

Replied

@_realnickk

blame wrd forums for the spacing on lines but blame me for the spaces in parentheses and < > and etc

  • 0

https://media.discordapp.net/attachments/1044764388546068510/1051935933836050482/Signature_4.png

Users viewing this thread:

( Members: 0, Guests: 1, Total: 1 )