UE4逆向初探-OverWatch 可以看这个线上培训 -先知社区
赛后下面那个偏移问题(主要是被网上某篇瞎写的博客和IDA字符串加载给暗算了)解决了自己做了下直接出了一段flag,后一段flag没找到只能看wp了
好的!我知道了尴尬了,我还是太着急了,刚刚写这个wp的时候又打开来了(之前保存的i64),搜了一下seamless,发现直接出现了,原来是IDA加载太慢了,我太急了,我就不该上课 T.T
dump工具:Spuckwaffel/UEDumper: The most powerful Unreal Engine Dumper and Editor for UE 4.19 - 5.3
可以看这个视频
https://www.youtube.com/watch?v=M7VLd1xrVoM
说一下找三件套吧
Fname找ByteObject
交叉引用这个方法,是最上面那个
第一个偏移:0x4869C80
ps:可以看那个印度佬的视频,挺好的,先去rebase里把机制定位0
找UWorld时,我是IDA没加载出来这个”Seamless”字符串
关于如何对照源码虚幻4 UE4 逆向 寻找 世界地址 UWORLD地址 教程_哔哩哔哩_bilibili
可以先去github把对应版本的源码下载下来,需要加入epicgame组织先,
所以我对照了源码最终找到一个
当然常规的方法更简单一点
搜索: SeamlessTravel FlushLevelStreaming
往上直接找到:
第二个uworld有了:49ee370
第三个gobject,我也是死在这了…
我找的偏移是0x48A5FC0
看了wp发现是:0x48A5FD0
….
就差0x10,可能是数据结构哪里搞错了应该
当时找了
当时字符串没加载出来,简单的把48A5FC0作为Gobject肯定不对,都跟上面不太像其实
实际上被误导了?
ue5游戏逆向之寻找GWorld,GName和GUObjectArray - 怎么可以吃突突 - 博客园
这里虽然是ue5的方法,但是道理应该差不多,为什么偏移不对?
官解搜索的是:NewObject with….
可是我看了下引用:
这找个damn…
不知道是不是我IDA的原因
运气足够好,第二个就是
但是我并没有找到源码中对应的寻找方式,可能是源码中把NewObject字符串包装了,得搜索引用这个函数的才能去找GUObject
推荐搜索Failed to load Enginee class,跟刚才的NewObject With到达的是一个地方
48A5FD0
offset.h里填好
dump成功如下
后面就是游戏逆向,猜测flag在墙外,因而只有几种常规方法:透视(墙不见) 穿墙 飞天遁地
在merged_AudioMixer_Engine_UMG_MovieScene_MovieSceneTracks.h种有
这个文件不是引擎原生的源码文件,而是 自动合并生成的头文件 ,
目的是把多个模块导出的类、枚举、结构体合并在一个文件中方便分析。
这个枚举定义在 UE 原版引擎中是 角色移动组件(Character Movement Component) 的核心枚举
模式
场景举例
行为逻辑
MOVE_None
不可移动(如被眩晕、冻结)
停止更新物理
MOVE_Walking
在地面上走
使用地面摩擦力、速度计算
MOVE_NavWalking
AI 路径导航行走
使用 NavMesh
MOVE_Falling
从高处坠落
使用重力
MOVE_Swimming
在水中游动
使用流体阻力、浮力
MOVE_Flying
飞行类角色(如幽灵、飞行器)
关闭重力,使用自由三维移动
MOVE_Custom
自定义移动,如“攀爬”、“滑行”
游戏开发者自己扩展逻辑
我们能发现这里还有
ACharacter是什么?
ACharacter:UE4 自带的行走类Actor,继承自 APawn。含网格体、胶囊体、UCharacterMovementComponent 等,负责角色移动、跳跃等行为。你操作飞行/穿墙时的目标对象就是本地玩家的 ACharacter 实例
这些是 编译时静态断言(static_assert) ,用于验证 类成员变量的内存偏移 是否正确。
UCharacterMovementComponent::MovementMode
与 PendingLaunchVelocity
这些字段属于 UCharacterMovementComponent
(角色移动组件),控制角色的物理状态。
我们除了这些关键属性之外还需要知道世界链路
在 UE 逆向中,找到世界链路 是理解游戏对象体系的关键。
世界结构简图:
1 2 3 4 5 6 7 8 9 GWorld → UWorld ├─ PersistentLevel (ULevel) │ ├─ AActor[0] = DefaultPawn │ ├─ AActor[1] = PlayerCharacter │ └─ ... ├─ GameInstance ├─ GameMode ├─ PlayerController └─ etc.
名称
类型
含义
GWorld
UWorld*
全局指针
当前正在运行的世界(全局变量)
UWorld
类对象
世界实例本身,包含关卡、玩家、Actor 列表等
GWorld
就是指向当前 UWorld
的全局变量。
在内存调试中,通常会通过 GWorld
找到整个世界的根:
1 2 3 UWorld* World = GWorld; ULevel* Level = World->PersistentLevel; TArray<AActor*> Actors = Level->Actors;
这样就能遍历世界中所有的角色对象。
元素
含义
逆向用途
offsetof
成员偏移
定位内存字段、直接读写对象成员
CharacterMovement
角色移动组件指针
控制角色物理行为(走、飞、跳)
CapsuleComponent
碰撞体组件
检测碰撞、修改 hitbox 尺寸
MovementMode
当前移动模式
判断或强制移动状态
PendingLaunchVelocity
等待应用的速度
修改跳跃或击飞效果
GWorld → UWorld
世界根节点
遍历所有 Actor,找到玩家对象
在游戏中找到了玩家对象地址 PlayerCharacter
。
1 UCharacterMovementComponent* MoveComp = *(UCharacterMovementComponent**)(PlayerCharacter + 0x288);
接下来:
1 2 MoveComp->MovementMode = EMovementMode::MOVE_Flying; MoveComp->PendingLaunchVelocity = FVector(0, 0, 3000);
角色立刻能在空中飞行或超高跳。
UWorld::OwningGameInstance:指向当前世界所属的 UGameInstance。GameInstance 持有全局状态,如本地玩家列表、子系统等,是沿 GWorld 找到你这边玩家控制器的入口。
APawn:可被玩家或 AI 控制的 Actor 基类。ACharacter 就是 APawn 的一个扩展版本,加入了骨骼网格和 CharacterMovement。
APlayerController::AcknowledgedPawn:玩家控制器当前“正式控制”的 Pawn 指针。正常游戏里它就是你的角色 Pawn(如 ACharacter),读取后才能继续修改移动组件/碰撞。
APlayerController:表示本地或远端的玩家控制器,处理输入、相机、HUD 等。我们从 UGameInstance::LocalPlayers 取得的 ULocalPlayer->PlayerController 就是本地玩家的控制器,顺着它的 AcknowledgedPawn 拿到角色后才能进行后续 hack。
世界链路
GWorld(基址 base + 0x49EE370,与setOffsets() 中 OFFSET_GWORLD 相符)指向当前关卡对应的 UWorld。
UWorld + 0x180(OwningGameInstance)拿到 UGameInstance,这是全局封装玩家列表的对象。
UGameInstance + 0x38(LocalPlayers 的 TArray)提供本地玩家数组,下标 0 通常是本地玩家。
ULocalPlayer->PlayerController(UPlayer::PlayerController 在 …:8986 给出 0x30)接到 APlayerController,再用 AcknowledgedPawn 偏移 0x2A0 取到实际 Pawn。
Pawn + 0x288(CharacterMovement)就能定位 UCharacterMovementComponent;后续通过 MovementMode、PendingLaunchVelocity 等偏移修改为飞行或冲刺,或者抓取 CapsuleComponent(0x290) 调 SetCollisionEnabled 实现穿墙。
在编写代码时我们可以用reinterpret_cast
reinterpret_cast(expr) 是 C++ 提供的强制类型转换之一:
1 2 在没有类型信息/类定义不足的情况下,把某个指针或整数当成别的类型的指针来访问。 与UE这类内存操作结合时,我们经常只有偏移值,所以先把基址转成 uint8_t*,加偏移后再 reinterpret_cast<目标类型*>,这样就能把那块内存看成某个字段或结构。
FVector 在 BasicType.h 里被定义成三个 float 分量(X/Y/Z)。C++ 允许对这种简单结构做聚合初始化,{a, b, c} 就会依次填入 X/Y/Z,所以 {0.f, 0.f, 800.f} 会写成 (0,0,800)。
数值 800/600 只是示例:PendingLaunchVelocity 相当于给角色一个即将施加的冲量,LastUpdateVelocity 是当前速度。这两个字段只要写入任何 FVector,UE4 就会按这些分量处理运动;如果想要更慢或更快的上升,可以自己改成别的值。
exp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 #include "pch.h" #include <Windows.h> #include <atomic> #include <thread> #include <chrono> #include "BasicType.h" struct UWorld ;struct UGameInstance ;struct ULocalPlayer ;struct APlayerController ;struct APawn ;struct ACharacter ;struct UCharacterMovementComponent ;struct FVector { float X, Y, Z; };enum class EMovementMode : uint8_t { MOVE_None = 0 , MOVE_Walking = 1 , MOVE_NavWalking, MOVE_Falling, MOVE_Swimming, MOVE_Flying, MOVE_Custom }; constexpr uintptr_t OFFSET_GWORLD = 0x49EE370 ;constexpr size_t OFFSET_UWORLD_OWNING_GI = 0x180 ;constexpr size_t OFFSET_UGAMEINSTANCE_LOCALPLAYERS = 0x38 ;constexpr size_t OFFSET_ULOCALPLAYER_PLAYERCONTROLLER = 0x30 ;constexpr size_t OFFSET_APLAYERCONTROLLER_ACKPAWN = 0x2A0 ;constexpr size_t OFFSET_ACHARACTER_CHARACTERMOVEMENT = 0x288 ; constexpr size_t OFFSET_UCHARMOVEMENT_MOVEMENTMODE = 0x168 ;constexpr size_t OFFSET_UCHARMOVEMENT_DEFAULTLANDMODE = 0x384 ;constexpr size_t OFFSET_UCHARMOVEMENT_PENDINGLAUNCHVELOC = 0x3C0 ;constexpr size_t OFFSET_UCHARMOVEMENT_LASTUPDATEVELOC = 0x25C ; static std::atomic<bool > g_running{ true };static std::atomic<bool > g_flyEnabled{ false };inline uintptr_t GetModuleBase () { static uintptr_t base = reinterpret_cast <uintptr_t >(::GetModuleHandleW (nullptr )); return base; } inline UWorld* GetWorld () { return *reinterpret_cast <UWorld**>(GetModuleBase () + OFFSET_GWORLD); } inline UGameInstance* GetGameInstance (UWorld* world) { if (!world) return nullptr ; return *reinterpret_cast <UGameInstance**>(reinterpret_cast <uint8_t *>(world) + OFFSET_UWORLD_OWNING_GI); } inline TArray<ULocalPlayer*>& GetLocalPlayers (UGameInstance* gi) { return *reinterpret_cast <TArray<ULocalPlayer*>*>(reinterpret_cast <uint8_t *>(gi) + OFFSET_UGAMEINSTANCE_LOCALPLAYERS); } inline APlayerController* GetPlayerController (ULocalPlayer* lp) { return *reinterpret_cast <APlayerController**>(reinterpret_cast <uint8_t *>(lp) + OFFSET_ULOCALPLAYER_PLAYERCONTROLLER); } inline ACharacter* GetAcknowledgedCharacter (APlayerController* pc) { return *reinterpret_cast <ACharacter**>(reinterpret_cast <uint8_t *>(pc) + OFFSET_APLAYERCONTROLLER_ACKPAWN); } inline UCharacterMovementComponent* GetCharacterMovement (ACharacter* character) { return *reinterpret_cast <UCharacterMovementComponent**>( reinterpret_cast <uint8_t *>(character) + OFFSET_ACHARACTER_CHARACTERMOVEMENT); } void ApplyFlyState (UCharacterMovementComponent* movement, bool enable) { if (!movement) return ; uint8_t * base = reinterpret_cast <uint8_t *>(movement); auto & movementMode = *reinterpret_cast <EMovementMode*>(base + OFFSET_UCHARMOVEMENT_MOVEMENTMODE); auto & defaultLandMode = *reinterpret_cast <EMovementMode*>(base + OFFSET_UCHARMOVEMENT_DEFAULTLANDMODE); auto & pendingLaunchVelocity = *reinterpret_cast <FVector*>(base + OFFSET_UCHARMOVEMENT_PENDINGLAUNCHVELOC); auto & lastUpdateVelocity = *reinterpret_cast <FVector*>(base + OFFSET_UCHARMOVEMENT_LASTUPDATEVELOC); if (enable) { movementMode = EMovementMode::MOVE_Flying; defaultLandMode = EMovementMode::MOVE_Flying; pendingLaunchVelocity = { 0.f , 0.f , 800.f }; lastUpdateVelocity = { 0.f , 0.f , 600.f }; } else { movementMode = EMovementMode::MOVE_Walking; defaultLandMode = EMovementMode::MOVE_Walking; pendingLaunchVelocity = { 0.f , 0.f , 0.f }; lastUpdateVelocity = { 0.f , 0.f , 0.f }; } } void SustainFly (UCharacterMovementComponent* movement) { if (!movement) return ; uint8_t * base = reinterpret_cast <uint8_t *>(movement); auto & movementMode = *reinterpret_cast <EMovementMode*>(base + OFFSET_UCHARMOVEMENT_MOVEMENTMODE); auto & lastUpdateVelocity = *reinterpret_cast <FVector*>(base + OFFSET_UCHARMOVEMENT_LASTUPDATEVELOC); movementMode = EMovementMode::MOVE_Flying; if (lastUpdateVelocity.Z < 300.f ) { lastUpdateVelocity.Z = 400.f ; } } DWORD WINAPI FlyThread (LPVOID) { while (g_running) { if (::GetAsyncKeyState (VK_F6) & 1 ) { UWorld* world = GetWorld (); auto gi = GetGameInstance (world); if (!gi) continue ; auto & players = GetLocalPlayers (gi); if (!players.IsValidIndex (0 ) || !players[0 ]) continue ; auto pc = GetPlayerController (players[0 ]); if (!pc) continue ; auto character = GetAcknowledgedCharacter (pc); auto movement = GetCharacterMovement (character); g_flyEnabled = !g_flyEnabled.load (); ApplyFlyState (movement, g_flyEnabled); } if (g_flyEnabled) { UWorld* world = GetWorld (); auto gi = GetGameInstance (world); if (gi) { auto & players = GetLocalPlayers (gi); if (players.IsValidIndex (0 ) && players[0 ]) { auto pc = GetPlayerController (players[0 ]); if (pc) { auto character = GetAcknowledgedCharacter (pc); auto movement = GetCharacterMovement (character); SustainFly (movement); } } } } std::this_thread::sleep_for (std::chrono::milliseconds (20 )); } return 0 ; } BOOL APIENTRY DllMain (HMODULE module , DWORD reason, LPVOID) { if (reason == DLL_PROCESS_ATTACH) { ::DisableThreadLibraryCalls (module ); ::MessageBoxW (nullptr , L"TSCTF DLL 注入成功\nF6 切换飞行模式" , L"TSCTF Helper" , MB_OK | MB_ICONINFORMATION); ::CreateThread (nullptr , 0 , FlyThread, nullptr , 0 , nullptr ); } else if (reason == DLL_PROCESS_DETACH) { g_running = false ; } return TRUE; }
visual studio新建dll项目
注意引如BasicType.h
然后生成项目
relase x64
然后找工具注入
如:
DarthTon/Xenos: Windows dll injector
注入即可
按F6起飞
这里再添加一个脚本兼容穿墙和起飞
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 #include "pch.h" #include <Windows.h> #include <atomic> #include <thread> #include <chrono> #include "BasicType.h" struct UWorld ;struct UGameInstance ;struct ULocalPlayer ;struct APlayerController ;struct APawn ;struct ACharacter ;struct UCharacterMovementComponent ;struct UCapsuleComponent ;struct FVector { float X, Y, Z; };enum class EMovementMode : uint8_t { MOVE_None = 0 , MOVE_Walking = 1 , MOVE_NavWalking, MOVE_Falling, MOVE_Swimming, MOVE_Flying, MOVE_Custom }; enum class ECollisionEnabled : uint8_t { NoCollision = 0 , QueryOnly = 1 , PhysicsOnly = 2 , QueryAndPhysics = 3 }; constexpr uintptr_t OFFSET_GWORLD = 0x49EE370 ;constexpr size_t OFFSET_UWORLD_OWNING_GI = 0x180 ;constexpr size_t OFFSET_UGAMEINSTANCE_LOCALPLAYERS = 0x38 ;constexpr size_t OFFSET_ULOCALPLAYER_PLAYERCONTROLLER = 0x30 ;constexpr size_t OFFSET_APLAYERCONTROLLER_ACKPAWN = 0x2A0 ;constexpr size_t OFFSET_ACHARACTER_MOVEMENT = 0x288 ;constexpr size_t OFFSET_ACHARACTER_CAPSULE = 0x290 ;constexpr size_t OFFSET_UCHARMOVEMENT_MOVEMENTMODE = 0x168 ;constexpr size_t OFFSET_UCHARMOVEMENT_DEFAULTLANDMODE = 0x384 ;constexpr size_t OFFSET_UCHARMOVEMENT_PENDINGLAUNCH = 0x3C0 ;constexpr size_t OFFSET_UCHARMOVEMENT_LASTUPDATEVELO = 0x25C ;constexpr size_t OFFSET_UPRIMITIVE_BODYINSTANCE = 0x2C8 ;constexpr size_t OFFSET_FBODYINSTANCE_COLLISIONENABLED = 0x20 ;static std::atomic<bool > g_running{ true };static std::atomic<bool > g_userFly{ false };static std::atomic<bool > g_autoFlyFromCollision{ false };static std::atomic<bool > g_noCollision{ false };inline uintptr_t GetModuleBase () { static uintptr_t base = reinterpret_cast <uintptr_t >(::GetModuleHandleW (nullptr )); return base; } inline UWorld* GetWorld () { return *reinterpret_cast <UWorld**>(GetModuleBase () + OFFSET_GWORLD); } inline UGameInstance* GetGameInstance (UWorld* world) { if (!world) return nullptr ; return *reinterpret_cast <UGameInstance**>(reinterpret_cast <uint8_t *>(world) + OFFSET_UWORLD_OWNING_GI); } inline TArray<ULocalPlayer*>& GetLocalPlayers (UGameInstance* gi) { return *reinterpret_cast <TArray<ULocalPlayer*>*>(reinterpret_cast <uint8_t *>(gi) + OFFSET_UGAMEINSTANCE_LOCALPLAYERS); } inline APlayerController* GetPlayerController (ULocalPlayer* lp) { return *reinterpret_cast <APlayerController**>(reinterpret_cast <uint8_t *>(lp) + OFFSET_ULOCALPLAYER_PLAYERCONTROLLER); } inline ACharacter* GetAcknowledgedCharacter (APlayerController* pc) { return *reinterpret_cast <ACharacter**>(reinterpret_cast <uint8_t *>(pc) + OFFSET_APLAYERCONTROLLER_ACKPAWN); } inline UCharacterMovementComponent* GetCharacterMovement (ACharacter* character) { return *reinterpret_cast <UCharacterMovementComponent**>(reinterpret_cast <uint8_t *>(character) + OFFSET_ACHARACTER_MOVEMENT); } inline UCapsuleComponent* GetCapsuleComponent (ACharacter* character) { return *reinterpret_cast <UCapsuleComponent**>(reinterpret_cast <uint8_t *>(character) + OFFSET_ACHARACTER_CAPSULE); } void ApplyFlyState (UCharacterMovementComponent* movement, bool enable, bool giveBoost) { if (!movement) return ; uint8_t * base = reinterpret_cast <uint8_t *>(movement); auto & movementMode = *reinterpret_cast <EMovementMode*>(base + OFFSET_UCHARMOVEMENT_MOVEMENTMODE); auto & defaultLand = *reinterpret_cast <EMovementMode*>(base + OFFSET_UCHARMOVEMENT_DEFAULTLANDMODE); auto & pendingLaunch = *reinterpret_cast <FVector*>(base + OFFSET_UCHARMOVEMENT_PENDINGLAUNCH); auto & lastUpdateVel = *reinterpret_cast <FVector*>(base + OFFSET_UCHARMOVEMENT_LASTUPDATEVELO); if (enable) { movementMode = EMovementMode::MOVE_Flying; defaultLand = EMovementMode::MOVE_Flying; if (giveBoost) { pendingLaunch = { 0.f , 0.f , 800.f }; lastUpdateVel = { 0.f , 0.f , 600.f }; } else { pendingLaunch = { 0.f , 0.f , 0.f }; lastUpdateVel = { 0.f , 0.f , 0.f }; } } else { movementMode = EMovementMode::MOVE_Walking; defaultLand = EMovementMode::MOVE_Walking; pendingLaunch = { 0.f , 0.f , 0.f }; lastUpdateVel = { 0.f , 0.f , 0.f }; } } void SustainFly (UCharacterMovementComponent* movement, bool giveBoost) { if (!movement) return ; uint8_t * base = reinterpret_cast <uint8_t *>(movement); auto & movementMode = *reinterpret_cast <EMovementMode*>(base + OFFSET_UCHARMOVEMENT_MOVEMENTMODE); auto & lastUpdateVel = *reinterpret_cast <FVector*>(base + OFFSET_UCHARMOVEMENT_LASTUPDATEVELO); movementMode = EMovementMode::MOVE_Flying; if (giveBoost && lastUpdateVel.Z < 300.f ) { lastUpdateVel.Z = 400.f ; } } void ApplyCollisionState (UCapsuleComponent* capsule, bool noCollision) { if (!capsule) return ; uint8_t * primitive = reinterpret_cast <uint8_t *>(capsule); auto & collisionEnabled = *reinterpret_cast <ECollisionEnabled*>( primitive + OFFSET_UPRIMITIVE_BODYINSTANCE + OFFSET_FBODYINSTANCE_COLLISIONENABLED); collisionEnabled = noCollision ? ECollisionEnabled::NoCollision : ECollisionEnabled::QueryAndPhysics; } bool ShouldFly () { return g_userFly.load () || g_autoFlyFromCollision.load (); } DWORD WINAPI FlyThread (LPVOID) { while (g_running) { if (::GetAsyncKeyState (VK_F6) & 1 ) { UWorld* world = GetWorld (); auto gi = GetGameInstance (world); if (!gi) continue ; auto & players = GetLocalPlayers (gi); if (!players.IsValidIndex (0 ) || !players[0 ]) continue ; auto pc = GetPlayerController (players[0 ]); if (!pc) continue ; auto character = GetAcknowledgedCharacter (pc); auto movement = GetCharacterMovement (character); if (!movement) continue ; g_userFly = !g_userFly.load (); ApplyFlyState (movement, ShouldFly (), g_userFly.load ()); } if (::GetAsyncKeyState (VK_F5) & 1 ) { UWorld* world = GetWorld (); auto gi = GetGameInstance (world); if (!gi) continue ; auto & players = GetLocalPlayers (gi); if (!players.IsValidIndex (0 ) || !players[0 ]) continue ; auto pc = GetPlayerController (players[0 ]); if (!pc) continue ; auto character = GetAcknowledgedCharacter (pc); auto movement = GetCharacterMovement (character); auto capsule = GetCapsuleComponent (character); if (!movement || !capsule) continue ; bool newState = !g_noCollision.load (); g_noCollision = newState; g_autoFlyFromCollision = newState; ApplyCollisionState (capsule, newState); ApplyFlyState (movement, ShouldFly (), g_userFly.load ()); } if (ShouldFly () || g_noCollision.load ()) { UWorld* world = GetWorld (); auto gi = GetGameInstance (world); if (gi) { auto & players = GetLocalPlayers (gi); if (players.IsValidIndex (0 ) && players[0 ]) { auto pc = GetPlayerController (players[0 ]); if (pc) { auto character = GetAcknowledgedCharacter (pc); if (auto movement = GetCharacterMovement (character)) { SustainFly (movement, g_userFly.load ()); } if (auto capsule = GetCapsuleComponent (character); g_noCollision.load ()) { ApplyCollisionState (capsule, true ); } } } } } std::this_thread::sleep_for (std::chrono::milliseconds (20 )); } return 0 ; } BOOL APIENTRY DllMain (HMODULE module , DWORD reason, LPVOID) { if (reason == DLL_PROCESS_ATTACH) { ::DisableThreadLibraryCalls (module ); ::MessageBoxW (nullptr , L"TSCTF DLL 注入成功\nF6 切换飞行模式\nF5 切换穿墙模式" , L"TSCTF Helper" , MB_OK | MB_ICONINFORMATION); ::CreateThread (nullptr , 0 , FlyThread, nullptr , 0 , nullptr ); } else if (reason == DLL_PROCESS_DETACH) { g_running = false ; } return TRUE; }
Flag:TSCTF-J{u0real_or_R1AL?!
还有一段flag找不到
只能看wp了
看了题解是藏在前面了_and_here}
TSCTF-J{u0real_or_R1AL?!_and_here}