Full Stack? Rust Recoil Script System Proof of Concept Pt1

· 7 min read ·
#webdev#astro#rust#recoil#script#C++

Part 1 of a Rust recoil script system proof of concept.

Download the project here: GitHub Repository

This project began as only a recoil script but evolved into a fully featured suite.

Don’t replicate to use in game mainly because the methods I used are outdated for evading detection and obsolete compared to hardware devices. This was mainly for fun. However if you’re interested in how to extract the recoil values that part is still good.

Sorry if this post doesn’t make much sense but I thought I should try to document the process I took while making this app in the past. I’m missing a lot of resources I used while making this but if you’re interested in making something similar on the Macro side there is a lot of useful information on online forums like https://unknowncheats.me

My project had two main technical goals from the start:

  1. Reconstruct exact recoil physics externally using offline data extraction, interacting with the live game.
  2. Build a secure distribution ecosystem resistant to reverse engineering, unauthorized sharing, and heuristic surveillance. (Which I don’t cover much in this part)

What I initially thought would just be a mouse script turned into a full authentication backend, a secure C++ loader application, an administrative panel, and Discord bot integration just for the love of the game.

Architecture Overview

Before diving into the code, here is a simple look at the complete data pipeline and ecosystem:

Game Engine

     │ (offline limits & keyframes)

Memory Dumper


Python Processing Pipeline


Generated C++ Recoil Tables and Macro


DLL / Executable Recoil Engine


Secure Loader App


Auth API + Discord Bot

Recoil Tables

Getting the recoil tables was not the easiest thing, although there are lots of online resources already available with the latest tables not all of them are 1:1 accurate so I elected to try and extract them myself.

Memory Extraction

One of the most annoying processes was extracting the proper pixel movements for the recoil tables. I use these tools, in addition to writing them.

The approach was relatively easy to adopt on its own. I booted up an unprotected client, temporarily attached a basic memory dumper using offsets from a text file, and fired the guns to log the raw AnimationCurve keyframes to a text document (tools/recoil_data.txt).

# Raw output example from the memory dump:
KeyPoint(Time: 0.0, Value: 2.338356, Slope: 0.0)
KeyPoint(Time: 1.0, Value: -0.076736, Slope: 1.0)

This gave me the exact horizontal (yaw) and vertical (pitch) boundaries the engine uses. On its own, getting 1:1 engine physics was great. The huge benefit here is mathematical perfection getting the exact needed values (Not including Bloom). The risk is that pulling memory live is risky, which is why I made sure this extraction happened completely on a anticheat disabled server.

File Extraction

I used a combination of methods to extract the data, including memory dumping and static analysis of the game’s assembled files through a third party tool which I forgot, I’m sure you could find it by searching something similar to Unity Game Extractor, also to note it was an update of an older tool.

Processing the Physics

Once I had the raw data, I needed to process it.

The game represents recoil trajectories using Cubic Hermite Splines, where each weapon defines a series of keyframes containing a time, value, and slope. The game engine interpolates between these keyframes to produce a smooth recoil curve. Instead of manually typing these values out or evaluating the splines at runtime, I built a Python automation pipeline via tools/convert_all.py that reads the dumped JSON engine files from tools/Unconverted Recoil and generates a raw text file formatted exactly as C++ arrays.

# Format output to perfectly match C++ array syntax
block_str = f"    // {name}\n    {{"
for i, line in enumerate(lines):
    block_str += line + ","

Modular DLL Architecture

One massive lesson I learned when transitioning to the C++ phase was the necessity of modular architecture. My early prototypes (evident if you ever found my old Main.cpp.oldrecoil backups at the repository root) threw literally everything into a single massive 1,600 line monolithic file. The pro of a monolith was that I could prototype quickly without worrying about compiler headers or linker errors. But this is unsustainable.

I eventually tore the entire codebase down and rebuilt it into modular, object oriented subsystems (src/Core/RecoilSystem.cpp, src/Core/AuthSystem.cpp, src/Core/ConfigWatcher.cpp). More importantly, I transitioned the main output (src/Main.cpp) from a raw executable (.exe) to a Dynamic Link Library (.dll), exposing basic Initialize(), Run(), and Shutdown() exports.

extern "C" __declspec(dllexport) void Run() {
    if (!g_initialized) return;
    g_running = true;
    RunApplication();
}

By compiling the core logic as a DLL, I could inject the tool directly into a dummy loader app rather than shipping it as a standalone executable. Although I eventually abandoned this approach for the final product due to stability issues and how extremely redundant it was, essentially just making an executable for it to inject into which achieved the same result as just compiling the app as an executable in the first place, it was a great learning experience as it shares a lot with how malware hijacks windows processes to avoid detection which I derived inspiration from.

Recoil Engine

Next came building the actual engine logic. This, unfortunately, turned into a surprising time sink. There was a lot of churn, as converting raw game angles into mouse pixel movements over a 130 millisecond delay window is incredibly delicate. The exact sensitivity, stance, and field of view values become critical points of failure.

Furthermore, game engines introduce movement penalties when navigating the map. I had to build a complete state machine monitoring W, A, S, D, Ctrl, and Shift using Windows’ GetAsyncKeyState within RecoilSystem::DetectMovementType to dynamically scale the recoil arrays. Game characters do not reach full sprint velocity instantly, so I also had to simulate acceleration ramp up to accurately match the penalty.

// Simulating acceleration ramp up to calculate accurate movement penalties
double t = std::min(elapsed / 500.0, 1.0);
double Vmts = GetMaxSpeedForMovement(currentMovementType);
double Vc = Lerp(0.0, Vmts, t);

I spent many hours experimenting and iterating on a conversion factor formula (RecoilSystem::CalculateDelta) that identically mirrored the game’s input handler.

// Converting game physics angles to raw pixel deltas
double factor = -0.03 * (sens * sensMod) * 3.0 * (fovVal / 100.0);
Vector2 delta = { 
    (point[0] * scopeM * barrelM * moveM) / factor, 
    (point[1] * scopeM * barrelM * moveM) / factor 
};

Humanizing the Input

One thing regarding macros, which I did adopt, was ignoring humanization. I tried, over many iterations on previous projects, to just pull the mouse down efficiently, but it never really worked out safely.

Perfectly deterministic mouse movement is easily detectable by server side heuristics. Real human input contains small inconsistencies in velocity and curvature. To emulate this, I introduced randomized Bezier control points and divided pixel movements into timed segments using high precision sleeps (RecoilSystem::InterpolateMove). Although this is a simple way to avoid detection this processes can be refined.

Securing the Ecosystem

I am pleased with the final practical result for the macro, but the real complexity was tying it into the other three parts of my ecosystem to satisfy my second core project goal.

I completely decoupled the tool from local execution. Instead, I built a dedicated loader app that required user login and registration. The loader generated a unique Hardware ID (HWID) fingerprint of the user’s machine. When a user registered an account key, that key permanently bound itself to their specific machine’s HWID.

I spent weeks tying this into a web application admin panel and a custom Discord bot. The backend API verified every login attempt, and if a footprint did not match the registered HWID, it rejected the session instantly.

End

The main result here is that building the entire ecosystem took me a long time to get working flawlessly. I was able to work through the backend key generation, discord integrations, Python math evaluations, and the C++ loader, but perfecting the transition between all those modular components took much longer than anticipated.