{"id":1086,"date":"2021-01-14T15:41:05","date_gmt":"2021-01-14T20:41:05","guid":{"rendered":"https:\/\/badecho.com\/?p=1086"},"modified":"2021-01-20T13:27:55","modified_gmt":"2021-01-20T18:27:55","slug":"hacking-ac-valhalla-part-6","status":"publish","type":"post","link":"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/","title":{"rendered":"Hacking Assassin&#8217;s Creed: Valhalla &#8211; Part 6 (1.1.1 Patch)"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" width=\"960\" height=\"540\" src=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/v111.png\" alt=\"Assassin's Creed Valhalla has been updated to v1.1.1.\" class=\"wp-image-1087\" srcset=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/v111.png 960w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/v111-300x169.png 300w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/v111-768x432.png 768w, https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/v111-480x270.png 480w\" sizes=\"(max-width: 960px) 100vw, 960px\" \/><figcaption>A new version! Hopefully we can salvage our Omnified hack.<\/figcaption><\/figure><\/div>\n\n\n\n<h2>A Somewhat Unexpected Update<\/h2>\n\n\n\n<p>Ah what joy. A new update for <em>Assassin&#8217;s Creed: Valhalla<\/em> has been released upon the masses. I&#8217;m sure most gamers, upon seeing an update for a game they enjoy queued for download, rejoice with much latent glee. Not this grumpy fellow, as any update to an <a href=\"https:\/\/badecho.com\/index.php\/what-is-omnified\/\" target=\"_blank\" rel=\"noreferrer noopener\">Omnified<\/a> game most of the time means that the binary has been altered, resulting in some inevitable breakage for our hacks.<\/p>\n\n\n\n<p>I typically will prevent any updates from being downloaded while I&#8217;m <a href=\"https:\/\/twitch.tv\/omni\" target=\"_blank\" rel=\"noreferrer noopener\">streaming<\/a> an Omnified game, however that dratted Uplay refused to launch the game unless I updated the game binaries. Perhaps if I left the launcher in offline mode it would&#8217;ve never known about the update. Well. That is neither here nor there now.<\/p>\n\n\n\n<p><a href=\"https:\/\/www.ubisoft.com\/en-us\/game\/assassins-creed\/valhalla\/news-updates\/5VJh2nOs6Mmyf8k7pfsCsf\" target=\"_blank\" rel=\"noreferrer noopener\">Here are the official patch notes<\/a>, and they look to be describing a mighty fine set of changes indeed. Isn&#8217;t that just <em>special<\/em>. No time for dawdling &#8212; time to get to updating our hacks! Let&#8217;s pray to whatever-is-up-there that we&#8217;re able to locate all the areas of code we were injecting into previously.<\/p>\n\n\n\n<h2>Updating the Player Data Retrieval Code<\/h2>\n\n\n\n<p>The first item on the list for updating is the code responsible for retrieving all pertinent data associated with our player. This code grabs the player&#8217;s root structure, health structure, and location structure. Very essential and very much the first thing we&#8217;ll go after.<\/p>\n\n\n\n<p>The unique array of bytes we had listed for the bit of code we were hooking into before was <code>2B 45 BC 89 44 24 58<\/code>. Hopefully the updates to the application haven&#8217;t eaten up this area of the code.<\/p>\n\n\n\n<p>Luckily it looks like our code is still present in the binary. Woot. Let&#8217;s update our hook then so that it gets injected into the proper place.<\/p>\n\n\n\n<h3>Updated Player Data Retrieval Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Creates pointers for the player's root, health, and location\n\/\/ structures.\n\/\/ UNIQUE AOB: 8B BB 38 01 00 00 75\ndefine(omniPlayerHook, &quot;ACValhalla.exe&quot; + 2195AC3)\n\nassert(omniPlayerHook, 8B BB 38 01 00 00)\nalloc(getPlayer,$1000, omniPlayerHook)\nalloc(player,8)\nalloc(playerHealth,8)\nalloc(playerLocation,8)\n\nregistersymbol(omniPlayerHook)\nregistersymbol(player)\nregistersymbol(playerHealth)\nregistersymbol(playerLocation)\n\ngetPlayer:\n  push rax\n  push rbx\n  push rcx\n  mov rax,playerHealth\n  mov [rax],rbx\n  \/\/ Root structure can be found at [playerHealth+70].\n  mov rax,player\n  mov rcx,[rbx+70]\n  mov [rax],rcx\n  \/\/ Location structure aligned for movement can be found \n  \/\/ at [player+1D0].\n  mov rax,playerLocation\n  mov rbx,[rcx+1D0]\n  mov [rax],rbx\n  pop rcx\n  pop rbx\n  pop rax\ngetPlayerOriginalCode:\n  mov edi,[rbx+00000138]\n  jmp getPlayerReturn\n\n\nomniPlayerHook:\n  jmp getPlayer\n  nop \ngetPlayerReturn:\n<\/pre>\n\n\n<p>Excellent! Now, to get to all the code that will <em>really<\/em> be a pain to go look for again.<\/p>\n\n\n\n<h2>Updating the Apocalypse System&#8217;s Hooks<\/h2>\n\n\n\n<p>Our <a href=\"https:\/\/badecho.com\/index.php\/2020\/10\/19\/apocalypse-system\/\" target=\"_blank\" rel=\"noreferrer noopener\">Apocalypse<\/a> initiation point is located smack dab in the middle of the damage application code for the player. This would be quite the pain to have to find again. The unique array of bytes for this is <code>2B 45 BC 89 44 24 58<\/code>. Let&#8217;s hope for the best.<\/p>\n\n\n\n<p>Searching for this array yields back a single result, perfect! None of the updates in the patch touched the code that applies damage to creatures. Let&#8217;s get that hook updated then.<\/p>\n\n\n\n<h3>Updated Apocalypse Initiation Point Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Apocalypse system.\n\/\/ Unique AOB: 2B 45 BC 89 44 24 58\ndefine(omnifyApocalypseHook, &quot;ACValhalla.exe&quot; + 2149247)\n\nassert(omnifyApocalypseHook, 2B 45 BC 89 44 24 58)\nalloc(initiateApocalypse,$1000, omnifyApocalypseHook)\n\nregistersymbol(omnifyApocalypseHook)\n\ninitiateApocalypse:\n  pushf\n  \/\/ Backing up a few SSE registers to hold converted floating points.\n  sub rsp,10\n  movdqu [rsp],xmm0\n  sub rsp,10\n  movdqu [rsp],xmm1\n  sub rsp,10\n  movdqu [rsp],xmm2\n  \/\/ Backing up the rbx register as it will be overwritten by\n  \/\/ the Apocalypse register. We don't care about the rax register\n  \/\/ as we'll be changing it anyway.\n  push rbx\n  \/\/ Backing up a working register to aid in value calculations, etc.\n  push rcx\n  \/\/ If we're freezing from cold water, the bits at [rsp+452] will be \n  \/\/ 0x14.\n  \/\/mov rcx,[rsp+452]\n  \/\/cmp rcx,0x14\n  \/\/je initiateApocalypseCheck\n  \/\/ Damage from arrows lack a root structure damage source, however\n  \/\/ the bits at [rsp+452] will be non-zero.\n  \/\/cmp rcx,0\n  \/\/jne skipLocationCheck\n  \/\/ Let's grab the damage source right now before the stack shifts\n  \/\/ anymore.\n  mov rcx,[rsp+44A]\n  \/\/ If no root structure is listed as the damage source, this means\n  \/\/ that the damage is from an ambient source (i.e. falling), which\n  \/\/ we want to prevent from triggering the Apocalypse system.\n  \/\/cmp rcx,0\n  \/\/je initiateApocalypseExit\nskipLocationCheck:\n  \/\/ We'll convert the working health and damage amount to floats.\n  cvtsi2ss xmm0,eax\n  cvtsi2ss xmm1,[rbp-44]\n  \/\/ If the player is the one receiving the damage, then the rdi register\n  \/\/ will point to the player's location structure.\n  mov rbx,playerLocation\n  cmp [rbx],rdi\n  je initiatePlayerApocalypse\n  \/\/ The player is the one damaging the NPC if the player's root structure\n  \/\/ is listed as the damage source.\n  mov rbx,player\n  cmp [rbx],rcx\n  je initiateEnemyApocalypse\n  jmp initiateApocalypseExit\ninitiatePlayerApocalypse:\n  \/\/ Realign the player's coordinates so it begins at the X coordinate.\n  mov rcx,[rbx]\n  lea rax,[rcx+50]\n  \/\/ Convert the player's maximum health to floating point.\n  mov rbx,playerHealth\n  mov rcx,[rbx]  \n  cvtsi2ss xmm2,[rcx+13C]\n  \/\/ Push the damage amount parameter.\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the working health value parameter.\n  sub rsp,8\n  movd [rsp],xmm0\n  \/\/ Push the maximum health value parameter.\n  sub rsp,8\n  movd [rsp],xmm2\n  \/\/ Push the aligned coordinates struct parameter.\n  push rax\n  call executePlayerApocalypse\n  jmp initiateApocalypseUpdateDamage\ninitiateEnemyApocalypse:\n  \/\/ Push the damage amount parameter.\n  sub rsp,8\n  movd [rsp],xmm1\n  \/\/ Push the working health value parameter.\n  sub rsp,8\n  movd [rsp],xmm0\n  call executeEnemyApocalypse\ninitiateApocalypseUpdateDamage:\n  \/\/ Convert the updated damage amount to an integer.\n  movd xmm0,eax\n  cvtss2si eax,xmm0\n  mov [rbp-44],eax\n  \/\/ Convert the updated working health value to an integer.\n  movd xmm0,ebx\n  cvtss2si eax,xmm0\ninitiateApocalypseExit:\n  pop rbx\n  pop rcx\n  movdqu xmm2,[rsp]\n  add rsp,10\n  movdqu xmm1,[rsp]\n  add rsp,10\n  movdqu xmm0,[rsp]\n  add rsp,10\ninitiateApocalypseOriginalCode:\n  popf\n  sub eax,[rbp-44]\n  mov [rsp+58],eax\n  jmp initiateApocalypseReturn\n\nomnifyApocalypseHook:\n  jmp initiateApocalypse\n  nop 2\ninitiateApocalypseReturn:\n\n\nnegativeVerticalDisplacementEnabled:\n  dd 0\n  \nteleportitisDisplacementX:\n  dd (float)5.0\n  \nyIsVertical:\n  dd 0\n  \nextraDamageX:\n  dd (float)2.0\n<\/pre>\n\n\n<p>In addition to the initiation point hook, we also have some code being inserted into the game that removes its one hit kill protection, which is a terrible thing really (the one hit kill protection, not my code <em>duh<\/em>). A world without one hit kills would be an awful world to live in!<\/p>\n\n\n\n<p>The unique array of bytes we wrote down for this was <code>0F B6 8D EC 00 00 00<\/code>, so let&#8217;s cross our fingers once again. Unfortunately, for this, we get two results back. So, we need to do some guessing. Disassembling the first result, I see an <code>idiv<\/code> instruction, indicating that some integer division is going on. <\/p>\n\n\n\n<p>This is something that I do remember occurring nearby the hook we made to prevent the one hit kill protection from going off (it was the integer division that was essentially testing whether or not our health was below the safe threshold), so we&#8217;ll update our code to inject into where the first result is pointing to.<\/p>\n\n\n\n<h3>Updated Depussification Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Bypasses the one hit kill protection system.\n\/\/ Unique AOB: 0F B6 8D EC 00 00 00\ndefine(omnifyDepussifyGameHook, &quot;ACValhalla.exe&quot; + 20EBE76)\n\nassert(omnifyDepussifyGameHook, 0F B6 8D EC 00 00 00)\nalloc(depussifyGame,$1000, omnifyDepussifyGameHook)\n\nregistersymbol(omnifyDepussifyGameHook)\n\ndepussifyGame:\n  \/\/ This is a hardcoded value used as a divisor applied against\n  \/\/ the player's maximum health to see if the player is protected\n  \/\/ from being one shot. By increasing this to max we essentially\n  \/\/ make all values of health unsafe.\n  mov [rbp+EC],0xFF\ndepussifyGameOriginalCode:\n  movzx ecx,byte ptr [rbp+000000EC]\n  jmp depussifyGameReturn\n\n\nomnifyDepussifyGameHook:\n  jmp depussifyGame\n  nop 2\ndepussifyGameReturn:\n<\/pre>\n\n\n<p>And we&#8217;re not quite done yet. We had another hook in place to allow for coordinate changes stemming from teleportitis to persist despite being in the middle of a damage-related animation. The unique array of bytes for this is <code>0F 28 48 30 0F 29 49 50<\/code>. Crossing my fingers.<\/p>\n\n\n\n<p>Only one result back. Fantastic. Time to update this then.<\/p>\n\n\n\n<h3>Updated Teleportitis Overwrite Bypass Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Bypasses a single location update pulse so that coordinates changes\n\/\/ from a teleportitis effect are not overwritten.\n\/\/ Unique AOB: 0F 28 48 30 0F 29 49 50\ndefine(omnifyBypassTeleportitisOverwriteHook, &quot;ACValhalla.exe&quot; + 7E878A)\n\nassert(omnifyBypassTeleportitisOverwriteHook,0F 28 48 30 0F 29 49 50)\nalloc(bypassTeleportitisOverwrite,$1000,omnifyBypassTeleportitisOverwriteHook)\n\nregistersymbol(omnifyBypassTeleportitisOverwriteHook)\n\nbypassTeleportitisOverwrite:\n  pushf\n  \/\/ Ensure that the player location struct has been initialized.\n  push rax\n  mov rax,playerLocation\n  cmp [rax],0  \n  pop rax\n  je bypassTeleportitisOverwriteOriginalCode  \n  \/\/ Backup registers used to hold the player's location structures.\n  push rax\n  push rbx\n  push rdx\n  \/\/ Backup the &quot;updated location&quot; structure address.\n  mov rdx,rax\n  mov rax,playerLocation\n  mov rbx,[rax]\n  \/\/ If the player is the one moving, we make sure that any new coordinates\n  \/\/ resulting from a recent teleport stick for one additional location\n  \/\/ update tick.\n  cmp rbx,rcx\n  jne bypassTeleportitisOverwriteExit\n  mov rax,teleported\n  cmp [rax],1\n  jne bypassTeleportitisOverwriteExit\n  \/\/ Clear the flag so this only happens once.\n  mov [rax],0\n  \/\/ Take the current coordinates and store them in the &quot;updated location&quot; \n  \/\/ structure used in the original code as the source for the new coordinates.\n  movups xmm1,[rcx+50]\n  movups [rdx+30],xmm1\nbypassTeleportitisOverwriteExit:  \n  \/\/ Restore backed up values.\n  pop rdx\n  pop rbx\n  pop rax\nbypassTeleportitisOverwriteOriginalCode:\n  popf\n  movaps xmm1,[rax+30]\n  movaps [rcx+50],xmm1\n  jmp bypassTeleportitisOverwriteReturn\n\nomnifyBypassTeleportitisOverwriteHook:\n  jmp bypassTeleportitisOverwrite\n  nop 3\nbypassTeleportitisOverwriteReturn:\n<\/pre>\n\n\n<p>That&#8217;s it for the Apocalypse system.<\/p>\n\n\n\n<h2>Updating the Predator System&#8217;s Hooks<\/h2>\n\n\n\n<p>Next up to bat are hooks related to the Predator system. Fortunately, for this game-neutral system, there is only a single hook to update: its initiation point. This resides right where the movement application code is, which wasn&#8217;t the easiest thing to find, of course.<\/p>\n\n\n\n<p>The unique array of bytes for this is <code>0F 10 56 50 4C 8D 4C 24 30<\/code>. Please, please, give me some good results here.<\/p>\n\n\n\n<p>Viola! A single result is returned. Let&#8217;s update our hook to work here.<\/p>\n\n\n\n<h3>Updated Predator Initiation Point Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Predator system.\n\/\/ Unique AOB:0F 58 C3 0F 11 06 F3\n\/\/ xmm0: Target's current coordinate values.\n\/\/ xmm3: Target's movement offsets.\ndefine(omnifyPredatorHook, &quot;ACValhalla.exe&quot; + F0CA43)\n\nassert(omnifyPredatorHook, 0F 58 C3 0F 11 06)\nalloc(initiatePredator,$1000, omnifyPredatorHook)\nalloc(identityValue,8)\nalloc(playerSpeedX,8)\n\nregistersymbol(omnifyPredatorHook)\nregistersymbol(playerSpeedX)\n        \ninitiatePredator:\n  pushf\n  \/\/ Ensure that the player location struct has been initialized.\n  push rax\n  mov rax,playerLocation\n  cmp [rax],0\n  pop rax\n  je initiatePredatorOriginalCode\n  \/\/ Backing up a few SSE registers we'll be using to perform a little\n  \/\/ memory management.\n  sub rsp,10\n  movdqu [rsp],xmm0\n  sub rsp,10\n  movdqu [rsp],xmm1\n  \/\/ Backing up the registers used by the Predator system to hold its\n  \/\/ return values.\n  push rax\n  push rbx\n  push rcx\n  \/\/ If it is the player moving, we'll want to avoid Predator execution\n  \/\/ and simply apply the player speed modifier.\n  \/\/ An interim data structure linking to the creature's location\n  \/\/ structure can be found on the stack.\n  mov rax,[rsp+14A]\n  \/\/ The location structure is found at the 0x18 offset of this\n  \/\/ interim structure.\n  push rcx\n  lea rcx,[rax+18]\n  call checkBadPointer\n  cmp rcx,0\n  pop rcx\n  jne initiatePredatorCleanup\n  mov rbx,[rax+18]\n  mov rax,playerLocation\n  cmp rbx,[rax]\n  je applyPlayerSpeed  \ninitiatePredatorExecute:\n  \/\/ The player's coordinates are pushed as the first parameter.\n  mov rax,playerLocation\n  mov rbx,[rax]\n  push [rbx+50]\n  push [rbx+58]\n  \/\/ Parameters values are expected to have been pushed to the stack as\n  \/\/ if a m32 operand was used. Since two of the parameter sets are on\n  \/\/ SSE registers, we'll need to split low and high words, and then\n  \/\/ dump them onto the stack as quadwords (low and then high).\n  movhlps xmm1,xmm0\n  \/\/ Lets push the target's coordinates as the second parameter.\n  sub rsp,8\n  movq [rsp],xmm0\n  sub rsp,8\n  movq [rsp],xmm1  \n  \/\/ An identity matrix is used as we have not made the determination as\n  \/\/ of yet as to whether the game uses true scaling or not. \n  \/\/ We pass this as the third parameter.\n  movss xmm0,[identityValue]\n  shufps xmm0,xmm0,0\n  sub rsp,10\n  movdqu [rsp],xmm0\n  \/\/ Now we split up the movement offset SSE register.\n  movhlps xmm1,xmm3\n  \/\/ Lets push the target's movement offsets as the final parameter.\n  sub rsp,8\n  movq [rsp],xmm3\n  sub rsp,8\n  movq [rsp],xmm1\n  \/\/ Time to execute dat Predator system.\n  call executePredator\n  jmp initiatePredatorExit\napplyPlayerSpeed:\n  \/\/ We'll be applying the player speed multiplier to all movement offsets\n  \/\/ except the Z (vertical) offset.\n  sub rsp,10\n  \/\/ We want to preserve the Z offset before applying the multiplier.\n  movups [rsp],xmm3\n  mov ecx,[rsp+8]\n  movss xmm0,[playerSpeedX]\n  shufps xmm0,xmm0,0\n  mulps xmm3,xmm0\n  movups [rsp],xmm3\n  \/\/ Load the modifier X and Y offsets.\n  mov eax,[rsp]\n  mov ebx,[rsp+4]\n  add rsp,10\ninitiatePredatorExit:\n  \/\/ We'll need to make some room on the stack for temporary use so\n  \/\/ we can load updated values back onto the SSE register used by\n  \/\/ the original code to apply the movement offsets.\n  sub rsp,10\n  \/\/ Start with the original movement offsets.\n  movups [rsp],xmm3\n  \/\/ Apply the updated offsets.\n  mov [rsp],eax\n  mov [rsp+4],ebx\n  mov [rsp+8],ecx\n  movups xmm3,[rsp]\n  add rsp,10\ninitiatePredatorCleanup:\n  \/\/ Restore backed up values.\n  pop rcx\n  pop rbx\n  pop rax\n  movdqu xmm1,[rsp]\n  add rsp,10\n  movdqu xmm0,[rsp]\n  add rsp,10  \ninitiatePredatorOriginalCode:\n  popf\n  addps xmm0,xmm3\n  movups [rsi],xmm0\n  jmp initiatePredatorReturn\n\n\nomnifyPredatorHook:\n  jmp initiatePredator\n  nop \ninitiatePredatorReturn:\n\n\nidentityValue:\n  dd (float)1.0\n  \nplayerSpeedX:\n  dd (float)1.0\n  \nskipBoostY:\n  dd 0\n  \nskipBoostZ:\n  dd 1\n<\/pre>\n\n\n<p>We&#8217;re actually almost done! All that remains is the Abomnification system. Hopefully not much damage was done here.<\/p>\n\n\n\n<h2>Updating the Abomnification System Hooks<\/h2>\n\n\n\n<p>As we <a href=\"https:\/\/badecho.com\/index.php\/2020\/12\/27\/hacking-ac-valhalla-part-4\/\" target=\"_blank\" rel=\"noreferrer noopener\">discussed at length earlier<\/a>, <em>Assassin&#8217;s Creed: Valhalla<\/em> lacks built-in easy scaling, which means that two hooks were needed in order to implement the Abomnification system. The first, the initiation point for the Abomnification system, was placed into a coordinate polling function for NPCs. We wrote down its unique array of bytes as <code>0F 10 56 50 4C 8D 4C 24 30<\/code>. <\/p>\n\n\n\n<p>Searching for that, it looks like we have a single hit! Yay! Hopefully we are able to make our hacks compatible with this latest version without incident. Let&#8217;s update our initiation point hook then.<\/p>\n\n\n\n<h3>Updated Abomnification Initiation Point Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Initiates the Abomnification system.\n\/\/ UNIQUE AOB: 0F 10 56 50 4C 8D 4C 24 30\ndefine(omnifyAbomnificationHook, &quot;ACValhalla.exe&quot; + 2823120)\n\nassert(omnifyAbomnificationHook, 0F 10 56 50 4C 8D 4C 24 30)\nalloc(initiateAbomnification,$1000, omnifyAbomnificationHook)\n\nregistersymbol(omnifyAbomnificationHook)\n\ninitiateAbomnification:\n  pushf\n  \/\/ Ensure that the player location struct has been initialized.\n  push rax\n  mov rax,playerLocation\n  cmp [rax],0\n  pop rax\n  je initiateAbomnificationOriginalCode \n  \/\/ Back up the registers used to hold return values.\n  push rax\n  push rbx\n  push rcx\n  \/\/ Ensure that the player isn't going to be Abomnified.\n  mov rax,playerLocation\n  mov rbx,[rax]\n  cmp rbx,rsi\n  je initiateAbomnificationExit\n  \/\/ Push the identifying address parameter and call the Abomnification system.  \n  push rsi\n  call executeAbomnification    \ninitiateAbomnificationExit:\n  \/\/ Restore the preserved values on the stack.\n  pop rcx\n  pop rbx\n  pop rax\ninitiateAbomnificationOriginalCode:\n  popf\n  movups xmm2,[rsi+50]\n  lea r9,[rsp+30]\n  jmp initiateAbomnificationReturn\n\n\nomnifyAbomnificationHook:\n  jmp initiateAbomnification\n  nop 4\ninitiateAbomnificationReturn:\n\n\nabominifyWidthResultUpper:\n  dd #250\n  \nabominifyHeightResultUpper:\n  dd #160\n  \nabominifyDepthResultUpper:\n  dd #200\n  \nunnaturalSmallX:\n  dd (float)0.5625\n<\/pre>\n\n\n<p>Fantabulous. All that remains now is the hook for applying the Abomnification generated scale multipliers. This was located in some rendering code, so for the sake out my sanity, let&#8217;s hope that we can find it again. The unique array of bytes for this was written down as <code>44 0F 59 05 15 B0 2C 03<\/code>.<\/p>\n\n\n\n<p>And&#8230;no results. Crap! Did the patch actually change something as low level as the rendering code we were hooking into? Looking at the actual original instructions that were at play here, I quickly realized that had nothing to do with it at all.<\/p>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nmulps xmm8,[ACValhalla.exe+415A470]\n<\/pre>\n\n\n<p>We were hooking into the above instruction. If you can&#8217;t remember, this instruction is taking what I termed as the &#8220;global scale multipliers&#8221; and multiplying them against some vertex offset values loaded into <code>xmm8<\/code>. These global scale multipliers were being stored and loaded from <em>static<\/em> memory. Well, of course there would be <em>zero<\/em> guarantee that this address wouldn&#8217;t change between versions.<\/p>\n\n\n\n<p>In fact, you would be reasonably safe if you bet money on the chance that its address <em>would<\/em> change. So, note to self: don&#8217;t use the unique array of bytes for an instruction referencing static memory as a means to locate code in the future. Luckily for me, I had this lovely hackpad website I could use, which had a nice article on implementing the Abomnification system into this game, with screenshots showing code nearby the hook.<\/p>\n\n\n\n<p>Using these screenshots, I found the proper place to insert the hook post-patch, and I wrote down a new unique array of bytes for code nearby, but not on top of where we were hooking into.<\/p>\n\n\n\n<h3>Updated Abomnification Scale Application Hook<\/h3>\n\n\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Applies Abomnification generated scale multipliers.\n\/\/ Unique AOB: 0F 11 62 10 4C 03 C1\ndefine(omnifyApplyAbomnificationHook, &quot;ACValhalla.exe&quot; + E8F813)\n\nassert(omnifyApplyAbomnificationHook, 44 0F 59 05 55 DC 2E 03)\nalloc(applyAbomnification,$1000, omnifyApplyAbomnificationHook)\n\nregistersymbol(omnifyApplyAbomnificationHook)\n\napplyAbomnification:\n  pushf\n  \/\/ Ensure that the player location struct has been initialized.\n  push rax\n  mov rax,playerLocation\n  cmp [rax],0\n  pop rax\n  je applyAbomnificationOriginalCode\n  \/\/ Backing up an SSE register to hold our multiplier.\n  sub rsp,10\n  movdqu [rsp],xmm0  \n  \/\/ Backing up the registers used to hold return values by the\n  \/\/ Abomnification system.\n  push rax\n  push rbx\n  push rcx  \n  \/\/ A rendering supplementary data structure is stored on the stack.\n  mov rax,[rsp+6A]\n  \/\/ If the bytes at 0x14 are not zeroed, then the rendering data structure\n  \/\/ is not pointing to a location structure.\n  mov rbx,[rax+14]\n  cmp ebx,0\n  jne applyAbomnificationExit\n  \/\/ The location structure is found here, however we need to check that \n  \/\/ it's a valid pointer, as there is still a chance for some junk data here.\n  mov rbx,[rax+18]  \n  push rcx\n  lea rcx,[rbx]\n  call checkBadPointer\n  cmp ecx,0\n  pop rcx\n  jne applyAbomnificationExit    \n  \/\/ Ensure that the player isn't going to be Abomnified.\n  mov rax,playerLocation\n  cmp rbx,[rax]\n  je applyAbomnificationExit\n  \/\/ Push the identifying address parameter and get the Abomnified scales.  \n  push rbx\n  call getAbomnifiedScales\n  \/\/ Make some room on the stack so we can construct the multiplier SSE register.\n  sub rsp,10\n  movss xmm0,[identityValue]\n  shufps xmm0,xmm0,0\n  movups [rsp],xmm0\n  mov [rsp],eax\n  mov [rsp+4],ecx\n  mov [rsp+8],ebx\n  movups xmm0,[rsp]\n  add rsp,10\n  \/\/ Apply the Abomnified scale multipliers to the register that will be applied\n  \/\/ against the global scale parameters.\n  mulps xmm8,xmm0\napplyAbomnificationExit:\n  \/\/ Restore the preserved values on the stack.\n  pop rcx\n  pop rbx\n  pop rax\n  movdqu xmm0,[rsp]\n  add rsp,10\napplyAbomnificationOriginalCode:\n  popf \n  mulps xmm8,[ACValhalla.exe+417D470]\n  jmp applyAbomnificationReturn\n\n\nomnifyApplyAbomnificationHook:\n  jmp applyAbomnification\n  nop 3\napplyAbomnificationReturn:\n<\/pre>\n\n\n<p>Whew. We avoided having to have to look for that crap again.<\/p>\n\n\n\n<h2>Omnified AC: Valhalla is 1.1.1 Ready!<\/h2>\n\n\n\n<p>Hooray! Hopefully there won&#8217;t be another patch for a little bit. Time to enjoy the updates along with the rest of the world.<\/p>\n\n\n\n<p>Until next time, take care.<\/p>\n\n\n\n<p>~<em>Omni<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Somewhat Unexpected Update Ah what joy. A new update for Assassin&#8217;s Creed: Valhalla has been released upon the masses. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[39,9],"tags":[24,22,53],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v14.9 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\r\n<title>Hacking Assassin&#039;s Creed: Valhalla - Part 6 (1.1.1 Patch) - omni&#039;s hackpad<\/title>\r\n<meta name=\"description\" content=\"Version 1.1.1 has been released for AC: Valhalla, which means we need to make some updates to our Omnified hack!\" \/>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/\" \/>\r\n<meta property=\"og:locale\" content=\"en_US\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"Hacking Assassin&#039;s Creed: Valhalla - Part 6 (1.1.1 Patch) - omni&#039;s hackpad\" \/>\r\n<meta property=\"og:description\" content=\"Version 1.1.1 has been released for AC: Valhalla, which means we need to make some updates to our Omnified hack!\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/\" \/>\r\n<meta property=\"og:site_name\" content=\"omni&#039;s hackpad\" \/>\r\n<meta property=\"article:published_time\" content=\"2021-01-14T20:41:05+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2021-01-20T18:27:55+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/v111.png\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/badecho.com\/#website\",\"url\":\"https:\/\/badecho.com\/\",\"name\":\"omni&#039;s hackpad\",\"description\":\"Game Code Disassembly. Omnified Modification. Madness.\",\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/badecho.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/badecho.com\/wp-content\/uploads\/2021\/01\/v111.png\",\"width\":960,\"height\":540,\"caption\":\"A new version! Hopefully we can salvage our Omnified hack.\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/#webpage\",\"url\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/\",\"name\":\"Hacking Assassin's Creed: Valhalla - Part 6 (1.1.1 Patch) - omni&#039;s hackpad\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/#primaryimage\"},\"datePublished\":\"2021-01-14T20:41:05+00:00\",\"dateModified\":\"2021-01-20T18:27:55+00:00\",\"description\":\"Version 1.1.1 has been released for AC: Valhalla, which means we need to make some updates to our Omnified hack!\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/#webpage\"},\"author\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"headline\":\"Hacking Assassin&#8217;s Creed: Valhalla &#8211; Part 6 (1.1.1 Patch)\",\"datePublished\":\"2021-01-14T20:41:05+00:00\",\"dateModified\":\"2021-01-20T18:27:55+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\"},\"image\":{\"@id\":\"https:\/\/badecho.com\/index.php\/2021\/01\/14\/hacking-ac-valhalla-part-6\/#primaryimage\"},\"keywords\":\"Hacking,Omnifying,Patches\",\"articleSection\":\"AC: Valhalla,Games\",\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/badecho.com\/#\/schema\/person\/3de67496328be7ae6e1f52faf582e9d2\",\"name\":\"Matt Weber\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/badecho.com\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/7e345ac2708b3a41c7bd70a4a0440d41?s=96&d=mm&r=g\",\"caption\":\"Matt Weber\"},\"logo\":{\"@id\":\"https:\/\/badecho.com\/#personlogo\"}}]}<\/script>\r\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1086"}],"collection":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/comments?post=1086"}],"version-history":[{"count":2,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1086\/revisions"}],"predecessor-version":[{"id":1089,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/posts\/1086\/revisions\/1089"}],"wp:attachment":[{"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/media?parent=1086"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/categories?post=1086"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/badecho.com\/index.php\/wp-json\/wp\/v2\/tags?post=1086"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}