Tutorial From start to finish: Writing a Bad Company 2 Hack

Hexui Undetected CSGO Cheats PUBG Accounts


Dank Tier VIP
Jul 15, 2018

Game: Battlefield: Bad Company 2
Engine: Frostbite
Developer: DiCE
Buy: Steam

I started this series a while ago, but I never completed it but there is still plenty of good information in the first 3 chapters. If you're looking to learn the information in the chapters I didn't complete, it's all available here: The Game Hacking Bible - Learn How to Hack Games


Chapter 01:
Basic Recon
Chapter 02: Building a Cheat Table
Chapter 03: Using symbol files
Chapter 04: Finding and reversing game classes
Chapter 05: Hooking the rendering engine
Chapter 06: Using an intermediate user interface (ImGui)
Chapter 07: A basic hack menu
Chapter 08: Bringing it all together
Chapter 09: Triggerbot
Chapter 0A: Aimbot
Chapter 0B: ESP / Chams
Chapter 0C: Examining the network protocol
Chapter 0D: Outtro
Last edited by a moderator:


Dank Tier VIP
Jul 15, 2018
Chapter 01: Basic Recon

In this chapter we're going to be looking at some of the tools you can use to gather useful information about a game prior to even launching it. The only Battlefield game I've ever played was Battlefield 1942 and even then I never reversed it. So this will be a good way to demonstrate how I do things from the ground up; not to say that you have to do it exactly the same way as I do but if you've got zero idea on where to start this will be a good framework for you to start with.

Something that everyone can do really easily is simply open the game's directory and poke around inside it:


One thing to note is the presence of three different versions of Direct X libraries.

As you can see above the presence of these libraries seem to indicate that the game may support DirectX 9 - 11: We can easily check this later however now we need to check for the presence of anti-cheat or copy protection.

We can use a tool called DiE (Detect it Easy). To quickly discover more details about the game's executable such as what it was compiled with, if its packed and whether or not it has some type of copy protection on it.


The fact it can't identify the linker would seem to indicate that the game is packed with something.

We can further confirm our suspicions by clicking the entropy button and taking a look:


Here DiE is 98% sure this exe is packed.

If we compare this diagram to a game I know 100% is not packed:


You can see the "entropy curve" is far less uniform on this game.

This is still not 100% confirmed however now when we're reversing we know to look out for obfuscation and packing when the game is launched.

Just google it:

A useful resource I use constantly is google: You can find out a lot of information very quickly if you know what to search for. The longer you reverse games the more familiar you'll become with different engines and how they operate. It can be very useful to know what engine a game is using as you might have already reversed something similar and can quickly modify existing code you may have.


Ahh wikipedia how much time have you saved me for free.

A two second search shows the wikipedia page for BC2 and what engine it uses:



I absolutely hate the Frostbite engine it's goddamn shitcode reversing it is like wading waist deep into donkey shit. So make sure you have some gumboots handy for when we begin reversing it.

We only need one more piece of missing information before we can continue the rendering engine. There's three basic rendering engines that games can use:
  • OpenGL
  • DirectX
  • Vulkan
The engine it uses is important as each one requires a slightly different approach for hooking and drawing with it.

Back to DiE

If you click the "Imports" button in DiE you can see all the libraries that the game depends on, if we scroll down we notice two very interesting things:
  1. DINPUT8.dll - This library is typically used to handle controller input although some games use this library to handle all input (easy to hook).
  2. d3d9.dll - This appears to be the primary rendering library.
So the game most likely uses DirectX 9 for rendering.

What about those other libraries? Well we can use DiE again to see what they're for:


Yeeeep shader / mesh libraries.

These libraries will become particularly useful later one when we're messing around with shaders and drawing.

Finally what AntiCheat does BC2 use?:


Interestingly enough the settings have this option:


However I was unable to test it while writing this as connecting to multiplayer requires an EA account:


More on this later.
Last edited:


Dank Tier VIP
Jul 15, 2018
Chapter 02: Building a Cheat Table

Let me preface by saying this chapter isn't going to cover how to actually use Cheat Engine if you've never used it before there's plenty of resources available already. Here's a link to a guide @Rake has already compiled with tons of information.

Guide - Start Here Cheat Engine Guide & Info

I'm also going to assume that you've created a few cheat tables already for different games and you're pretty familiar with the basics of assembly. If you're not then you might want to take a look at this guide here:

Guide - GHB2 - Beginners Guide To Reverse Engineering

That being said I'll attempt to explain everything I'm doing and why however if you find yourself not understanding head back and do the tutorials again.

The first value:

Since this is one of those new fangled health regenerating games searching for our player's health is going to be more trouble than it's worth. Better to focus on something we always know the value of like the ammo:


Once you've located the correct value for the ammo you should be able to freeze it and fire unlimited bullets.

Here's a visual breakdown of the entire process:


The steps:
  1. Search for current ammo value: 29.
  2. Narrow the search results down until you have a small number.
  3. Begin modifying the remaining values until you find the correct one (remember to label it).
  4. Right click -> What accesses this address.
  5. Fire the weapon in game a specific amount (4x in this case).
  6. Look for a function that was hit the same amount of times.
  7. Examine each individual function until you find one that is reducing the value.
  8. Locate the base address (ESI in this case).
  9. Load this value into Reclass.
  10. Go to the offset (0x7C) and modify the value.
  11. Confirm it updates in game.
If the value updates you've found a pointer to the ammo address now we need to make sure we don't lose the fucking thing.

Pointer scanning:

The first thing you'll need to do is add the base address to cheat engine then generate a pointermap by right clicking and selecting generate pointermap. The time it takes depends on the size of the game and the speed of your system. It's a GH tradition to eat ice cream while waiting for the pointermap to be generated in honor of Fleep.

Once you have the pointermap right click on the base address and click "Pointer scan for this address".


When you're setting this up make sure you check the first box and load the pointer-map that you just generated. You can tweak these settings but I find the default values work fine for most games.

After the scan you should get a list of results:


You can see some pointer chains already point to invalid values. So what I like to do is filter out all invalid values first.


Then sort by the shortest to longest:


Generally speaking you want the shortest pointer chain as it's more efficient to resolve and less prone to failure. At the moment we have about 700 results that we'll need to narrow down until we have very reliable pointers. Reload your current game and take a look at the pointer window you should see the values update as the game reloads. You'll want to remove the invalid pointers again and see how much that trimmed off.

For me I ended up with about 87 values. Now we just need to confirm which new pointer actually points to our ammo value. Being putting the values into reclass and look at the value at offset 7C:


So our correct value is 0x1A72E440 which means we can filter our results again looking for this address. After that filter result we've now got around 60 or so entries left but that's only a soft check we need to reboot the game and check it again.

Close the game completely and relaunch it make sure you're back inside the mission or level or whatever before attaching cheat engine. With a bit of luck we should have about 18 chains left that should survive a game restart. SHOULD being the operative word you need to repeat this process a few times to be sure so do it again until you're sure you've found reliable pointer chains.

Once you've found a suitable chain add it to CE by double clicking it. Name it AmmoBase or something similar now copy it and paste it again and lets call the copy CurrentAmmo or something similar open it up and click add offset:


Now a bit of quick maths: B0 + 7C = 12C.

So go ahead and change B0 to 12C and you should have the current ammo displayed.


I also added the max ammo as well which was the next value (+ 4).
Last edited by a moderator:


Dank Tier VIP
Jul 15, 2018
Chapter 03: Using symbol files

If you've been programming for awhile you're probably familiar with Program Debug Database files or PDB for short. These files are automatically generated by the compiler at compile time and provide a database of debugging information that tools like IDA and x64dbg and Cheat Engine can read and automatically insert function names and what not. You're probably thinking "yeah but a commercial games company wouldn't ship with the PDB?".


This really made reversing MK10 a breeze and best of all most of this information can be applied to 11.

That's one example: savvier games companies understand how valuable this information can be to hackers and reverse engineers so they rarely ship it. However sometimes mistakes get made.

Bad Company 2 Big oof

So the dedicated server files were leaked and included in that leak was you guessed it a PDB file. The actual server itself is a pain in the ass to setup and run as the game is quite old now however all we care about is the debugging information. While this information is server specific you can almost guarantee that both the server and the client are sharing large portions of the code base. This means whatever we can learn from the server's debugging information will greatly help us in reversing the client.

Dumping symbol information:

Funnily enough Visual Studio actually includes a tool for this specific purpose DIA:

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\DIA SDK
DIA is a small command line utility that will read PDBs and extract whatever information you want from it. I had issues attempting to build it in x64 mode so make sure you've got x86 selected.

usage: Dia2Dump.exe [ options ] <filename>
  -?                : print this help
  -all              : print all the debug info
  -m                : print all the mods
  -p                : print all the publics
  -g                : print all the globals
  -t                : print all the types
  -f                : print all the files
  -s                : print symbols
  -l [RVA [bytes]]  : print line number info at RVA address in the bytes range
  -c                : print section contribution info
  -dbg              : dump debug streams
  -injsrc [file]    : dump injected source
  -sf               : dump all source files
  -oem              : dump all OEM specific types
  -fpo [RVA]        : dump frame pointer omission information for a func addr
  -fpo [symbolname] : dump frame pointer omission information for a func symbol
  -compiland [name] : dump symbols for this compiland
  -lines <funcname> : dump line numbers for this function
  -lines <RVA>      : dump line numbers for this address
  -type <symbolname>: dump this type in detail
  -label <RVA>      : dump label at RVA
  -sym <symbolname> [childname] : dump child information of this symbol
  -sym <RVA> [childname]        : dump child information of symbol at this addr
  -lsrc  <file> [line]          : dump line numbers for this source file
  -ps <RVA> [-n <number>]       : dump symbols after this address, default 16
  -psr <RVA> [-n <number>]      : dump symbols before this address, default 16
  -annotations <RVA>: dump annotation symbol for this RVA
  -maptosrc <RVA>   : dump src RVA for this image RVA
  -mapfromsrc <RVA> : dump image RVA for src RVA
If you run Dia with the flag -t it will dump all the class information available in the PDB. Using -type will allow you to dump specific classes:

C:\Users\timb3r\Desktop>Dia2Dump.exe -type dice::GamePhysicsEntity Frost.Game.Main_Win32_Final.pdb
UserDefinedType: dice::GamePhysicsEntity
VTable         :   , Type:  *
UserDefinedType:   ImpulseInfo
Function       :     public void ImpulseInfo(const class dice::GamePhysicsEntity::ImpulseInfo &)
Function       :     public void ImpulseInfo(const struct dice::Vec3 &, const struct dice::Vec3 &)
Data           :     this+0x0, Member, Type: struct dice::Vec3, m_position

Data           :     this+0x10, Member, Type: struct dice::Vec3, m_impulse

Function       :     public class dice::GamePhysicsEntity::ImpulseInfo & operator=(const class dice::GamePhysicsEntity::ImpulseInfo &)
Function       :   public void onImpulse(const class dice::GamePhysicsEntity::ImpulseInfo &)
Function       :   public class dice::physics::PhysicsEntityBase * physicsEntity()
Function       :   public float health()
Function       :   public struct dice::Vec3 velocity()
Function       :   public const class dice::Material * defaultMaterial()
Function       :   public const class dice::Material * material(const struct dice::Vec3 &)
Function       :   public const class dice::Material * getPartMaterial(unsigned int, const struct dice::Vec3 &)
Function       :   public float closestSurfaceDistance(const struct dice::Vec3 &, const struct dice::LinearTransform &)
Function       :   public void closestSurfacePosition(const struct dice::Vec3 &, const struct dice::LinearTransform &, struct dice::Vec3 &)
Function       :   public void GamePhysicsEntity(const class dice::GamePhysicsEntity &)
Function       :   protected void GamePhysicsEntity(const class dice::GamePhysicsEntityData &, class dice::GameContext *)
Function       :   protected void ~GamePhysicsEntity()
Function       :   protected void internalSetHealth(float)
Function       :   protected float internalGetHealth()
Function       :   protected bool belongsInPhysicsWorld()
Data           :   this+0x4, Member, Type: const class dice::Material *, m_material
Data           :   this+0x8, Member, Type: float, m_health
Function       :   public class dice::GamePhysicsEntity & operator=(const class dice::GamePhysicsEntity &)
Function       :   protected void * __vecDelDtor(unsigned int)
We can see here that health is located at 0x08 we can also see the entities position and impulse. As you can probably imagine having access to this information can make reversing something much much easier. Later on we're going to use these symbols and Cheat Engine to locate and find these classes in a really easy way.

Now we've already covered basic pointer scanning with cheat engine and how to extract useful information from PDB files we can move on to probably the most difficult part of game hacking: reversing the game's classes and functions. Before you even open Visual Studio we need to spend time reversing the game's logic and data structures. Because we have a copy of the server's symbols this process will be much easier than if we didn't have them.

After finding out about the server leak I began searching around to see what type of effect it had on the hacking community: the answer EXPLOSIVE. Very quickly people had begun reversing the games classes and logic and in a matter of weeks had completely reverse engineered the EA Standard Templating Library.


You can download 0 Attachments
Last edited by a moderator:


I'm not your friend
Jan 21, 2014
god i fucking loved this game
loved it too, supposedly they're making a "remake" of it, the next battlefield will be more like BC2 and less like BF4, sounds good to me. after BF1 and BF5 they got alot of feedback that people liked the run and gun style of the old games
  • Wow
Reactions: mambda
Community Mods