-
Notifications
You must be signed in to change notification settings - Fork 5
Getting SDL offsets
For rendering the menu, the game needs to hook SDL_GL_SwapWindow and
SDL_PollEvent. In cs:go, we can get each function with dlsym()
and replace a
pointer inside it (osiris, thread). We would get those functions from
GAMEDIR/bin/linux64/libSDL2-2.0.so.0
. On tf2, however, we only have
GAMEDIR/bin/libSDL2-2.0.so.0
, and there is no jmp
instruction to patch there.
Finding the offsets is not hard, we just have to open the library in IDA and look for the function. The symbols are exported so we can just Ctrl + L.
Once we find one of the functions, it should look something like this:
The offset we want will be the second off_*
, the one in the call
instruction.
Now we have to get the location from C. First of all, what kind of pointer is this? This is a pointer to a function pointer. To make it more visual, I typedef’d it:
/* In the cheat this is declared with the DECL_SDL_FUNC macro.
* Note that it's a pointer to the function pointer we just typedef'd */
typedef int (*PollEvent_t)(SDL_Event* event);
PollEvent_t* PollEventPtr;
Now that we have the offset, we can get it with my GET_OFFSET
macro. The macro
simply casts the void*
handler we pass it to a link_map
struct, and then adds
the offset to the l_addr
member.
#define GET_OFFSET(HANDLER, OFFSET) \
((void*)(((struct link_map*)HANDLER)->l_addr) + OFFSET)
void* h_sdl2 = dlopen("./bin/libSDL2-2.0.so.0", RTLD_LAZY | RTLD_NOLOAD);
PollEventPtr = (PollEvent_t*)GET_OFFSET(h_sdl2, 0xFCF64);
The link_map
structure is defined in <link.h>
, and it’s the following:
struct link_map {
ElfW(Addr) l_addr; /* Difference between the address in the ELF file and the address in memory */
char* l_name; /* Absolute pathname where object was found */
ElfW(Dyn) * l_ld; /* Dynamic section of the shared object */
struct link_map *l_next, *l_prev; /* Chain of loaded objects */
/* Plus additional fields private to the implementation */
};
For hooking we can just store and replace the pointer. I made a HOOK_SDL
macro
for this:
#define HOOK_SDL(name) \
ho_##name = *name##Ptr; \
*name##Ptr = h_##name;
/* For storing the original function ptr. Note that its not a PollEvent_t* since
* this is a direct pointer to the function */
PollEvent_t ho_PollEvent = NULL;
/* Our hook */
int h_PollEvent(SDL_Event* event);
/* Hook it */
HOOK_SDL(SwapWindow);
We can call the original with the ORIGINAL
macro just like any other VMT hook.
With the new 64-bit update, this is no longer needed, since you can just patch
the jmp
instruction inside SDL_PollEvent
and SDL_GL_SwapWindow
.