diff --git a/include/externs.inc b/include/externs.inc index 21e25ec..d092120 100644 --- a/include/externs.inc +++ b/include/externs.inc @@ -62,70 +62,48 @@ EXTERNDEF Native_GameViewportClient_PostRender :QWORD EXTERNDEF Native_InitializeAll :PROC ; patterns.asm — Pattern byte arrays and mask strings (.const) -EXTERNDEF Pat_ProcessEvent :BYTE -EXTERNDEF Pat_ProcessEvent_Mask :BYTE -EXTERNDEF Pat_FMemory_Malloc :BYTE -EXTERNDEF Pat_FMemory_Malloc_Mask :BYTE -EXTERNDEF Pat_FMemory_Realloc :BYTE -EXTERNDEF Pat_FMemory_Realloc_Mask:BYTE -EXTERNDEF Pat_FMemory_Free :BYTE -EXTERNDEF Pat_FMemory_Free_Mask :BYTE EXTERNDEF Pat_FNameToString :BYTE -EXTERNDEF Pat_FNameToString_Mask :BYTE EXTERNDEF Pat_GObjects :BYTE -EXTERNDEF Pat_GObjects_Mask :BYTE -EXTERNDEF Pat_NetDebug :BYTE -EXTERNDEF Pat_NetDebug_Mask :BYTE +EXTERNDEF Pat_Free :BYTE +EXTERNDEF Pat_Malloc :BYTE +EXTERNDEF Pat_Realloc :BYTE +EXTERNDEF Pat_ReceiveFString :BYTE +EXTERNDEF Pat_ReceiveUniqueIdRepl :BYTE EXTERNDEF Pat_TickFlush :BYTE -EXTERNDEF Pat_TickFlush_Mask :BYTE -EXTERNDEF Pat_GetPlayerViewPoint :BYTE -EXTERNDEF Pat_GetPlayerViewPoint_Mask :BYTE -EXTERNDEF Pat_SpawnPlayActor :BYTE -EXTERNDEF Pat_SpawnPlayActor_Mask :BYTE -EXTERNDEF Pat_CollectGarbage :BYTE -EXTERNDEF Pat_CollectGarbage_Mask :BYTE -EXTERNDEF Pat_GiveAbility :BYTE -EXTERNDEF Pat_GiveAbility_Mask :BYTE -EXTERNDEF Pat_FindAbilitySpec :BYTE -EXTERNDEF Pat_FindAbilitySpec_Mask:BYTE -EXTERNDEF Pat_InternalTryActivate :BYTE -EXTERNDEF Pat_InternalTryActivate_Mask :BYTE -EXTERNDEF Pat_ServerReplicateActors :BYTE -EXTERNDEF Pat_ServerReplicateActors_Mask :BYTE -EXTERNDEF Pat_ReceiveNetGUIDBunch :BYTE -EXTERNDEF Pat_ReceiveNetGUIDBunch_Mask :BYTE -EXTERNDEF Pat_KickPlayer :BYTE -EXTERNDEF Pat_KickPlayer_Mask :BYTE -EXTERNDEF Pat_WelcomePlayer :BYTE -EXTERNDEF Pat_WelcomePlayer_Mask :BYTE -EXTERNDEF Pat_SpawnActor :BYTE -EXTERNDEF Pat_SpawnActor_Mask :BYTE +EXTERNDEF Pat_PauseBeaconRequests :BYTE EXTERNDEF Pat_BeaconNotifyAccept :BYTE -EXTERNDEF Pat_BeaconNotifyAccept_Mask :BYTE -EXTERNDEF Pat_NotifyControlMessage :BYTE -EXTERNDEF Pat_NotifyControlMessage_Mask :BYTE +EXTERNDEF Pat_InitHost :BYTE +EXTERNDEF Pat_BeaconNotifyCtrl :BYTE +EXTERNDEF Pat_WelcomePlayer :BYTE +EXTERNDEF Pat_WorldNotifyCtrl :BYTE +EXTERNDEF Pat_SpawnPlayActor :BYTE +EXTERNDEF Pat_WorldNotifyAccept :BYTE +EXTERNDEF Pat_GetNetMode :BYTE +EXTERNDEF Pat_GiveAbility :BYTE +EXTERNDEF Pat_InternalTryActivate :BYTE +EXTERNDEF Pat_MarkAbilitySpecDirty:BYTE +EXTERNDEF Pat_LocalPlayerSpawnPA :BYTE +EXTERNDEF Pat_GetPlayerViewPoint :BYTE +EXTERNDEF Pat_KickPlayer :BYTE +EXTERNDEF Pat_InitListen :BYTE EXTERNDEF Pat_PostRender :BYTE -EXTERNDEF Pat_PostRender_Mask :BYTE -EXTERNDEF Pat_GetPlayerName :BYTE -EXTERNDEF Pat_GetPlayerName_Mask :BYTE -EXTERNDEF Pat_SeamlessTravel :BYTE -EXTERNDEF Pat_SeamlessTravel_Mask :BYTE -EXTERNDEF Pat_CreateTemporaryItem :BYTE -EXTERNDEF Pat_CreateTemporaryItem_Mask :BYTE +EXTERNDEF Pat_CollectGarbage :BYTE +EXTERNDEF Pat_NetDebug :BYTE ; util.asm — Utility functions -EXTERNDEF Utils_FindPattern :PROC ; (Imagebase:QWORD, pattern:PTR BYTE, mask:PTR BYTE, len:DWORD) -> QWORD +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) EXTERNDEF Utils_RotToQuat :PROC ; (rot:PTR FRotator, out_quat:PTR FQuat) EXTERNDEF Utils_VecToRot :PROC ; (vec:PTR FVector, out_rot:PTR FRotator) EXTERNDEF Utils_RandomIntInRange :PROC ; (min:DWORD, max:DWORD) -> DWORD -; logger.asm — spdlog bridge +; logger.asm — switched to sprintf EXTERNDEF Logger_Initialize :PROC ; () -EXTERNDEF Logger_LogInfo :PROC ; (fmt:PTR BYTE, ...) -EXTERNDEF Logger_LogWarn :PROC ; (fmt:PTR BYTE, ...) -EXTERNDEF Logger_LogError :PROC ; (fmt:PTR BYTE, ...) +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 ; hooks.asm — All hook implementations EXTERNDEF Hooks_TickFlush :PROC @@ -173,6 +151,7 @@ EXTERNDEF FString_Free :PROC ; (str:PTR TArrayHeader) 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 ; logic/game.asm EXTERNDEF Game_Start :PROC diff --git a/include/macros.inc b/include/macros.inc index c7c157f..5adffc6 100644 --- a/include/macros.inc +++ b/include/macros.inc @@ -142,15 +142,12 @@ LOG_ERROR_M MACRO fmt_sym add rsp, SHADOW_SPACE ENDM -FIND_PATTERN_M MACRO result_reg, pattern_sym, mask_sym, pattern_len - sub rsp, SHADOW_SPACE - mov rcx, [Imagebase] - lea rdx, pattern_sym - lea r8, mask_sym - mov r9d, pattern_len +FIND_PATTERN_M MACRO result_reg, pattern_sym, bRelative, offset_val + lea rcx, pattern_sym + mov edx, bRelative + mov r8d, offset_val call Utils_FindPattern mov result_reg, rax - add rsp, SHADOW_SPACE ENDM RESOLVE_RIP_M MACRO result_reg, addr_reg diff --git a/include/structs.inc b/include/structs.inc index 2f2769f..83e28c0 100644 --- a/include/structs.inc +++ b/include/structs.inc @@ -292,7 +292,7 @@ UOBJECT_Class EQU 018h UOBJECT_Name EQU 020h ; FName UOBJECT_Outer EQU 028h -; UFunction field offsets (UObject base = 0x28 → UField 0x30 → UStruct 0x80 → UFunction 0x70 more) +; UFunction field offsets (UObject base = 0x28 -> UField 0x30 -> UStruct 0x80 -> UFunction 0x70 more) UFUNC_FunctionFlags EQU 0D0h UFUNC_NumParms EQU 0D6h UFUNC_ParmsSize EQU 0D8h diff --git a/logger.asm b/logger.asm new file mode 100644 index 0000000..dc32c8c --- /dev/null +++ b/logger.asm @@ -0,0 +1,77 @@ +INCLUDE include\master.inc + +; CRT printf +EXTRN printf :PROC + +.const + +szFmtInfo DB "[INFO] %s", 0Ah, 0 +szFmtWarn DB "[WARN] %s", 0Ah, 0 +szFmtError DB "[ERROR] %s", 0Ah, 0 + +.code + +; Logger_Initialize() +; Sets up the logger. With printf-based output the console is +; already usable after AllocConsole(); nothing extra is required. +; Kept as a callable stub so call sites from raider.asm compile. +Logger_Initialize PROC + ret +Logger_Initialize ENDP + +Logger_LogInfo PROC + ; Entry: RSP ≡ 8 mod 16 (return address pushed on aligned stack) + push rbp + mov rbp, rsp + sub rsp, 32 ; shadow space; push rbp -> RSP = 0 mod 16; sub 32 -> 0 + + ; printf(szFmtInfo, msg) + mov rdx, rcx ; arg2 = msg + lea rcx, szFmtInfo ; arg1 = format + call printf + + mov rsp, rbp + pop rbp + ret +Logger_LogInfo ENDP + +Logger_LogWarn PROC + push rbp + mov rbp, rsp + sub rsp, 32 + + mov rdx, rcx + lea rcx, szFmtWarn + call printf + + mov rsp, rbp + pop rbp + ret +Logger_LogWarn ENDP + +Logger_LogError PROC + push rbp + mov rbp, rsp + sub rsp, 32 + + mov rdx, rcx + lea rcx, szFmtError + call printf + + mov rsp, rbp + pop rbp + ret +Logger_LogError ENDP + +Logger_LogInfoFmt PROC + push rbp + mov rbp, rsp + sub rsp, 32 + ; RCX, RDX, R8, R9 pass through as-is to printf + call printf + mov rsp, rbp + pop rbp + ret +Logger_LogInfoFmt ENDP + +END \ No newline at end of file diff --git a/patterns.asm b/patterns.asm new file mode 100644 index 0000000..3632b8e --- /dev/null +++ b/patterns.asm @@ -0,0 +1,48 @@ +.const + +; Core UE4 globals +Pat_FNameToString DB "48 89 5C 24 ? 57 48 83 EC 40 83 79 04 00 48 8B DA 48 8B F9", 0 +Pat_GObjects DB "48 8B 05 ? ? ? ? 48 8D 1C C8 81 4B ? ? ? ? ? 49 63 76 30", 0 + +; FMemory +Pat_Free DB "48 85 C9 74 1D 4C 8B 05 ? ? ? ? 4D 85 C0 0F 84 ? ? ? ? 49 8B 00 48 8B D1 49 8B C8 48 FF 60 20 C3", 0 +Pat_Malloc DB "4C 8B C9 48 8B 0D ? ? ? ? 48 85 C9 75 08 49 8B C9 E9 ? ? ? ?", 0 +Pat_Realloc DB "4C 8B D1 48 8B 0D ? ? ? ? 48 85 C9 75 08 49 8B CA E9 ? ? ? ? 48 8B 01 45 8B C8 4C 8B C2 49 8B D2 48 FF 60 18", 0 + +; Net connection helpers +Pat_ReceiveFString DB "40 55 53 56 57 41 56 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 27 0F B6 41 28", 0 +Pat_ReceiveUniqueIdRepl DB "48 89 5C 24 ? 55 56 57 48 8B EC 48 83 EC 40 F6 41 28 40 48 8B FA 48 8B D9 0F 84 ? ? ? ? F6 41 2B 02", 0 + +; NetDriver / Beacon +Pat_TickFlush DB "4C 8B DC 55 49 8D AB ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 49 89 5B 18 48 8D 05 ? ? ? ? 49 89 7B E8 48 8B F9 4D 89 63 E0 45 33 E4", 0 +Pat_PauseBeaconRequests DB "40 53 48 83 EC 30 48 8B D9 84 D2 74 68 80 3D ? ? ? ? ? 72 2C 48 8B 05 ? ? ? ? 4C 8D 44 24 ? 48 89 44 24 ?", 0 +Pat_BeaconNotifyAccept DB "48 83 EC 48 48 8B 41 10 48 83 78 ? ?", 0 +Pat_InitHost DB "48 8B C4 48 81 EC ? ? ? ? 48 89 58 18 4C 8D 05 ? ? ? ?", 0 +Pat_BeaconNotifyCtrl DB "40 55 53 56 57 41 54 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 33 FF 48 89 4C 24 ? 89 7C 24 60 49 8B F1 48 8B 41 10 45 0F B6 E0 4C 8B F2 48 8B D9 44 8B FF 48 39 78 78 0F 85 ? ? ? ? 80 3D ? ? ? ? ?", 0 + +; World / Engine +Pat_WelcomePlayer DB "48 8B C4 55 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 48 89 70 20", 0 +Pat_WorldNotifyCtrl DB "40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 45 33 F6 49 8B D9 44 89 74 24 ? 45 8B E6 48 8B 41 10 45 0F B6 F8 48 8B FA 4C 8B E9 4C 39 60 78", 0 +Pat_SpawnPlayActor DB "44 89 44 24 ? 48 89 54 24 ? 48 89 4C 24 ? 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 33 F6 48 8D 05 ? ? ? ? 89 75 67 4D 8B E9 4C 8B 65 77 49 39 04 24 74 2A 41 89 74 24 ? 41 39 74 24 ?", 0 +Pat_WorldNotifyAccept DB "40 55 48 83 EC 50 48 8B 41 10 48 8B E9 48 83 78 ? ? 74 45 80 3D ? ? ? ? ? 72 34 48 8B 05 ? ? ? ? 4C 8D 44 24 ? 48 89 44 24 ? 48 8D 0D ? ? ? ? 48 8D 05 ? ? ? ? 41 B9 ? ? ? ? BA ? ? ? ? 48 89 44 24 ?", 0 +Pat_GetNetMode DB "48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 48 8B D9 FF 90 ? ? ? ? 4C 8B 83 ? ? ? ? 48 8B F8 33 C0 48 C7 44 24", 0 + +; Ability System +Pat_GiveAbility DB "48 89 5C 24 ? 56 57 41 56 48 83 EC 20 83 B9 ? ? ? ? ? 49 8B F0 4C 8B F2 48 8B D9 7E 61", 0 +Pat_InternalTryActivate DB "4C 89 4C 24 ? 4C 89 44 24 ? 89 54 24 10 55 53 56 57 41 54 41 57 48 8D AC 24", 0 +Pat_MarkAbilitySpecDirty DB "48 89 5C 24 ? 57 48 83 EC 20 80 B9 ? ? ? ? ? 48 8B FA 48 8B D9 75 4A C6 81", 0 + +; Player +Pat_LocalPlayerSpawnPA DB "40 55 53 56 57 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 40 48 8B D9 4D 8B F1 49 8B C9 4D 8B F8 48 8B F2", 0 +Pat_GetPlayerViewPoint DB "48 89 5C 24 ? 48 89 74 24 ? 55 41 56 41 57 48 8B EC 48 83 EC 50 48 8B F2 48 C7 45 ? ? ? ? ? 48 8B 55 D0 4D 8B F0 48 8B D9 45 33 FF E8 ? ? ? ? 84 C0 74 4A 80 BB ? ? ? ? ? 75 41", 0 +Pat_KickPlayer DB "48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 49 8B F0 48 8B DA 48 85 D2 74 ? 48 8B BA ? ? ? ? 48", 0 + +; Misc +Pat_InitListen DB "48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 50 48 8B BC 24 ? ? ? ? 49 8B F0", 0 +Pat_PostRender DB "48 89 74 24 ? 57 48 81 EC ? ? ? ? 80 B9 ? ? ? ? ? 48 8B F2", 0 +Pat_CollectGarbage DB "E8 ? ? ? ? EB 26 40 38 3D ? ? ? ?", 0 + +; Hook-specific patterns +Pat_NetDebug DB "40 55 56 41 56 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 48 8B 01 48 8B F1 FF 90 ? ? ? ? 4C 8B F0 48 85 C0 0F", 0 + +END \ No newline at end of file diff --git a/raider.asm b/raider.asm new file mode 100644 index 0000000..3fb6009 --- /dev/null +++ b/raider.asm @@ -0,0 +1,162 @@ +INCLUDE include\master.inc + +; printf from the MSVC CRT (needed for the formatted base-address log line) +EXTRN printf :PROC + +.const + +szWelcome DB "Welcome to Raider!", 0 +szInitHooks DB "Initializing hooks!", 0 +szFailNetDebug DB "Failed to find NetDebug", 0 +szBaseAddrFmt DB "[INFO] Base Address: 0x%I64X", 0Ah, 0 + +.data + + +.code + +; Main — worker thread entry point +; RCX = lpParam (hModule passed from DllMain; not used inside Main) +; +; Stack frame layout (after prologue): +; [rbp+ 0] = saved rbp +; ---- 48 bytes sub rsp ---- +; [rbp- 8] = local: NetDebug function pointer (8 bytes) +; [rbp- 16] = alignment pad (8 bytes) +; [rbp- 48] … [rbp-17] = 32-byte shadow space for callees ([rsp+0..31]) +; +; Alignment check: +; entry RSP ≡ 8 mod 16 (ret addr pushed on 16-byte-aligned stack) +; push rbp → RSP ≡ 0 mod 16 +; sub rsp, 48 (48 mod 16 = 0) → RSP ≡ 0 mod 16 at every CALL site +Main PROC + push rbp + mov rbp, rsp + sub rsp, 48 ; shadow(32) + local_NetDebug(8) + pad(8) + + ; initialise local NetDebug function pointer to NULL + mov QWORD PTR [rbp - 8], 0 + + call AllocConsole + + call Logger_Initialize + + lea rcx, szWelcome + call Logger_LogInfo + + lea rcx, szInitHooks + call Logger_LogInfo + + call Native_InitializeAll + + call UFunctionHooks_Initialize + + call DetourTransactionBegin + + call GetCurrentThread + mov rcx, rax + call DetourUpdateThread + + lea rcx, Native_NetDriver_TickFlush + lea rdx, Hooks_TickFlush + call DetourAttach + + lea rcx, Native_LocalPlayer_SpawnPlayActor + lea rdx, Hooks_LocalPlayerSpawnPlayActor + call DetourAttach + + lea rcx, Pat_NetDebug + xor edx, edx ; bRelative = false + xor r8d, r8d ; offset = 0 + call Utils_FindPattern + + test rax, rax + jnz @@netdebug_found + + lea rcx, szFailNetDebug + call Logger_LogError + xor eax, eax ; return 0 (thread exit) + jmp @@main_exit + +@@netdebug_found: + ; NetDebug = (void*(*)(void*))Address + mov QWORD PTR [rbp - 8], rax + + lea rcx, QWORD PTR [rbp - 8] + lea rdx, Hooks_NetDebug + call DetourAttach + + lea rcx, ProcessEvent + lea rdx, Hooks_ProcessEventHook + call DetourAttach + + lea rcx, Native_PlayerController_GetPlayerViewPoint + lea rdx, Hooks_GetPlayerViewPoint + call DetourAttach + + call DetourTransactionCommit + + lea rcx, szBaseAddrFmt + mov rdx, QWORD PTR [Imagebase] + call printf + + call SDK_CreateConsole + + xor eax, eax ; return 0 (DWORD thread exit code) + +@@main_exit: + mov rsp, rbp + pop rbp + ret +Main ENDP + +; DllMain — DLL entry point +; RCX = hModule (HMODULE) +; EDX = dwReason (DWORD) +; R8 = lpReserved (LPVOID) +; +; Stack frame layout (after prologue): +; [rsp+48] = return address <- above frame +; [rsp+40] = saved rbx +; [rsp+32] = saved rbp <- standard frame base +; [rsp+ 0] = our frame (56 bytes total): +; [rsp+48] = CreateThread arg6 (lpThreadId = NULL) +; [rsp+40] = CreateThread arg5 (dwCreationFlags = 0) +; [rsp+ 0]..[rsp+31] = shadow space for callees +DllMain PROC + push rbp + push rbx ; callee-saved; corrects alignment + sub rsp, 56 ; shadow(32) + arg5(8) + arg6(8) + pad(8) + + ; save hModule (RCX) for use as CreateThread lpParameter + mov rbx, rcx ; rbx = hModule, preserved across calls + + cmp edx, DLL_PROCESS_ATTACH + jne @@dllmain_done + + ; CreateThread(NULL, 0, Main, hModule, 0, NULL) + ; arg1 RCX = lpThreadAttributes = NULL + ; arg2 RDX = dwStackSize = 0 + ; arg3 R8 = lpStartAddress = Main + ; arg4 R9 = lpParameter = hModule + ; arg5 [rsp+32] = dwCreationFlags = 0 + ; arg6 [rsp+40] = lpThreadId = NULL + xor ecx, ecx ; NULL + xor edx, edx ; 0 + lea r8, Main ; Main thread proc + mov r9, rbx ; hModule as lpParam + xor eax, eax + mov QWORD PTR [rsp + 32], rax ; dwCreationFlags = 0 + mov QWORD PTR [rsp + 40], rax ; lpThreadId = NULL + call CreateThread + +@@dllmain_done: + mov eax, 1 ; return TRUE + + add rsp, 56 + pop rbx + pop rbp + ret +DllMain ENDP + +END \ No newline at end of file