About me

I'm Divo, also known as module, an experienced web & software engineer from Germany.
Passionate about C++, reverse engineering, cybersecurity & building scalable, high-performance web platforms.

2 Aug 2025 - 19:40 • written by module • 3965 views

Remote Code Execution in GTA V / CFX (FiveM)

In this post, I will talk about how I found an critical vulnerability in Grand Theft Auto 5, rather said FiveM / CFX.
This exploit allowed a malicious server to execute arbitrary code on connected clients.

What is FiveM / CFX ?

FiveM is a multiplayer modification for Grand Theft Auto V that allows players and developers to create and host custom servers with scripting capabilities. It improves the game by supporting better player synchronization, a wide range of mods, and more customizable gameplay options.

Recently, FiveM / CFX was acquired and officially integrated into Rockstar Games. Today, it has around 200,000 daily active players, making it more popular than GTA: Online itself.

First thought

Users have the ability to code their scripts with in-built GTA V functions, called natives. These natives serves as a wrapper/bridge from scripting language, such as Lua or JS, to the game in C++.

Through my previous research on the game engine RAGE (Rockstar Advanced Game Engine) in several other projects, I already reverse engineered this whole native handling system.

After dumping all natives and their corresponding addresses, I would directly know which native lies where and be able to read their instructions. After digging around through several natives, I came across this specific one:

Pseudocode of Native

Pseudocode of “HUD::SET_FLOATING_HELP_TEXT_STYLE”
This native writes an element to an array, but only if the index is less than 3.

This seems rather limited in functionality, doesn't it?

But what if I used a negative index?
That's where things get interesting - it essentially turns this into a full-blown write-what-where primitive. All I need is to map the right index to the desired memory address.

To calculate that index, I take the target address I want to write to, subtract the base address of the vulnerable buffer, divided by 4 (since each index writes a four-byte chunk), and then subtract 1 - because the index gets incremented internally.

Latex

We're almost there!

With a reliable write-what-where primitive in place, the step was to turn it into arbitrary code execution. I used a classic shellcode that opens the calculator: essentially the Hello World of exploitation.

I didnt bother scanning for executable memory at runtime - instead, I just picked an address I knew was already mapped and executable, and wrote the shellcode there.

To trigger execution, I hijacked the control flow of an existing native function. By overwriting its first instructions with a jmp to my shellcode, any call to that native would now redirect straight into my code.

And what now??

https://www.youtube.com/watch?v=eS4d7RlkYwc

This issue has been responsibly disclosed to the CFX team in accordance with their security reporting guidelines, and it was addressed quickly and transparently.

Cheers.