// Exercise the observer against memory owned by this process. No game, hooks, // or native camera calls are used; only the native TLS lookup is substituted. #include #include #include #include #include #include #include #include thread_local std::array fixture_tls; unsigned __int64 fixture_gs(unsigned long) { return reinterpret_cast(fixture_tls.data()); } #define __readgsqword fixture_gs #include "Extension/Skater/camera_observer.cpp" #undef __readgsqword namespace dingosdk { HookStatus WINAPI hook_prepare(void*, void*, void**) { return HookNotInitialized; } HookStatus WINAPI hook_enable(void*) { return HookNotInitialized; } HookStatus WINAPI hook_remove(void*) { return HookNotInitialized; } } using namespace dingosdk; void check(bool value, const char* message) { if (!value) throw std::runtime_error(message); } template struct Block { alignas(8) std::array bytes{}; std::uintptr_t address() const { return reinterpret_cast(bytes.data()); } template void put(std::size_t at, T value) { std::memcpy(bytes.data() + at, &value, sizeof(value)); } }; struct Camera { Block<0x28> callback; Block<0x98> entry; Block<0x70> helper; Block<0x140> evaluator; Block<0x188> camera; Block<0x18> collection; Block<0x10> selection, input; Block<8> context, graph; explicit Camera(std::uintptr_t entry_type = camera_addresses::entry_vtable) { const auto base = camera_state().base; callback.put(0, base + camera_addresses::callback_vtable); callback.put(0x10, entry.address()); callback.put(0x18, helper.address()); callback.put(0x20, graph.address()); entry.put(0, base + entry_type); entry.put(0x60, callback.address()); entry.put(0x90, context.address()); helper.put(0, base + camera_addresses::helper_vtable); helper.put(0x50, callback.address()); evaluator.put(0, context.address()); evaluator.put(8, collection.address()); evaluator.put(0x138, camera.address()); camera.put(0, base + addr::engine::camera_vtable); camera.put(0x180, evaluator.address()); collection.put(0, evaluator.address()); collection.put(8, selection.address()); collection.put(0x10, selection.address() + 0x10); selection.put(0, entry.address()); input.put(8, evaluator.address()); } }; struct NativeTls { Block<0xb20> block; explicit NativeTls(const Camera& camera) { block.put(0xb19, static_cast(1)); block.put(0x550, camera.context.address()); fixture_tls[0] = block.address(); } ~NativeTls() { fixture_tls[0] = 0; } }; void observe(Camera& camera, bool returned = true) { CameraCall call(camera_state(), camera.callback.address(), camera_state().base + camera_addresses::native_caller_return, camera.input.address()); call.finish(returned); } bool ready(Camera& camera) { camera_tick_enter(0x10000); camera_tick_native_return(); const bool result = camera_probe_phase_observed(camera.context.address()); camera_tick_leave(); return result; } void native_entry_variants() { // The live stuck-camera capture selected the alternate entry. Both constructors // initialize the same evaluator-facing entry base, then set their own type. Camera alternate(camera_addresses::alternate_entry_vtable); NativeTls tls(alternate); observe(alternate); check(ready(alternate), "The alternate native entry must establish camera readiness"); alternate.entry.put(0, camera_state().base + camera_addresses::alternate_entry_vtable + 0x10); check(!ready(alternate), "Unverified entry types remain rejected"); alternate.entry.put(0, camera_state().base + camera_addresses::alternate_entry_vtable); alternate.entry.put(0x60, std::uintptr_t{}); check(!ready(alternate), "Supported entry variants still require a reciprocal callback"); alternate.entry.put(0x60, alternate.callback.address()); check(ready(alternate), "A supported entry with restored ownership remains usable"); } void recovery() { Camera camera; NativeTls tls(camera); observe(camera); check(ready(camera), "An isolated local update enables flight"); check(!camera_probe_phase_observed(camera.context.address()), "Flight is blocked outside the native post-tick phase"); camera_tick_enter(0x10000); camera_tick_native_return(); std::promise entered, release; auto released = release.get_future(); std::thread worker([&] { NativeTls worker_tls(camera); CameraCall call(camera_state(), camera.callback.address(), camera_state().base + camera_addresses::native_caller_return, camera.input.address()); entered.set_value(); released.wait(); call.finish(true); }); entered.get_future().wait(); const bool during = camera_probe_phase_observed(camera.context.address()); release.set_value(); worker.join(); const bool after = camera_probe_phase_observed(camera.context.address()); camera_tick_leave(); check(!during && !after, "An overlap blocks both active operations and stale pre-overlap evidence"); observe(camera); check(ready(camera), "A fresh isolated update recovers without restarting or resetting counters"); camera.helper.put(0x60, camera.input.address()); check(!ready(camera), "Live helper scratch pointers block flight even with a previous valid sample"); camera.helper.put(0x60, std::uintptr_t{}); camera.selection.put(0, std::uintptr_t{}); check(!ready(camera), "A changed camera selection invalidates historical readiness"); camera.selection.put(0, camera.entry.address()); check(ready(camera), "An unchanged idle ownership chain is valid between sampled updates"); std::thread fresh_thread([&] { NativeTls worker_tls(camera); check(!ready(camera), "Another thread cannot borrow the local camera observation"); }); fresh_thread.join(); observe(camera, false); check(!ready(camera), "A native exception invalidates previous evidence even during sampling throttle"); observe(camera); check(ready(camera), "An isolated returned update recovers after a failed update"); } void replacement_cameras() { // Many identities, as after repeated respawns/editor transitions/joins. // Keep allocations alive to avoid reuse. std::array, 80> cameras; for (std::size_t i = 0; i < cameras.size(); ++i) { auto& item = cameras[i]; item = std::make_unique(i % 2 ? camera_addresses::alternate_entry_vtable : camera_addresses::entry_vtable); NativeTls tls(*item); observe(*item); check(ready(*item), "Replacement cameras remain usable"); Camera other; check(!camera_probe_phase_observed(other.context.address()), "A different world cannot use the previous observation"); } } int main() { try { const auto image = reinterpret_cast(VirtualAlloc(nullptr, 0x7900000, MEM_RESERVE, PAGE_READWRITE)); check(image != 0, "Reserve fixture address range"); check(VirtualAlloc(reinterpret_cast(image + (addr::engine::tls_index & ~std::uintptr_t{0xfff})), 4096, MEM_COMMIT, PAGE_READWRITE) != nullptr, "Commit fixture TLS index page"); camera_state().base = image; camera_state().active = true; native_entry_variants(); recovery(); replacement_cameras(); VirtualFree(reinterpret_cast(image), 0, MEM_RELEASE); std::cout << "Camera observation recovery checks passed.\n"; return 0; } catch (const std::exception& e) { std::cerr << e.what() << '\n'; return 1; } }