Skip to content

RE: Basics

Introduction

So you wanted to dip into basic RE, huh?

Im going to list some tech I personally think is important to have in order to achieve anything substantial, so you should be familiar with atleast most of these if you want to proceed.

Requirements

  • Basics of x86 Assembly and Calling Conventions and its implications in regarding to LTCG Optimizations.
  • You are familiar with static analysis programs such as IDA, GHidra, Radare
  • You are familiar with Debuggers such as X64Dbg, WinDbg, OllyDbg
  • You are familiar with Memory Manipulation Tools such as ReClass.NET or Cheat Engine
  • You are familiar with how Windows works to some extent (Stuff such as the PEB and the LDR and WINAPI and its related terminology)
  • You are great at working with low level coding (fully understanding how pointers work, interop with assembly, etc)
  • You are decent at C#, Lua (4.0.1) and can work with it

Understanding the Project

Before we can even begin to think about adding some kind of feature, we first have to get to know the project, or game in this case beforehand.

What I mean by this is to understand (atleast to some extent; 100% is not requires nor always possible) the surrounding game code and its used structures. This extents to knowing what surrounding function(calls) do and what the functions most likely name is (guesswork), and of course also to manually map out the structures which are used at the place (before and after).

Structures specifically are quite important but sadly sometimes quite hard to map out, because in some circumstances the structures are just laid out in the stack of the function, and many static analysis applications struggle to identify such structs being there, and may think there is just a random assortment of 4 DWORDS, where in reality its a struct that mirrors the size of 4 DWORDS.

As for how to find the relevant game code that you think you might need to hook/change, this is a job for a Debugger, theres many ways of finding the place you need to work with, but in most cases setting some breakpoints will do the trick, then you just have to trace the callstack at most.

The true strength of having knowledge of static analysis tools and realtime debuggers is that you can look at it from the perspective of both sides: static code <-> live code and this makes it 100x easier to understand structures for example, because you're going to notice a const char* string pointer a lot faster when you look at the memory dump than looking at some bizarre pointer in the static analysis app.

Lastly, I can only recommend using ReClass.NET if you want to reverse engineer some of the structures of the game. Feel free to base off of the work of the mappingclassesX.rcnet file, this is the main ReClass.NET project file this project is using. It is fully based off of the knowledge by the IDA (.idb) project file. You may find difference in practice if you look at both projects simulatenously, this is just human error on my part in such cases.

Modifying the Project

If you have found the relevant sections(functions) you want to modify, then you need to know if you can get away with just hooking the function itself and relaying it to a C# managed function OR you need to do a InlineAsmHook/MidFunctionHook.

The former is a lot easier, but still comes with some gotchas, such as: mutated calling conventions. As mentioned earlier, LTCG knowledge comes in handy for this: LTCG is Link-Time-Code-Generation -- its an optimization to allow for function calls to reduce pressure on the stack by passing some arguments through registers insead of the stack. This complicates hooking endeavouers by a lot in practice. There is no programming language that can work with LTCG optimized functions, so you cannot call them.

BUT: We have the power of Assemblers! The MutatedHooks and its sub-project CallingConventionDispatcher are libraries which I have specifically written to make calling into the functions (and from!) possible, AFAIK: this might be the only public library that has these capabilities. I found Reloaded.Hooks to be lacking (cannot parse structs as args!), and seemingly its the only other library in the world that tries to address this.

With MH and CCD we can actually hook these places without trouble, IF: You fully know the proper arguments getting passed to the LTCG optimized function, this step is crucial and you have to analyse the call-site to the function and its epilogue/prologue manually by hand via any disassembler available to you in order to deduce the proper calling convention info such as: Amount of arguments, Order of arguments & Stack Cleanup rules.

So this is pretty much it for normal function hooks and mutated hooks. Now lets get a word in for InlineHooks.

InlineHooks (or rather X86InlineHook) is a special class made to hook assembly stubs at any point and allows the usage of an actual Assembler to emit code to a new stub (which gets JMP'd to by the hooked place in the original function) executes code and then goes back to resume normal operation. It works exactly like a normal hook, but instead of at the very beginning of the function, we can just place a JMP in the middle or pretty much anywhere inside of it.

WARNING: InlineHooks and its related classes are subject to change as their API is still a Work in Progress! I plan to make them more ergonomic to use and perhaps similiar in style like MonoMod's ILGenerator and ILCursor toolset.

Another caveat is: You really have to know what you're doing if going for InlineHooks, any type of wrong input is basically guaranteeing a crash.