Today, we start the the Omnification of The Witcher 3! This has been one of my favorite games to have come out in the last few years, and one I’ve been waiting to Omnify since I started the whole Omnifying shebang. The Witcher is definitely a game rich with story and interesting characters; all it is missing is an adequate level of hellish gameplay difficulty.
By the time we’re done here, it certainly won’t be wanting in that department any longer. We’ll begin our hacking by charting out some of the most important of data structures as it pertains to our player and other creatures.
The Matter of Geralt’s Health
As is tradition, we typically start by locating the player’s health. It is a requirement of a number of our game-neutral systems, and it gives us a good head start in finding (if we’re lucky) a root structure for the player. More often than not the exact numeric value for the player’s health is hidden from us in the user interface. Fortunately, in The Witcher 3, the health is displayed to us, plain as day.
So it’s a simple matter of just plugging this into our friendly Cheat Engine and searching for changes being made to the value. The only question we have is what particular data type it might be. It would appear to be an integer based value, however, a little birdy has just whispered into my ear that it might indeed actually be a float (translation: I tried searching for integers earlier and failed). Let’s see if I am correct.
We quickly narrow it down to just four results after searching for a single value change (from 3500 to 3271). From there we just change each of the four remaining addresses’ values until we find the one that is directly responsible for updating the player’s health in the game.
Finding a Proper Place to Hook the Player Health
Now that we have found the source of truth for the player’s health, time to learn a little more about the data structure housing our player’s health value. While we do that, we can start to find a suitable piece of code to hook into in order to reliably create a pointer to our player’s health between game sessions.
We give our new field in our address list a little right click and choose Find out what accesses this address, and soon enough we’re greeted with some jovial looking instructions.
Hopefully from these four instructions we can find one ideally only accessing our player’s health. What we’re likely to see is a number of these accessing health values belonging to multiple NPCs, as many of these kinds of functions tend to be map or area-wide HP pollers for the entities that lie within its borders.
Unfortunately, most of them appear to be accessing too many addresses to be of any real use to us.
Upon reaching the very end of the list however, we find a very interesting instruction that, while accessing more than one address in memory, appeared to be accessing three very different kinds of values.
Initially the second address listed above was at a 100.0. Suspicious, I made my character run around a bit, and noticed it drop down. Clearly, this second address is pointing towards the player’s stamina. Plot twist.
The addresses being accessed are all statistics related to, and only to, the player. My guess is that these are functions used to poll for various stat values for the purpose of displaying them on the screen. The first value is clearly the health, the second is the stamina, and the third could be either toxicity or even adrenaline, I suppose.
Looking at Vitals Access Code and Data Structure
So, if we want to use this code, how can we differentiate between whether our player’s health is being accessed vs our stamina? Does it matter?
I noticed from how the code behaved during execution that the base address for this vitals structure seemed to be stored in
rax, with an indexer stored in
rdx being applied to this base address in order to yield the desired stat. Here are the stats returned for each possible value of
- rdx = 0: Health
- rdx = 3: Stamina
- rdx = 6: Toxicity
The whole indexed-based access thing doesn’t matter much here, the address of interest for us seems to always be found in the
rax register. Lets have a gander at this vitals data structure next then.
So we’ve got the player’s most basic stats available right in this vitals structure. There appear to be additional game stats as well, although I haven’t been able to identify them yet. These are actually live values, so updating the maximum for health, for example, actually changes my maximum health amount. It’s nice to have them all stored in this single data structure as opposed to some of the values being stored in a separate, more “character-defining” data structure (which I’ve seen in games).
At this point in time, it doesn’t appear as if this game has any RTTI (I named the Vitals structure myself). We can’t be sure of this 100% yet, but I’ve grown accustomed to not having it present anyway. We’ll just cross our fingers and hope for the best…
With all of this in hand, I think it’s fair to say that we should now be able to create our first hook into the game that will secure our player’s vitals structure.
Player Vitals Structure Pointer Creation via Injection
For our first bit of code, we’ll create a simple hook that’ll grab the vitals structure stored in
rax and set our pointer to…point to it!
Player Vitals Structure Hook
// Gets the player's vitals. define(omniPlayerVitalsHook, "witcher3.exe" + E3BEB1) assert(omniPlayerVitalsHook, 8B 0C 90 89 0E) alloc(getPlayerVitals,$1000, omniPlayerVitalsHook) alloc(playerVitals,8) registersymbol(omniPlayerVitalsHook) registersymbol(playerVitals) getPlayerVitals: pushf push rbx mov rbx,playerVitals mov [rbx],rax pop rbx getPlayerVitalsOriginalCode: popf mov ecx,[rax+rdx*4] mov [rsi],ecx jmp getPlayerVitalsReturn omniPlayerVitalsHook: jmp getPlayerVitals getPlayerVitalsReturn:
Pretty simple stuff: we’re just grabbing what’s in
rax and setting it to
Knowing our health is a requirement for a number of our Omnified systems. It would be great to figure out where our root structure for the player is kept, but we don’t have enough information yet.
The Matter of Geralt’s Location
After finding our player’s vitals, the next most important bits of information most certainly have to be that which pertains to the character’s locational coordinates. By tradition, we look for the player’s coordinates after we find the health, and I mean to keep to that tradition!
Since we haven’t found a root structure yet, we’re going to need to perform another “change in values” search in order to find the coordinates. We typically make use of the vertical plane of movement, as that’s the easiest to isolate from the other axes. So, we’ll begin with an Unknown initial value search for Float (almost always the value type used for coordinates) value types.
We then proceed to move the character up and down an incline, narrowing down our search results by looking for both Increased values and Decreased values as appropriate. After dealing with a few crashes and much hair pulling, I finally was able to isolate a particular value in memory which seemed to control the character’s vertical position.
Note that I said it seemed to control our vertical position. After increasing the value, I would observe the character hanging out high in the sky. The character remains there until we make some sort of movement. After initiating said movement, instead of our character falling to their deaths, our character would immediately return to their original location and carry out the movement.
Furthermore, freezing the value (preventing updates) does nothing to actually prevent the player from changing position along the vertical axis. What this all means, then, is that the value we found was not actually the source of truth vertical axis coordinate position. What it reminded me of immediately was a similar acting value that was present in Dark Souls II. Not being what we were looking for, I tabled it and began a new search.
After an hour or so (broadcasting live might I say) of searching, I simply could not find the character’s actual source of truth vertical coordinate point in memory. Desperate to maintain my “aura of coolness” in front of the viewers, I started to panic internally. So, looking for some clues, I decided to venture into some code that was responsible for updating the previously found “immediate vertical position” value we were just discussing.
The place from which the “immediate vertical position” was getting its value from might have nothing to do with the actual vertical position, but there was a chance it might. Looking at the code writing to the immediate value, I quickly saw the use of a
cvtpd2ps instruction, meaning that the reason why we were unable to find the actual positional values might’ve been because these values were not float, but DOUBLES.
I was in shock at the implications. Of all the games I’ve hacked, the only time ever that I’ve seen anything other than float used for a coordinate’s value type was while hacking Subnautica. Even then, it was only the character’s coordinates while they were on land. In water, it reverted to using normal floats.
That’s why I was unable to, thus far, find the location coordinates! With renewed vigor, I redid all the previous steps, this time looking for doubles instead of floats. Not long after, I managed to find them!
Finding a Proper Place to Hook the Player Coordinates
Now that I the found the coordinates, we of course want to be able to reliably find them again in the future. Therefore, time to find a reliable bit of code accessing them which we can hook into. Looking at what was accessing the coordinates, I found the following instructions:
Out of all of these instructions, the only one that was running constantly was the first one, highlighted above. All of the other instructions only seemed to be executing when the player was moving. For our purposes, we need to be able to detect the player’s location in memory at any given point in time, not just when we’re moving. This is mainly due to us having to filter out the player from being affected by the Predator system (otherwise the player will ZOOOOOM), etc.
So, the only viable instruction to hook into from above is the first one. Unfortunately, the address being used to access the location in that instruction is aligned to be directly on top of the X coordinate. This is most likely not how the location structure is aligned in other parts of the program, in particular the code responsible for making creatures move.
We’ll need to be able to do a straight compare between what’s moving and our player’s own coordinates in order to filter them out, so we’ll want to realign the structure prior to creating a pointer pointing to it.
Player Location Structure Pointer Creation via Injection
This will be another simple hook, for the most part, and it will simply create a pointer that is pointing to what’s in
rax after its address has been adjusted for proper alignment.
Player Location Structure Hook
// Gets the player's location. define(omniPlayerLocationHook, "witcher3.exe" + 31A26D) assert(omniPlayerLocationHook, F2 0F 10 00 F3 0F 11 74 24 74) alloc(getPlayerLocation,$1000, omniPlayerLocationHook) alloc(playerLocation,8) registersymbol(omniPlayerLocationHook) registersymbol(playerLocation) getPlayerLocation: pushf push rax push rbx mov rbx,playerLocation sub rax,0x1B8 mov [rbx],rax pop rbx pop rax getPlayerLocationOriginalCode: popf movsd xmm0,[rax] movss [rsp+74],xmm6 jmp getPlayerLocationReturn omniPlayerLocationHook: jmp getPlayerLocation nop 5 getPlayerLocationReturn:
Again, a fairly simple hook. We adjust the location structure pointed to by
rax by an amount of
0x1B8, which I confirmed is the offset used in the movement code to access the coordinates.
On the Relationship Between Immediate and Actual Position
Just because we found the actual position in memory for the character does not mean that the “immediate” value we were exploring earlier is useless to us. In fact, it is very much required. The immediate value, while confusingly not representing the actual value, is interpreted by the game to be the location in which the player last occupied for purposes of fall damage and movement, etc.
That means if I boost the character up into the sky with the actual vertical position, and neglect to update the immediate “apparent” position, the character will fall to the ground and not suffer any wounds. The camera also doesn’t move correctly to track the character. This is because the game thinks that the character is actually still on the ground as their last position. We need to update both to achieve a true and total locational change.
So, knowing this, we must create a hook for these particular “immediate” coordinate positions as well. While examining its data structure, I was delighted to see that it had an assigned name, meaning that RTTI was indeed present in the binary. Fabulous! Since the given name was
CPhysicsCharacterWrapper, we shall call this new data structure the player’s “physics structure”.
Player Physics Structure Hook
// Gets the player's physics wrapper. define(omniPlayerPhysicsHook, "witcher3.exe" + 30FCA9) assert(omniPlayerPhysicsHook, 0F 2F 83 98 01 00 00) alloc(getPlayerPhysics,$1000, omniPlayerPhysicsHook) alloc(playerPhysics,8) registersymbol(omniPlayerPhysicsHook) registersymbol(playerPhysics) getPlayerPhysics: pushf push rax mov rax,playerPhysics mov [rax],rbx pop rax getPlayerPhysicsOriginal: popf comiss xmm0,[rbx+00000198] jmp getPlayerPhysicsReturn omniPlayerPhysicsHook: jmp getPlayerPhysics nop 2 getPlayerPhysicsReturn:
Excellent. I confirmed that I was able to send the player hurtling to their death by increasing both the source of truth vertical position and the immediate vertical position.
Now that we have all these basic data types in hand, it’s time to see if we can’t find the root structure for the player.
On the Matter of the Root Structure
Up until now, the holy grail of data structures (the root structure for character entities) has eluded us. From all the data structures we’ve examined, it became painfully evident that these (most likely) child data structures had no knowledge of their parents (the structures containing them). There is nothing offensive or surprising about this; in fact I’ve always been surprised to not see more games following such a model. Nevertheless, it makes things a lot less convenient for us.
When there are no direct links to a parent structure in a given data structure, the way you go about finding said parent structure then is to look at the code accessing our given child data structure and seeing where and how that code is sourcing the child data structure’s address. Clearly, it must be sourcing it from a parent of some type, no?
So with the vitals structure, for example, we take a look at the code accessing that, and soon see it’s being access via the
0x60 offset of some other structure:
Taking a look at the parent data structure pointed to by
rsi, we’re greeted with a new data structure, the W3AbilityManager:
Is this the root structure for our player? Well, it could be, although the name is a bit strange for such a structure. Typically root structures will be named something with “Player” or “Entity” in the name or some such. The only way to find out is to see where this ability manager structure comes from.
Long story short, I had issues finding the origin of this particular data structure and didn’t actually stumble onto the root structure until looking at how damage is handled in the game. It was actually rather random; I just took a random address stored in one of the registers, plopped it into the Structure dissect window, and saw that we found a new type: CR4Player. Definitely the root structure for a player.
Analyzing the Root Player Structure
When I first started Omnifying games, I usually had trouble finding creature root structures. Since I started being able to find them, they’ve all been structured more or less as expected in each game I found them in. These data structures act as a table of contents of sorts for entities, containing static links that point to topics of interests, or in our case, other structures containing player-related data.
So, after finding the root structure, I assumed I would be able to crawl down through it and find all other previously discovered structures, etc. However, this turned out to not be the case. I was first alerted to something amiss when trying to find the vitals structure from the root.
Nestled within our root structure, at offset
0x1C0, we stumble upon a structure seemingly responsible for containing various player stats. Fantastic. If we go a bit deeper into this structure, we eventually stumble upon our much desired ability manager class.
As you might be able to tell from looking at the values in the Vitals structure, this is not actually our ability manager structure for our player. This is not good. How does the game figure out where in memory the ability manager is for a given creature then?
Infuriated, I decided I had to reexamine how the code was getting our W3AbilityManager instance; something which I previously gave up on fully figuring out, due to code that was utterly confounding in how difficult it was to debug.
Tracking Our W3AbilityManager Resolution
How did the game acquire our ability manager? Typically, you would find it on a root structure. Not in the case of The Witcher 3. When I tried to see how it was coming up with the ability manager’s address before, I was led to a section of code that was very difficult to debug.
It was difficult to debug because its purpose was very generic in that it was being used to resolve a plethora of data types. Not only that, but it was highly recursive, something I haven’t had to deal with much when reverse engineering. That means to actually figure out how something was getting resolved required basically guessing on the meaning behind particular register states and trying to break execution on the correct value or values of said registers.
So, to start off, we looked at all the code accessing our ability manager’s address directly. This led us to this particular instruction:
Figuring out where
rcx comes from here is very difficult. If you look at the stack, you’ll see we’re in the middle of a recursive call chain, with who knows how many various jumps and other function calls between each of them. Going up a single level on the stack leads us to an oh-so-lovely dynamically addressed function call, which makes things even more difficult.
This function here is actually called at the very start of this long chain of recursive function calls, and it is executed for a ton of things. We had to hope that some kind of register state existed that we could break on. One thing I did notice while debugging this is that the
r12 register appeared to be our root structure (not in the above photo, that is just a random breakpoint hit)! So, we could at least filter out on data requests for our own character.
So what I did then is add a breakpoint with a condition just for our root structure, and then I hit the Run button until the ability manager access occurred. This is a rather…primitive way to do things, and it requires near perfect photographic memory, but luckily I managed to notice that the
rax register was
0x1C before the ability manager was accessed.
Ah hah! It would appear then perhaps that
rax is used as a data discriminator value, provided to this “lookup function” in order to tell it what type of data to retrieve. And, it seems
0x1C is the code for ability manager lookups.
Each time this breakpoint hits, execution would immediately shift to the ability manager access. Perfect! We found the perfect place to do a big ol’ execution trace. So that’s what I did. A trace of 10,000 instructions, conditioned to only go off when
rax was 0x1C and
r12 was my root structure address, and then I delved deep into it, and discovered the magic sauce.
It was buried deep in the trace, but I actually managed to figure out how the hell the game was looking up creature data! If you’ll look at the above picture, you’ll see that
rcx has our root structure for the player, and that we’re adding the value stored in
r8 to the value stored at
0x20 in that root structure.
The value in
r8 comes from another structure, and specifically from offset
0x20 in it. That structure, it turns out, is a property definition structure named CProperty:
Very interesting! It appears that the value being read from this structure is an offset to add on to a base property address stored in our root player structure, so I named the field shown above at
0x20 as the Property Offset. If you scroll up to the original root player structure image I provided, you’ll see that I named the field at
0x20 as the Property Base.
After adding the offset to the base property address we get
0x16D66D943F8. So what the hell is this? It is an unnamed structure, but it contains the goods.
And there it is! This is how the game resolves properties dynamically. Not going to lie, I’m a bit proud of myself for figuring it out!
Player Root Structure Pointer Creation via Injection
While analyzing the CR4Player struct I came across a few (actually quite a few) instructions accessing it. After going through a number of them I found one that was dedicated to only accessing our own struct. By the by, the name for the struct when it belongs to an NPC appears to be CNewNPC. We’ll verify that later…
Player Root Structure Hook
// Gets the player's root structure. define(omniPlayerHook,"witcher3.exe"+AB139) assert(omniPlayerHook,48 8B 01 48 8D 54 24 60) alloc(getPlayer,$1000,omniPlayerHook) alloc(player,8) registersymbol(omniPlayerHook) registersymbol(player) getPlayer: pushf push rax mov rax,player mov [rax],rcx pop rax getPlayerOriginalCode: popf mov rax,[rcx] lea rdx,[rsp+60] jmp getPlayerReturn omniPlayerHook: jmp getPlayer nop 3 getPlayerReturn:
Given the number of steps required in order to calculate addresses to other data types from the root structure, we will keep the other hooks we defined earlier in the article for purposes of convenience.
A Fantastic Initial Look Into Witcher 3
This article was written live on my stream. Thanks to everyone who kept me company during the start of the new journey!
I am also extremely pleased to announce that I have completely changed the “tooling” behind my hacks — all work on the hacks is now done through a single editor: VS Code. I have organized the way the hacks are organized so that the assembly code is actually completely separated from the Cheat Engine tables — we now have a “boilerplate” Cheat Engine table file that I just copy and paste between games. The Omnified framework code is also now in a common location that all games will be referencing.
This means my live hacking workspace is ready to be able to be checked into source control! I’ll post an announcement on that soon.
Next up for The Witcher 3 is the implementation of my Apocalypse system! I cannot wait. This Omnified game is truly going to be something else. Pay attention to the latest scheduling updates to know when you’ll be able to catch me online, or simply join my Discord server to get real time go-live notifications.
Until next time, take care!