After a pretty long time of inactivity I decided to give you guys a short and interesting insight in my current project: It’s a simple CS:GO Hack, which I implemented both, externally and internally. Beforehand you should know, that I will not provide my code to you, but an overview of how I got things done. I didn’t do much with kernel mode drivers yet, that’s why I will only write about the more interesting internal hack itself. This article will help rookies and also advanced game hackers, extending their knowledge. If you are looking for a tutorial you should rather look here: unkonwcheats.com
The internal hack looks pretty much like the external (who would have thought that?) with one major difference: There is no overlay window, so it can be run in fullscreen mode yae! This hack is derived from on an old GDI hack. A few lines in the section of data grabbing is the same as before, but all other stuff is different. But never mind, lets go!
Related Books I can recommend:
Some things are easier when programming internal, that’s why I dropped a bunch of functions from the external hack, got rid of this ReadProcessMemory crap and dereferenced all my pointers without a process handle because it is injected code, thats runs in a thread created by the CS:GO Process itself! What a kind present from Lord Gaben, that this is possible without any ring0 driver or thread hijacking! Welcome to the commercial world of Valve Anti Cheat! 🙂
The data I used for my Hack are basically player coordinates, the view matrix, the bone matrix, crosshair-id and the dormant-flag. (Nice to know: dormant-flag is only set, when enemy data is transmitted. That’s a nice help to avoid a frozen ESP-Box!).
Some thoughts regarding view matrices
When I think back to 2016: I understood literally nothing about projection and view matrices. But after all it’s basically not that difficult to understand. The only thing we do is to calculate a projection from 3-dimensional to 2-dimensional “coordinates” (actually vector spaces) in relation to the camera perspective. We are so lucky that the source engine already provides us the viewmatrix, so that we don’t need to build our own. But only multiplying a matrix with a vector is not fun, isn’t it? You should take a look over here . It’s a nice article about camera- and view matrices, helped me to understand what I’m actually doing. In some games (like PUBG i think) there is no viewmatrix like in source engine games. But in PUBG e.g. there is a vector called “Point Of View Rotation”, which is used to build a viewmatrix (chapter “FPS Camera”, link above) depending on pitch, yaw, roll and FOV (eye-position). I will definitely try this out in another game, but not yet I guess. Since we got a ready-to-use view matrix, we can just perform the matrix multiplication with a world coordinate-vector and get our results.
GDI was an easy and straight-forward introduction to just “paint on something”. It is easy to paint simple, primitive shapes like lines and squares and stuff. To paint on an overlay it seems to be perfect, but there are several drawbacks. The heaviest one imo is the god-damn flickering. I’m sure that anyone who already has experience in external hacking knows what I’m talking about. On higher frame rates the whole painted overlay starts to flick and that’s ugly as hell! Another disadvantage is, that GDI is useless if you are internal! So i decided to upgrade my overlay to D3D instead of GDI. No flickering, high performance and many ,many opportunities! It made the move from external to internal quite a bit easier.
What does my hack do?
- ESP and Bones
- Miscellaneous enemy information
Who would have thought that after looking at the picture above? 😀 It’s always the same and meanwhile this is no more that interesting to me. And why no aimbot? Because it was difficult for me to emulate human mouse behavior from scratch. And everything besides looks like artificial movement, which can be easily detected, either by a experienced player or several anti cheats (like FACEIT AC) . Here is a very quick overview:
It’s a box (yes, made out of 4 lines) which covers the enemy. It’s the classic wallhack and a must-have! The bones are just some selected vertices connected to each other. Info
Triggerbot. Pew, Pew.
The most important information for me personally are the player-name and -health. That’s why there is no other information disguised by my hack. Any additional information creates confusion and I wanted to keep it flat. That’s why I made a bar (green for full, yellow for medium, red for low HP) for the health, to avoid using my brain, which causes increased throughput time. 🙂
If the cross hair hits the model of an enemy, it gets ‘locked’ on the head.
The key to an internal hack is to inject code to a victim process and force the victim to execute it. There are many different ways to inject and to execute.
What we create and inject is a DLL, because of the method that we use later to execute our code. A DLL gets dynamically loaded by the OS and mapped in the process’ memory. After that, the DLL gets an entry in the Process Environment Block (PEB). This is what happens when you call LoadLibrary in your own application. But we want our victim process to execute LoadLibrary with our malicious DLL as parameter. There are several ways to map code into a process, but I covered the imo easiest one. So what I exactly do is to obtain a process handle to the victim process, allocate memory and safe the absolute path of my DLL (ANSI) in this space. The next thing is to figure out the address of the LoadLibraryA (use LoadLibraryEx when path is unicode). Its located in kernel32.dll and much thanks to the windows environment: The kernel32.dll base address is equal for every process. 🙂 Because of that it’s possible to execute GetModuleHandleA in your own injector process and voilá! Go for GetProcAddress and execute a remote thread via CreateRemoteThread with the address of your path: DLL injected!
(MSDN: To handle stuff depending on call reason watch “fdwReason“)
Hiding the Injection
Like I said above, the DLL is mapped into the process-memory and an gets entry in the PEB. It follows, that the process/application just need to iterate through this PEB to know which modules are loaded. We can easily patch that, because the PEB is a linked list. Steps to do:
- Iterate through the PEB and find the entry for the injected module.
- Let the previous entry point to the next one.
Sounds pretty easy, but it’s tricky. The Windows function NtQueryInformationProcess helps us to get the PEB pointer. The function is located in ntdll.dll, but it’s not available via libraries which means, that it must be called by a function pointer. It’s a stdcall pointer with the respective function arguments. Get the address of the function via GetProcAddress and call it like so:
(funcPointer)(processHandle, ProcessBasicInformation, &processInfo, sizeof(processInfo), &size);
The ProcessInfo-structure delivers the PEB Pointer which has to get read out and put into a PEB structure. We are interested in the loadermodule of the PEB, in which we now iterate through the InMemoryOrderModuleList, InInitializationOrderModuleList,InLoadOrderModuleList and HashTableEntry to capture all module entries. To get e.g. the name of the module, each flink/blink (next/previous) ListEntry we need to cast each of them to (unofficial) LDR_MODULE structure, which need to get self defined (more info here). The List is completely iterated, when the last element of the list points to the first. Now just hide the entry:
listEntry->Blink->Flink = listEntry->Flink;
listEntry->Flink->Blink = listEntry->Blink;
And you’re done! 🙂
There are easier ways to detect an injected DLL. Because of that we will make it more difficult to locate our sections with PE-Header erasing. A DLL is a portable executable File (PE), which contains a header, where among other information such as sizes and versions, relative addresses for import and export tables are located. We will delete those references to aggravate the reversing of our DLL. Here is an example code to do this.
There is another method I didn’t test, but the community prefers it: the manual mapping. Due to anti cheat systems already operate on kernel mode (imagine that impact in privacy!) they can easily hook any winapi function. That’s why it’s not that smart using a LoadLibrary injector, am I right? Here does the manual mapping come into the game: roughly said, it allocates memory and does similar procedures like the LoadLibrary without entries in the PEB and only with the minimal necessary data (could be only text-section with necessary meta data e.g.). Combined with signed kernel mode drivers or handle hijacking it’s a pretty stealth method.
What is a Hook?
Imagine an arbitrary assembly. Cut an amount of instructions which size corresponds to the size of “jmp”. Insert a jmp to your code where you cut the instructions, paste the instructions at the top of your code, push the required registers, execute your code, pop the registers and return.
Its not hard to write a hook, but Microsoft provides us a nice tool to manage these: detours. It’s worth to check it out!
In case of D3D-hooking it’s possible to do it in another way: the vtable hook. We will abuse the functionality of the virtual table of a (base-)class. The procedure works like this: find the vtable of the D3D device, get and store the the pointer to the respective function from vtable, create a new vtable with same length, create a function that should be called and overwrite the respective entry with a pointer to your function. In your function: call the function from the old vtable which you stored before. The result is, that every time the function X is called, your function will be called.
Why do I need a hook?
When you want to draw something with a D3D-device, you always have to call the function EndScene in the end to Render the frame. Imagine you have injected your dll, found the D3D-device and want to draw a line. Your thread runs asynchronous, that’s why you don’t know when a frame gets rendered. Try to call EndScene and DirectX will throw an exception (or crashs when you didn’t attach a debugger) because there will be the point, where you can’t call it, because the device is “in the wrong state” (as far as I understood). What you gonna do? You have to find out when a frame should be rendered. And thats where the EndScene hook comes into the game! Like I said above this function gets called when a frame should be rendered. So hook it, execute your drawing code and call the original EndScene! Pretty easy, isn’t it? Google “EndScene hook” and you will find lots of example code. This vtable-pointer-switching-method is kind of more “stealth” than changing code directly in the respective function, but already detected by several anti cheat systems.
Note: When you want to run in full screen mode and minimize the game, you should hook the Reset function and call OnLostDevice for all your fonts and lines. Otherwise the game will have a black screen.
How to get the D3D Device?
A question which took a long time for me to answer. There were a few ways to find it out. I decided to do it with signature scanning. Some smart hackers from unknowncheats reversed and found a generic occurrence of the device. It’s located in shaderapidx9.dll and can be found with the signature “A1 ? ? ? ? 50 8B 08 FF 51 0C“. An example with a function that searches for signatures:
d3ddevice = (IDirect3DDevice9*)(**(uint32_t**)(SigScan((“shaderapidx9.dll“), (“A1 ? ? ? ? 50 8B 08 FF 51 0C“)) + 1));
As you can see, the SigScan only finds a double pointer to the device, which has to get casted and then dereferenced. Definitely an interesting topic for future hacks!
If I knew these things earlier, I would have saved a lot of time. That’s why I’m offering this to you. I spent months and years to more or less completely understand what I was doing. No code, no tutorial – only some knowledge! imo is the tutorial I linked in the introduction is very well made and totally worth it to read (especially for noobs).
I don’t use my hacks to play online. I only develop them, because this topic contains lots of interesting stuff like reverse engineering, operating systems, low level programming, etc. and the connection to one of my favorite games makes it stay interesting. Be fair to others and don’t cheat online!
Please leave a comment, if you have questions or want to have some code!