Why last VAC Anticheat update is useless
A couple of days ago, Valve released a new update for CSGO, that “improve” its already pointless anticheat. And I decided to make a thread about it because it’s stupidly funny.
The article blur
In this article, they detail :
I will analyse this by paragraphs.
So let’s start with the second one, they will “restricts” the types of programs and files that can interact with the game. If you don’t know CSGO, and common programs behaviour, know that some programs that have overlays like Discord, OBS, Nvidia stuff, need to inject DLLs (see my post about hooking functions) to execute code in the CSGO process, for overlay purposes. But a cheat is also about injecting and executing a code in CSGO, so VAC Anticheat has to make the difference between a cheat and a legit software like Discord. And during all it’s existance, there was false positives made by VAC.
The next paragraph explain that now, if VAC detect that you load an incompatible file, it will block you from joining the game and impact your trust factor. This is a good thing, but like I wrote above, if their are false positives, this lead to banning non cheating people.
In the final pargraph, we have an explantation in details about what they actualy block. So all of this is about loaded DLLs of the game. Now legit software will need to “digitally sign” with “Authenticode signature” there DLL to be injected in the game. But this is very blured, because we don’t know what is this signature. It could be 3 things : a real digital signed certificate used in Windows to sign executables. A memory signature of the DLL, or a token in the DLL that “certify” its provider.
Those 3 cases are already bypassable and can lead to problems regarding non cheating users of CSGO.
Check by certificate
In the first case, we can assume that VAC Anticheat will check the integrity of the digital signature certificate. The certificate contain the code signature of the executable, but the certificate check only verify its integrity regarding the executable. So if VAC check the certificate, it doesn’t check the code signature, it check the validity certificate that could be sign with any code signature. And about this, PE file digital signature certificate is easy to bypass (example : https://github.com/secretsquirrel/SigThief), and it will be easy to apply a valid certificate to a cheat.
Check by file signature
The second case is to check the code signature manualy, it’s the more hardest method to bypass without patching the verification system itself, but it’s still highly possible. So it’s the best method in those 3 right ? well not at all, because if it’s the case, the 3 party software provider will have to send its new DLL signature that change at each update. And considering that Valve doesn’t care about CSGO and is not very reactive, this will lead to a lot of false positives if an update is not signed in time. A software provider like Discord will not wait that Valve checks its signature to publish its update for only one game. And, in the utopia where this is the case, the delay of applying this signature to the entire world will lead to false positives if Discord release its update faster then Valve release the signature. Because everytime, there are people playing CSGO no matter the day or the time.
Check by token
The last method is the worst, because a cheat could just copy the code of the legit DLL, and send it to the anticheat like the legit DLL does.
So just by looking at this article, we can see that there is a lot of weird things in their explanations, but before checking this out. I would note that the last sentence says “we will block signed DLL if their functionality interferes with the game in any way”. So even if we bypass the signature check, they will check the injected DLL, which is a good thing, but they already said that in the past, and they are already supposed to do it.
What are they actually doing ?
Well it’s even worst than what I though.
To find a way to start, we can assume that everything is dealing with DLL injections. There is a lot of DLL injection methods, I made a short article about the most common one called LoadLibrary (see : https://whereisr0da.github.io/blog/posts/2019-06-24-function-hooking/).
To summarize, the LoadLibrary method will execute the function LoadLibrary in the target application. And like its name said, this function will load a library (DLL) in the application, and will call its entrypoint to execute the code contained in the DLL.
DLL injections are done by “Injectors” that will handle this task. Legit softwares like Discord use this LoadLibrary method in their Injectors. And in this context, public / bad coded / pasted injectors for internal CSGO cheats are using this method with LoadLibrary, or other functions.
The reality
So considering this, let’s look how VAC handle it. There are a lot of way to block injections like this, but after research, it seems that VAC Anticheat only hook the functions used by LoadLibrary !
To summarize again my article, a hook is the ability to redirect the execution flow of one function to another. For exemple, Discord uses it with its overlay to execute the code that draw the overlay on top of a game (EndScene function in DirectX9 for example). A cheat also use this method to execute its code while CSGO is running.
I will explain later why hooking LoadLibrary is a good and a bad idea at the same time. But for now, let’s just see what they do.
The LoadLibrary function use the function called NtOpenFile (ZwOpenFile) to get the handle of the DLL, and apparently, VAC Anticheat hook this function.When the LoadLibrary function will be called, the execution pointer will jump to Valve code.
This is the code executed by CSGO after the jump.
To explain in short, the function will check if the DLL is signed using the function isDllSigned. If so, the original ZwOpenFile is executed. But this function is incredibly easy to bypass, but I will return to that later.
So the isDllSigned function is too big to be covered in assembly, so I made a pseudocode to show you what is going on.
Here is my pseudo code of this function :
As you can see in my pseudocode, the signature check method is the second one (Manual code signature check).
The result of this function look like this :
Results
And now we start to see the impact of this signature check :
I noticed that there is a signature file named as “foreign.signatures”. We can think that this file could / will contain all the new 3 party DLL signatures. Because currently there is only one DLL from Microsoft in this file.
Note that LoadLibrary is not the only one function that is hook by VAC Anticheat, but the method is the same.
Why it’s useless ?
Because it’s extremely easy to bypass this check, instead of jumping to the original ZwOpenFile if the DLL Module name is NULL. We can patch this to jump everytime without considering the check !
And the injector of a cheat just have to patch one byte to change the jump if zero (JZ) in a jump (JMP). It’s so easy that some crackers bypassed it in 15 minutes after the update !
So it doesn’t take long to know the exploit (POC : https://github.com/danielkrupinski/OneByteLdr)
But even if this was not patchable, remember that there is a lot of injection technics, and LoadLibrary is the most common one used in badly made cheats. All others use Manual Mapping Injections that is less detected by anticheats in general and especially by VAC. And handling Manual Mapping Injections or any kind of memory allocations from another process to CSGO is the thing that Valve should concentrate its efforts on. All internal commercial cheats use this injection method, so this update will maybe erase 1/4 of CSGO cheaters just regarding injection, not regarding the cheat it self.
And this concerned only cheats that are internal (injected code with DLL), external cheats are not conserned by this all.
The CSGO cheating community is very active, and it didn’t took long before everyone update their injectors.
If you want an additional point of view, check out Menalix’s video where he explain that this update will change nothing.
Conclusion
Ok, so I have nothing against fighting cheaters in this game, because the game is totaly unplayable sometimes because of them. I’m a cheat coder myself, to have the ability to cheat against cheaters ingame, but think that cheating is not fair.
And about this, like in all the project regarding CSGO, Valve don’t give a **** about improving the game. Because of Valoran, CSGO devs implemented a lot of new things comming from this game. And considering that Valoran has its own Kernel Level Anticheat, this update could be a little attempt to show to the CSGO community that they “care” about cheaters. And would erase the hug count of cheater from the game now because of Valoran (but we have been waiting that since years…).
Like they said, it’s a new beta branch of CSGO Steam repo, so we will probably see new improvements in the next months regarding this.
I would like to point that they should make a real security, instead of making one that erase a little part of cheats, and annoy a big part of the normal players.
To conclude this, I will just show how people will see this update.