Hacking in Among Us

James Sebree
Tenable TechBlog
Published in
12 min readNov 17, 2020

--

Cute, clumsy jelly bean shaped characters are one of the latest crazes to sweep the internet. Whether you’re a fan of the games or not, you’ve undoubtedly heard of Fall Guys and Among Us. Other than being exceptionally good at ruining friendships, these two games have provided immense volumes of entertainment over these last few months but have fallen victim to pretty incredible amounts of cheating. In this post, I discuss some of the recent trends regarding cheating in popular video games and their prevalence in recent titles, with Among Us used as a technical example later on in the piece.

TL;DR

While I’ve done my best to keep this post fairly short and to the point, here’s a quick summary for those that wanna get straight to the action:

  • Full technical details on how Among Us cheats work can be found in the final section of the blog.
  • Other than flaws affecting gameplay or creating denial-of-service-like conditions, I did not discover any major security flaws with Among Us that would have a direct impact on end-users outside the context of the game.
  • Expect things to get worse before they get better. With better tooling and resources available these days, a huge rise in the popularity of games developed by smaller studios and teams is expected. We can expect a surge in cheating due to lack of common protections seen in games developed by AAA publishers or teams with significantly greater resources.

Recent Prevalence of Cheating

Fall Guys was an instant hit when it launched. After a couple of weeks, however, it became apparent that hacking was a huge problem for the game. Users on Reddit, Twitter, and other platforms were constantly complaining about how many cheaters there were, and there was no shortage of video evidence. A few examples include:

Flying and ruining the game for everyone | Source: https://www.reddit.com/r/FallGuysGame/comments/imzbnc/so_this_guy_cheated_and_made_the_seasaw_unusable/
Going just a littttttle faster… | Source: https://www.reddit.com/r/FallGuysGame/comments/imi6ue/cheater_trying_to_hide_his_cheats_going_just_a/
Literally every player in the final round of a match teleporting to the end | Source: https://www.reddit.com/r/FallGuysGame/comments/ipmxjn/ever_played_a_round_of_fall_mountain_where_all/

Cheating, of course, isn’t anything new, but it’s rarely bad enough to warrant massive outcries from players and fans of a game as we’ve seen with Fall Guys. Why is the cheating in Fall Guys so egregious? Well, that’s not something easy to answer objectively, but I personally think it’s due to two major factors:

  1. Tools and resources for developing and publishing high quality and accessible games have never been better — especially for small, independent studios and teams of developers.
  2. The teams/individuals behind these popular titles often lack the resources — time, money, experience, etc. — of games backed by larger entities and are often forced to prioritize new content over unseen features, such as anti-cheat measures.

For Fall Guys, the outcry was loud enough that the developers felt it was necessary to issue public responses. Their initial response was to speak to the anti-cheat efforts already present in the game. A twitter thread detailing this response can be found here: https://twitter.com/FallGuysGame/status/1305486780851007489. Unfortunately, these efforts proved to be insufficient.

There’s always a trade-off to these things. If the game weren’t so massively popular, the original protections probably would have sufficed — and been absolutely hilarious (the entire concept of a cheater island is amazing). Sure, hacks would have happened and cheaters would have had their fun, but they wouldn’t have had as major an impact as they do now that this game is a massive hit.

That said, the developers took a step back, evaluated their options, and opted to license and implement an anti-cheat engine developed by a large scale firm (EPIC Games), which is seen in many many other games (https://www.easy.ac/en-us/partners/).

Fall Guys is not the only game to experience these sorts of flaws. It’s simply the most recent in a long line of games developed without strict security or anti-cheat measures taken into account from day one, which, as already mentioned, isn’t necessarily a bad thing. Here are a few resources on other recent video game flaws. Each of the following videos represents a talk given at the yearly DEF CON hacking conference, and there are many additional resources available if you wish to seek them out:

  • In 2020, Jack Baker discussed a number of flaws in Unity and Unreal Engine. These are currently two of the most popular game development engines available today. Fall Guys and Among Us were both developed with Unity. (https://www.youtube.com/watch?v=4weoWSzuCxs)
  • At DEF CON 25, Manfred spoke about his history of hacking various MMOs over the last 20 or so years. Basically, the games have gotten more elaborate, but the hacks have remained the same. (https://www.youtube.com/watch?v=ZAUf_ygqsDo)
  • At DEF CON 23, Tamas talked about gaining remote code execution against other players via custom maps in games such as DotA 2 and Garry’s Mod. (https://www.youtube.com/watch?v=XxyRDkmNMHg)

Cheating in Among Us

This brings us to Among Us. While the game has been out for a couple of years, it saw a massive spike in popularity when highly viewed Twitch streamers began playing. It’s become so popular, in fact, that even Congresswoman AOC made an appearance on Twitch to hold a “Get out the vote” event while playing: https://www.theverge.com/2020/10/20/21526164/aoc-among-us-twitch-debut-top-concurrent-viewers.

After putting entirely too many hours into this game with friends, I was curious how it worked and if it was possible to mod the game at all (add custom maps, increase player count, modify certain settings, etc.). I’d gone in assuming it would lack many security measures designed to thwart any unofficial modding… but I was shocked at how trivial it would be to actually cheat at the game.

Throughout my own research and the hours poured into the game, I’ve come across many cheats. From players spamming political messages (https://kotaku.com/mass-among-us-hack-forces-players-to-advertise-hackers-1845464612) or mass advertising youtube channels, to those simply out to ruin the fun for everyone else, it became clear that cheating has ramped up for this game as it has increased in popularity just as it has for so many others.

Of the cheats I’ve witnessed, researched, or developed, here are some of the highlights:

  • Revealing imposters
  • Impersonating other players
  • Sending chat messages on behalf of other players
  • Changing the color of your own or other players’ characters
  • Changing player names
  • Walking through walls
  • Removing fog of war (character vision distance)
  • Killing imposters
  • Killing players when you’re not the imposter
  • Removing cooldowns for tasks, kills, calling meetings, etc.
  • Controlling other players
  • Kicking or banning players even when you’re not the host
  • Invading private lobbies
  • Accessing paid content without paying for it (such as DLC pets, hats, and other cosmetic items)
  • Reviving yourself or other players
  • Increasing character speed
  • Teleporting yourself and others
  • Removing player bans (if you’re kicked out of a game, you can remove the ban yourself and rejoin)
  • Marking tasks as complete without actually doing them
  • And so much more…

How is any of this possible? Well, as far as I can tell, there is a total lack of server-side validation for player actions and interactions. This means that by manipulating the game client, players are able to modify certain values that affect other players. While there are mechanisms that could be used to thwart many of these cheats (such as validating that player and client IDs match up when communicating with the server), they simply aren’t in place.

As evidenced in the screenshots below, there does appear to be some very rudimentary anti-cheat implemented, but it only appears to be triggered when certain server-side limitations or checks are hit. In both of the instances below, I was in a private game and attempting to change my character’s name to extend beyond the default character limit (in some cases, this would actually crash the game for some, if not all, other players).

Before I dig into the exact technical details here, I’d like to first state a couple of things:

  1. This is not at all intended to slam or speak ill of the developers. It’s an absolutely fantastic game. It’s also developed by a company that only has three employees and only one of them is a developer. We can only expect so much.
  2. My research into these capabilities concluded in mid-October, 2020. I have not revisited any of these capabilities since then. I cannot comment on further security enhancements that may have taken place or been pushed out between then and now.
  3. As mentioned earlier in this post, I did not find any security-related issues beyond denial-of-service-like flaws throughout the course of this research. We did attempt to contact Innersloth but never received a response. Based on their social media presence, it appears that they are fully aware of many of these issues and are hard at work to push out solutions.

Dissecting Among Us

Finally, let’s get into the technical details of how hackers are able to develop these cheats. Among Us was developed using the Unity gaming engine. This is evidenced by the files present in the directory that houses the game’s data:

Unity-related files present in game directory

Luckily for us, Unity makes life easy for inspecting gameplay logic. It allows developers to use a variety of programming languages to develop their games. One of the most common choices is C#. In many games that are simply developed and deployed for Windows, inspecting this code is absurdly easy.

Let’s use another currently popular game, In Silence, as an example here. When compiling the game for distribution, Unity will place all custom gameplay logic into a single dedicated DLL. This is usually called something along the lines of Assembly-CSharp.dll, but may vary from game to game. By using tools like dotPeek or dnSpy, which are dedicated to decompiling .Net binaries and inspecting IL code, we can see exactly how the game functions. These tools also allow us to modify code and make changes to the game as we please. If there aren’t protections in place to verify that a game client hasn’t been tampered with server-side, players are free to use their own modified clients, which can contain their own custom cheats, in order to play the game.

In Silence environment interfaces
Modifying the In Silence game logic

For Among Us, this process is a bit less trivial since the game is also distributed for mobile devices. To accomplish this cross-platform support, Unity uses something called IL2CPP (https://docs.unity3d.com/Manual/IL2CPP.html). This makes the code a bit more cumbersome to work with. That said, there are tools out there to mitigate this headache. For example, IL2cppdumper will do most of the heavy lifting for us.

The output from this tool gives us everything we need to open the game dlls up with dnSpy as in the example with In Silence above. The main caveat here is that the game logic itself is largely incomplete. This means we need to resort to more traditional methods of reverse engineering by using Ghidra or another similar tool. Luckily, IL2CPPdumper helps us by creating a script that will rename and fix up the disassembly for us.

From here, we have a couple of options. Knowing that there isn’t any real anti-cheat functionality to detect client tampering, we could modify the game client itself. That generally isn’t a great tactic, however, because whenever the developers push out patches or updates to the game, your custom client may cease to work. The next best option, in my opinion, is to create a malicious DLL that hooks the game logic you want to manipulate. This not only makes the cheats more portable, but also makes them a bit more resilient.

While I’m not going to go into details on how to perform DLL injection in this post, the following can be used as a template to create your own custom DLL for use with the game.

First we’ll fire up Visual Studio or whatever development environment you’re comfortable with and create a new project that will build a dynamic library. Next, we’ll add some boilerplate code that will confirm DLL injection is working as expected.

#include "pch.h"
#include <stdio.h>
void insertConsole()
{
// Spawn the console
AllocConsole();
// Set up the console for logging output and accepting input
FILE* f = new FILE();
freopen_s(&f, "CONOUT$", "w", stdout);
freopen_s(&f, "CONIN$", "r", stdin);
printf("[*] Injected...\n");
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hModule);
// Spawn a new thread for our console/cheats when we attach to the process
HANDLE hThread = CreateThread(nullptr, 0,
(LPTHREAD_START_ROUTINE)insertConsole, hModule, 0, 0);
if (hThread != nullptr)
CloseHandle(hThread);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Verifying that our library pops a console as expected

At this point, it’s just a matter of creating references to the game’s libraries and coding the functionality we want to add by using our decompilation and disassembly as a guide on where game functionality is located. As an example, let’s modify our character’s speed.

First, poke around dnSpy a bit to see if anything obviously related to player speed pops out at you.

Searching for player speed values

Next, reference these offsets in the cheat library. If you’d like the cheat to persist across patches, you could create signatures for the relevant functions, but that won’t be discussed here. In most cases, there will be a decent amount of messy dereferencing due to nested properties. There are plenty of code snippets and libraries online to help with this, but for these examples, I’ll do everything the quick and dirty way. Please note that the code presented and offsets in the screenshots may differ slightly due to being taken at different times.

void commandLoop()
{
// Create a reference to the library we plan on using
auto hLib = LoadLibraryA("GameAssembly.dll");
printf("[*] GameAssembly.dll located at: %x\n", hLib);
// Working backwards from the speed variable found in dnSpy,
// create references to all the necessary pieces to the puzzle
uintptr_t* player_typeinfo = (uintptr_t*)((uintptr_t)hLib + 0x1468910);
printf("[*] Player TypeInfo located at: %x\n", player_typeinfo);
uintptr_t* physics = (uintptr_t*)(*player_typeinfo + 0x5c);
printf("[*] Player Physics located at: %x\n", physics);
uintptr_t* properties = (uintptr_t*)(*physics + 4);uintptr_t* speed = (uintptr_t*)(*stuff + 0x14);
printf("[*] Speed located at: %x\n", speed);
// Get command inputs from the user
int command = 0;
while (true)
{
command = 0;
printf("Available commands:\n 1 - change speed\n\n");
printf("Enter a command: ");
cin >> command;
if (command != 0)
{
switch (command)
{
case 1: // Change speed
{
printf("Your current speed is: %f\n", *(float*)speed);
int new_speed;
printf("Enter new speed: ");
scanf("%d", &new_speed);
// We know from dnSpy that this variable is a float. Make it so.
*(float*)speed = (float)new_speed;
break;
}
default:
printf("Invalid command\n");
break;
}
}
}
}
}
void insertConsole()
{
AllocConsole();
FILE* f = new FILE();
freopen_s(&f, "CONOUT$", "w", stdout);
freopen_s(&f, "CONIN$", "r", stdin);
printf("[*] Injected...\n");
commandLoop();
}

Finally, run the game, inject the library, and watch the cheat in action.

Speedy speedy

Now let’s try something a bit more elaborate. Let’s try changing our character’s color.

 ...
// Again, work backwards from function calls to get the information needed
uintptr_t* gamedata = (uintptr_t*)((uintptr_t)hLib + 0x1468864);
uintptr_t* gamedataSession_ptr = (uintptr_t*)((uintptr_t)*gamedata + 0x5c);
uintptr_t* gamedataSession = (uintptr_t*)*gamedataSession_ptr;
// Create references to the functions needed
uintptr_t* (*getPlayerByID)(uintptr_t, char) = (uintptr_t * (*)(uintptr_t, char))((uintptr_t)hLib + 0xB027B0);
uintptr_t* (__cdecl * rpcSetColor)(uintptr_t * player, char color) = (uintptr_t * (__cdecl*)(uintptr_t*, char))((uintptr_t)hLib + 0x88AFA0);
int command = 0;
while (true)
{
command = 0;
printf("Available commands:\n 1 - change speed\n 2 - send chat\n 3 - set name\n\n");
printf("Enter a command: ");
cin >> command;
if (command != 0)
{
switch (command)
{
case 1: // Change speed
{
...
}
case 2: // Change color
{
uintptr_t* player;
// Using a player ID of 0 for demo purposes
player = getPlayerByID(*gamedataSession, 0);
player = (uintptr_t*)((uintptr_t)player + 0x2c);
int color;
printf("Enter new color: ");
wcin >> color;
rpcSetColor((uintptr_t*)*player, (char)color);
break;
}
default:
printf("Invalid command\n");
break;
}
}
}
}
Demo of color changing

Now I understand that a good amount of details are missing from this piece and a few explanations have been oversimplified, but that is intentional to keep this post short. Hopefully I’ve been able to demonstrate how trivial it is to hack or cheat in many modern games that ship without many of the protections we’ve become accustomed to over the years. With increased visibility to these issues, though, my hope is that many of the popular engines targeted to smaller dev teams will begin providing functionality to prevent many of these sorts of cheats in the future.

Removing wall collisions and walking around outside the map
Forcing another player to call a meeting and forcing all other players to vote them off the ship

--

--