UFunctionHooks — 27 PEHOOK handlers + Initialize

This commit is contained in:
ApfelTeeSaft
2026-05-05 14:13:41 +02:00
parent f27024a5e0
commit 240dba4a89
9 changed files with 1252 additions and 51 deletions
+16 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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