Anti-cheat tool reverse Srungoat Protector WebView2 + YARA Ships screenshots

Trace Anti-Cheat Scanner — Trace_7TXBS1AV.exe

A complete static reverse of the Trace Anti-Cheat scanner. Three-and-a-quarter megabytes of MSVC C++ wrapped in Srungoat Protector v1.0, whose entire contribution is a 61-byte badge in a section literally named .1337. Every string, every URL, every registry key, every YARA path, every Event Log query is in plaintext. Below: the complete C2 map (nine endpoints on traceac.cc), the injected WebView2 JavaScript that auto-fills the PIN input and auto-clicks the scan button, the seven finding categories the scanner emits, the twenty-two FiveM cheat brands it hunts, the sixty-three cheat-vendor auth panels it compares against browser history, the five hardcoded wevtutil XPath queries, and the eight decoy JWTs plus seventeen fake auth-response templates it uses as trip-wires.

22 min read Published 2026-07-10 Static reverse + string forensic + protocol inference Third-party scanner
Prologue  ·  The unreverseable file

Let's begin.

Two people on the internet spent an afternoon reposting an AI hallucination that said our scanner was stealing browser tokens. Then, in the same breath, they promised the next release of Trace_7TXBS1AV.exe — their scanner — would be “unreverseable”. They had, they said, hired new devs. Their protection was final.

The file eventually arrived. Three-point-three-five megabytes, unsigned, with a manifest demanding administrative privileges and an executable section named .1337 that was sixty-one bytes long and contained, in plaintext, the literal words Protected by Srungoat Protector v1.0. That was the entire protection. No control-flow flattening. No section decryption. No TLS callback shell. No anti-debug beyond the same IsDebuggerPresent import every C++ template ships with. The badge was the shield.

The strings inside were not obfuscated. Not one. The scanner's own name for itself is the C++ namespace TraceScanner; its seven finding categories are stored as MSVC-mangled types — UActivityEntry, UAdminAppEntry, UFileFinding, UFiveMModEntry, UMemoryFinding, URegistryFinding, USystemFinding — visible to undname.exe and printed by any RTTI dump. Its C2 domain, traceac.cc, appears seven times in the binary as a wide-character constant, exactly as the compiler emitted it. The header on every outbound POST reads X-Trace-Scanner: TRACE-Scanner/QMSAPRSqM4xK2JnP. The download URL for its YARA binary is https://scanner.traceac.cc/static/bin/yara64.exe?pin=<PIN>, also in plaintext, and it is verified against a SHA-256 that is itself a plaintext JSON field named sha256.

The WebView2 UI it renders is served from a remote page at https://scanner.traceac.cc/send/ui/. Into that page it injects, at load-time, a JavaScript block whose prefix is stored — in full, uncompressed, UTF-16-LE — starting at file offset 0x290E00, and whose suffix is stored at 0x290C00. Between them, the C++ concatenates the user's runtime PIN. Together they auto-fill the #pin-input field, dispatch an input event so React (or whatever) sees the change, wait for the #scan-btn to become enabled, and click it. That is the whole authentication flow.

What follows is every string, every path, every field, every URL. Nine C2 endpoints. Twenty-two cheat brand names. Sixty-three cheat-vendor auth panels searched in the user's browser history. Seven forensic sources. Five hardcoded Windows Event Log XPath queries. Seventeen fake auth-response JSON templates the scanner uses to detect that a machine has been talking to cheat panels. Eight decoy JWTs. Every AV vendor it looks for. Every reverse-engineering tool it flags. Every VPN. Every hypervisor CPUID string. Every registry hive it walks.

The tool reads browser history, Event Logs, Prefetch, BAM, SRUM, Amcache, and the Discord LevelDB store, takes a JPEG of the desktop with GDI+, and ships the lot as JSON to https://traceac.cc/api/scan/submit. Whether that qualifies as an infostealer is a definitional question. Whether the file is unreverseable is not.

— Every claim below is anchored to a byte-offset, a section, or a wide-string reference in the sample's .rdata. Nothing here is inference where a plaintext string wasn't there to read.

Executive summary

File size
3.19 MB
Protector
Srungoat v1.0
C2
traceac.cc
Strings encrypted
0 / 6,577
  • Third-party FiveM anti-cheat retroactive-trace scanner. Internal namespace is TraceScanner. Public brand is traceac.cc (“Trace Anti-Cheat”). Requires local administrator. Users get a PIN via the vendor's website; the scanner validates and consumes it against scanner.traceac.cc URL parameters (?pin=<PIN>).
  • Srungoat Protector v1.0 is decorative. No section encryption, no TLS callback, no anti-debug of substance, no runtime string decoder. The .1337 section contains 61 bytes: SRUNGOATPROT\\xde\\xad\\xbe\\xef v1.0\\0Protected by Srungoat Protector v1.0. Strings appear in plaintext at multiple encodings.
  • Nine hardcoded C2 endpoints on traceac.cc / scanner.traceac.cc. Fixed User-Agent TraceScanner and header X-Trace-Scanner: TRACE-Scanner/QMSAPRSqM4xK2JnP. All bodies are JSON (nlohmann::json v3.11.3, git 961c151d2e87f2686a955a9be24d316f1362bf21).
  • Downloads YARA at runtime. Fetches yara64.exe from its own CDN with SHA-256 verification against a manifest JSON, drops it under %APPDATA%\\trace, writes rules text to custom_rules.yar, executes the CLI (-w -m --scan-list).
  • WebView2 UI is remote-hosted at scanner.traceac.cc/send/ui/. A hardcoded JavaScript prefix + runtime PIN + hardcoded JS suffix is injected as a script into the page; it auto-fills the PIN and auto-clicks the scan button. The full prefix and suffix are quoted verbatim in section § WebView2 UI + injected JS.
  • Captures a JPEG desktop screenshot with GDI+ and includes it in the POST /api/scan/submit body. The visible copy inside the binary reads [*] Capturing desktop screenshot... and, on failure, [-] JPEG encoder not found.
  • No embedded secrets. No Discord webhook, no Telegram bot token, no Slack hook, no X.509 certificate, no RSA/AES key material, no high-entropy blob larger than 4 KB anywhere in .rdata or .data. Everything routes through the fixed traceac.cc hosts.
  • Kills cmd.exe and powershell.exe before submission via taskkill /f /im cmd.exe >nul 2>&1 and the same for PowerShell. This is a hardcoded self-hygiene step, not a defensive one against user tampering.
  • Watches for four environment variables: PIN, YARA, SELF_SCAN, and TRACE_YARA_VALIDATION_FILE. Single-instance mutex is Global\\TraceAntiCheatScanner_Mutex.

On the “unreverseable” claim

The vendors of this scanner publicly stated, at the time this build was released, that they had hired new developers and that their protection was unreverseable. The claim is stated here without paraphrasing because the file itself refutes it in a specific and measurable way:

  • Srungoat Protector v1.0 is a marker, not a transform. It contributes exactly 61 bytes of text in a section named .1337. The bytes read: 53 52 55 4E 47 4F 41 54 50 52 4F 54 DE AD BE EF 76 31 2E 30 00 00 00 00 50 72 6F 74 65 63 74 65 64 20 62 79 20 53 72 75 6E 67 6F 61 74 20 50 72 6F 74 65 63 74 6F 72 20 76 31 2E 30 00 (“SRUNGOATPROT…v1.0…Protected by Srungoat Protector v1.0”). The rest of the binary is the compiler's output verbatim.
  • No section is encrypted. Entropy scans of every 4 KB window in .rdata and .data yield zero windows above 7.5 bits/byte — the threshold below which content is not compressed or encrypted. The strings the scanner uses to identify itself, its C2, its user-agent, its endpoints, its cheat-brand watchlist, and every one of its 22 cheat family names is stored in plaintext at either UTF-8 or UTF-16-LE.
  • No TLS callback is registered. The Thread Local Storage directory's AddressOfCallBacks pointer resolves to a table whose first entry is NULL. There is no pre-main shim to unwrap. Entry-point at 0x140266520 jumps straight to the MSVC CRT's __scrt_common_main_seh.
  • No control-flow flattening, no opaque predicates. Disassembly of the WinHttp call chains at 0x1400CF920, 0x1400B9C90, and 0x1401ED500 reads as standard MSVC WinHttpOpen → WinHttpConnect → WinHttpOpenRequest → WinHttpSendRequest boilerplate with no interposed junk instructions.
  • No anti-debug beyond three imports. The binary imports IsDebuggerPresent, CheckRemoteDebuggerPresent, and OutputDebugStringA/W. None of them is called in a loop or timed; none checks the PEB's NtGlobalFlag; none uses NtQueryInformationProcess(ProcessDebugPort). The imports are here because MSVC's CRT references them.
  • No PE header wipe, no IAT hiding, no FNV-1a API resolution. The Import Address Table lists 36 imports from USER32, 40 from ADVAPI32, 186 from MSVCP140, and every other import in the clear.

A binary that ships with all of the above is not, in any operational sense, protected. The claim of un-reverse-engineerability describes a build state that does not exist in the file that was released. What follows is what the file actually contains, extracted with pefile, strings -eL, and half a page of Python.

File identity

Original nameTrace_7TXBS1AV.exe
TypePE32+ EXE (x64, GUI)
Size3.19 MB (3,345,920 bytes)
ImageBase0x140000000
Entry RVA0x266520
Compile time2026-06-25 19:21:28 UTC (real)
Sections.text · .rdata · .data · .pdata · .1337 · .rsrc · .reloc
MD537644acaf1725dcf01b8c0b9227ca111
SHA-15c40f76fc4b25c00f60970bb17dae9e16f9f45a1
SHA-2569d1b210b06d942863e49f0cf7baf629fcdc3cf76d33a5383a6caec65783eb4fc
AuthenticodeUnsigned (Security dir size = 0)
ManifestrequestedExecutionLevel level='requireAdministrator' uiAccess='false'
Class nameTraceAntiCheatScannerClass
Single-instance mutexGlobal\TraceAntiCheatScanner_Mutex
ProtectorSrungoat Protector v1.0 (marker-only .1337 section)
RuntimeMSVC (MSVCP140 · 186 imports), WebView2, nlohmann::json v3.11.3, GDI+

Srungoat Protector v1.0

The scanner is wrapped by a commodity protector that has left a marker section and nothing else. The .1337 section is 61 virtual bytes, entropy 1.01 — well below the level of even compressed text. Its raw contents:

Offset (raw)  : 0x00302000
Size (virtual): 0x3d bytes
Entropy       : 1.01 bits/byte

00: 53 52 55 4E 47 4F 41 54  50 52 4F 54 DE AD BE EF   SRUNGOATPROT.....
10: 76 31 2E 30 00 00 00 00  50 72 6F 74 65 63 74 65   v1.0....Protecte
20: 64 20 62 79 20 53 72 75  6E 67 6F 61 74 20 50 72   d by Srungoat Pr
30: 6F 74 65 63 74 6F 72 20  76 31 2E 30 00            otector v1.0.

That is the full protection. Every other byte of executable code was emitted by MSVC unmodified. TLS callback table is empty; entry point at 0x140266520 is a stock CRT initialiser; strings live in .rdata at both UTF-8 and UTF-16-LE and are readable with any triage tool.

C2 map — everything talks to traceac.cc

Nine URLs. Two hostnames (traceac.cc for API, scanner.traceac.cc for downloads and UI). Every wide-character copy of these strings is emitted verbatim by the linker — no obfuscation, no runtime assembly. Auth is the ?pin=<PIN> query parameter on GETs plus a static header X-Trace-Scanner: TRACE-Scanner/QMSAPRSqM4xK2JnP on POSTs.

VerbURLPurpose
GEThttps://traceac.cc/api/versionversion check (UA = 'blablublewidfjhsfhdshGFDSBSDUFGDFDSBNTRACE' — placeholder)
GEThttps://scanner.traceac.cc/api/scanner/yara_manifest?pin=<PIN>YARA manifest JSON (url + sha256 + min_size)
GEThttps://scanner.traceac.cc/api/scanner/yara_rules?pin=<PIN>YARA rules text
GEThttps://scanner.traceac.cc/api/scanner/rules?pin=<PIN>rules dispatch
GEThttps://scanner.traceac.cc/static/bin/yara64.exe?pin=<PIN>YARA CLI binary; SHA-256 verified against manifest before execution
POSThttps://traceac.cc/api/scan/progresslive progress updates during scan
POSThttps://traceac.cc/api/scan/submitfindings JSON + JPEG screenshot
POSThttps://traceac.cc/api/scan/closedfinalize scan session
POSThttps://traceac.cc/api/download/validatedownload-integrity validation
UIhttps://scanner.traceac.cc/send/ui/WebView2 UI host (WebResourceRequested filter = https://scanner.traceac.cc/*)
Fixed header pair on every outbound request:
User-Agent: TraceScanner
Content-Type: application/json
X-Trace-Scanner: TRACE-Scanner/QMSAPRSqM4xK2JnP

# (except the /api/version ping, which uses a placeholder UA:)
User-Agent: blablublewidfjhsfhdshGFDSBSDUFGDFDSBNTRACE

WebView2 UI + injected JavaScript

The scanner renders its UI by embedding a Microsoft Edge WebView2 controller and navigating it to https://scanner.traceac.cc/send/ui/. A resource-request filter of https://scanner.traceac.cc/* permits fetches to that host and blocks everything else. On NavigationCompleted the C++ side calls ExecuteScript with a script built as three concatenated pieces: the constant prefix stored at .rdata:0x290E00, the user's runtime PIN, and the constant suffix stored at .rdata:0x290C00. The prefix and suffix are quoted here verbatim from the binary:

// prefix — .rdata offset 0x290E00 (UTF-16-LE, constant)
(function() {
    function waitForElement(selector, callback, maxWait, interval) {
        maxWait = maxWait || 3000;
        interval = interval || 50;
        const start = Date.now();
        const check = setInterval(function() {
            const element = document.querySelector(selector);
            if (element) {
                clearInterval(check);
                callback(element);
            } else if (Date.now() - start > maxWait) {
                clearInterval(check);
                console.warn('Element not found: ' + selector);
            }
        }, interval);
    }
    waitForElement('#pin-input', function(pinInput) {
        pinInput.value = '<RUNTIME_PIN>

// suffix — .rdata offset 0x290C00 (UTF-16-LE, constant)
';
        pinInput.dispatchEvent(new Event('input', { bubbles: true }));
        waitForElement('#scan-btn', function(scanBtn) {
            if (!scanBtn.classList.contains('disabled')) {
                scanBtn.click();
            }
        });
    });
})();

The full set of state / event names passed between the WebView2 UI and the native side (via WebMessageReceived):

opentypestart_scanpinscan_errorSELF_SCANmessageclose_afterpin_validatedcheck_security_before_consenthas_security_toolssecurity_blockeddefender_realtime_enableddefender_service_runningantivirus_processesthird_party_antivirus_processesantivirus_blockedsecurity_clearantivirus_clearstart_scan_consentedtos_acceptedprivacy_accepteddrag_windowclose_appmin_appwindow_restoredscan_progressscan_doneprogressresultverdictseverityreasoncategorysysmain_enableddiagtrack_enabledsecure_boot_enabledis_signedis_live

Auth flow — PIN + fixed header

Users obtain a numeric PIN from the vendor's website and paste it into the UI (or receive it via the PIN environment variable). All GET requests to scanner.traceac.cc append ?pin=<PIN>to the URL, and on failure the UI is told scan_error = "Invalid, expired, or used PIN.". The consent chain before any scan can start is:

  1. tos_accepted and privacy_accepted must both be true
  2. check_security_before_consent — inventory Defender + third-party AV
  3. if has_security_tools — display “Disable the blocking protection temporarily, then reopen the scanner” and set state security_blocked / antivirus_blocked
  4. pin_validated — HTTP validation against traceac.cc
  5. start_scan_consented — user pressed the button (or the injected JS pressed it for them)

YARA download chain

The scanner does not carry a YARA engine. It downloads one, at runtime, from its own CDN. The chain is:

  1. Read PIN from UI / PIN env var.
  2. GET https://scanner.traceac.cc/api/scanner/yara_manifest?pin=<PIN> — server returns a JSON with fields url, sha256, min_size. Manifest failures produce the strings YARA manifest HTTP failed, YARA manifest URL rejected, YARA manifest SHA256 is invalid, or YARA manifest JSON parse failed — all present verbatim in .rdata.
  3. GET https://scanner.traceac.cc/static/bin/yara64.exe?pin=<PIN> — download and SHA-256 verify against the manifest.
  4. GET https://scanner.traceac.cc/api/scanner/yara_rules?pin=<PIN> — download rules text; write to %APPDATA%\\trace\\custom_rules.yar.
  5. Validate rules with the downloaded binary: yara64.exe -w -m --scan-list. Emit output to TRACE_YARA_VALIDATION_FILE.
  6. Run YARA against the enumerated file list; every hit is turned into a UMemoryFinding or UFileFinding.

Directory exclusions embedded in the binary (fed to YARA's --scan-list): windows, program files, program files (x86), programdata, $windows.~bt, $windows.~ws, $recycle.bin, system volume information, recovery, perflogs.

Scan orchestration — 7 finding types

The C++ side runs its scan tasks via std::async / PPL and emits one of seven finding-vector types back to the UI. Each is a fully-mangled MSVC namespace visible with undname.exe?$vector@U<Type>@TraceScanner@@V?$allocator@U<Type>@TraceScanner@@@std@@@std@@.

Vector typeWhat it holds
UActivityEntrybrowser typed URLs, execution history, recent-activity artefacts
UAdminAppEntryapplications launched with elevated tokens (Security EventID 4688 + TokenElevationType %%1936 / %%1937)
UFileFindingcheat / injector / spoofer files on disk
UFiveMModEntrymods/plugins under \FiveM\FiveM.app\{mods,plugins,citizen\common\data,data}
UMemoryFindingYARA memory-scan hits against live processes
URegistryFindingcheat / VPN / VM / secure-boot registry markers
USystemFindinghypervisor CPUID, DeviceGuard/HVCI state, SecureBoot state, Defender/AV posture

The console-style status lines printed to the WebView2 UI during scanning are also embedded verbatim: [*] Scanning FiveM mods... · [*] Scanning admin-executed applications (Event Log 4688)... · [*] Scanning all services for unsigned kernel drivers... · [*] Scanning for newly installed drivers (Event Log 7045)... · [*] Scanning recent computer activity (BAM full dump)... · [*] Capturing desktop screenshot... · [*] Submitting.

Complete cheat family inventory (22)

Every FiveM cheat brand that the scanner searches for by file name. Each brand is checked in up to four variants — <name>.exe, <name>.dll, <name>menu.exe, <name>menu.dll — plus its known driver and registry markers.

2Take1AbsoluteBrutanCheraxCobra (cobrafree, cobraloader)Crystal (crystalunban)Desudo (+ desudoclient)DisturbedDopamineEulen (+ eulen_loader, eulenclient, C:\Windows\eulen_hwid.ini)FalloutFalcon / RedEngine (falcon.sys, HKLM\Services\FalconDriver, falcon.redengine.eu)Hammafia (+ hammafiaclient)HydroImpulseKeyser (keyser_core.dll in C:\Windows\Temp)LumiaLynxMaestroMidnightOzarkParagonPhantom / PhantomXReaperRobustSkript (+ skriptclient, skriptgg, skriptloader)StandSurgeSusano (susano.sys, api.susano.cc, HKLM\Services\susano)tiagomodzhostXenos / Xenos64 (DLL injector)

Injector / loader / bypass tools

extremeinjector.exeghinjector.exeinjector.exekdmapper.exemanualmapper.exemapper.exetdloader.exetdfree.exetdpremium.exeprocesshacker.execheatengine.execheatengine-x86_64.execobraloader.exe

HWID / spoofer / cleaner tools

hwid_changer.exehwid_clean.exehwid_get.exehwid_reset.exe/.dllhwid_spoof.exe/.dllmac_changer.exeserial_changer.exespoofer.exe/.dllbrowser_loader.exechrome_loader.exeedge_loader.exefirefox_loader.exeloader.exeloader_prod.exe

Cheat-vendor auth URLs (63) — browser-history matches

The scanner reads typed-URL history from every installed Chromium browser and compares each entry against a list of 63 hardcoded cheat-vendor authentication panels. A hit becomes an UActivityEntry with severity suspicious. The full list, in the order it appears in .rdata:

https://api.cryptauth.net/v2/verify?key=
https://api.fluxauth.net/v2/validate?token=
https://api.secureauth.net/v2/auth?license=
https://auth-guard.cc/api/v1/session?hwid=
https://auth-panel.com/api/v2/init?ver=
https://auth-protect.com/panel/validate?token=
https://auth-secure.net/api/v2/check?license=
https://auth-service.net/api/check?hwid=
https://auth-system.io/api/v3/verify?key=
https://auth.cryptauth.io/v1/session?token=
https://auth.fluxauth.io/v1/verify?license=
https://auth.secureauth.cc/v1/validate?token=
https://authifly.cc/panel/customer?id=
https://authifly.co/dashboard?session=
https://authifly.com/api/v1/check?license=
https://authifly.net/api/validate?token=
https://crypt-auth.com/panel/user?license=
https://cryptauth.cc/dashboard?session=
https://cryptauth.com/api/v3/check?uid=
https://cryptauth.io/api/validate?license=
https://cryptauth.net/panel/admin?token=
https://cryptauth.org/api/v2/init?auth=
https://flux-auth.com/api/v3/init?session=
https://fluxauth.cc/panel/reseller?user=
https://fluxauth.com/api/check?key=
https://fluxauth.io/api/session?auth=
https://fluxauth.net/api/verify?hwid=
https://fluxauth.org/dashboard/user?id=
https://guard-system.com/panel/auth?id=
https://guard.secure.cc/api/v2/check?hwid=
https://license-api.com/v1/verify?key=
https://license-guard.com/panel/verify?key=
https://license-system.net/api/v2/validate?key=
https://license-verify.com/api/auth?key=
https://license.auth.io/v3/verify?hwid=
https://license.protection.cc/v2/check?id=
https://license.secure.com/api/check?token=
https://license.shield.io/api/v3/validate?hwid=
https://licensing.pro/api/v1/check?session=
https://panel.cryptauth.com/admin/check?hwid=
https://panel.fluxauth.com/admin/check?key=
https://panel.secureauth.com/admin/verify?key=
https://protect-auth.com/api/v1/verify?key=
https://protect.license.io/v1/auth?session=
https://protection-api.com/v2/verify?license=
https://protection.cc/api/v2/validate?token=
https://secure-auth.com/api/v1/check?token=
https://secure-license.net/api/validate?token=
https://secure.auth-api.com/v3/check?hwid=
https://secure.cryptauth.cc/api/v3/validate?id=
https://secure.fluxauth.net/api/check?hwid=
https://secureauth.cc/panel/validate?hwid=
https://secureauth.cloud/api/v2/init?session=
https://secureauth.io/api/v3/session?id=
https://secureauth.win/api/v2/verify?key=
https://security-auth.com/panel/user?key=
https://security-guard.io/api/v1/session?key=
https://security.shield.com/api/v3/verify?key=
https://shield-auth.net/api/v3/check?hwid=
https://shield.auth-api.net/v3/validate?token=

Cheat-vendor hostnames (short form)

eulen.ccapi.eulen.ccapi.susano.ccapi.tzproject.comapi.hxsoftwares.comhxsoftwares.comtzproject.comfalcon.redengine.euban-bypass.comban-evade.netcfx-unban.netfivem-cleaner.comfivem-unban.comhwid-reset.comhwid-spoof.comhwid-spoofer.commac-changer.comserial-spoof.netspoofer-service.net

Forensic sources read

ArtifactLocation / detail
PrefetchC:\Windows\Prefetch — .pf files enumerated for execution artefacts
BAMHKLM\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings — per-user execution timestamps
SRUDBC:\Windows\System32\sru\SRUDB.dat — per-hour process network activity (SRUM)
ShimCache / AppCompatCacheHKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache
AppCompat persistedSOFTWARE\...\AppCompatFlags\{Persisted,Store,Custom,InstalledSDB}
Image File Execution OptionsSOFTWARE\...\Image File Execution Options
USN JournalNTFS $UsnJrnl — file activity history
EventTranscriptC:\ProgramData\Microsoft\Diagnosis\EventTranscript
ETLLogsC:\ProgramData\Microsoft\Diagnosis\ETLLogs — Windows telemetry event traces
DiagTrackC:\ProgramData\Microsoft\Diagnosis\DownloadedSettings
USBSTORHKLM\SYSTEM\CurrentControlSet\Enum\USBSTOR\ — USB storage history
Clipboard History\Packages\Microsoft.Windows.ShellExperienceHost_cw5n1h2txyewy\LocalState — clipboard log
MuiCacheClasses\Local Settings\Software\Microsoft\Windows\Shell\MuiCache
TypedURLs / TypedURLsTimebrowser typed-URL history (matched vs cheat-vendor URL list)
TypedPathsSoftware\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths
Task SchedulerC:\Windows\System32\Tasks — task XML enumeration
Discord Local State\discord\Local Storage\leveldb — discord username extraction
SteamSoftware\Valve\Steam registry + \Steam\config\config.vdf + loginusers.vdf — SteamID

Cross-references: Discord username is read from the LevelDB store and matched against the SteamID and Steam username extracted from Software\\Valve\\Steam and the loginusers.vdf / config.vdf files. A match becomes an UActivityEntry with description "Same username used across platforms".

Event Log XPath queries (5 hardcoded)

Every Windows Event Log channel the scanner reads, with the exact XPath filter it emits to wevtutil. All are dropped verbatim into the binary — no runtime construction.

ChannelQueryPurpose
Security*[System[(EventID=4624 or EventID=4625)]]logon success + logon failure events (last 20)
Security*[System[(EventID=5152 or EventID=5156 or EventID=5157)]]Windows Filtering Platform packet allowed/blocked (network telemetry)
Security*[System[(EventID=4688)] and EventData[Data[@Name='TokenElevationType']='%%1937' or Data[@Name='TokenElevationType']='%%1936']]process creation events with elevated tokens (admin apps)
Application*[System[(EventID=7045)]]service installation (driver/service register)
Microsoft-Windows-DNS-Client/Operational*[System[(EventID=3008 or EventID=3010)]]DNS query completed / blocked
Microsoft-Windows-Sysmon/Operational*[System[(EventID=3)]]Sysmon network connection events
Microsoft-Windows-Sysmon/Operational*[System[(EventID=6)]]Sysmon driver-load events

AV / EDR presence detection

The scanner enumerates process names against a hardcoded AV/EDR list. If Defender real-time is enabled or any third-party AV process is running, the UI displays "PIN accepted, but active protection is blocking the scanner. Disable the blocking protection temporarily, then reopen the scanner." and the scan will not proceed. The list embedded in the binary:

VendorProcess names
Avastavastsvc.exe · avguard.exe · aswidsagent.exe
AVGavgnt.exe · avgsvc.exe · avguard.exe
Aviraavira.servicehost.exe · egui.exe · savservice.exe
Bitdefenderbdagent.exe · bdservicehost.exe · epsecurityservice.exe
BullGuardbullguard.exe
ESETekrn.exe · egui.exe · edevmon · eamonm
F-Securef-secure.exe · fsav32.exe
Kasperskyavp.exe · kavfs.exe
McAfeemcshield.exe · mfemms.exe
Malwarebytesmbamservice.exe · mbamtray.exe
Nortonnortonsecurity.exe · ns.exe · ccsvchst.exe
Pandapavfnsvr.exe · psanhost.exe · psuamain.exe
Sophossophoshealth.exe · savservice.exe
Webrootwrsa.exe
ZoneAlarmvsmon.exe · zatray.exe
Qihoo 360360tray.exe
Windows Defenderwindowsdefender / MsMpEng (registry + service state)

Reverse-engineering + analysis tool detection

Process names the scanner treats as evidence of an ongoing reversing session (turned into a USystemFinding with description "analysis or credential dumping"):

ida.exe / ida64.exeghidra.exex32dbg.exe / x64dbg.exeollydbg.exewindbg.exeimmunitydebugger.exehttpdebugger.exednspy.exe / dnspy-x86.exepestudio.exelordpe.exepetools.exeimportrec.exescylla.exewireshark.exedumpcap.exefiddler.execharles.exenetworktrafficview.exesniff_hit.exeprocesshacker.exeprocexp.exeprocmon.exeregmon.exefilemon.exeapimonitor.exesysanalyzer.exesysinspector.exeproc_analyzer.exexenos.exe / xenos64.exe (DLL injector)kdmapper.exe / manualmapper.exe (kernel driver mappers)cheatengine.exeautohotkey.exe / autoit3.exe

BYOVD driver watchlist

DriverNotes
capcom.sysCapcom vulnerable driver (arbitrary kernel R/W)
iqvw64e.sysIntel Network Adapter Diagnostic (BYOVD favourite)
gdrv.sysGIGABYTE tool driver (BYOVD)
dbk64.sysCheat Engine driver
kerb3961kernel.sysunclassified — suspicious name
fse.sysflagged
dbgmflagged as debug helper

The full driver-services enumeration (HKLM\\SYSTEM\\CurrentControlSet\\Services) is compared against a whitelist of ~200 canonical Windows drivers embedded in the binary; anything not in the whitelist and not signed by Microsoft becomes a URegistryFinding.

Decoy JWTs + fake auth-response templates

The scanner carries a corpus of well-known example JWTs (from RFC/documentation samples and cheat-panel boilerplate) plus seventeen fake auth-response JSON shapes. They are matched against browser cache and LocalStorage entries as trip-wires: any of these values found in a browser storage file indicates the machine has been interacting with a cheat vendor's licensing panel.

JWTs (8 embedded)

Base64URLDecoded
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9{"alg":"HS256","typ":"JWT"}
eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9{"alg":"HS512","typ":"JWT"}
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9{"alg":"RS256","typ":"JWT"}
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9{"typ":"JWT","alg":"HS256"}
eyJ1c2VyIjoicHJlbWl1bSIsInBsYW4iOiJlbnRlcnByaXNlIiwiZXhwIjoxNzA5MjkzMDIxfQ{"user":"premium","plan":"enterprise","exp":1709293021}
eyJpZCI6IjEyMzQ1Njc4OTAiLCJuYW1lIjoiQWxpY2UiLCJhZG1pbiI6dHJ1ZX0{"id":"1234567890","name":"Alice","admin":true}
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ{"sub":"1234567890","name":"John Doe","iat":1516239022}
eyJzdWIiOiJhZG1pbiIsInJvbGUiOiJzdXBlcnVzZXIiLCJwZXJtcyI6ImFsbCJ9{"sub":"admin","role":"superuser","perms":"all"}

JSON response templates (17 embedded)

{"success":true,"data":{"user":{"id":"","username":"","email":"","role":"premium"},"license":{"key":"","type":"lifetime","expires":"never"},"session":{"token":"","expires":"3600"},"hwid":""}}
{"success":false,"error":"Invalid license key","code":"AUTH001"}
{"success":0,"error":"Version outdated","required":"2.0.0"}
{"license":"active","plan":"premium","restrictions":{"ip_lock":true}}
{"auth":"granted","permissions":{"admin":true,"modify":true}}
{"security":{"integrity":"valid","tamper":"none","debug":"none","vm":"none"}}
{"protection":{"level":"maximum","encryption":"enabled","monitoring":"active"}}
{"valid":true,"type":"subscription","expires":"2025-01-01","features":[]}
{"verification":"success","level":"enterprise","modules":["premium","business"]}
{"check":{"memory":"clean","process":"verified","modules":"valid"}}
{"environment":{"secure":true,"trusted":true,"verified":true}}
{"status":"success","response":{"account":{"id":"","level":"vip","created":"2024-01-01"},"subscription":{"plan":"enterprise","features":["premium","priority"],"active":true},"security":{"2fa":true,"ip_lock":true}}}
{"result":"ok","auth":{"token":"","refresh":"","scope":"full","permissions":["read","write","admin"]},"user":{"verified":true,"status":"active"},"app":{"version":"1.0.0","build":"stable"}}
{"code":401,"error":"Unauthorized","details":"Invalid token"}
{"error":true,"code":403,"message":"Access denied","info":"IP blocked"}
{"status":"error","message":"Session expired","details":"Please login again"}
{"status":"failed","type":"security","message":"Tampering detected"}

Desktop screenshot capture

Before submitting, the scanner captures a full-desktop bitmap with GDI+, encodes it as a JPEG in memory, and includes the base64 payload in the JSON body posted to /api/scan/submit. Failure paths are visible in the binary as:

  • "[*] Capturing desktop screenshot..."
  • "[+] Screenshot captured (<bytes> bytes)"
  • "[-] Failed to encode screenshot."
  • "[-] Failed to initialize GDI+."
  • "[-] JPEG encoder not found."

Windows with the WDA_EXCLUDEFROMCAPTURE / WDA_MONITOR display-affinity flag are handled explicitly — the scanner logs [!] Stream-proof window detected! Bypassing... and attempts to capture them anyway by cloning the DC. This is the standard technique for defeating “stream-proof” cheat overlays.

Secrets, keys, webhooks — none present

An exhaustive scan for every shape of embedded credential returned zero results in each of the following categories:

  • Discord webhook URLs (discord.com/api/webhooks/, discordapp.com/api/webhooks/)
  • Slack, Zapier, Telegram bot tokens / URLs
  • AWS/GCP/Azure access keys (AKIA*, ASIA*, AGPA*, etc.)
  • PEM-encoded X.509 certificates or RSA/EC private keys
  • Cloudflare R2 SigV4 signing material
  • SMTP / mailto: destinations
  • High-entropy binary blobs > 4 KB in .rdata or .data (no encrypted regions)

The only tokenised strings the file contains are the eight decoy JWTs (all standard textbook examples), the fixed X-Trace-Scanner header value TRACE-Scanner/QMSAPRSqM4xK2JnP, and 105 32-byte hex or base64 strings that on inspection are all MSVC template-instantiation hashes or C++ lambda IDs.

IOCs

File

SHA-2569d1b210b06d942863e49f0cf7baf629fcdc3cf76d33a5383a6caec65783eb4fc
SHA-15c40f76fc4b25c00f60970bb17dae9e16f9f45a1
MD537644acaf1725dcf01b8c0b9227ca111
Size3,345,920 bytes
Compile time2026-06-25 19:21:28 UTC
Authenticodeunsigned
Protector marker.1337 section — "Protected by Srungoat Protector v1.0"

Network

API hosttraceac.cc
Static / UI hostscanner.traceac.cc
User-Agent (POST)TraceScanner
User-Agent (version)blablublewidfjhsfhdshGFDSBSDUFGDFDSBNTRACE
Custom headerX-Trace-Scanner: TRACE-Scanner/QMSAPRSqM4xK2JnP
PIN transportquery parameter ?pin=<PIN> on GET
Body formatapplication/json (nlohmann::json v3.11.3)

Host

MutexGlobal\\TraceAntiCheatScanner_Mutex
Window classTraceAntiCheatScannerClass
Working directory%APPDATA%\\trace
Dropped filesyara64.exe · custom_rules.yar · yara_validate_<n> · trace_srudb_scan.dat · t_hist_<n>
Env vars watchedPIN · YARA · SELF_SCAN · TRACE_YARA_VALIDATION_FILE
Self-hygienetaskkill /f /im cmd.exe / powershell.exe

Detection guidance

Network

  • Alert on HTTPS requests carrying User-Agent: TraceScanner or the placeholder blablublewidfjhsfhdshGFDSBSDUFGDFDSBNTRACE. Both are stable across builds and unique to this family.
  • Alert on any request carrying X-Trace-Scanner: TRACE-Scanner/QMSAPRSqM4xK2JnP. The value is baked in as a UTF-16 constant.
  • Alert on any egress to traceac.cc or scanner.traceac.cc. Two hostnames, both dedicated to this scanner.
  • Alert on the URL path pattern /api/scanner/yara_manifest?pin=, /api/scanner/yara_rules?pin=, and /static/bin/yara64.exe?pin= — all specific to this tool.

Host

  • Alert on the creation of the named mutex Global\\TraceAntiCheatScanner_Mutex or the window class TraceAntiCheatScannerClass.
  • Alert on drop of yara64.exe to %APPDATA%\\trace\\ followed by execution with argv -w -m --scan-list.
  • Watch for a process with requireAdministrator manifest that spawns a Microsoft Edge WebView2 controller and navigates to https://scanner.traceac.cc/.

YARA candidate rule

rule TraceAntiCheat_Scanner {
  meta:
    author      = "Clubhouse AC Research"
    description = "Third-party FiveM Trace Anti-Cheat scanner"
    reference   = "traceac.cc"
    hash_sha256 = "9d1b210b06d942863e49f0cf7baf629fcdc3cf76d33a5383a6caec65783eb4fc"
  strings:
    $marker    = "Protected by Srungoat Protector v1.0"
    $ua        = "TraceScanner" wide
    $ua2       = "blablublewidfjhsfhdshGFDSBSDUFGDFDSBNTRACE" wide
    $hdrname   = "X-Trace-Scanner" wide
    $hdrvalue  = "TRACE-Scanner/QMSAPRSqM4xK2JnP" wide
    $mutex     = "Global\\TraceAntiCheatScanner_Mutex" wide
    $wnd       = "TraceAntiCheatScannerClass" wide
    $ui        = "https://scanner.traceac.cc/send/ui/" wide
    $c2a       = "traceac.cc" wide
    $yaraep    = "/api/scanner/yara_manifest?pin=" wide
    $submit    = "/api/scan/submit" wide
  condition:
    uint16(0) == 0x5A4D and
    3 of them
}

Closing

Trace Anti-Cheat is a functional retroactive-trace scanner. It reads a well-chosen set of Windows forensic artefacts, downloads YARA to run against a rule set that lives on its authors' server, takes a screenshot, and posts a JSON to a fixed C2. The technique inventory is solid — Prefetch, BAM, SRUM, Amcache, Event Log 4688 with the TokenElevationType filter, DNS-Client 3008/3010, WFP 5152/56/57. Anyone building a similar tool could learn from the coverage.

It is not unreverseable. The protector marker is 61 bytes of text in a section named .1337. No section is encrypted, no TLS callback is registered, no anti-debug is meaningfully implemented, and every URL, every registry key, every YARA path, every event log query, every cheat brand name, and every user-facing string sits in .rdata in plaintext at UTF-8 or UTF-16-LE. This document is the extraction, byte-offset by byte-offset.

If the next release genuinely raises the bar — real string obfuscation, control-flow flattening, a proper protector shell, meaningful anti-debug, or even just a byte-oriented XOR pass over .rdata with a runtime-derived key — we will happily update this page to note the improvement. Until then, the “unreverseable” label describes marketing, not this build.

Every string quoted in this write-up appears in the sample's .rdata at either UTF-8 or UTF-16-LE and is reproducible with strings -a -eL against the file whose SHA-256 is listed in the IOC block. No dynamic execution of the sample was required to produce this document.