macOS Csgo Internal Hack partI

Overviews

  • Inject a dylib to csgo_osx64
  • Get the interface and method’s address
  • Hook method
  • Build up the project

PartI, Injection and Read module handle and method address

  To build a internal hack, we simply inject a Dynamic Link Library to the gaming process. Start a new Thread, and gather the information we care, and do something.
  In this part of the article, we start with the topic of Injection, which is a very normal task in windows and linux, luckily, there are few wheel we can use in macOS:

First step: Build the project

  Let us start with the project the second repo mention last section, and copy the third’s repo’s testdylib’s code to replace the second one. so now we get the project. however as valve currently update cogs to 64bit, we need to set 4 project to x86_64 in project setting. after this, our project look like this: there should be a image

1
2
3
4
5
// the code in install will run after the dylib's injection
void install()
{
printf("loaded\n!");
}

Get the module address and Find CreateInterface:

  In windows we have GetModuleHandle(may be wrong..)to get the handle of a dll. in macOS, we have the dlopen from dlfcn.h and apple provide detailed docs:

1
2
3
4
5
auto address_of_engine = dlopen("client.dylib", RTLD_NOW);
if (!address_of_engine){
printf("Unable to read the address of client.dylib: %s\n", dlerror());
exit(0)
}

  if the dylib has been added into the process’s scope, what is the situation what we meets here, the method will return the handle(address of the dylib in the memory).
  After we get the address of the module, we start to ask where is CreateInterface which is the function to get the interface(like entity_list, engine_trace) which module expose to the extern.
use the dlsym to the the address:

1
2
3
4
5
6
7
8
// define the CreateInterface first
typedef void* (*CreateInterface)(const char*, int *);
// next call method dlsym
auto clintFactory = (CreateInterface)dlsym(address_of_engine, "CreateInterface");
if (!address_of_create_interface){
printf("Unable to read the address of CreateInterface: %s\n", dlerror());
}

Use *Factory to get the Interface:

  After we get the ClientFactory and EngineFactory we have to get the useful object we need when making a hack. like this

auto entity_list = (IClientEntityList *)clientFactory(“VClientEntityList003", nil);

After doing this, we get the basic to making a Internal Hack.