Permalink
Fetching contributors…
Cannot retrieve contributors at this time
293 lines (276 sloc) 16 KB
;////////////////////////////////////////////////////////////////////////////////////////////////////////
;// Part of Injectable Generic Camera System
;// Copyright(c) 2017, Frans Bouma
;// All rights reserved.
;// https://github.com/FransBouma/InjectableGenericCameraSystem
;//
;// Redistribution and use in source and binary forms, with or without
;// modification, are permitted provided that the following conditions are met :
;//
;// * Redistributions of source code must retain the above copyright notice, this
;// list of conditions and the following disclaimer.
;//
;// * Redistributions in binary form must reproduce the above copyright notice,
;// this list of conditions and the following disclaimer in the documentation
;// and / or other materials provided with the distribution.
;//
;// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
;// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;// DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
;// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;// DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
;// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
;// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
;// OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;////////////////////////////////////////////////////////////////////////////////////////////////////////
;---------------------------------------------------------------
; Game specific asm file to intercept execution flow to obtain addresses, prevent writes etc.
;---------------------------------------------------------------
;---------------------------------------------------------------
; Public definitions so the linker knows which names are present in this file
PUBLIC cameraStructInterceptor
PUBLIC cameraWrite1Interceptor
PUBLIC cameraWrite2Interceptor
PUBLIC cameraWrite3Interceptor
PUBLIC fovReadInterceptor
;---------------------------------------------------------------
;---------------------------------------------------------------
; Externs which are used and set by the system. Read / write these
; values in asm to communicate with the system
EXTERN g_cameraEnabled: byte
EXTERN g_cameraStructAddress: qword
EXTERN g_fovConstructAddress: qword
EXTERN g_timestopStructAddress: qword
;---------------------------------------------------------------
;---------------------------------------------------------------
; Own externs, defined in InterceptorHelper.cpp
EXTERN _cameraStructInterceptionContinue: qword
EXTERN _cameraWrite1InterceptionContinue: qword
EXTERN _cameraWrite2InterceptionContinue: qword
EXTERN _cameraWrite3InterceptionContinue: qword
EXTERN _fovReadInterceptionContinue: qword
EXTERN _timestopInterceptionContinue: qword
.data
;---------------------------------------------------------------
; Scratch pad
; player intercept. Is matrix (3x4, where the the coords are the lower row, write like this:
;---------------------------------------------------------------
; Blocks used by camera tools, not by this .asm file, blocks are used in AOB scans to obtain RIP relative addresses (see commments below)
; Supersampling read
; patch v1.0.3
;0000000140FC3FF0 | 41 F7 F8 | idiv r8d << START OF AOB BLOCK
;0000000140FC3FF3 | 44 8B C0 | mov r8d,eax
;0000000140FC3FF6 | 8B C1 | mov eax,ecx
;0000000140FC3FF8 | 8B 0D 7A E7 4E 01 | mov ecx,dword ptr ds:[1424B2778] << Supersampling read
;0000000140FC3FFE | 99 | cdq
;0000000140FC3FFF | F7 FF | idiv edi
;0000000140FC4001 | 44 3B C0 | cmp r8d,eax
;0000000140FC4004 | 41 0F 4C C0 | cmovl eax,r8d
;0000000140FC4008 | 83 F9 01 | cmp ecx,1
;0000000140FC400B | 7D 07 | jge prey_dump.140FC4014
;0000000140FC400D | B8 01 00 00 00 | mov eax,1
;0000000140FC4012 | EB 05 | jmp prey_dump.140FC4019
;0000000140FC4014 | 3B C8 | cmp ecx,eax
;0000000140FC4016 | 0F 4C C1 | cmovl eax,ecx
;0000000140FC4019 | 39 83 F4 F3 00 00 | cmp dword ptr ds:[rbx+F3F4],eax
;0000000140FC401F | 74 13 | je prey_dump.140FC4034
;0000000140FC4021 | 89 83 F4 F3 00 00 | mov dword ptr ds:[rbx+F3F4],eax
;0000000140FC4027 | B0 01 | mov al,1
;0000000140FC4029 | 48 8B 5C 24 30 | mov rbx,qword ptr ss:[rsp+30]
;0000000140FC402E | 48 83 C4 20 | add rsp,20
;0000000140FC4032 | 5F | pop rdi
;0000000140FC4033 | C3 | ret
;0000000140FC4034 | 32 C0 | xor al,al
;0000000140FC4036 | 48 8B 5C 24 30 | mov rbx,qword ptr ss:[rsp+30]
;0000000140FC403B | 48 83 C4 20 | add rsp,20
;0000000140FC403F | 5F | pop rdi
;0000000140FC4040 | C3 | ret
;
; sys_flash cvar read (for hud toggle)
; v1.0.3
;0000000146F06D30 | 48 89 74 24 10 | mov qword ptr ss:[rsp+10],rsi
;0000000146F06D35 | 57 | push rdi
;0000000146F06D36 | 48 83 EC 20 | sub rsp,20
;0000000146F06D3A | 83 3D 2B 46 48 FB 00 | cmp dword ptr ds:[14238B36C],0 << sys_flash read << START OF AOB BLOCK
;0000000146F06D41 | 0F B6 F2 | movzx esi,dl
;0000000146F06D44 | 48 89 CF | mov rdi,rcx
;0000000146F06D47 | 74 2E | je prey_dump.146F06D77
;0000000146F06D49 | 48 8B 81 C8 00 00 00 | mov rax,qword ptr ds:[rcx+C8]
;0000000146F06D50 | 48 89 5C 24 30 | mov qword ptr ss:[rsp+30],rbx
;0000000146F06D55 | 48 8B 58 38 | mov rbx,qword ptr ds:[rax+38]
;0000000146F06D59 | 48 8B 01 | mov rax,qword ptr ds:[rcx]
;0000000146F06D5C | FF 10 | call qword ptr ds:[rax]
;0000000146F06D5E | 48 8B 03 | mov rax,qword ptr ds:[rbx]
;0000000146F06D61 | 48 8D 57 08 | lea rdx,qword ptr ds:[rdi+8]
;0000000146F06D65 | 44 0F B6 C6 | movzx r8d,sil
;0000000146F06D69 | 48 89 D9 | mov rcx,rbx
;0000000146F06D6C | FF 90 68 03 00 00 | call qword ptr ds:[rax+368]
;0000000146F06D72 | 48 8B 5C 24 30 | mov rbx,qword ptr ss:[rsp+30]
;0000000146F06D77 | 48 8B 74 24 38 | mov rsi,qword ptr ss:[rsp+38]
;0000000146F06D7C | 48 83 C4 20 | add rsp,20
;0000000146F06D80 | 5F | pop rdi
;0000000146F06D81 | C3 | ret
;
.code
cameraStructInterceptor PROC
; Struct interceptor is also a write interceptor for coords/quaternion
; patch 1.0.2
;Prey.exe+150E5DF - F3 0F11 4E 0C - movss [rsi+0C],xmm1 // quaternion << intercept here
;Prey.exe+150E5E4 - F3 0F11 56 10 - movss [rsi+10],xmm2
;Prey.exe+150E5E9 - F3 0F11 5E 14 - movss [rsi+14],xmm3
;Prey.exe+150E5EE - F3 0F11 46 18 - movss [rsi+18],xmm0
;Prey.exe+150E5F3 - F3 0F11 3E - movss [rsi],xmm7 // coords
;Prey.exe+150E5F7 - F3 0F11 76 04 - movss [rsi+04],xmm6
;Prey.exe+150E5FC - F3 44 0F11 46 08 - movss [rsi+08],xmm8
;Prey.exe+150E602 - E8 8946D5FF - call Prey.exe+1262C90 << continue here
; This function intercepts the camera address and also blocks the writes by reading from our own two structs.
mov [g_cameraStructAddress], rsi
cmp byte ptr [g_cameraEnabled], 1 ; check if the user enabled the camera. If so, just skip the write statements, otherwise just execute the original code.
je exit ; our own camera is enabled, just skip the writes
originalCode:
movss dword ptr [rsi+0Ch],xmm1 ; quaternion (x/y/z/w)
movss dword ptr [rsi+10h],xmm2
movss dword ptr [rsi+14h],xmm3
movss dword ptr [rsi+18h],xmm0
movss dword ptr [rsi],xmm7 ; coords
movss dword ptr [rsi+04h],xmm6
movss dword ptr [rsi+08h],xmm8
exit:
jmp qword ptr [_cameraStructInterceptionContinue] ; jmp back into the original game code, which is the location after the original statements above.
cameraStructInterceptor ENDP
cameraWrite1Interceptor PROC
; patch 1.0.2
;Prey.exe+386A10 - 8B 02 - mov eax,[rdx] << INTERCEPT HERE
;Prey.exe+386A12 - 89 01 - mov [rcx],eax // coords
;Prey.exe+386A14 - 8B 42 04 - mov eax,[rdx+04]
;Prey.exe+386A17 - 89 41 04 - mov [rcx+04],eax
;Prey.exe+386A1A - 8B 42 08 - mov eax,[rdx+08]
;Prey.exe+386A1D - 89 41 08 - mov [rcx+08],eax
;Prey.exe+386A20 - 8B 42 0C - mov eax,[rdx+0C]
;Prey.exe+386A23 - 89 41 0C - mov [rcx+0C],eax // qX
;Prey.exe+386A26 - 8B 42 10 - mov eax,[rdx+10]
;Prey.exe+386A29 - 89 41 10 - mov [rcx+10],eax
;Prey.exe+386A2C - 8B 42 14 - mov eax,[rdx+14]
;Prey.exe+386A2F - 89 41 14 - mov [rcx+14],eax
;Prey.exe+386A32 - 8B 42 18 - mov eax,[rdx+18]
;Prey.exe+386A35 - 89 41 18 - mov [rcx+18],eax // qW
;Prey.exe+386A38 - 8B 42 1C - mov eax,[rdx+1C]
;Prey.exe+386A3B - 89 41 1C - mov [rcx+1C],eax << CONTINUE HERE
;Prey.exe+386A3E - 8B 42 20 - mov eax,[rdx+20]
;Prey.exe+386A41 - 89 41 20 - mov [rcx+20],eax
;Prey.exe+386A44 - 8B 42 24 - mov eax,[rdx+24]
;Prey.exe+386A47 - 89 41 24 - mov [rcx+24],eax
;Prey.exe+386A4A - 8B 42 28 - mov eax,[rdx+28]
;Prey.exe+386A4D - 89 41 28 - mov [rcx+28],eax
;Prey.exe+386A50 - 8B 42 2C - mov eax,[rdx+2C]
;Prey.exe+386A53 - 89 41 2C - mov [rcx+2C],eax
;Prey.exe+386A56 - 8B 42 30 - mov eax,[rdx+30]
;Prey.exe+386A59 - 89 41 30 - mov [rcx+30],eax
;Prey.exe+386A5C - 8B 42 34 - mov eax,[rdx+34]
;Prey.exe+386A5F - 89 41 34 - mov [rcx+34],eax
;Prey.exe+386A62 - 0FB6 42 38 - movzx eax,byte ptr [rdx+38]
;Prey.exe+386A66 - 88 41 38 - mov [rcx+38],al
;Prey.exe+386A69 - 0FB6 42 39 - movzx eax,byte ptr [rdx+39]
;Prey.exe+386A6D - 88 41 39 - mov [rcx+39],al
cmp byte ptr [g_cameraEnabled], 1 ; check if the user enabled the camera. If so, just skip the write statements, otherwise just execute the original code.
je exit ; our own camera is enabled, just skip the writes
originalCode:
mov eax,[rdx]
mov [rcx],eax
mov eax,[rdx+04h]
mov [rcx+04h],eax
mov eax,[rdx+08h]
mov [rcx+08h],eax
mov eax,[rdx+0Ch]
mov [rcx+0Ch],eax
mov eax,[rdx+10h]
mov [rcx+10h],eax
mov eax,[rdx+14h]
mov [rcx+14h],eax
mov eax,[rdx+18h]
mov [rcx+18h],eax
exit:
jmp qword ptr [_cameraWrite1InterceptionContinue] ; jmp back into the original game code, which is the location after the original statements above.
cameraWrite1Interceptor ENDP
cameraWrite2Interceptor PROC
; coord write intercept is broken up in two blocks as it has a relative read in the middle.... WHY is that statement placed at that spot!
;Prey.AK::Monitor::PostCode+24A38A - F3 44 0F58 68 04 - addss xmm13,[rax+04] << INTERCEPT HERE
;Prey.AK::Monitor::PostCode+24A390 - F3 44 0F58 20 - addss xmm12,[rax]
;Prey.AK::Monitor::PostCode+24A395 - F3 44 0F58 70 08 - addss xmm14,[rax+08]
;Prey.AK::Monitor::PostCode+24A39B - F3 44 0F11 67 1C - movss [rdi+1C],xmm12 // write x
;Prey.AK::Monitor::PostCode+24A3A1 - F3 44 0F11 6F 20 - movss [rdi+20],xmm13 // write y
;Prey.AK::Monitor::PostCode+24A3A7 - F3 44 0F10 2D 08DAC401 - movss xmm13,[Prey.CreateAudioInputSource+51B6B8] << CONTINUE HERE
addss xmm13, dword ptr [rax+04h] ; original statement
addss xmm12, dword ptr [rax]
addss xmm14, dword ptr [rax+08h]
cmp byte ptr [g_cameraEnabled], 1 ; check if the user enabled the camera. If so, just skip the write statements, otherwise just execute the original code.
je exit ; our own camera is enabled, just skip the writes
movss dword ptr [rdi+1Ch],xmm12
movss dword ptr [rdi+20h],xmm13
exit:
jmp qword ptr [_cameraWrite2InterceptionContinue] ; jmp back into the original game code, which is the location after the original statements above.
cameraWrite2Interceptor ENDP
cameraWrite3Interceptor PROC
;Prey.AK::Monitor::PostCode+24A3B0 - F3 44 0F11 77 24 - movss [rdi+24],xmm14 << INTERCEPT HERE, write Z
;Prey.AK::Monitor::PostCode+24A3B6 - F3 0F10 8D 88000000 - movss xmm1,[rbp+00000088]
;Prey.AK::Monitor::PostCode+24A3BE - 48 8D 4F 1C - lea rcx,[rdi+1C]
;Prey.AK::Monitor::PostCode+24A3C2 - E8 79410000 - call Prey.AK::Monitor::PostCode+24E540 << CONTINUE HERE
cmp byte ptr [g_cameraEnabled], 1 ; check if the user enabled the camera. If so, just skip the write statements, otherwise just execute the original code.
je noWrite ; our own camera is enabled, just skip the writes
movss dword ptr [rdi+24h],xmm14
noWrite:
movss xmm1, dword ptr [rbp+00000088h]
lea rcx,[rdi+1Ch]
exit:
jmp qword ptr [_cameraWrite3InterceptionContinue] ; jmp back into the original game code, which is the location after the original statements above.
cameraWrite3Interceptor ENDP
timestopInterceptor PROC
; start of function which contains timestop read. Contains CryAction instance (with m_pause) in rcx
;Prey.exe+5D6AD0 - 48 89 5C 24 10 - mov [rsp+10],rbx <<< INTERCEPT HERE
;Prey.exe+5D6AD5 - 48 89 6C 24 18 - mov [rsp+18],rbp
;Prey.exe+5D6ADA - 48 89 74 24 20 - mov [rsp+20],rsi
;Prey.exe+5D6ADF - 57 - push rdi <<< CONTINUE HERE
;Prey.exe+5D6AE0 - 41 54 - push r12
;Prey.exe+5D6AE2 - 41 55 - push r13
;Prey.exe+5D6AE4 - 41 56 - push r14
;Prey.exe+5D6AE6 - 41 57 - push r15
;...
;Prey.exe+5D6C99 - 74 09 - je Prey.exe+5D6CA4
;Prey.exe+5D6C9B - 44 38 6B 08 - cmp [rbx+08],r13l <<< TImestop read
;Prey.exe+5D6C9F - 75 03 - jne Prey.exe+5D6CA4
;Prey.exe+5D6CA1 - 45 8B FD - mov r15d,r13d
;
mov [g_timestopStructAddress], rcx
originalCode:
mov [rsp+10h],rbx
mov [rsp+18h],rbp
mov [rsp+20h],rsi
exit:
jmp qword ptr [_timestopInterceptionContinue] ; jmp back into the original game code, which is the location after the original statements above.
timestopInterceptor ENDP
fovReadInterceptor PROC
;Prey.exe+1511CAE - F3 0F10 4B 18 - movss xmm1,[rbx+18]
;Prey.exe+1511CB3 - 48 8B 05 26D9EF00 - mov rax,[Prey.exe+240F5E0] { [2ED22CE0] }
;Prey.exe+1511CBA - F3 0F5C C8 - subss xmm1,xmm0
;Prey.exe+1511CBE - F3 0F10 05 F256AC00 - movss xmm0,[Prey.exe+1FD73B8] { [1.00] }
;Prey.exe+1511CC6 - F3 0F58 48 08 - addss xmm1,[rax+08] << INTERCEPT HERE. FOV Read
;Prey.exe+1511CCB - 0F2F C8 - comiss xmm1,xmm0
;Prey.exe+1511CCE - 76 03 - jna Prey.exe+1511CD3
;Prey.exe+1511CD0 - 0F28 C1 - movaps xmm0,xmm1
;Prey.exe+1511CD3 - 48 83 C4 20 - add rsp,20 { 32 }
;Prey.exe+1511CD7 - 5B - pop rbx << CONTINUE HERE
;Prey.exe+1511CD8 - C3 - ret
mov [g_fovConstructAddress], rax
originalCode:
addss xmm1, dword ptr [rax+08h]
comiss xmm1,xmm0
jna noMove
movaps xmm0,xmm1
noMove:
add rsp, 20h
exit:
jmp qword ptr [_fovReadInterceptionContinue] ; jmp back into the original game code, which is the location after the original statements above.
fovReadInterceptor ENDP
END