
Nick Powers: You. All right, we're gonna go ahead and get started, and today, Max and I will be talking about our Fourier into some entry level game hacking with the title here. Don't play fair game hacking for security professionals. Unknown: I
think this is working. Try it. Okay. So quick introduction. A little bit about me. My name is Nick powers. I'm currently a service architect at specter ops. I've spent most of my career in like pen testing and red teaming in my handle on Twitter, GitHub, everything else is at xenergy. Max Harley: Hey, my name is Max. I'm a Clemson graduate. I now work at software engineer at Prelude. I used to work with Nick at spec drops, and my Twitter handle is up here. 0x Unknown: Closer, I can see the slides. Dabo.
Okay, so just to give a quick intro about what we'll be covering over the next 25 or 30 minutes, is first. We'll cover why that why we think this is relevant to offensive securities in general, how it kind of had some overlap with our day to day in the industry. We'll give an overview of the game that we're going to be focusing on a little bit about how the game works, like a functionality as well as, kind of, like the intro into some of the like suspicious behavior we saw that we might that we thought might be exploitable. Max will dig into actually weaponizing this client side abuse and making it practical to abuse during, like, the multiplayer gameplay. Then
we'll go over a demo, kind of tying all of the abuse together, and we'll wrap up with some real world application of like, how some of these techniques bleed over into our everyday, everyday work. So also, still kind of like introducing this topic, we are not game hackers. That will probably become apparent. This isn't like a huge game that we're digging into hacking. So we're basically just cosplaying game hackers at this point, but we do play video games, and we do think that what we kind of learned along the way here has a lot of overlap with offensive security. So anybody that's familiar with the industry or things associated with the offensive security industry might be familiar with topics like process, injection,
windows, internals, reverse engineering, whether that's static or dynamic. Reverse Engineering, definitely a lot of overlap in that regard. And lastly, like I mentioned at the end of the presentation, we'll kind of tie some of these techniques together to at least one or a couple real world scenarios that we've seen in like assessment scenarios, or even in other corporate networks that we've been exposed to. So why did we do this? Well, I mentioned before we play video games. We enjoy playing video games. And while we were playing, playing some of these video the game that we'll be focusing on in this presentation, a friend of ours was like we were in the middle of a game, and he focused the
window, like he just held the window, so it kind of like froze the game up, and the rest of us notice certain like values in the games or game or functionality in the game started to work a little differently. So that was like, our first, first kind of exposure to like. Some of these values might be controlled on the client side of the game, versus like validated on the server side of the game. So we thought that might be interesting. Focus on potentially exploitable and again, like I mentioned before, this was kind of our, like, Fourier into, like, entry level game hacking, like our baby's first cheat. But it made it a little bit more interesting, in my opinion, because this is a
multiplayer game. So the effects, kind of, you know, are the friends that we were playing with. Got to see, like, what was happening as well. So how does the target game work that we're talking about? It's a very simple game. You start off either as a hunter, so this is the view for being a hunter, or you start off as a deer. There's one hunter. The rest of the players are going to be a deer. The goal is to find the other players that are deer, that kind of blend in amongst all the like NPC deer. But to give a little bit more specifics of like how each role works, if you start off as a hunter. You see here
the hunter has a certain amount of arrows in the bottom left. Hunter also has sanity bar you can see at the top. So there's only, like, a limited amount of time to, like, find, find the other player, deer, the versus the NPC during the game. And you'll also see in the bottom right, there's some trail cams that helps the hunter, like, find some of the other player deer blending in amongst the NPCs as you're playing. And then if you're a deer, the game developer decided to implement this feature that's like a sprinting feature, but you can see to help you get away from the hunter. There's this very helpful parting feature that kind of shoots you across the
map. So there's a pro and a con here. The Pro is, obviously, you get away from the hunter. But the con is, it makes it obvious where, like, You're not an NPC, you're one of the players that you're trying to you're avoiding the hunter. So if the hunter sanity runs out, like towards the end of the game, all the deer turn into these, like Monster Windigo creatures, and then it kind of reverses the role you. Get to hunt the hunter, and that's how the game ends if the hunter doesn't find the deer. So that's a quick overview of kind of like how the game works. But as we were digging into what might be abusable here, we mentioned the whole like holding the window,
some values might be controlled on the client side. Well, the first thing I already mentioned, this is a multiplayer game, so values being controlled on the client side is not a good thing if they're not being validated on the server. So we need to determine, determine what, which one of those values are controlled on the client side. And the first, the first thing that came to mind for us was there, I mentioned the trail cam feature. You can see in the bottom right of the next slide that I'll go to here in a second. The hunter can put down a few trail cams that lets you, like, if a deer runs by it, you'll see where they are kind of roughly on the map. And you
start with six that you can lay down. So that's like a finite number. We can look for that number potentially in memory using a tool like Cheat Engine. And giving a quick overview of what Cheat Engine is, it allows you to do things like scan memory for particular values, like an integer of, let's say like six, like the hunter starts off with six trail cams, and we can filter that for that value as the value changes. So we have six trail cams. We set down a trail cam. Now we have five, and we can continue to filter down those potential values in memory until we find the one that's like this is definitely representative of the amount of trail cams we have in the game.
So this is, this is what it would look like you start off the game your Hunter. You can see in the bottom here we have six trail trail cams left. We're about to sit one down. So then in Cheat Engine, we attach to the game process, and then we can scan the process memory for this value that we're interested in. So here we just look for six. But the problem is, you can see in the top left here, roughly that we have over 100,000 values that that equal the number that we're looking for. So not, not going to be helpful at first, but like I mentioned, we can just keep setting down trail cams. We set
one down now we have five. We filter, we continue doing that basically, until we found, find the value that we're interested in in the target game process, memory, and then we can arbitrarily modify that value. And we'll see here, if that value is not validated on the server side, which is kind of like what we're getting to here, not only on the client side, but for all the other players in the game, we'll have an arbitrary number of trail cams, and that can lead to chaos in a lot of scenarios. So we can just control, potentially, any of these values. So, oh, look at this camera. Yeah, here I'll switch with you. You have to, like, put your hand up. It got me. It's got me. So
while that's really cool, that doesn't really work in a real game that might take, sorry, that might be a three minute process, to find a value, modify the game, search for the value again, modify the game until we find the right value. That won't work, the round will already be over and just don't have enough time for it. So is there a better way to do this? Yes. Cheat Engine has great support for scripting. So we could have scripted this out in cheat engine, but we decided not to do that. We decided to develop this cheat outside of cheat engine because it allows more flexibility. So we did some researching. We're extremely lazy security researchers, so we
looked on the internet. How do most cheats work? Well, it's actually a pretty simple process. You inject code into the game process so that you have code running as the game, and then you can modify whatever values and memory you want as the game. So we decided to use a DLL, really nice little feature, package up some code for us. We can inject this DLL into the target process and start modifying values we want. So how does this work? So pretty well known technique called cross process DLL injection, or just cross process like process injection, uses a number of internal like Windows API functions. So we can see we have a loader script on the left hand
side and the game client on the right hand side. In order to perform process injection and load a DLL, we first call open process to get a process handle. Then we use virtual allocex and write process memory to write the DLL path into memory on that in that remote process. And then we call create remote thread, calling load library a what that's going to do is find that DLL path in memory that we set load the library that we've designated, which is our malicious code, and boom, we have code execution in the target process. So if you've ever done c2 internals, like looked at how cobalt strike works. This is exactly what cobalt strike does for most of
its like post X capability. So if you do like PowerShell, power pick, execute assembly, any of these, they're all implemented the same exact way. Instead of loading a library, it may run PowerShell or unmanaged PowerShell or load a.net assembly. But this is we're using things that we. Do in our everyday job to hack games. So it's kind of this fun, fun similarity there. So we're now able to execute code in a target game. What are we going to do? We want to modify values. How do we modify values instead of searching for them every time? How do we find them every time we start up our cheat, how do we load and find these values that we need to modify? Well, there
are these things called offsets. So offset is just the distance from the beginning of an object in memory to a property we're interested in. Why do we need these offsets? Well, memory addresses change. You have a base address that will be randomized every single time you if you find where the trail cam number is, close the process, open it back up, the place in memory that trail cam value is is going to be different every time. So we need these offsets because they will stay the same every time, because that object is packed in a specific format, whatever the struct that we're using is, it's going to be the same every time. So if we can use offsets, we can always find
the value we want to change. So Cheat Engine is good, you know, doing this, this is like find, find Val or find by value. You know, we're finding an address by value. We can also use Find by address or find by offset, which is a much better way to run cheats, where you can do it quickly in an automated fashion. Cheat Engine does have scripting support for this scenario, exactly that we're about to perform. But again, we chose a DLL. It's more fun to implement from scratch. So what are offsets? Let's take this little toy example of a game. We have a world object. We have a player object. So we have this world object. When we execute this in memory, the structure will be
pushed onto the stack. The beginning of that structure is the world, and the offset that we're interested in is hex 24 bytes away. That's where this player object, this player pointer, is located. Then we have the player object, and we have a health which is hex C bytes away from the beginning of the player object. So if we know where the world object is in memory, if we can discover that, we can always find where health is by going to the beginning of the world object, going hex 24 bytes forward, evaluating where that pointer is going to the pointer, and then going hex C bytes from the beginning of the player object to that health place, that health integer. This
is how it would look like in memory. So we have this world object in memory. Let's say that the world object is static, so we can find it. Every single time we have this world object, it hex, 24 bytes later, we have a pointer to the player object. Hex, C bytes away from the beginning of the player object is the health help address. So what's really nice in most video game platforms for whatever reason a game developer is going to need to talk to me about this, but world objects are typically static. So the nice thing about static variables is, you know where they are every single time, they have the same offset every single time because they live in a different part of
executable space. So let's find these offsets. We could do a lot of reverse engineering, but neither of us do a lot of reverse engineering, like low level. I'm not the vestiged, but we have this thing called Unreal Engine. So Unreal Engine is the game platform that the game that we've compromised or hacked written hacks for is built on. So let's do some enumeration. Let's see, has anyone written tools for finding offsets in Unreal Engine? And the answer is yes, there's this tool called number seven, which works up to Unreal Engine five has support for pretty much any unreal game, super easy to use. You build a DLL, use like process hacker or system informer to load that DLL
into the target game, and it dumps a C Plus Plus SDK that has all of the offsets pre defined in like C Plus Plus classes. So this is super useful for us. We automatically build a C Plus Plus. SDK, all of our offsets are defined. We can just write C Plus Plus as if we were the game and we have code execution, malicious code, where we can start referencing values in memory. So how does dumper seven work? So like I said, Get World is typically a static object for most video game platforms, so we can find the world object by getting the image base. We'll see how image base works in a second, and then adding that
offsets, colon, colon, G world, in the offsets namespace that G world, static offset. Get Image base just gets module handle zero. So this is we get module handle zero will get us the beginning of the game. So we've injected this DLL into this game memory. Get module handle zero will get us to the beginning of this game. And then you can see offsets. Is just a static that's a integer offset value that we add to that image base. And we get where G, G world is every single time. The other important thing here is G objects. So every object in Unreal is in a packed as a list at the beginning of this G offset
value. So any objects, you can reference it by by G objects and then perform your enumeration from there. So offsets very easy to get if you're looking at unreal. So let's dig into the code a bit. Let's look at this, this SDK that that was dumped. We see this Hunter character class. This a hunter BPC. This is the hunter character class. We can see some pretty interesting objects or properties. Here we have current arrows, player name, Max arrows like this is kind of indicative to us that this is the class for the hunter object. So if we want to modify anything, it's all right here. So let's see if these offsets are correct. Well, we're going to use this SDK.
There's a for loop that just enumerates through all of the G objects in the game. We attempt to see whether that object is a hunter class or not. So we just use this is a function that comes in dumper seven. We check to see if the object that we're enumerating is a hunter and then print out the name, print out the player name, and we'll see if this works, or does it crash? The answer is, it works totally fine. We print out the object and then we print out the player name. We can see the offsets that dumper seven gave us are entirely valid. So this is going to make hacking this game so much easier. So let's see if we
can modify errors. So we've injected this DLL, and we filter for the name, my Steam username, and then set the current arrows to 1000 and we can see this works really well. It modifies my the number of arrows I have to 1000 and then I shoot one off 999, and it's able to find my my player object in memory. So this is the basis of all the rest of the cheats we're going to perform. We load a DLL using process injection. We have all of these offsets defined with this SDK that dump or seven provided us. So let's try another cheat. Well, we wrote this helper function called find actors, which just performs that is a function on every object in the
game and returns us all actors of this ad or BPC. We did some enumeration. Again, we're lazy security researchers. There's a whole documentation page of unreal, how unreal works. In Unreal, there's this object called a mesh that every character object has. We can enumerate the mesh, and there's two functions, set render custom depth and set custom depth stencil value. If we do that, we can highlight all the deer, all the non NPC deer. So we've we've won this game. We know where every player is in the game. We can just walk up to them, they're highlighted, and shoot them. So we can see there's deer here that are not outlined. We find this deer and 360 no scope.
And that's a player. This was just a public, public lobby. So that's where the rest of our game, you know, there's, that's kind of the basis of all of our hacks.
Cool. So yeah, Max gave a couple demos of like drawing kind of stenciled outlines around, like helping us distinguish the NPC here from the actual players we showed, like removing cooldowns from certain game functionality. But we wanted to kind of tie this together and like what the gameplay looks like from our perspective after we like combined everything that we found. So we play video games every Monday night with a group of friends. We didn't tell them that we had done this. We'd been playing this game for a little bit, and we just recorded their reaction with a few seconds of gameplay. So maybe audio works? Yeah, we'll see if the audio works. But before I play the
first clip, if you remember, before I handed it over to Max, I showed the incredibly crucial feature of the game where the deer can, like, fart away from the hunter. And that was, that was one of the most like removing a cool down from that feature, was what something we were very interested in targeting in this game, so that that's kind of kind of where we start in this demo. So hopefully the audio works. Here am I, oh, so
we're obviously starting his video, drawing him over to us.
All right, beaten, bro.
What is that guy doing?
Good value. He's legendary.
Sick. Oh, my God. Anyways, we had to bleep a lot out.
So I did also, like that was from the deer perspective. I wanted to show what it looks like actually on our screen. So like Max mentioned, we wrote the loader, like the executable that injects the DLL, just a very like simple screen here, like one for deer hacks, two for Hunter hacks, some other features we were testing there at the end. So we start the game. It's as easy as pressing two. It does a lot of what Max talked about, but kind of in an automated fashion. And we can, we can see it outlines. We have basically machine gun arrows here. And we can kind of skip to some of the gameplay of what it
looks like to be the hunter in this game with our friend. Oh, oh thank
you. Am I no? Am I Am I no?
Am I not? Am I can we switch out a speaker mode. That's not a huge deal either way. Yeah. Oh, alright. Well, we're supposed to be able to skip this. We can do it up here. Oh, yeah, good idea. Where was it? Like 75% of the way through a little past that. Yeah, that looks good. Look at that. There it is. Okay, yeah, yeah. So this, this is actually starting a game we were playing with them from the hunter perspective. So you can see outlines. Are there? We're kind of going around the map unwitting to them. Poor guy here, hiding behind the rock, not anymore.
And yeah, there's no way to get around that, really, although our friend here makes a valiant effort, but,
and at this point, everyone in Discord is like freaking out so they know what's up. Yeah, the jig is up here. There's, there's no, but he tries, yeah, he tries to get rid
still, no, it's a good effort.
Okay, so hacking the game. Oh yeah. There we go. Okay, nope, it's still on you. It likes me. Oh, I'll just stand there. Yeah, cool. So hacking the game was a lot of fun, but we did want to tie this back together with like, how this relates to our everyday job and offensive security. So like I mentioned in the beginning, there are several real world applications of these techniques, in my opinion, and a couple in that we actually leverage during like assessments in some of the networks that we see. So the core of this is that the same logic or finding these client side control values applies in a lot of scenarios, particularly in offensive
security, when a value is completely controlled by the client and not validated in any way by the server, there's a lot of room for abuse there. So again, what we're looking for is the making sure that we want to make sure that the server of whatever client application is validating the integrity of these values when that's not happening, we can do things like the practical application we have here is abusing posture checks of devices connecting to like VPN that would usually happen during like the SSO or single sign on process, making sure devices in a certain state, like enforcing disk encryption, making sure AV is installed, simple checks like that. But again, if those values aren't, if the integrity of those values
are not validated on the server side, if it's a simple like, yes, no, is this enforced? Is this not enforced, and that's sent up to the server and not validated? There's room for abuse there. So where the game hacking? It was a simple like, the server's not checking. If we have only three arrows we now we have 1000 in this use case, it's if the server of a posture check when you're connecting to a VPN doesn't actually do anything to validate is disc encryption enforced, is certain security products installed, then there's room for abuse. So in this case, this is like that. This is we didn't want to like Target the particular software here, but because they're not really doing
anything wrong. In this case, it's just, this is how a lot of posture checking works. There just needs to be some integrity on the server side. In this case, the check you can see that's failing right here is BitLocker disk encryption. So the problem here is that it's just a true. Like, is it enforced? Is it not enforced? That's sent to the server? You can see when we try to log into the single sign on just like, Microsoft authentication, oh, Microsoft authentication, here we get an error because bit lockers, Bit Locker encryption is not enforced. So just like Max told us, just like we stepped through with the offsets finding the right functions or properties in memory, we do the same thing here. We inject into
the remote process, find the right base address, find the target function using the offsets, and then we inject the right bytes to just kind of overwrite that function. Say always return true instead of actually check it. Once that's done, we just try to log in again, because the integrity of that value is not checked on the server side, we're allowed to actually authenticate. So to kind of wrap this up, we wanted to make reference to first, I'll reiterate again, we're not like professional game hackers. We have a lot of respect for the community that does this like regularly and very well. We also wanted to give a shout out to the author of the dumper seven,
tool that we that we leveraged for this, as well as YouTube channel, a guy that both of us watched a little bit to kind of get more familiar with these topics. And lastly, just the guided hacking form in general, provided a lot of like advice along the way as we were learning this. So anything else we did Cool? Well, that's it. Thanks everyone. Thank you. Applause.