Tuuuup! wrote: ↑Sat Oct 09, 2021 12:48 pm
...
Just letting you know the "Quick (E) Interact button" fucks up every key/action timer passing through there
For example, when you move left (hold A), right (hold D), forward (hold W), backward (hold S) or press and hold C to crouch or get up.. and even when you hold E without an event notification in the middle of the screen (in thin air). If you break here, you'll see what I mean (set breakpoint, press C key):
Code: Select all
FC_m64d3d12.dll+1098510 - F3 0F11 4F 04 - movss [rdi+04],xmm1
So it's not doing your "movss xmm2,xmm0" for just E action when, for example, you want to disable an alarm in a base. You have to filter this piece of code, else I don't know what the side-effects are. Sure, you might not have noticed anything and maybe you don't use it that much -- these would be excuses -- though bad practice shouldn't be the way to do it.
I've done some investigation, so here it is:
Code: Select all
FC_m64d3d12.dll+10A7430 - 4C 69 E8 70010000 - imul r13,rax,00000170
FC_m64d3d12.dll+10A7437 - 8B 45 B0 - mov eax,[rbp-50]
FC_m64d3d12.dll+10A743A - 4D 03 AF 401C0000 - add r13,[r15+00001C40]
FC_m64d3d12.dll+10A7441 - 4C 89 6D A8 - mov [rbp-58],r13
FC_m64d3d12.dll+10A7445 - 41 39 45 14 - cmp [r13+14],eax
The above is an iterator through all the processed key/hold/action timers. In my case, the offset for the E-action event is 0x48. Won't be the same for everyone. Am just mentioning it, so it's said. We won't use that offset.
Then:
Code: Select all
FC_m64d3d12.dll+10A8D55 - 41 89 8D 40010000 - mov [r13+00000140],ecx
This is the piece of code that constantly writes 0 to the timers for key events. Notice the offset is 0x140, meaning that sometime before this CALL..
Code: Select all
FC_m64d3d12.dll+10A6F82 - E8 2915FFFF - call FC_m64d3d12.dll+10984B0
..our R8 (cuz that's where the timer ptr is in that function; and it's then moved in RDI) will be offset by 0x140.
Then:
Code: Select all
FC_m64d3d12.dll+10A8D90 - 41 8B 85 3C010000 - mov eax,[r13+0000013C] // hash
FC_m64d3d12.dll+10A8D97 - 48 8D 55 00 - lea rdx,[rbp+00]
FC_m64d3d12.dll+10A8D9B - F3 41 0F10 5D 1C - movss xmm3,[r13+1C]
FC_m64d3d12.dll+10A8DA1 - 49 8B CF - mov rcx,r15
FC_m64d3d12.dll+10A8DA4 - F3 41 0F10 95 40010000 - movss xmm2,[r13+00000140]
FC_m64d3d12.dll+10A8DAD - 89 45 00 - mov [rbp+00],eax
FC_m64d3d12.dll+10A8DB0 - 41 0FB6 85 5C010000 - movzx eax,byte ptr [r13+0000015C]
Finally, this is where it forms up the args list and calls the perform action function when timer > 0. The point in all of the above is you can check the timer hash when a key is pressed. I believe these are unique. Here's my script:
Practical Example:
Now, in my case, when I "Find out what addresses this instruction accesses" at:
Code: Select all
FC_m64d3d12.dll+1098510 - F3 0F11 4F 04 - movss [rdi+04],xmm1
I get the following:
Out of that list, the only one that, when frozen, doesn't allow the horizontal white bar underneath E to increase is this one:
28EBDAF3290. If you look at the instruction -- movss [rdi+04],xmm1 -- that means my base (rdi) would be 28EBDAF3290 - 0x4. So
28EBDAF328C.
Then we set a breakpoint at the prologue of this function to determine where it exits:
Code: Select all
FC_m64d3d12.dll+10984B0 - 40 55 - push rbp
Press E and CE breaks. Then F5 to remove breakpoint, Ctrl+G > [rsp], then F9 to resume. And you can see where the return is:
Code: Select all
FC_m64d3d12.dll+10A6F7B - F3 44 0F11 6C 24 20 - movss [rsp+20],xmm13
FC_m64d3d12.dll+10A6F82 - E8 2915FFFF - call FC_m64d3d12.dll+10984B0 <<
FC_m64d3d12.dll+10A6F87 - E9 94F9FFFF - jmp FC_m64d3d12.dll+10A6920
So above that CALL, somewhere, our 28EBDAF328C will be calculated from another base + 0x140. Remember this:
Code: Select all
FC_m64d3d12.dll+10A8D55 - 41 89 8D 40010000 - mov [r13+00000140],ecx
If I debug that, I see that r13 is:
28EBDAF3150.
If we do a bit of math: our 28EBDAF328C vs. 28EBDAF3150. Subtraction: 0x13C. So not 0x140. Let's see why.
Our 28EBDAF328C is written to r8 here, from r14:
Code: Select all
FC_m64d3d12.dll+10A6F45 - 4D 8B C6 - mov r8,r14 <<
FC_m64d3d12.dll+10A6F48 - 8B 4C 24 54 - mov ecx,[rsp+54]
FC_m64d3d12.dll+10A6F4C - 41 0FB6 D5 - movzx edx,r13l
Just a bit above the CALL. So I set a bp at FC_m64d3d12.dll+10A6F48, then applied the condition "r8 == 0x28EBDAF328C":
CE breaks as soon as I press E on the alarm box. So what we need now to do is determine where r14 comes from. And that's from here:
Code: Select all
FC_m64d3d12.dll+10A6A5C - 4D 8D B7 3C010000 - lea r14,[r15+0000013C] <<
FC_m64d3d12.dll+10A6A63 - 83 FB 02 - cmp ebx,02
FC_m64d3d12.dll+10A6A66 - 0F85 9B010000 - jne FC_m64d3d12.dll+10A6C07
FC_m64d3d12.dll+10A6A6C - 41 8B 06 - mov eax,[r14]
In case you wonder how I got there, I used x64dbg, I've highlighted R14 and scrolled up, moving backwards through code -- visually, not with breakpoints; so a manual process -- like so:
P.S.1: Right-click > Open the GIF above in another tab to see it in full size.
P.S.2: You can highlight a register by pressing H, so the red rectangle shows, then click on the register you want to highlight.
So we want now to check r15 register when our break hits:
Bingo:
28EBDAF3150.
Now, based on the remark I made here:
Code: Select all
FC_m64d3d12.dll+10A8D90 - 41 8B 85 3C010000 - mov eax,[r13+0000013C] // hash
If we now look at 28EBDAF3150 + 13C, we see this:
If I do a "Find out what addresses this instruction accesses" at..
Code: Select all
FC_m64d3d12.dll+10A8D90 - 41 8B 85 3C010000 - mov eax,[r13+0000013C] // hash
FC_m64d3d12.dll+10A8D97 - 48 8D 55 00 - lea rdx,[rbp+00]
FC_m64d3d12.dll+10A8D9B - F3 41 0F10 5D 1C - movss xmm3,[r13+1C] << this
FC_m64d3d12.dll+10A8DA1 - 49 8B CF - mov rcx,r15
FC_m64d3d12.dll+10A8DA4 - F3 41 0F10 95 40010000 - movss xmm2,[r13+00000140] << and this
..the two addresses I marked above (+10A8D9B and +10A8DA4), I get these:
Max Timers:
Hashes:
As you can see, there aren't any duplicate hash values in that list
In my case, the ones I am looking for to filter just the E hold action on the alarm box or a supply drop are these:
So, from all the above, I can say the E hold action lasts
6 seconds and its hash is
0x4E1A8F19. And all of the above says you can hot-patch the timer max values on access (so no need to do it on write, when you actually press E) and you're good to go
BR,
Sun
P.S.#1: I've not checked if supply drop hold action has the same hash; but if it doesn't, I'll just add more hashes to the list
L.E.: Yeah, the supply drop has a different hash ->
0x2AFFAB03. Timer is 7.5s. There's another one I found with 8s, but I don't know what it is for yet (hash is
0x3D4C0F7A).