mirror of
https://github.com/ApfelTeeSaft/Perfectium.git
synced 2026-08-26 19:33:36 +00:00
UFunctionHooks — 27 PEHOOK handlers + Initialize
This commit is contained in:
@@ -2,7 +2,7 @@ INCLUDE include\master.inc
|
||||
|
||||
; Local offset supplements
|
||||
APLAYER_CurrentNetSpeed EQU 038h
|
||||
UNETCONN_InternalAck EQU 0C8h ; bool — estimated, verify against dump
|
||||
UNETCONN_InternalAck EQU 0C8h ; bool - estimated, verify against dump
|
||||
AFPCA_OverriddenBackpackSize EQU 0720h
|
||||
|
||||
.data?
|
||||
@@ -44,18 +44,18 @@ Hooks_KickPlayer PROC
|
||||
ret
|
||||
Hooks_KickPlayer ENDP
|
||||
|
||||
; Hooks_LocalPlayerSpawnPlayActor — tail-call or early return
|
||||
; Hooks_LocalPlayerSpawnPlayActor - tail-call or early return
|
||||
; void* Hooks_LocalPlayerSpawnPlayActor(ULocalPlayer*, FString*, FString*, UWorld*)
|
||||
; If not yet traveled: tail-call original (all regs untouched).
|
||||
; If already traveled: return 1 (suppress duplicate actor spawns).
|
||||
;
|
||||
; Stack: no frame — either ret-1 or jmp to original (tail call).
|
||||
; Stack: no frame - either ret-1 or jmp to original (tail call).
|
||||
Hooks_LocalPlayerSpawnPlayActor PROC
|
||||
movzx eax, BYTE PTR [bTraveled]
|
||||
test al, al
|
||||
jnz @@already_traveled
|
||||
|
||||
; Not traveled yet — forward all args unchanged via tail call
|
||||
; Not traveled yet - forward all args unchanged via tail call
|
||||
jmp QWORD PTR [Native_LocalPlayer_SpawnPlayActor]
|
||||
|
||||
@@already_traveled:
|
||||
@@ -127,7 +127,7 @@ Hooks_World_NotifyControlMessage PROC
|
||||
Hooks_World_NotifyControlMessage ENDP
|
||||
|
||||
; Hooks_Beacon_NotifyAcceptingConnection(AOnlineBeacon*) -> uint8
|
||||
; Beacon is accepting a new peer — forward to World's handler.
|
||||
; Beacon is accepting a new peer - forward to World's handler.
|
||||
; Args: RCX = AOnlineBeacon*
|
||||
;
|
||||
; Stack: push rbp + push rbx = 2 pushes; sub 40 -> 0
|
||||
@@ -155,7 +155,7 @@ Hooks_Beacon_NotifyAcceptingConnection PROC
|
||||
Hooks_Beacon_NotifyAcceptingConnection ENDP
|
||||
|
||||
; Hooks_SeamlessTravelHandlerForWorld(UEngine*, UWorld*)
|
||||
; Args: RCX=Engine, RDX=UWorld* (ignored — use GetWorld())
|
||||
; Args: RCX=Engine, RDX=UWorld* (ignored - use GetWorld())
|
||||
;
|
||||
; Stack: push rbp + push rbx = 2 pushes; sub 40 -> 0
|
||||
Hooks_SeamlessTravelHandlerForWorld PROC
|
||||
@@ -221,7 +221,7 @@ Hooks_PostRender ENDP
|
||||
; Args: RCX=NetDriver, XMM1=DeltaSeconds (float)
|
||||
;
|
||||
; Stack: push rbp,rbx = 2 pushes (RSP=8 after 2×8); sub 40(=8) -> 0
|
||||
; [rsp+32] — spill slot for DeltaSeconds (REAL4)
|
||||
; [rsp+32] - spill slot for DeltaSeconds (REAL4)
|
||||
Hooks_TickFlush PROC
|
||||
push rbp
|
||||
push rbx
|
||||
@@ -241,7 +241,7 @@ Hooks_TickFlush PROC
|
||||
test eax, eax
|
||||
jle @@call_orig
|
||||
|
||||
; ClientConnections[0] — dereference Data ptr
|
||||
; ClientConnections[0] - dereference Data ptr
|
||||
mov rax, QWORD PTR [rbx + UNETDRIVER_ClientConns]
|
||||
mov rax, QWORD PTR [rax] ; first element
|
||||
test rax, rax
|
||||
@@ -316,7 +316,7 @@ Hooks_GetPlayerViewPoint PROC
|
||||
ret
|
||||
Hooks_GetPlayerViewPoint ENDP
|
||||
|
||||
; Hooks_SpawnPlayActor — spawn and set up new player controller
|
||||
; Hooks_SpawnPlayActor - spawn and set up new player controller
|
||||
; Original: APlayerController* (*)(UWorld*, UPlayer*, ENetRole, FURL&, void*, FString&, uint8)
|
||||
; We replace UWorld* with GetWorld() and wire up the resulting PC.
|
||||
;
|
||||
@@ -325,7 +325,7 @@ Hooks_GetPlayerViewPoint ENDP
|
||||
; RDX = UPlayer* NewPlayer
|
||||
; R8 = ENetRole
|
||||
; R9 = FURL*
|
||||
; [RSP+40] = void* UniqueId (5th arg — see note)
|
||||
; [RSP+40] = void* UniqueId (5th arg - see note)
|
||||
; [RSP+48] = FString* Error (6th arg)
|
||||
; [RSP+56] = uint8 NetIdx (7th arg)
|
||||
;
|
||||
@@ -413,10 +413,10 @@ Hooks_SpawnPlayActor ENDP
|
||||
; uint8 MessageType, FBitReader* Bunch
|
||||
;
|
||||
; Dispatch by MessageType:
|
||||
; 4 (NMT_Netspeed) — set Connection->CurrentNetSpeed = 30000
|
||||
; 5 (NMT_Login) — receive FStrings + UniqueId, then WelcomePlayer
|
||||
; 15 (NMT_PCSwap) — call original Beacon_NotifyControlMessage
|
||||
; default — call Native_World_NotifyControlMessage(GetWorld(), ...)
|
||||
; 4 (NMT_Netspeed) - set Connection->CurrentNetSpeed = 30000
|
||||
; 5 (NMT_Login) - receive FStrings + UniqueId, then WelcomePlayer
|
||||
; 15 (NMT_PCSwap) - call original Beacon_NotifyControlMessage
|
||||
; default - call Native_World_NotifyControlMessage(GetWorld(), ...)
|
||||
;
|
||||
; Stack: push rbp,rbx,rsi = 3 pushes (RSP=0 after 3×8).
|
||||
; sub 112(=0) -> 0 .
|
||||
@@ -470,7 +470,7 @@ Hooks_Beacon_NotifyControlMessage PROC
|
||||
; FString str2 at [rsp+48..63]
|
||||
mov QWORD PTR [rsp + 48], rax
|
||||
mov QWORD PTR [rsp + 56], rax
|
||||
; FUniqueNetIdRepl at [rsp+64..103] — 40 bytes (5 QWORDs)
|
||||
; FUniqueNetIdRepl at [rsp+64..103] - 40 bytes (5 QWORDs)
|
||||
mov QWORD PTR [rsp + 64], rax
|
||||
mov QWORD PTR [rsp + 72], rax
|
||||
mov QWORD PTR [rsp + 80], rax
|
||||
@@ -561,7 +561,7 @@ Hooks_ProcessEventHook PROC
|
||||
cmp rsi, r12 ; Function == ReadyToStartMatch?
|
||||
jne @@check_traveled
|
||||
|
||||
; Match — server is ready to start: set flag, travel, hook network
|
||||
; Match - server is ready to start: set flag, travel, hook network
|
||||
mov BYTE PTR [bPlayButton], 1
|
||||
|
||||
call SDK_GetWorld
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ DLL_THREAD_DETACH EQU 3
|
||||
|
||||
; Vtable slot indices
|
||||
VTABLE_SLOT_ProcessEvent EQU 40h ; = 64 decimal
|
||||
VTABLE_SLOT_ServerReplicateActors EQU 53h ; = 83 decimal — on UReplicationDriver
|
||||
VTABLE_SLOT_ServerReplicateActors EQU 53h ; = 83 decimal - on UReplicationDriver
|
||||
|
||||
; Network message type codes (NMT_ values)
|
||||
NMT_Netspeed EQU 4
|
||||
|
||||
+20
-20
@@ -1,4 +1,4 @@
|
||||
; sdk_globals.asm — Global UE4 runtime pointers and GObjects
|
||||
; sdk_globals.asm - Global UE4 runtime pointers and GObjects
|
||||
EXTERNDEF Imagebase :QWORD ; base address of FortniteClient-Win64-Shipping.exe
|
||||
EXTERNDEF ProcessEvent :QWORD ; void (*)(UObject*, UFunction*, void*)
|
||||
EXTERNDEF FMemory_Malloc :QWORD ; void* (*)(int32 size, int32 alignment)
|
||||
@@ -7,18 +7,18 @@ EXTERNDEF FMemory_Free :QWORD ; void (*)(void* original)
|
||||
EXTERNDEF FNameToString :QWORD ; void (*)(FName* name, FString& out)
|
||||
EXTERNDEF GObjects :QWORD ; TUObjectArray* (the global UObject array)
|
||||
|
||||
; sdk_globals.asm — Global mutable state
|
||||
EXTERNDEF bTraveled :BYTE ; bool — has the server traveled yet?
|
||||
EXTERNDEF bPlayButton :BYTE ; bool — play button clicked?
|
||||
EXTERNDEF bListening :BYTE ; bool — server is listening?
|
||||
EXTERNDEF bStartedBus :BYTE ; bool — battle bus launched?
|
||||
EXTERNDEF bSpawnedFloorLoot :BYTE ; bool — floor loot spawned?
|
||||
; sdk_globals.asm - Global mutable state
|
||||
EXTERNDEF bTraveled :BYTE ; bool - has the server traveled yet?
|
||||
EXTERNDEF bPlayButton :BYTE ; bool - play button clicked?
|
||||
EXTERNDEF bListening :BYTE ; bool - server is listening?
|
||||
EXTERNDEF bStartedBus :BYTE ; bool - battle bus launched?
|
||||
EXTERNDEF bSpawnedFloorLoot :BYTE ; bool - floor loot spawned?
|
||||
EXTERNDEF HostBeacon :QWORD ; AFortOnlineBeaconHost*
|
||||
EXTERNDEF ExistingBuildings :QWORD ; pointer to TArray<ABuildingActor*> head (Data ptr)
|
||||
EXTERNDEF ExistingBuildingsNum :DWORD ; current Num of ExistingBuildings array
|
||||
EXTERNDEF ExistingBuildingsMax :DWORD ; current Max of ExistingBuildings array
|
||||
|
||||
; native.asm — Native:: function-pointer table
|
||||
; native.asm - Native:: function-pointer table
|
||||
; Native::Actor
|
||||
EXTERNDEF Native_Actor_GetNetMode :QWORD
|
||||
; Native::PlayerController
|
||||
@@ -58,10 +58,10 @@ EXTERNDEF Native_Engine_SeamlessTravelHandlerForWorld :QWORD
|
||||
; Native::GameViewportClient
|
||||
EXTERNDEF Native_GameViewportClient_PostRender :QWORD
|
||||
|
||||
; native.asm — InitializeAll entry point
|
||||
; native.asm - InitializeAll entry point
|
||||
EXTERNDEF Native_InitializeAll :PROC
|
||||
|
||||
; patterns.asm — Pattern byte arrays and mask strings (.const)
|
||||
; patterns.asm - Pattern byte arrays and mask strings (.const)
|
||||
EXTERNDEF Pat_FNameToString :BYTE
|
||||
EXTERNDEF Pat_GObjects :BYTE
|
||||
EXTERNDEF Pat_Free :BYTE
|
||||
@@ -90,7 +90,7 @@ EXTERNDEF Pat_PostRender :BYTE
|
||||
EXTERNDEF Pat_CollectGarbage :BYTE
|
||||
EXTERNDEF Pat_NetDebug :BYTE
|
||||
|
||||
; util.asm — Utility functions
|
||||
; util.asm - Utility functions
|
||||
EXTERNDEF Utils_FindPattern :PROC ; (RCX=pszPattern, EDX=bRelative, R8D=offset) -> RAX:QWORD (address or 0)
|
||||
EXTERNDEF Utils_Sin :PROC ; (angle:REAL4) -> REAL4 (result in XMM0)
|
||||
EXTERNDEF Utils_Cos :PROC ; (angle:REAL4) -> REAL4 (result in XMM0)
|
||||
@@ -98,14 +98,14 @@ EXTERNDEF Utils_RotToQuat :PROC ; (rot:PTR FRotator, out_quat:PTR FQ
|
||||
EXTERNDEF Utils_VecToRot :PROC ; (vec:PTR FVector, out_rot:PTR FRotator)
|
||||
EXTERNDEF Utils_RandomIntInRange :PROC ; (min:DWORD, max:DWORD) -> DWORD
|
||||
|
||||
; logger.asm — switched to sprintf
|
||||
; logger.asm - switched to sprintf
|
||||
EXTERNDEF Logger_Initialize :PROC ; ()
|
||||
EXTERNDEF Logger_LogInfo :PROC ; (RCX=msg:PTR BYTE)
|
||||
EXTERNDEF Logger_LogWarn :PROC ; (RCX=msg:PTR BYTE)
|
||||
EXTERNDEF Logger_LogError :PROC ; (RCX=msg:PTR BYTE)
|
||||
EXTERNDEF Logger_LogInfoFmt :PROC ; (RCX=fmt:PTR BYTE, RDX/R8/R9=args) — printf passthrough
|
||||
EXTERNDEF Logger_LogInfoFmt :PROC ; (RCX=fmt:PTR BYTE, RDX/R8/R9=args) - printf passthrough
|
||||
|
||||
; hooks.asm — All hook implementations
|
||||
; hooks.asm - All hook implementations
|
||||
EXTERNDEF Hooks_TickFlush :PROC
|
||||
EXTERNDEF Hooks_ProcessEventHook :PROC
|
||||
EXTERNDEF Hooks_LocalPlayerSpawnPlayActor :PROC
|
||||
@@ -123,20 +123,20 @@ EXTERNDEF Hooks_Beacon_NotifyControlMessage :PROC
|
||||
EXTERNDEF Hooks_PostRender :PROC
|
||||
EXTERNDEF Hooks_InitNetworkHooks :PROC
|
||||
|
||||
; ufunctionhooks.asm — UFunction dispatch hooks
|
||||
; ufunctionhooks.asm - UFunction dispatch hooks
|
||||
EXTERNDEF UFunctionHooks_Initialize :PROC
|
||||
EXTERNDEF UFunctionHooks_ToHook_Data :QWORD ; base of UFunction* array
|
||||
EXTERNDEF UFunctionHooks_ToHook_Num :DWORD ; count of registered hooks
|
||||
EXTERNDEF UFunctionHooks_ToCall_Data :QWORD ; base of handler QWORD* array (BYTE (*)(UObject*,void*))
|
||||
|
||||
; sdk/sdk_classes.asm — UObject / GObjects accessors
|
||||
; sdk/sdk_classes.asm - UObject / GObjects accessors
|
||||
EXTERNDEF SDK_GetObjectByIndex :PROC ; (index:DWORD) -> QWORD (UObject*)
|
||||
EXTERNDEF SDK_FindObject :PROC ; (name:PTR BYTE) -> QWORD (UObject*)
|
||||
EXTERNDEF SDK_FindClass :PROC ; (name:PTR BYTE) -> QWORD (UClass*)
|
||||
EXTERNDEF SDK_GetWorld :PROC ; () -> QWORD (UWorld*)
|
||||
EXTERNDEF SDK_GetEngine :PROC ; () -> QWORD (UFortEngine*)
|
||||
|
||||
; sdk/sdk_classes.asm — TArray helpers (element-size-agnostic)
|
||||
; sdk/sdk_classes.asm - TArray helpers (element-size-agnostic)
|
||||
EXTERNDEF TArray_Num :PROC ; (arr:PTR TArrayHeader) -> DWORD
|
||||
EXTERNDEF TArray_GetByIndex :PROC ; (arr:PTR TArrayHeader, idx:DWORD, elem_size:DWORD) -> QWORD
|
||||
EXTERNDEF TArray_Add :PROC ; (arr:PTR TArrayHeader, elem:PTR BYTE, elem_size:DWORD) -> DWORD
|
||||
@@ -144,15 +144,15 @@ EXTERNDEF TArray_RemoveAt :PROC ; (arr:PTR TArrayHeader, idx:DWORD,
|
||||
EXTERNDEF TArray_RemoveSingle :PROC ; (arr:PTR TArrayHeader, elem:PTR BYTE, elem_size:DWORD) -> BYTE
|
||||
EXTERNDEF TArray_FreeArray :PROC ; (arr:PTR TArrayHeader)
|
||||
|
||||
; sdk/sdk_classes.asm — FString helpers
|
||||
; sdk/sdk_classes.asm - FString helpers
|
||||
EXTERNDEF FString_FromWideChar :PROC ; (out:PTR TArrayHeader, wstr:PTR WORD)
|
||||
EXTERNDEF FString_Free :PROC ; (str:PTR TArrayHeader)
|
||||
|
||||
; sdk/sdk_fort.asm — Fortnite-specific helpers
|
||||
; sdk/sdk_fort.asm - Fortnite-specific helpers
|
||||
EXTERNDEF FortHelper_GetAbilitySystemComponent :PROC ; (pawn:QWORD) -> QWORD
|
||||
EXTERNDEF FortHelper_GetWorldInventory :PROC ; (pc:QWORD) -> QWORD
|
||||
EXTERNDEF FortHelper_GetQuickBars :PROC ; (pc:QWORD) -> QWORD
|
||||
EXTERNDEF SDK_CreateConsole :PROC ; () — spawns UConsole on GameViewport
|
||||
EXTERNDEF SDK_CreateConsole :PROC ; () - spawns UConsole on GameViewport
|
||||
|
||||
; logic/game.asm
|
||||
EXTERNDEF Game_Start :PROC
|
||||
|
||||
+1
-1
@@ -127,7 +127,7 @@ Native_InitializeAll PROC
|
||||
xor r8d, r8d
|
||||
call Utils_FindPattern
|
||||
mov QWORD PTR [Native_OnlineBeacon_PauseBeaconRequests], rax
|
||||
; Also store in the host-specific slot — same function pointer
|
||||
; Also store in the host-specific slot - same function pointer
|
||||
mov QWORD PTR [Native_OnlineBeaconHost_PauseBeaconRequests], rax
|
||||
|
||||
; OnlineBeacon::NotifyAcceptingConnection (direct)
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@ szBaseAddrFmt DB "[INFO] Base Address: 0x%I64X", 0Ah, 0
|
||||
|
||||
.code
|
||||
|
||||
; Main — worker thread entry point
|
||||
; Main - worker thread entry point
|
||||
; RCX = lpParam (hModule passed from DllMain; not used inside Main)
|
||||
;
|
||||
; Stack frame layout (after prologue):
|
||||
@@ -105,7 +105,7 @@ Main PROC
|
||||
ret
|
||||
Main ENDP
|
||||
|
||||
; DllMain — DLL entry point
|
||||
; DllMain - DLL entry point
|
||||
; RCX = hModule (HMODULE)
|
||||
; EDX = dwReason (DWORD)
|
||||
; R8 = lpReserved (LPVOID)
|
||||
|
||||
+2
-2
@@ -766,7 +766,7 @@ SDK_FindClass PROC
|
||||
test eax, eax
|
||||
jnz @@scan_loop
|
||||
|
||||
; Exact match — reload object ptr
|
||||
; Exact match - reload object ptr
|
||||
mov rax, QWORD PTR [rbx]
|
||||
lea rcx, [rsi - 1]
|
||||
imul rcx, rcx, 24
|
||||
@@ -798,7 +798,7 @@ ProcessEvent_Call PROC
|
||||
mov rax, QWORD PTR [ProcessEvent]
|
||||
test rax, rax
|
||||
jz @@done
|
||||
call rax ; ProcessEvent(obj, fn, params) — rcx/rdx/r8 already set
|
||||
call rax ; ProcessEvent(obj, fn, params) - rcx/rdx/r8 already set
|
||||
|
||||
@@done:
|
||||
add rsp, 40
|
||||
|
||||
+8
-8
@@ -4,13 +4,13 @@ INCLUDE include\master.inc
|
||||
|
||||
; Core UE4 runtime function pointers
|
||||
ProcessEvent QWORD ? ; void (*)(UObject*, UFunction*, void*)
|
||||
Imagebase QWORD ? ; uintptr_t — base of game .exe module
|
||||
Imagebase QWORD ? ; uintptr_t - base of game .exe module
|
||||
|
||||
FMemory_Malloc QWORD ? ; void* (*)(int32 size, int32 alignment)
|
||||
FMemory_Realloc QWORD ? ; void* (*)(void* mem, int64 newSize, uint32 align)
|
||||
FMemory_Free QWORD ? ; void (*)(void* mem)
|
||||
FNameToString QWORD ? ; void (*)(FName* this, FString& out)
|
||||
GObjects QWORD ? ; TUObjectArray* — global UObject table
|
||||
GObjects QWORD ? ; TUObjectArray* - global UObject table
|
||||
|
||||
; Native:: function pointers
|
||||
; Actor
|
||||
@@ -70,17 +70,17 @@ Native_Engine_SeamlessTravelHandlerForWorld QWORD ?
|
||||
Native_GameViewportClient_PostRender QWORD ?
|
||||
|
||||
; Game state globals
|
||||
bTraveled BYTE ? ; bool — server has traveled to map
|
||||
bPlayButton BYTE ? ; bool — play button clicked
|
||||
bListening BYTE ? ; bool — server is listening for connections
|
||||
bStartedBus BYTE ? ; bool — battle bus has launched
|
||||
bSpawnedFloorLoot BYTE ? ; bool — floor loot has been spawned
|
||||
bTraveled BYTE ? ; bool - server has traveled to map
|
||||
bPlayButton BYTE ? ; bool - play button clicked
|
||||
bListening BYTE ? ; bool - server is listening for connections
|
||||
bStartedBus BYTE ? ; bool - battle bus has launched
|
||||
bSpawnedFloorLoot BYTE ? ; bool - floor loot has been spawned
|
||||
BYTE 3 DUP (?) ; pad to QWORD boundary
|
||||
|
||||
; Pointer globals
|
||||
HostBeacon QWORD ? ; AFortOnlineBeaconHost*
|
||||
|
||||
; ExistingBuildings — std::vector<ABuildingActor*> represented as TArrayHeader
|
||||
; ExistingBuildings - std::vector<ABuildingActor*> represented as TArrayHeader
|
||||
; Layout matches TArrayHeader: Data(QWORD), Count(DWORD), Max(DWORD)
|
||||
ExistingBuildings QWORD ? ; Data: ABuildingActor** array ptr
|
||||
ExistingBuildingsNum DWORD ? ; Count
|
||||
|
||||
+1201
File diff suppressed because it is too large
Load Diff
@@ -108,7 +108,7 @@ Utils_FindPattern PROC
|
||||
sub r14d, esi ; r14d = SizeOfImage - pat_len
|
||||
js @@not_found ; underflow -> image too small
|
||||
|
||||
; r12d = pat_len (repurpose r12 — pszPattern no longer needed)
|
||||
; r12d = pat_len (repurpose r12 - pszPattern no longer needed)
|
||||
mov r12d, esi ; r12d = pat_len
|
||||
xor esi, esi ; esi = i (outer counter)
|
||||
; rbx = &pat_ints[0] = rsp + 32
|
||||
|
||||
Reference in New Issue
Block a user