Tech News
← Back to articles

In-depth analysis on Valorant's Guarded Regions

read original related products more articles

This post is not meant to be an attack towards Riot Games’ Vanguard or Microsoft’s Windows, they have done an excellent job with their products and will continue to do so for the coming years, the content of this post is gathered solely by me, and I am not tied to any game hack publisher or entities. I have no intention of harming any company’s product, and everything here is constructed for educational purposes.

In the cutthroat world of online gaming, there is no greater threat to the sanctity of competition than cheating. From sophisticated aimbots to cunning wallhacks, cheaters have employed every trick in the book to gain an unfair advantage over their rivals. As a result, game developers are constantly pushing the boundaries of innovation to stay one step ahead of these nefarious tactics.

Enter Vanguard - Riot Games’ revolutionary anti-cheat system designed specifically for their popular tactical shooter, Valorant. In this article, we’ll delve into the intricacies of how Vanguard operates by analyzing its guarded regions. By gaining a deeper understanding of how this cutting-edge technology safeguards the gameplay experience in Valorant, players can truly appreciate the level of dedication and meticulousness that goes into ensuring fair play and balanced competition. Are you ready to discover the secrets behind Vanguard’s fortress?

The problem⌗

A game’s anti-cheat measures must take innovative measures in order to eliminate cheaters. The Vanguard team has deployed a very smart and innovative technique to protect game variables from being accessed outside of the game. As any cheater might tell you, VALORANT is a particularly challenging game to deal with due to its interference with cheating necessities like reading memory, while maintaining the integral aspect of low performance overhead. Any partial attempt to circumvent such mechanisms is typically met with an unavoidable system page fault. Most often than not, this spurs the confusion of cheaters leading to trivial and ineffective second-guessing of code.

Reversing the logic⌗

As someone who has delved into analyzing Vanguard, I had devised a plan to create a semi-emulator that could bypass many of its detection mechanisms. During my research, I came across an interesting Input/Output Control (IOCTL) command that was being sent from the game to Vanguard. At first, I assumed that it was an initialization command meant to inform Vanguard of the game’s presence. However, upon further investigation, I discovered that the command was actually directed to a large and complex function in stub.dll , which is the packer component of VALORANT. This module is responsible for protecting the game from potential threats by utilizing a variety of techniques, including binary encryption and more. As I studied the function, it became clear to me just how formidable Vanguard’s defenses truly were. It was a humbling experience to see firsthand the level of sophistication and complexity that had gone into protecting the game from cheaters. The function responsible for hiding memory looked like the following:

NOTE: This code is heavily edited and stripped to be readable.

uint64_t * InputBuffer = ( uint64_t * )malloc( 8 ); // Allocate 8 bytes for the input buffer. * InputBuffer = __rdtsc(); // Write the TSC timestamp to the allocated input buffer. // Input Buffer encryption block removed. uint64_t * OutputBuffer = ( uint64_t * )malloc( 16 ); // Allocate 16 bytes for the output buffer. memset(OutputBuffer, 0 , 16 ); // Nullify the output buffer memory allocation. // Call DeviceIoControl to request the shadow base from vgk, and also check if it // failed, and if so, free the allocations and return a failure code. if ( ! DeviceIoControl(Data :: VgkHandle, [REDACTED], InputBuffer, 8 , OutputBuffer, 16 , & BytesReturned, 0 ) || BytesReturned != 16 ) { free(InputBuffer); free(OutputBuffer); return EPackmanStatus :: VanguardFailure; } // Output Buffer decryption block removed. // Write the shadow base retrieved from vgk to the 2nd argument passed to the function. * Arg2_pShadowBase = OutputBuffer[ 1 ]; // Free the allocations previously created. free(InputBuffer); free(OutputBuffer); return EPackmanStatus :: Success;

After analyzing this, I became interested to see what exactly was being sent to stub.dll by VGK. So, I dumped the output buffer and proceeded to decrypt it, which led me to obtain this: 17 96 75 76 3E 29 00 00 00 00 00 00 80 00 00 00 . We can format it further so we don’t just look at some random hex gibberish.

... continue reading