AdrenalineGuard

Stops memory editors from changing your gold, health, ammo and score — and tells you when someone tried.

Unreal Engine 5.8 Win64 · Linux · Mac C++ source included No content, no assets Version 1.0.0
0times a memory scan found the store, across every attack run
~14 nsto read a protected value
~1.1 µsper frame for 64 protected values
0false positives in 100 000 steps of honest play

Every number on this page comes from a test you can run yourself: the headless gates in the source, or the attack suite described under Under attack.

What AdrenalineGuard does

In plain words, before any of the technical detail.

A player downloads a memory editor, scans for the number on their HUD, finds the address, types a bigger number, and your economy is gone. It takes about two minutes and there are thousands of videos explaining it.

AdrenalineGuard makes that workflow stop working. A protected value is never stored as a plain number; its encrypted form keeps changing on a timer even when the value itself does not; and the value moves to a new address while the game runs. A scan finds nothing to keep, a saved address goes stale, a pointer path breaks, and a frozen address is detected.

It also leaves a decoy: a plain copy of the number that no game code ever reads. A scanner will find it, because that is what it is for. The moment someone writes to it, you know — there is no innocent path to that write.

It never takes a player's progress away. It reports, restores the last known good value so the game keeps running, and leaves the decision to you. Zeroing an account on a heuristic is how an anti cheat earns a support queue.

Three layers, one score:

1Install

Two minutes. Works on a C++ project, and on a Blueprint project that is allowed to compile a plugin.

Copy the folder

Unzip into your project's Plugins folder, so you end up with YourProject/Plugins/AdrenalineGuard/. If there is no Plugins folder, make one with exactly that name.

Open the project

Unreal offers to build the plugin. Say yes. Nothing is added to your level, your settings or your content: this plugin ships no assets at all.

Protect one value

In BeginPlay, call Make Protected Int with a minimum, a maximum and a label such as Gold. Keep the handle it gives you.

Use it instead of the variable

Replace Gold = Gold + 50 with Add Protected Int and a reason code of your own — 1 for loot, 2 for a sale. Replace reads with Get Protected Int. The reason code shows up in the report next to anything that goes wrong.

2Check that it works

Do this once, on your own project, before you trust anything on this page.

Drop in the demo

Place an AdrenalineGuard Demo actor in an empty level and press Play. It shows a protected value, the address it currently lives at, the decoy, and the live suspicion score. It is built from code alone: no meshes, no materials, nothing to migrate.

Try to find the value

Open your memory editor of choice and scan for the number on screen. You will find the decoy and the copies your HUD uses — and then watch what happens when you write to them. The number comes straight back, and the panel reports the attempt.

Watch the address move

The panel prints the address of the protected value as it migrates. That is what breaks a saved address and a pointer scan: by the time a path is built, it points at nothing.

Console

AG.Status prints the report, AG.Verify forces a full check of every protected value.

3Under attack

What happened when we ran the memory editor workflow against a live process.

The protection is tested by attacking a running game, not by reading the code. The attacker reproduces the whole workflow: scan for an exact value; scan for an unknown initial value and narrow it with changed and unchanged passes; write to each candidate and undo when nothing happens; freeze an address from another thread; pointer scan; and finally set a hardware breakpoint through DR0–DR3, which is what "find out what accesses this address" does.

Every attack runs against an unprotected value first. If it fails there, the run is thrown away — it would mean the scanner is broken, not that the protection is good. That control is the only reason the rest of this table means anything.
AttackPlain intProtected value
Full scan workflowfound — 671 candidates narrowed to 2never points at the store
Write to the found addressgold becomes 999999unchanged
Freeze the addressfrozen at 424242nothing left to freeze
Write into the store directly—reported, suspicion 99.6
Touch the decoy—reported, suspicion 198.9
Hardware breakpoint—reported, suspicion 199.0

Alongside that, the headless gates run 100 000 random operations against an independent model of what the values should be, and 100 000 steps of randomised honest movement — variable frame rate, hitches down to 10 fps, pauses, 695 jumps — with zero reports.

Two things said plainly. A scan for the number on your HUD will find something: the decoy holds that number on purpose, and your game has to keep it somewhere to draw it. Those copies are read only — writing to them does not survive the frame. And no plugin protects a game from crashing when someone writes blindly across its memory; our own attacker crashed the target that way. The cheater gains nothing, but the game still dies.

4Settings worth knowing

The defaults are chosen so that an honest player is never accused. Two checks are deliberately off.

SettingDefaultWhat it means
Rotate Interval0.35 sHow often a value gets a new key. Shorter defeats "unchanged" scans and costs a little more CPU.
Migrate Interval2.0 sHow often a value moves to a new address.
Suspicion Threshold100Where your callback fires. A touched decoy alone is 100; a single teleport is 20.
Use LedgeroffTurn on for economy values: the value must match the sum of recorded transactions, which catches a cheat that knows every key.
Max AccelerationoffOff on purpose: for characters, going from run to sprint in one frame reads as 9000 cm/s², so it would report anyone pressing Shift. Enable it for vehicles.
Check ClockoffOff on purpose: Unreal clamps world time to 2000 fps, so a faster game drifts on its own. See Limits.

5When something is detected

The plugin never punishes anyone. This is the part you have to write, and the part worth thinking about before you ship.

Two events are raised on the guard subsystem, which you get with Get Guard:

EventGives youWhen
On ViolationFAGViolationEventEvery single violation, as it happens.
On Suspicion Thresholdthe score as a floatOnce the score crosses your threshold, default 100.

The event carries Violation, Certainty, the Label you gave the value, Observed, Expected, At Time and Suspicion After. The one to branch on is Certainty:

CertaintyMeaningReasonable response
HintCould be an unusual mechanic of yours, or lag.Count it. Do nothing visible.
StrongHard to explain innocently, but not impossible.Log it, flag the session, tell your server.
ProofNo legal path exists: a touched decoy, a forged handle, a memory breakpoint.Act. This did not happen by accident.

Is Proof answers that in one node, and Get Violation Text gives you a readable sentence for a log or a report.

Do not zero the account. One false positive and a player lost a save, wrote a review, and told a forum. In single player the honest response is usually a log and a flag on the save; in multiplayer it is a message to your server, which already holds the truth. A ban decided on the player's own machine can be undone on the player's own machine anyway.

For a HUD or a support report, Get Report returns running totals: suspicion, total violations, Proof Violations (above zero means it really happened), protected values, key rotations, address migrations and clamped writes. AG.Status prints the same thing in the console.

6Protecting movement

Add AG Motion Guard to a Character or Pawn. Four settings and one function matter.

Match the limits to your game

Set Max Speed to your real maximum in cm/s, including sprint. Speed Tolerance is the headroom on top (1.35 by default, for slopes and buffs). Teleport Distance must be larger than your speed times your longest frame, or a hitching game reports itself.

Tell it about scripted movement

Call Allow Next Movement immediately before a respawn, a lift, a cutscene teleport, entering a vehicle or loading a save. That one step is skipped and the reference point moves with the pawn. Without it, every scripted teleport in your game is a report.

After a level change or anything that moves the pawn behind your back, call Reset Tracking.

Flight and falling

If your game lets players fly, build, or possess a spectator, set Allow Flight. Otherwise Max Air Time (6 s) and Max Fall Speed apply. An empty test level has no floor, so a pawn there is permanently airborne: that is a property of the level, not a cheat.

Bind the event

On Motion Violation gives you the violation, what was observed and what was allowed. It also goes into the shared score, so movement and memory add up: two teleports are lag, two teleports and a touched decoy are not.

7Signing save files

Closing memory is pointless if the save opens in Notepad.

Set the key once, at startup, with Set Save Key — or type it into Project Settings, knowing what that means (see Limits). To tie a save to one account, add Set Save Binding with a player id: the binding is never written to the file, only mixed into the signature, so a save copied to another account fails to open.

FunctionUse
Sign Save DataTakes your bytes (for example from Save Game To Memory) and returns signed bytes.
Open Save DataVerifies and gives back the original bytes. Returns a status.
Sign Save To FileSigns and writes the file in one call.
Load Signed Save From FileReads and verifies in one call.
Load Signed Save And ReportSame, and reports a tampered file into the suspicion score.

The status tells you why a file was refused: Ok, Too Short, Bad Magic (not our file), Bad Version, Length Mismatch, or Bad Signature (edited, or a different key or binding).

Nothing is returned for a file we cannot vouch for. A failed check gives you no payload, so a half edited save can never be loaded as if it were fine.

8Troubleshooting

Everything here has actually happened, most of it to us.

What you seeWhat it is
Get returns the right number but bTrusted is false Verification failed and the value was restored from the last known good one. That is the design: your game keeps running. Read the event to find out what happened.
Get returns 0 and the handle looks fine The handle is from a previous level or a previous store. Handles carry a serial for exactly this reason. Create protected values after the world exists, not in a constructor.
Flight reported in an empty test level No floor, so the pawn is airborne the whole time. Set Allow Flight for that level, or test on a level with ground.
A scripted teleport is reported Allow Next Movement was not called before moving the pawn, or was called a frame too early.
Clamped Writes keeps climbing Not a cheat. Your game writes past its own limits all the time, usually regenerating at full health. Harmless, but it often means Max Value is wrong.
Nothing is ever detected Usually correct: nobody touched the protected memory. To check detection really works, edit the decoy in a memory editor — the demo actor prints its address.
A clock mismatch at a very high frame rate Unreal clamps world time to 2000 fps, so the game clock legitimately runs ahead. Check Clock is off by default for this reason; see Limits.
Assertion about the game thread A protected value was used from another thread. The store is deliberately single threaded; call it from the game thread.

9Reference

Everything the plugin exposes. The same names in Blueprint and C++.

Protected values
Make Protected Int / Make Protected FloatCreate a value from a policy and a label.
Get Protected Int / FloatRead it. Also returns whether it is trusted.
Set Protected Int / FloatWrite it outright. Prefer Add when the policy uses a ledger.
Add Protected Int / FloatChange it by a delta, with a reason code of your own.
Release Protected IntFree the slot when the value is gone for good.
Guard subsystem
Get GuardThe subsystem for this world.
On Violation, On Suspicion ThresholdThe two events.
Get ReportRunning totals for a HUD or a support report.
Verify NowCheck every protected value immediately, for example before writing a save.
Reset SuspicionClear the score, for example on a new game.
Report Save Tampered, Report Motion ViolationFeed your own findings into the same score.
Policy fields
Min Value, Max ValueWhat is legal. Writes outside are clamped silently.
Max Increase Per Second, Burst SecondsRate limit as a token bucket, with an allowance for one legitimate jump.
Use LedgerThe value must equal the sum of its transactions. For economy values.
Use DecoyKeep a decoy copy. On by default.
Rotate IntervalPer value override of the key rotation period.

Console: AG.Status, AG.Verify, and on the demo actor AG.Demo.Earn, AG.Demo.Save, AG.Demo.Load.

Limits

What this plugin does not do. We would rather write it here than have you find out.

Support

Something not working, or a number on this page that does not match what you see in your project? Tell us — a report that contradicts our measurements is the most useful mail we can get.

support@adrenalinegames.pl

Please include your engine version and the output of AG.Status.