How to get caught by Fallout’s anti-cheat

You probably aren’t hacking Fallout 76 because you probably aren’t playing it at all.  But if the new Battle Royale seems attractive to you here are a few easy and simple ways to get caught by their anti-cheat.


What it does:

Looks for windows with titles that contain ‘bad word’ substrings

How it does it:

download (1)

Each of the three primary anti-cheat scans are implemented as IOTasks, created, dispatched, and destructed with each iteration of the anti-cheat scanning loop.  The EnumWindowsTask is the first.  The scan is started by IOManager::ExecuteIOTask, which looks something like this:

download (2)

On line 12 you can see the indirect call to the EnumWindowsTask object that leads to the actual scan.  That indirect call lands in a function that calls EnumWindow with the scanning callback


The scanning callback gets the Window Text and converts it to ASCII from widechar.  Then, it does some string encoding.  Yeah encoding, not decoding.

download (3)

I know it looks weird, IDA didn’t quite realize that those long ass constants are actually pointers.

download (4)

So the usual suspects – Cheat Engine, IDA, and I think Spiro’s memory hacking thing.  Which is kind of weird to see in 2019 but whatever.

But you might be asking yourself, “Why are they encoding the strings they’re searching for?”.  Well, they’re encoding them so that they can turn around and *decode* them.

download (5)

Get used to this, it happens a lot in the Fallout76 anti-cheat.  It *appears* that they meant to store the offending string in an encoded form and decode it at runtime, but they’ve botched it.  Instead, the strings are stored in the clear, encoded, then decoded for comparison.

Each decoded string is passed through a case insensitive strstr against the title of the window that’s been passed by the EnumWindow function.  If there’s a match, a variable is set that is used later in the function to mark you as a dirty, filthy cheater.

Also, some of the strings are built on the stack instead of going through the encoding/decoding stuff.  So on top of the previous verboten window titles, you can also get flagged for “IDA – ” (the IDA window title if you’ve got a project active), WInDbg, x64dbg, and x96dbg (which is a launcher for x32dbg/x64dbg, I think).

download (6)

If you’re lucky enough to get detected by the galaxy brains at Bethesda who don’t realize people use debuggers and IDA as part of their jobs and might accidentally leave one open when launching Fallout, you’ll get marked as a cheater.  Each bad window title has its own value that’s added to the cheater flag.

download (7)


What it does:

Looks for debuggers

How it does it:

EnumToolsTask is created and dispatched in the same way as the EnumWindowsTask.  The scanning function is mostly nothing out of the ordinary – it checks IsDebuggerPresent, CheckRemoteDebuggerPresent, and calls OutputDebugString and checks GetLastError.  If a debugger is attached the error code shouldn’t change during the call to OutputDebugString.  But if there’s no debugger, the error code will be changed. At least, according to this blog from 2008  It makes sense to me but I actually couldn’t get it to work in a test application, the error code didn’t change without a debugger attached.  So who knows, I’m a boomer that’s not good with computers so I probably botched it.

download (8)


What it does:

Enumerates modules in the game process and executable names of other processes and checks their names against a whitelist and blacklist of substrings

How it does it:

EnumLibrariesTask is started the same way as the other two.  It starts off with a call to CreateToolhelp32Snapshot with flag TH32CS_SNAPPROCESS, so we have an idea of what it’s going to be doing.

download (9)

String Obfuscation

This particular scan makes heavy use of string obfuscation.  One of the first things you’ll encounter in the function is a bunch of strange values being dumped onto the stack

download (13)

Followed by a routine that manipulates them and then runs strstr on the manipulated value

download (14)

It’s obvious that the garbage values on the stack are actually encoded strings.  If you try to decode the first value, 0xEB79CC25 and XOR it with the key, 0x64, you’ll get junk instead of valid ASCII.  The Fallout devs cleverly only use the least significant byte of each 4 byte wide value as a character in the string.  So take the least significant byte of each of these values and XOR them against the key to get the decoded string.  In this case, “Cheat Engine.exe“.

download (15)

Yes, I once wrote a GUI tool to do XOR encoding/decoding.  I’m a Windoze user and I don’t know how to use the terminal.

Naughty Executables

I glossed over what the string is compared against.  The snapshot handle is passed into the function getProcessInfo which calls Process32First (don’t worry, there’s another function that calls Process32Next) and fills out a structure with process information, to include the .exe file name of the process’ main module.

download (16)

download (17)

The .exe file name is what the decoded string in the previous example is being compared against.  So FO76 enumerates processes and checks that none of them are Cheat Engine.  And if one of them IS…well you know what happens.

The next two obfuscated strings are “cheatengine-i386.exe” and “cheatengine-x86_64.exe“.  After our obfuscated strings,  we have a few strings in clear text – “x64dbg.exe“, “MHS.exe“, “IDA.exe“, and “windbg.exe“.  The same software that the window scan was trying to detect above.  If one of these executables is found to be running on your system, you get flagged.

download (18)

Whitelisted Libraries

Uh oh

download (19)

CreateToolhelp32Snapshot called with TH32CS_SNAPMODULE.  I think you all know what’s going to happen next.  At least, I *thought* I knew what was going to happen next – I expected FO76 to enumerate modules in the current process and flag for any blacklisted module.  And that’s what we encounter to begin with.  Obfuscated strings start us out here, as before.  The first encoded string is “speedhack-x86_64.dll“, a dll injected by Cheat Engine to achieve its speedhack functionality.

download (20)

The next obfuscated string is “speedhack-i386.dll“, the same thing but 32 bit.  If either of these modules is found in the FO76 process, you’re flagged as a cheater.

download (21)

But that’s the end of the DLL blacklist.  Only two entries?  Well, what we see next are names of modules that are probably not from cheating software.

download (22)

The modulepath is strstr’d against these plaintext strings – “ntdll“, “KERNEL32“, etc. and if it is NOT a match, FO76 keeps comparing against more and more benign modules.  As we fall through this search we see a few obfuscated strings –

download (23)

Here we see “vivoxsdk_x64“, which is a VOIP library for games or something.  As we go down (and we go down for a looooong time) we notice a trend – short strings are stored as literals in the module, VERY short strings are built on the stack, and longer strings are obfuscated.

When we get waaaaaaaaaaay down there to the last few module names, they fall into a new category – the string literal is passed into a function that encodes the string, and the result of that is passed into a function that both decodes the string and runs strstr against it.  What I think is happening is the optimizer has pretty much ruined Bethesda’s attempt at obfuscating the strings their anti-cheat uses and, for some reason, gave up toward the end of the function.

download (24)


If the module gets to the last module in the whitelist (of which there are over 200), “fraps64“, and isn’t a match…you’re marked as a dirty hecker.

download (25)

The path of the dirty module is stuffed into a std::string which is then put into a SuspiciousModuleLoadedMsg object and sent over to the good old boys at Bethesda.

download (27)

We don’t know, however, whether Bethesda bans for this.  Each detection vector sets a unique value in the ‘cheater’ variable that is eventually sent to Bethesda, so it’s possible they don’t ban for bad modules.  But if your module is named “WastedLandsHax42069.dll” or something that will stick out to whoever hopefully manually reviews your report, you’re probably in for a bad time.


To get caught by Bethesda’s anti-cheat, you need to:

  1. Use a debugger that doesn’t hide itself
  2. Use Cheat Engine, Jiro’s memory hacking software, IDA, or Windbg
  3. Use Cheat Engine’s speedhack functionality or have a detectable module running in the game process that doesn’t disguise itself as a whitelisted module

It’s worth noting that I’ve only looked at what stood out to me and what interacts with the set_cheat_found function, so it’s possible there’s some more leet anti-cheat stuff in there I haven’t come across.  But so far it looks like Bethesda isn’t doing a great job detecting cheaters in their newest game – which probably isn’t a big deal so far because not only is no one playing it, but the client-server architecture is pretty good and there’s not a ton of juicy hacky stuff you can do anyway.

But, if the Battle Royale mode catches on then that changes.  Suddenly teleporting and aimbotting become a problem and people are going to cheat more.  And if that happens, Todd Howard is going to need to step up the anti-cheat game if he wants to keep the game full of legitimate players that enjoy playing the game.

5 thoughts on “How to get caught by Fallout’s anti-cheat

  1. Pingback: How to get caught by Fallout’s anti-cheat – Douggem’s game hacking and reversing notes – The Library 6.0
  2. Hey, I don’t really know a whole lot about reverse engineering but how did you uncover the functions like EnumWindowsTask?

  3. Pingback: IT Security Weekend Catch Up – June 22, 2019 – BadCyber

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s