Zombie Army 4: Dead War [Engine:Asura]
Posted: Tue Feb 18, 2020 3:21 am
[ 24 Feb 20 - Update #3 ]
Added the following:
[ 21 Feb 20 - Update #2 ]
Added the following:
And I'm tired of this game
BR,
Sun
[ 19 Feb 20 - Update #1 ]
I've taken a short break from hacking the actual game to focus a bit more on Asura engine The game, as mentioned, allows access to its console via Tilde (~`) key. Once opened, you'll then wonder "what can I do with this console?". The first thing I tried, considering this isn't documented in places (perhaps in older Sniper Elite games, someone, somewhere, posted a comprehensive commands/vars list[?]) was to type in the word help. Most command-line console windows feature this command as a starting point. And so I did:
So, "help" with no parameters will print the default user-friendly information. Using this with a parameter will show extensive information about given command/variable. Then I noticed two important commands which helped me in the upcoming analysis of the game engine: listcmds and listvars.
Typed the first and saw this:
Really, Rebellion? This many commands? Hmm Then I noticed SearchCmds and SearchVars which allow you to search the list of commands and variables for strings that contain your query (e.g.: like InStr function - find a sub-string in a string). Then Clear command will clear the console buffer, as well as the screen. Ran that.
Then ran the listvars command to see what's there:
Again.. really, Rebellion?.. Really?
From past encounters with idTech 5 engine I kinda expected something like this. The question is: are there more commands and variables one can make use of - OR - were they stripped? Rephrasing: is there a condition based on which they are not shown - OR - stripped? I soon discovered it was the first one: the condition is the command/variable flag. Not only for display when queried, but also for execution.
In the first post down below I mentioned this:
This will happen with any marked command/variable execution. So then I said to myself "welp, in order to find that flag check, I'll need a starting point". And that starting point was the error message. So I searched for all string references and found the string here:
Set a breakpoint and re-ran the command. And x64dbg breaks.
I could detail all the logic I then devised to determine these checks, but to make it short I will leave you with these key points:
Here's an example of looking for "player"-related commands:
Here's an example of a command that populates the total XP you've gained to the console:
I hope you do realize these executions can be traced and you can create some nice table or trainer options out of them, right?
Like I said, these are undocumented, so asking "what does this do?" will result in a big IGNORE from my part. Why? Because the least you can do is freakin' test them out yourselves, considering I've done the heavy-lifting and made these available.
Lastly, what for you seems useless.. to me it is useful. Why? Because I could learn more about the engine's internals than be happy to use some god or whatever command and play the game More games Asura-driven are going to be produced by Rebellion in the future. Keep that in mind when you look condescendingly over the usefulness of my posts here, mmk? Vision over short-moment.
[ 18 Feb 20 - First Release ]
Game Name: Zombie Army 4: Dead War
Game Vendor: Epic
Game Version: ZA4 D3D12_Retail_Submission_Epic v1.15 (2020.02.10.170) - 21:31:46, Feb 10 2020 - NID 503
[ open the console with Tilde (~`) key in-game and check it out ]
Game Process: ZA4_dx12.exe
[Link]
This is yet another zombie brain smasher from Rebellion, the guys who've also brought us Strange Brigade (see my topic here) Need I tell you that the array I used in the [ Enable ] script for that game works in this one as well? Try scanning for the below array, you'll see what I mean:
Features:
Theory (and for me to remember in later Asura games):
- this array works in both Strange Brigade and Zombie Army 4, pin-pointing the location where, if scrolling a bit, you find the global TEST instruction through which our Player structure is processed; just remember to do Memory Map > Ctrl+B so it's scanned in all memory (not just main executable module) -> "B8 79 91 F3 D5"
- you will find this:
- next-up, so I don't have to apply that filter there, I used this array: "48 8B 47 08 48 63 48 04 F6 44 39 10 01 0F 85"
- there will be many results; start F2-ing in the References window till one breaks
- note down the address composite and add it to CE list, then debug it to obtain a substantial list of breaks
- find one occurrence that runs ONLY for your player (when debugging it to "Find out what addresses this instruction accesses", you should have only 1 result)
- make sure you debug "TEST BYTE PTR [R64+R64+10],1" instructions, not something else (like "TEST BYTE PTR [R64+8],1")
- you'll have a sequence like this:
- the offset to the Player structure is taken out of [RAX+4]
- the offset to the Player sub-systems is taken out of [RAX+8]
- add base + [RAX+8] to your list and inspect its memory; somewhere close to 0x58 or 0x70 you will see a float; that's your HP
- debug that float on access and inspect the results, scrolling up, till you find one that looks like this:
- the function above is then hookable, stable and does real-time reading of your HP
- the above represents the hook I use in [ Enable ] script to get all I need :]
- and I think LocalActor can be obtained from the static pointer within "StatTracking.PopulateCurrentBankedScore":
BR,
Sun
P.S.: That game banner under "Game Process".. yeah, I made that in Fireworks based on the Steam model. Too bad the plugin (or code) STN added into phpBB doesn't cover Epic Store titles as well.
Added the following:
- Unlimited Ammo/Items
Gives you 999 magazine ammo and items. Note that this is not a value I've chosen to hard-code, it exists in the engine itself. It was just a matter of finding the flip switch.
- Coordinates
Expanding this header will allow access to player's Y,Z,X coordinates and some already defined arrays. 'Full Array' should help you pin-point specific locations where collectibles are found (includes the facing vector). Just stop in front of a collectible, as fixed as you can, then copy-paste the Full Array to Notepad++. Move away from to some other spot, then copy-paste the value you stored over the current Full Array's value. You'll see what happens: instant teleport to the collectible's position (in front of it), including the Actor orientation (we want to be teleported facing the collectible, not with our back turned).
- Hook Weapon Scope Target Coords
Enable the script, then use a sniping weapon to target a random location. 'ScopePos_YZX_Array', 'ScopePos_Y', 'ScopePos_Z' and 'ScopePos_X' will become available.- Teleport To Scope Pos
Enable the script, then press Numpad 0 to teleport to scoped position. You might want to target the spot first. This should also help you get out of bugged locations. Example: pin-point a roof-top or something high enough. See the screenshot below in Venice.
- Teleport To Scope Pos
[ 21 Feb 20 - Update #2 ]
Added the following:
- Unlimited Clip/Attachment Ammo
Will keep your Clip or Attachment locked to current value. Player only.
- Unlimited Stamina/Heart Rate
Heart Rate (as it's called internally) won't decrease when you run or hold your breath. It might when you stomp bodies, but don't worry about it. Player only.
- No Recoil
Does what it says. Player only.
- Super Accuracy
Does what it says. Player only.
- Fast Fire
Does what it says. You might experience some occasional pause while firing machine guns, every 5-10s or so, can't be arsed to adjust that. Player only.
- Upgrade Tokens
You can edit them in the table directly, manually.
And I'm tired of this game
BR,
Sun
[ 19 Feb 20 - Update #1 ]
- Console Goodies
Will enable the exec flag for all commands and variables in the engine. Read more in the below to make sense of this.
- [CE Lua Console] Log Commands/Variables
Will log to CE Lua window all console output, regardless of flag status:
- comment/uncomment lines 9/10 in the script based on your query
- comment/uncomment lines 23/24/25/26 in the script based on your query
- e.g.: to list all commands using 'listcmds' uncomment line 9 and comment line 10, then comment lines 24/25/26 leaving only line 23 uncommented
- keep in mind these are paired
Read more in the below to make sense of this.
I've taken a short break from hacking the actual game to focus a bit more on Asura engine The game, as mentioned, allows access to its console via Tilde (~`) key. Once opened, you'll then wonder "what can I do with this console?". The first thing I tried, considering this isn't documented in places (perhaps in older Sniper Elite games, someone, somewhere, posted a comprehensive commands/vars list[?]) was to type in the word help. Most command-line console windows feature this command as a starting point. And so I did:
So, "help" with no parameters will print the default user-friendly information. Using this with a parameter will show extensive information about given command/variable. Then I noticed two important commands which helped me in the upcoming analysis of the game engine: listcmds and listvars.
Typed the first and saw this:
Really, Rebellion? This many commands? Hmm Then I noticed SearchCmds and SearchVars which allow you to search the list of commands and variables for strings that contain your query (e.g.: like InStr function - find a sub-string in a string). Then Clear command will clear the console buffer, as well as the screen. Ran that.
Then ran the listvars command to see what's there:
Again.. really, Rebellion?.. Really?
From past encounters with idTech 5 engine I kinda expected something like this. The question is: are there more commands and variables one can make use of - OR - were they stripped? Rephrasing: is there a condition based on which they are not shown - OR - stripped? I soon discovered it was the first one: the condition is the command/variable flag. Not only for display when queried, but also for execution.
In the first post down below I mentioned this:
Well, try to run that command and see what you get (you can copy it and paste it in the console):and I think LocalActor can be obtained from the static pointer within "StatTracking.PopulateCurrentBankedScore"
This will happen with any marked command/variable execution. So then I said to myself "welp, in order to find that flag check, I'll need a starting point". And that starting point was the error message. So I searched for all string references and found the string here:
Set a breakpoint and re-ran the command. And x64dbg breaks.
I could detail all the logic I then devised to determine these checks, but to make it short I will leave you with these key points:
- 0xC and 0x1C offsets hold the flags for a command (0xC) and variable (0x1C)
- patching both of the above to flag of value 0x1 will render ALL commands/variables shown when queried for and executable
- the function behind the execution of a command can be determined by checking the member-functions pointer in same structure with 0xC flag, 2nd function in the vtable (0x8); example of a run-down (using "Clear" command):
MOV RCX,QWORD PTR DS:[RCX+20] <-- 0x20 in struct with 0xC flag
MOVZX EDX,R8B
MOV RAX,QWORD PTR DS:[RCX]
JMP QWORD PTR DS:[RAX+20]
..
MOV RAX,RCX
MOVZX ECX,DL
JMP QWORD PTR DS:[RAX+8] <-- the exec function
- these commands need patching - ListCmds, SearchCmds, ListVars, SearchVars - making it so the flag is set to 0x1 for each checked item
- you get to the patching spots by tracing the code of each command above:
//ListCmds
000000014C8BFC27 | F643 0C 01 | TEST BYTE PTR DS:[RBX+C],1 | cmd_flag_check
//SearchCmds
000000014C8C16E0 | F643 0C 01 | TEST BYTE PTR DS:[RBX+C],1 | cmd_flag_check
//ListVars
000000014C8C0907 | F643 1C 01 | TEST BYTE PTR DS:[RBX+1C],1 | var_flag_check
//SearchVars
000000014C8C2220 | F643 1C 01 | TEST BYTE PTR DS:[RBX+1C],1 | var_flag_check
- flag set to 0x1 for commands and variables so they become executable needs to be set at these spots:
//commands
000000014C8C3C20 | 8B40 0C | MOV EAX,DWORD PTR DS:[RAX+C] | cmd_flag_read
000000014C8C3C66 | 41:FF51 08 | CALL QWORD PTR DS:[R9+8] | exec_cmd
//variables
000000014C8C3C8B | 8B40 1C | MOV EAX,DWORD PTR DS:[RAX+1C] | var_flag_read
000000014C8C3CDB | E8 40689DF3 | CALL za4_dx12.14029A520 | exec_var
- the "Console Goodies" script already does that; the content is hard-coded for JUST this version of the game; I will not keep up with updates!
- if you patch the 4 commands and RUN 1 of each type - cmds, vars - you won't need to patch the 2 execution spots above, as the script already patches those flags
- from what I could gather, the variables are restored to their default value
- from what I could gather, most useful commands do "RET 1" a.k.a. "nothing" (e.g.: Player.Die, Cheat.Player.TeleportToEntity, etc.)
- the engine's print function is virtualized (I bet they used VMProtect crypt markers for this shit)
- due to that virtualization in use, once you make all commands and variables usable, you will experience a big lag when running the list or search commands; just don't freak out and end process cuz you'd think it's frozen; it's normal
commands
variables
Here's an example of a command that populates the total XP you've gained to the console:
I hope you do realize these executions can be traced and you can create some nice table or trainer options out of them, right?
Like I said, these are undocumented, so asking "what does this do?" will result in a big IGNORE from my part. Why? Because the least you can do is freakin' test them out yourselves, considering I've done the heavy-lifting and made these available.
Lastly, what for you seems useless.. to me it is useful. Why? Because I could learn more about the engine's internals than be happy to use some god or whatever command and play the game More games Asura-driven are going to be produced by Rebellion in the future. Keep that in mind when you look condescendingly over the usefulness of my posts here, mmk? Vision over short-moment.
[ 18 Feb 20 - First Release ]
Game Name: Zombie Army 4: Dead War
Game Vendor: Epic
Game Version: ZA4 D3D12_Retail_Submission_Epic v1.15 (2020.02.10.170) - 21:31:46, Feb 10 2020 - NID 503
[ open the console with Tilde (~`) key in-game and check it out ]
Game Process: ZA4_dx12.exe
[Link]
This is yet another zombie brain smasher from Rebellion, the guys who've also brought us Strange Brigade (see my topic here) Need I tell you that the array I used in the [ Enable ] script for that game works in this one as well? Try scanning for the below array, you'll see what I mean:
I really hope the game is good and entertaining, already seeing the engine is somewhat identical.aobscanmodule( GetBaseStuff, StrangeBrigade_DX12.exe, F64439??010F85????????803D????????000F85????????4885FF0F84????????486348??0F2F7C39 )
registersymbol( GetBaseStuff )
Features:
- God Mode (no stagger;no visuals)
Does what it says. Gotten tired of seeing the various trainers out there freezing just your health and moronically show-casing 3 minutes of how you don't die in the presentation video. Game-hackers, can we have some *proper* options? It's been years already since you've been pulling the same routine. Evolution, please?
Theory (and for me to remember in later Asura games):
- this array works in both Strange Brigade and Zombie Army 4, pin-pointing the location where, if scrolling a bit, you find the global TEST instruction through which our Player structure is processed; just remember to do Memory Map > Ctrl+B so it's scanned in all memory (not just main executable module) -> "B8 79 91 F3 D5"
- you will find this:
Code: Select all
000000014B57DEFD | F643 08 01 | TEST BYTE PTR DS:[RBX+8],1 |<-- boom
000000014B57DF01 | 0F85 42010000 | JNE za4_dx12.14B57E049 |
000000014B57DF07 | 44:3825 0F1938F6 | CMP BYTE PTR DS:[1418FF81D],R12B |
000000014B57DF0E | 0F85 35010000 | JNE za4_dx12.14B57E049 |
000000014B57DF14 | 807B 0C 01 | CMP BYTE PTR DS:[RBX+C],1 |
000000014B57DF18 | 0F85 2B010000 | JNE za4_dx12.14B57E049 |
000000014B57DF1E | 807B 0D 01 | CMP BYTE PTR DS:[RBX+D],1 |
000000014B57DF22 | 0F85 21010000 | JNE za4_dx12.14B57E049 |
000000014B57DF28 | 41:8B49 0C | MOV ECX,DWORD PTR DS:[R9+C] |
000000014B57DF2C | 85C9 | TEST ECX,ECX |
000000014B57DF2E | 0F84 09010000 | JE za4_dx12.14B57E03D |
000000014B57DF34 | 41:8B41 08 | MOV EAX,DWORD PTR DS:[R9+8] |
000000014B57DF38 | 83F9 01 | CMP ECX,1 |
000000014B57DF3B | 0F85 EF000000 | JNE za4_dx12.14B57E030 |
000000014B57DF41 | 29C8 | SUB EAX,ECX |
000000014B57DF43 | 41:8941 08 | MOV DWORD PTR DS:[R9+8],EAX |
000000014B57DF47 | 75 63 | JNE za4_dx12.14B57DFAC |
000000014B57DF49 | 44:3825 075C3AF6 | CMP BYTE PTR DS:[141923B57],R12B |
000000014B57DF50 | 74 57 | JE za4_dx12.14B57DFA9 |
000000014B57DF52 | 41:C741 0C 02000000 | MOV DWORD PTR DS:[R9+C],2 |
000000014B57DF5A | 8B0D 24527DF5 | MOV ECX,DWORD PTR DS:[140D53184] |
000000014B57DF60 | 8B05 1A527DF5 | MOV EAX,DWORD PTR DS:[140D53180] |
000000014B57DF66 | 44:0FBF05 14527DF5 | MOVSX R8D,WORD PTR DS:[140D53182] |
000000014B57DF6E | C1E0 10 | SHL EAX,10 |
000000014B57DF71 | 01C8 | ADD EAX,ECX |
000000014B57DF73 | 41:01C0 | ADD R8D,EAX |
000000014B57DF76 | B8 7991F3D5 | MOV EAX,D5F39179 |
- there will be many results; start F2-ing in the References window till one breaks
- note down the address composite and add it to CE list, then debug it to obtain a substantial list of breaks
- find one occurrence that runs ONLY for your player (when debugging it to "Find out what addresses this instruction accesses", you should have only 1 result)
- make sure you debug "TEST BYTE PTR [R64+R64+10],1" instructions, not something else (like "TEST BYTE PTR [R64+8],1")
- you'll have a sequence like this:
Code: Select all
000000014DF17023 | 48:8B47 08 | MOV RAX,QWORD PTR DS:[RDI+8] |
000000014DF17027 | 48:6348 04 | MOVSXD RCX,DWORD PTR DS:[RAX+4] |
000000014DF1702B | F64439 10 01 | TEST BYTE PTR DS:[RCX+RDI+10],1 |
- the offset to the Player sub-systems is taken out of [RAX+8]
- add base + [RAX+8] to your list and inspect its memory; somewhere close to 0x58 or 0x70 you will see a float; that's your HP
- debug that float on access and inspect the results, scrolling up, till you find one that looks like this:
Code: Select all
000000014F0C727B | 48:8B43 08 | MOV RAX,QWORD PTR DS:[RBX+8] |<-
000000014F0C727F | 48:6348 04 | MOVSXD RCX,DWORD PTR DS:[RAX+4] |<-
000000014F0C7283 | F64419 10 01 | TEST BYTE PTR DS:[RCX+RBX+10],1 |<-
000000014F0C7288 | 0F85 5E010000 | JNE za4_dx12.14F0C73EC |
000000014F0C728E | 803D 888583F2 00 | CMP BYTE PTR DS:[1418FF81D],0 |
000000014F0C7295 | 0F85 51010000 | JNE za4_dx12.14F0C73EC |
000000014F0C729B | 48:85DB | TEST RBX,RBX |
000000014F0C729E | 0F84 48010000 | JE za4_dx12.14F0C73EC |
000000014F0C72A4 | 48:6348 08 | MOVSXD RCX,DWORD PTR DS:[RAX+8] |<-
000000014F0C72A8 | 0F2F7C19 70 | COMISS XMM7,DWORD PTR DS:[RCX+RBX+70]|<-- checks HP
000000014F0C72AD | 0F83 39010000 | JAE za4_dx12.14F0C73EC |
000000014F0C72B3 | 49:8B7F 48 | MOV RDI,QWORD PTR DS:[R15+48] |
000000014F0C72B7 | 48:85FF | TEST RDI,RDI |
- the above represents the hook I use in [ Enable ] script to get all I need :]
- and I think LocalActor can be obtained from the static pointer within "StatTracking.PopulateCurrentBankedScore":
Code: Select all
0000000150AB4186 | 48:8B15 6BE4E9F0 | MOV RDX,QWORD PTR DS:[1419525F8] |<-- LocalActor
0000000150AB418D | 48:85D2 | TEST RDX,RDX |
0000000150AB4190 | 74 16 | JE za4_dx12.150AB41A8 |
0000000150AB4192 | 48:8B42 08 | MOV RAX,QWORD PTR DS:[RDX+8] |
0000000150AB4196 | 48:6348 04 | MOVSXD RCX,DWORD PTR DS:[RAX+4] |
0000000150AB419A | 8B5C11 18 | MOV EBX,DWORD PTR DS:[RCX+RDX+18] |<-- is initialized?
0000000150AB419E | 81FB E7030000 | CMP EBX,3E7 |
Sun
P.S.: That game banner under "Game Process".. yeah, I made that in Fireworks based on the Steam model. Too bad the plugin (or code) STN added into phpBB doesn't cover Epic Store titles as well.