I've been at this all day long, interpreting
UnrealScript tokenized code.. so here goes:
Starting from the HP processing function, I figured that I could swap the processed UFunction here:
Code: Select all
Darksiders3-Win64-Shipping.exe+32BCF2 - 48 8D 54 24 40 - lea rdx,[rsp+40]
Darksiders3-Win64-Shipping.exe+32BCF7 - E8 44B0EBFF - call Darksiders3-Win64-Shipping.exe+1E6D40
Enter the CALL and trace till here:
Code: Select all
Darksiders3-Win64-Shipping.exe+1E6EA5 - E8 D6F15100 - call Darksiders3-Win64-Shipping.exe+706080
Darksiders3-Win64-Shipping.exe+1E6EAA - 4C 8B 0B - mov r9,[rbx] <-- stop here
Note that all that happens inside "Darksiders3-Win64-Shipping.exe+1E6D40" is generic; so if you don't first break at "Darksiders3-Win64-Shipping.exe+32BCF2" and just go break inside the CALL, it'll break like mad
You've been warned. OK, let's continue.
At that location where I told you to stop you'll find that RAX points to this:
Code: Select all
[050266] Function Widget_HUD.Widget_HUD_C.Update Health 0x000001C78C7C8440
What I did was to look for "god" in the ObjectsDump.txt file and found this:
Code: Select all
[069023] Function BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode 0x000001C7B2A51A80
So I swapped 000001C78C7C8440 in RAX with 000001C7B2A51A80
If it doesn't run from first try, do it again.. there's some race condition that skips execution. 2nd try should work.
Once you do that, you'll notice 2 things:
a) you don't take anymore damage; nor are knocked-off
b) when you hit Escape, you can't exit to main menu anymore; aside from Resume, the other two options are grayed out; and we don't want that
So I started my crusade to see what really happens when Unreal Engine processes that SetFuryGodMode function. And found this logic:
Code: Select all
[050266] Function Widget_HUD.Widget_HUD_C.Update Health 0x000001C78C7C8440
Line 67780: [069023] Function BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode 0x000001C7B2A51A80
0000: 0F B0 4F 6D B7 C7 01 00 00 00 B0 4F 6D B7 C7 01
0010: 00 00 21 7F 66 03 00 7F 66 03 00 00 00 00 00 07
0020: 86 00 00 00 00 80 75 8A B7 C7 01 00 00 5F 00 80
0030: 80 8A B7 C7 01 00 00 19 20 F0 16 5F FA C7 01 00
0040: 00 0B 00 00 00 80 80 8A B7 C7 01 00 00 1C 70 17
0050: 19 FA C7 01 00 00 17 16 19 00 80 80 8A B7 C7 01
0060: 00 00 13 00 00 00 00 00 00 00 00 00 00 00 1C 30
0070: AF 12 FA C7 01 00 00 00 B0 4F 6D B7 C7 01 00 00
0080: 16 06 DB 00 00 00 5F 00 00 80 8A B7 C7 01 00 00
0090: 19 20 F0 16 5F FA C7 01 00 00 0B 00 00 00 00 80
00A0: 8A B7 C7 01 00 00 1C 70 17 19 FA C7 01 00 00 17
00B0: 16 19 00 00 80 8A B7 C7 01 00 00 14 00 00 00 00
00C0: 00 00 00 00 00 00 00 1C 90 E7 12 FA C7 01 00 00
00D0: 00 B0 4F 6D B7 C7 01 00 00 27 16 04 0B 53
000001C7B31C3EA0: 0F // +0x1
000001C7B31C3EA1: B0 4F 6D B7 C7 01 00 00 // +0x8
--> [069029] NameProperty BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode.EnteringCinematicTag 0x000001C7B76D4FB0
000001C7B31C3EA9: 00 // +0x1
000001C7B31C3EAA: B0 4F 6D B7 C7 01 00 00 // +0x8
--> [069029] NameProperty BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode.EnteringCinematicTag 0x000001C7B76D4FB0
Darksiders3-Win64-Shipping.exe+711D5C - 4C 63 41 44 - movsxd r8,dword ptr [rcx+44] // [0x000001C7B76D4FB0+0x44] == 0000000000000008
Darksiders3-Win64-Shipping.exe+711D60 - 4C 03 42 28 - add r8,[rdx+28]
Darksiders3-Win64-Shipping.exe+711D64 - 4C 89 42 38 - mov [rdx+38],r8
000001C7B31C3EB2: 21 // +0x1
000001C7B31C3EB3: 7F 66 03 00 7F 66 03 00 00 00 00 00 // +0xC (find function)
000001C7B31C3EBF: 07 // +0x1
000001C7B31C3EC0: 86 // +0x4
000001C7B31C3EC4: 00 // +0x1
000001C7B31C3EC5: 80 75 8A B7 C7 01 00 00 // +0x8
--> [069024] BoolProperty BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode.On 0x000001C7B78A7580
Darksiders3-Win64-Shipping.exe+711D5C - 4C 63 41 44 - movsxd r8,dword ptr [rcx+44] // [0x000001C7B78A7580+0x44] == 0000000000000000
Darksiders3-Win64-Shipping.exe+711D60 - 4C 03 42 28 - add r8,[rdx+28]
Darksiders3-Win64-Shipping.exe+711D64 - 4C 89 42 38 - mov [rdx+38],r8
000001C7B31C3ECD: 5F // +0x1
000001C7B31C3ECE: 00 // +0x1
000001C7B31C3ECF: 80 80 8A B7 C7 01 00 00 // +0x8
--> [069047] ObjectProperty BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode.CallFunc_GetDarksiders3Player_ReturnValue1 0x000001C7B78A8080
Darksiders3-Win64-Shipping.exe+711D5C - 4C 63 41 44 - movsxd r8,dword ptr [rcx+44] // [0x000001C7B78A8080+0x44] == 0000000000000018
Darksiders3-Win64-Shipping.exe+711D60 - 4C 03 42 28 - add r8,[rdx+28]
Darksiders3-Win64-Shipping.exe+711D64 - 4C 89 42 38 - mov [rdx+38],r8
000001C7B31C3ED7: 19 // +0x1
000001C7B31C3ED8: 20 // +0x1
000001C7B31C3ED9: F0 16 5F FA C7 01 00 00 // +0x8
--> [043132] Darksiders3Util Darksiders3.Default__Darksiders3Util 0x000001C7FA5F16F0
000001C7B31C3EED: 1C // +0x1
000001C7B31C3EEE: 70 17 19 FA C7 01 00 00 // +0x8
--> [017569] Function Darksiders3.Darksiders3Util.GetDarksiders3Player 0x000001C7FA191770
000001C7B31C3EF6: 17 // +0x1 +0x1
//GetCharacterFromPlayerController ;) (use PlayerController as RCX)
Darksiders3-Win64-Shipping.exe+208180 - 40 57 - push rdi
Darksiders3-Win64-Shipping.exe+208182 - 48 83 EC 20 - sub rsp,20 { 32 }
Darksiders3-Win64-Shipping.exe+208186 - 48 8B 81 90060000 - mov rax,[rcx+00000690] //
RCX --> [056850] Player_Controller_C World.World.PersistentLevel.Player_Controller_C_1 0x000001C78A7E4970
--> RAX: 0
Darksiders3-Win64-Shipping.exe+20818D - 48 8B F9 - mov rdi,rcx
Darksiders3-Win64-Shipping.exe+208190 - 48 85 C0 - test rax,rax
..
Darksiders3-Win64-Shipping.exe+20819A - 48 8B 99 48030000 - mov rbx,[rcx+00000348]
--> [396081] Character_Fury_C World.World.PersistentLevel.Character_Fury_C_1 0x000001C7B2192AE0
Darksiders3-Win64-Shipping.exe+2081A1 - 48 85 DB - test rbx,rbx
..
ret
000001C7B31C3EF6: 19 // +0x1
000001C7B31C3EF9: 00 // +0x1
000001C7B31C3EFA: 80 80 8A B7 C7 01 00 00 // +0x8
--> [069047] ObjectProperty BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode.CallFunc_GetDarksiders3Player_ReturnValue1 0x000001C7B78A8080
Darksiders3-Win64-Shipping.exe+711D5C - 4C 63 41 44 - movsxd r8,dword ptr [rcx+44] // [0x000001C7B78A8080+0x44] == 0000000000000018
Darksiders3-Win64-Shipping.exe+711D60 - 4C 03 42 28 - add r8,[rdx+28]
Darksiders3-Win64-Shipping.exe+711D64 - 4C 89 42 38 - mov [rdx+38],r8
basically returns:
[396081] Character_Fury_C World.World.PersistentLevel.Character_Fury_C_1 0x000001C7B2192AE0
000001C7B31C3F0E: 1C // +0x1
000001C7B31C3F0F: 30 AF 12 FA C7 01 00 00 // +0x8
--> [014614] Function GunfireRuntime.CharacterGunfire.AddTag 0x000001C7FA12AF30
000001C7B31C3F21: 06 // +0x1
000001C7B31C3F22: DB // +0x4 - - DB is an offset; leads to end of script
[069023] Function BP_DefaultStage.BP_DefaultStage_C.SetFuryGodMode 0x000001C7B2A51A80
Might not say much to you, but what I found was that in the damage processing function, before HP processing, this bit changes the flow of execution:
Code: Select all
Darksiders3-Win64-Shipping.exe+3048AC - 49 8B CF - mov rcx,r15
Darksiders3-Win64-Shipping.exe+3048AF - FF 50 18 - call qword ptr [rax+18]
Darksiders3-Win64-Shipping.exe+3048B2 - 84 C0 - test al,al
Darksiders3-Win64-Shipping.exe+3048B4 - 0F84 D9070000 - je Darksiders3-Win64-Shipping.exe+305093
Depending on the outcome of that CALL, the TEST will determine whether or not the JE is taken. So.. If AL is 0, the JE exits the function; thus you receive no damage. If AL is 1 (which is the normal behavior), you get damaged. Digging a bit deeper inside that CALL I found this:
Code: Select all
Darksiders3-Win64-Shipping.exe+41EE92 - 88 8C 24 F0010000 - mov [rsp+000001F0],cl // force 1
Darksiders3-Win64-Shipping.exe+41EE99 - 48 8B CB - mov rcx,rbx
Darksiders3-Win64-Shipping.exe+41EE9C - 41 FF 91 F8010000 - call qword ptr [r9+000001F8]
Darksiders3-Win64-Shipping.exe+41EEA3 - 48 8D 94 24 08010000 - lea rdx,[rsp+00000108]
Darksiders3-Win64-Shipping.exe+41EEAB - 48 8B CD - mov rcx,rbp
Darksiders3-Win64-Shipping.exe+41EEAE - E8 2DFBDCFF - call Darksiders3-Win64-Shipping.exe+1EE9E0 // run func
Darksiders3-Win64-Shipping.exe+41EEB3 - 0FB6 84 24 F0010000 - movzx eax,byte ptr [rsp+000001F0] // retrieve bool
The CALL @ "Darksiders3-Win64-Shipping.exe+41EEAE" will iterate and fetch an UFunction:
Code: Select all
[240383] Function Character_Fury.Character_Fury_C.FilterIncomingDamage 0x000002521C833A00
And that is applied to:
Code: Select all
[396259] Character_Fury_C World.World.PersistentLevel.Character_Fury_C_1 0x00000252F17A9570
So this is where we are.
We now have two spots where we can get proper god mode, without the need to run anything in the console:
Code: Select all
Darksiders3-Win64-Shipping.exe+3048AF - FF 50 18 - call qword ptr [rax+18]
Darksiders3-Win64-Shipping.exe+3048B2 - 84 C0 - test al,al
- OR -
Code: Select all
Darksiders3-Win64-Shipping.exe+41EEB3 - 0FB6 84 24 F0010000 - movzx eax,byte ptr [rsp+000001F0]
Let's study what happens in the registers at this location:
Code: Select all
00007FF61EA448AC | 49:8BCF | MOV RCX,R15 |
00007FF61EA448AF | FF50 18 | CALL QWORD PTR DS:[RAX+18] |
00007FF61EA448B2 | 84C0 | TEST AL,AL |
Right at the CALL, we have (keep in mind I'm taking damage from some AI that throws daggers at me):
RBP == [256328] DamageType_Light_NoParry_C DamageType_Light_NoParry.Default__DamageType_Light_NoParry_C | 0x000002523B96A100
RSI == [368324] Character_Sycophant_Stalker_Ranged_C Haven_D_Combat.Haven_D_Combat.PersistentLevel.Character_Sycophant_Stalker_Ranged_C_1 | 0x00000252C4820DC0
But nowhere above in the registers do we see OUR Character's UObject pointer or something relevant to the script in the table
So let's go inside the CALL:
Code: Select all
00007FF61EA52AB0 | 48:895C24 10 | MOV QWORD PTR SS:[RSP+10],RBX |
00007FF61EA52AB5 | 57 | PUSH RDI |
00007FF61EA52AB6 | 48:83EC 20 | SUB RSP,20 |
00007FF61EA52ABA | 48:8D99 E0F8FFFF | LEA RBX,QWORD PTR DS:[RCX-720] | <--
00007FF61EA52AC1 | C64424 30 01 | MOV BYTE PTR SS:[RSP+30],1 |
If you check RBX after executing the 4th line.. we get..
Code: Select all
[396259] Character_Fury_C World.World.PersistentLevel.Character_Fury_C_1 0x00000252F17A9570
Bingo
So at the CALL we got RCX-0x720 == Character
Script goes like this:
Code: Select all
[ENABLE]
aobscanmodule( HP_hk, Darksiders3-Win64-Shipping.exe, FF501884C00F84????????4D85ED740B488BD7498BCDE8????????4D )
registersymbol( HP_hk )
label( HP_hk_o )
registersymbol( HP_hk_o )
label( hk_HP_exit )
alloc( hk_HP, 0x1000, Darksiders3-Win64-Shipping.exe )
registersymbol( hk_HP )
label( back )
hk_HP:
push rax
push rcx
lea rcx,[rcx-720] // adjust this to Character
mov rax,[LocalPlayer]
test rax,rax // just in case this is NULL when you enable it;
// if you break here, then enable script, interrupts occur
je short hk_HP_exit
mov rax,[rax+30] // PlayerController
cmp rcx,[rax+348] // Character
jne short hk_HP_exit // if not us, process HP
pop rcx // if us, restore RCX & RAX
pop rax
xor al,al
test al,al
jmp back // and exit (don't run function)
hk_HP_exit:
pop rcx
pop rax
HP_hk_o:
readmem( HP_hk, 5 )
jmp back
align 8 CC
HP_hk:
jmp hk_HP
back:
[DISABLE]
HP_hk:
readmem( HP_hk_o, 5 )
unregistersymbol( hk_HP )
dealloc( hk_HP )
unregistersymbol( HP_hk_o )
unregistersymbol( HP_hk )
You can try the same with the other hook spot I mentioned
Updated table in main post. Steal away.
Enjoy!