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.

Behold! The player vitality is displayed to unabashedly!
Behold! The health!

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.

Behold! 189 results and counting! Soon we shall narrow it down!
Only 189 floats set to 3500 in memory…this’ll be like shootin’ fish in a barrel.

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.

Behold! I have found the player's health!
Behold! I have found the player’s health!

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.

Four instructions are accessing the player's health. Which one will be of most use to us?
A reasonably small number of functions are reading our health.

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.

Shows too many addresses being accessed for the instruction to be of use to us.
We’re looking for a function accessing a single address, not a bunch.

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.

Shows what the most promising of the health instructions is accessing.
Three addresses — perhaps related to various player stats?

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.

Shows the stamina bar having the same value as the second address in the previous image.
Ah hah! It is the stamina!

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?

Shows the instruction polling the player stats.
The rax register is the base address for the player vitals structure, with rdx serving as an indexer.

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:

  • 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.

Shows the contents of our mapped Vitals structure for the player.
I’ve filled in the stats I was able to identify: Health, Stamina, and Toxicity (both currents and maximums).

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 playerVitals.

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.

Shows over a billion floats to sift through in order to find the coordinates.
Whelp, only about 1.4 billion values to look through. Not the worst I’ve seen.

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.

Shows the character floating far above the ground after changing the immediate Z value.
Increasing this value boosts our character high into the sky.

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.

Shows some code that goes off before our "immediate vertical position" value is written to.
The “immediate vertical position” value seems to be sourcing values that were originally DOUBLES.

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:

Shows the instructions reading from our location coordinates.
A respectable number of instructions are reading our location coordinates.

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:

Shows where the player vitals structure comes from.
The player vitals structure is living comfortable inside another one, being accessed by the highlighted instruction.

Taking a look at the parent data structure pointed to by rsi, we’re greeted with a new data structure, the W3AbilityManager:

Shows the W3AbilityManager structure, with the Vitals structure highlighted.
The W3AbilityManager, with our Vitals structure highlighted.

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

Shows the contents of the root player structure.
The contents of 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.

Shows the "character stats" structure within our root structure.
At 0x1C0 inside the root structure, we see a CCharacterStats structure.

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.

Shows the incorrect ability manager structure found in the previous character stat
Here’s our ability manager, pointed to by the root structure. The various values for the vitals, however, are bad.

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:

Shows code directly accessing our ability manager.
This code is reading our ability manager from rcx, so where does rcx’s value come from?

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.

Shows code at the top of this recursive property lookup scheme.
A dynamically addressed function is called here at the start of the lookup. What are the register states to filter on?

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.

Shows execution stopped at lookup start with proper data discriminator for ability manager.
It appears that rax is used as a data discriminator, and 0x1C indicates the ability manager.

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.

Shows a gigantic execution trace from the lookup start, and the magic sauce therein.
Here’s the magic sauce baby. Thousands of instructions from the start.

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:

Shows the property definition class for our ability manager property.
This is a property definition for our ability manager property.

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.

Shows the contents of the resolved data structure for our ability manager.
Here it is folks. The actual data manager, resolved by applying the defined property offset to our root structure’s property base address.

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!