Susano Setup.exe
A four-build family of the Susano loader (Setup.exe, Setup1.exe, Setupuptodate.exe, Setup_1.exe) plus the fully recovered 5.6 MB second-stage payload it delivers. This write-up documents the full compiled-in config table in .rdata, the complete wire cipher (AES-256-CBC + XOR mask keystream) with per-build keys tabulated for every observed build, both C2 endpoints (/v2/oauth.php and /v2/buffer.php), the layout of the delivered payload (2.58 MB user-mode Susano cheat DLL plus a 2.81 MB Windows kernel driver), the complete feature inventory (76 config keys across 12 categories) and the driver's full kernel-API import list showing exactly what ring-0 capability the operator ships to a paying customer.
Summary
Setup.exe is a 10.79 MB PE32+ GUI executable that asks for administrator on launch. No commercial packer wraps it. Standard MSVC 14.44 (VS 2022) build with normal .text / .rdata / .data / .pdata / .rsrc / .reloc sections. .pdata and .reloc are both populated, which VMProtect and Themida would strip. The high entropy of .text (7.296) is from statically linked crypto libs (multiple copies of AES and SHA-256 tables) and inline encrypted-config blobs, not from a runtime unpacker.
The critical single-page config table lives at 0x1408eb7b0 and everything the operator wants to configure per build sits there in 16-byte-aligned adjacent slots. Three C2 hosts, a service-kill list, a PCA file-delete list, a process interaction list, the elevation privilege it acquires and a couple of 128-bit constants that could be an IV or pinned key material. This is the strongest static IOC for the whole Susano family. Any build the operator ships will keep this layout because it is a compiled-in structure, not a runtime download.
On the wire it POSTs a 176-byte binary body under application/x-www-form-urlencoded (deliberately mislabelled) with UA SusanoUA/1.0 to http://susano.gg/v2/oauth.php and receives a 112-byte binary response under a mislabelled text/html. Replaying the exact same request produces a different response every time, confirming server-side freshness per session. Second endpoint /v2/download.php is confirmed to exist (POST returns 200, GET returns 403 CF-blocked, wrong-format POST returns 200 with an empty body suggesting an auth-gated 401-in-disguise). No other /v2/*.php endpoints responded to enumeration.
The crypto architecture is unusual. Exactly one CryptEncrypt call in the whole binary and it is DES(8-byte block, ALG_ID 0x6601), not AES. A SHA-256 KDF via CryptAcquireContextW + CryptCreateHash + CryptGetHashParamhashes an input into a 32-byte digest. The full AES S-box, inverse S-box, Rcon and full SHA-256 K constants sit in the on-disk .rdata at byte-perfect canonical values. A second copy of the AES S-box and Rcon appears in the runtime-decrypted body of the loader (at 0x1408ec590 and 0x1408ec790) and that second copy is actively consumed by an AES-256 key schedule. The 176-byte HTTP body is not built by any CryptoAPI call: it is produced by that runtime-decrypted AES-256 routine keyed off internal state.
Second-stage recovery is complete. The /v2/buffer.php endpoint (which quietly replaced /v2/download.phpin the three newest builds) hands back a 5,648,480-byte blob to any authenticated session. Once the wire cipher is peeled off, the blob resolves into two Windows PE files sitting back-to-back inside a single memory region: a 2.58 MB user-mode cheat DLL followed by a 2.81 MB kernel driver (Subsystem = Native, Machine = x86-64, 52 kernel APIs from ntoskrnl.exe). The driver is the actual product Susano sells to its customers. The loader is disposable and gets rebuilt almost daily. What matters is what the driver can do, and that surface covers the full BYOVD toolkit: PsLookupProcessByProcessId to walk to any process, KeAttachProcess to attach the driver's context to it, MmCopyVirtualMemory to read and write GTA5.exe memory without going through OpenProcess, ZwProtectVirtualMemory to reflow read-only pages, and ZwSetSystemInformation to unlink itself from PsLoadedModuleList. The user-mode DLL is what the driver drops into GTA5.exe once it is attached. The DLL holds the full menu (76 config keys spanning aimbot, silent aim, trigger bot, ESP, player mods, vehicle mods, weapon mods, actions and stealth) along with explicit named bypasses for the four most-deployed community FiveM anticheats (Cyber, Nb, Putin, Reason).
Sample identity
| Field | Value |
|---|---|
| Name on disk | Setup.exe (as delivered by the Susano landing page) |
| Type | PE32+ EXE, x64, GUI subsystem |
| Size | 10,797,648 bytes (10.79 MB) |
| MD5 | 111bb3f93444d8e873e0b11b0dec2275 |
| SHA-256 | 65922561c8304fadf5d01c50ca7375f9b2b8afbd2aebac4202657b930d214558 |
| Linker | MSVC 14.44 (Visual Studio 2022) |
| Overlay after last section | 80 bytes (small padding, plausibly a signature stub) |
| Manifest | level='requireAdministrator' uiAccess='false' |
| Signed | no |
| ImpHash | 89279bc839f47ce69afbd562c3637253 |
| Product user-agent | SusanoUA/1.0 (constructed at runtime, never stored plaintext) |
| Section | VA | VSize | RSize | Notes |
|---|---|---|---|---|
| .text | 0x140001000 | 0x008e2fb4 | 0x008e3000 | 9.06 MB, entropy 7.296 (high, from statically linked crypto libs plus embedded encrypted config) |
| .rdata | 0x1408e4000 | 0x00115b3a | 0x00115c00 | 1.13 MB, entropy 6.200 (holds the config table plus AES and SHA-256 tables) |
| .data | 0x1409fa000 | 0x00049164 | 0x00047400 | 295 KB, mostly zero (entropy 0.283) |
| .pdata | 0x140a44000 | 0x0000b964 | 0x0000ba00 | SEH unwind info, present (a commercial protector would strip) |
| .fptable | 0x140a50000 | 0x00000100 | 0x00000200 | Control Flow Guard function table |
| .rsrc | 0x140a51000 | 0x000001e8 | 0x00000200 | Manifest resource only |
| .reloc | 0x140a52000 | 0x000010c4 | 0x00000000 | Base relocations present (a commercial protector would strip these) |
Loader family (4 builds observed)
Susano's landing page rebuilds the outer loader almost every day. Every build keeps the same wire protocol and the same config-table layout in .rdata but rotates the AES-256 master key, the CBC IV and the XOR mask that get compiled into the request-body prefix. We watched four distinct builds land inside a two-week window. Feature parity across all four (same target games, same anti-forensic list, same endpoint set) tells us they are the same product behind different cover.
| Build | SHA-256 | Size (B) | HWID behaviour | Notes |
|---|---|---|---|---|
| Setup.exe (original) | 65922561c8304fadf5d01c50ca7375f9b2b8afbd2aebac4202657b930d214558 | 10,797,648 | HWID-locked, rejected our client with 'Incorrect HWID, request support for reset.' | First build analysed. Section 2 of this write-up covers it in depth. |
| Setup1.exe | 4041080fe7... | 10,796,624 | HWID-locked, same 'Incorrect HWID' UI, uses updated wire keys. | Second variant. Same protocol, different compile-time key material. |
| Setupuptodate.exe | 00d4284edb... | 10,796,624 | No HWID lock. Auto-registers the caller's HWID on first oauth call. Shows a live '[*] Requesting data. This may take a while...' console UI. | This build binds any first-seen HWID to a fresh user ID. Server-assigned integer user ID observed at 17943118. |
| Setup_1.exe (freshest) | 4c43f0b310b960623002a60d53f5462fc8595b95c0004adae3118f5edfecea8f | 10,796,624 | No HWID lock. Compiled 2026-07-15 20:13 UTC. Same protocol, new wire keys. Successfully delivered the 5.6 MB second-stage payload. | The build used for end-to-end payload recovery. All second-stage findings below trace to this sample. |
| Claude Setup.exe (ssn3996 masquerade build) | efe82dade7a22e9225a54a5d33292ca93f156a41767060b09e0ab4c37f89f52f | 37,258,832 | Distributed via WeTransfer under the Claude Desktop installer filename. Different product tier: a monolithic self-contained FiveM HWID spoofer + BYOVD kernel loader + game-DLL hooker with ImGui UI, all inlined into the loader binary. Wire keys (KEY/IV/MASK above) extracted live from a Wine-run oauth.php request prefix. oauth.php returns 96 bytes. buffer.php returns 96 bytes on every probe shape tried. No 5.6 MB DLL+driver second-stage exists for this SKU because the cheat isn't downloaded. It's compiled into the 37 MB loader alongside the embedded Intel iqvw64e.sys BYOVD driver. The 96-byte oauth bundle is the entire wire payload for this build (session/license material consumed locally). | Fifth build observed. Same protocol, new wire keys, self-contained product SKU rather than second-stage-download SKU. |
Setup_1.exe (2026-07-15 build) is the freshest and the one used for full payload recovery. Everything from Payload architecture onward is sourced from that build's session with the origin server.
Per-build wire cipher keys (extracted from each build's request-body prefix)
| Build | KEY (AES-256, req[0:32]) | IV (req[32:48]) | MASK (req[48:64]) |
|---|---|---|---|
| Setup.exe (original) | af56ff55e111107ce29b836b8da3256333dfb7ce5dd8e38c617f29dcf54a4c75 | af7a753a83ede99599cc135c934289e4 | 391db0a5de41163b09777883e787ae4d |
| Setup1.exe | 59361ae634f1c5505ae30ead94605778a1ddf74c480f10c6cdbac349da68f43b | 3baf76f8f5494e05ce10781d36d72f5c | da4028243f4ede9aa7b9b5d32fb83124 |
| Setupuptodate.exe | af891552647a33c2701c1f4aac6d4b52cae468734269a3d765e6d90a8774c77f | f064995f2a8907ece748d8528d6d9302 | 98148602769f0782e97cb809816d2e2c |
| Setup_1.exe | 68d2cc44c5c233e895117b30df371b09815223c911c55b2d2ff35a54136196ce | 55bfe2b67a8d96677c1a8598efbe8cd3 | adb99f7816cc1b312bb0818aae79bc66 |
| Claude Setup.exe (ssn3996 masquerade build) | f2243896195a1838262a8e851de3bbe3b1555a592360c039fdb9bf8643e96788 | 72228a52acf3bcc5cc8260e1cc888e78 | c16562116af10599e9c7ea0e49b55b75 |
All four sets of keys decrypt cleanly against their respective build's captured traffic. The rotation confirms that the Susano operator does a fresh source rebuild with a new compile-time seed for every drop.
No protector on the outer shell
Nothing here matches the shape of a commercial protector. Sections have real names (.text / .rdata / .data / .pdata / .rsrc / .reloc / .fptable), .pdata holds real SEH unwind info, .reloc is populated, imports are a full-fat 150+ from KERNEL32 with real per-DLL function counts (not the one-stub-per-DLL pattern VMProtect uses). MSVC linker fingerprint matches Visual Studio 2022 (14.44). Entropy in .text is 7.3 which is high but explained by (a) three separate statically linked crypto libraries each bundling AES and SHA-256 tables, and (b) inline encrypted configuration blobs. The entry point at 0x1408a9c64 begins with a clean jmp 0x14068c837 into a normal MSVC startup shell. No VM handler noise, no fbld-style filler instructions, no cascading call +0 obfuscation.
Import table
| DLL | Count | Notes |
|---|---|---|
| dwmapi.dll | 1 | DwmExtendFrameIntoClientArea (composition setup for the overlay) |
| KERNEL32.dll | 150 | CreateFileMappingA, AllocConsole, SetConsoleTextAttribute, VirtualAlloc, service-adjacent helpers, plus 145 others |
| USER32.dll | 39 | DestroyWindow, MessageBoxW, OpenClipboard, GetAsyncKeyState-adjacent, standard cheat UI plus input surface |
| ADVAPI32.dll | 37 | CryptAcquireContextW, CryptEncrypt, CryptImportKey, CryptGenRandom, CryptHashData, CryptCreateHash, CryptGetHashParam, CryptDestroyKey plus token APIs (OpenProcessToken, DuplicateTokenEx, SetThreadToken, GetTokenInformation, SetTokenInformation) |
| ole32.dll | 1 | CoInitializeEx |
| WS2_32.dll | 34 | send, recv, connect, getaddrinfo, WSAStartup, WSASocketW, htons/htonl plus a full SOCKS5 client surface |
| IMM32.dll | 4 | ImmSetCompositionWindow, ImmReleaseContext, ImmGetContext plus one more (IME support for the overlay) |
| ntdll.dll | 6 | NtQueryVirtualMemory, RtlInitUnicodeString, RtlVirtualUnwind, NtLoadDriver, NtUnloadDriver plus one more (direct Nt-level driver load without going through the SCM) |
The ntdll.dll row is the most operationally significant one. Direct NtLoadDriver and NtUnloadDriverimports means the loader has the surface to load a kernel driver without going through the Service Control Manager (which would be logged in the Event Log the loader is about to kill anyway).
The static config table at 0x1408eb7b0
Everything the operator wants to configure per build sits in a single tightly packed page at 0x8eb7b0 in .rdata. Every entry is 16-byte-aligned and null-padded to the slot width. This is a compiled-in static const struct config in the original source. Layout below.
| VA | Content | Purpose |
|---|---|---|
| 0x1408eb7b0 | susano.re (ASCII, null-padded to 16B) | Fallback C2 host |
| 0x1408eb7c0 | susano.gg (ASCII, null-padded to 16B) | Primary C2 host |
| 0x1408eb7d0 | vps93241.serveur-vps.net (ASCII, null-padded to 32B) | Direct VPS backup C2 (bypasses Cloudflare, points at the origin server directly) |
| 0x1408eb7ec | PcaSvc | Program Compatibility Assistant Service. Windows tracks program launches here |
| 0x1408eb7f4 | DPS | Diagnostic Policy Service. Network and system diagnostic logging |
| 0x1408eb7f8 | DiagTrack | Connected User Experiences and Telemetry. The main Windows telemetry pipe |
| 0x1408eb808 | Dnscache | DNS Client service. Killed to hide C2 lookups from the local DNS cache |
| 0x1408eb818 | EventLog | Windows Event Log. The primary audit source for any post-hoc forensic investigation |
| 0x1408eb828 | services.exe (UTF-16LE) | Target or hooked system process |
| 0x1408eb840 | explorer.exe (UTF-16LE) | Target or hooked |
| 0x1408eb860 | smartscreen.exe (UTF-16LE) | Target. Windows SmartScreen. Interacts to suppress reputation warnings |
| 0x1408eb880 | lsass.exe (UTF-16LE) | Target. LSA. Very sensitive. |
| 0x1408eb8a0 | csrss.exe (UTF-16LE) | Target. Client-Server Runtime Subsystem |
| 0x1408eb8b8 | dwm.exe (UTF-16LE) | Target. Desktop Window Manager |
| 0x1408eb8d8 | int64[6] = {7, 9, 15, 24, 31} | Small integer array. Plausibly PID slots or PROCESS_ACCESS_RIGHTS flags for the six process entries above |
| 0x1408eb900 | SeTcbPrivilege (UTF-16LE) | The 'act as part of the operating system' privilege |
| 0x1408eb920 | winlogon.exe (UTF-16LE) | Target (7th process, listed separately from the six above) |
| 0x1408eb940 | 16 bytes: f2aa156f08d2894e9ab4489535d34f9c | Unknown 128-bit constant (IV candidate or fixed nonce) |
| 0x1408eb960 | double 10.0 (0x4024000000000000) | Numeric constant (poll interval or timeout) |
| 0x1408eb970 | 32 bytes = SHA-256 H0..H7 (little-endian) | Software SHA-256 initial hash values from a statically linked crypto lib. Appears 3x in .rdata (three libs each bundle SHA-256) |
| 0x1408eb990 | 256 bytes = AES S-box (verified 100% match) | From a statically linked crypto lib (NOT referenced by any active AES code) |
| 0x1408eba90 | 256 bytes = AES inverse S-box | Same as above |
| 0x1408ebb91 | 10 bytes = AES Rcon (01 02 04 08 10 20 40 80 1b 36) | Same |
| 0x1408ebba0 | 256 bytes = SHA-256 K constants (round constants) | Same as SHA-256 IV: statically linked crypto lib |
FiveM target inventory
Five FiveM DLL names appear plaintext in .rdata, confirming the target game surface.
- citizen-scripting-lua.dll
- gta-net-five.dll
- extra-natives-five.dll
- gta-streaming-five.dll
- adhesive.dll
adhesive.dll is FiveM's anti-cheat component. Its presence in the target list means the loader specifically inspects or hooks it. citizen-scripting-lua.dll is where Lua scripts get evaluated by the FiveM runtime, a natural aimbot or cheat-menu injection surface.
Anti-forensic service kill-list
Five Windows services listed in the config, each of which is the source of truth for a specific piece of the Windows execution audit trail. Every service on this list is where a forensic reviewer would look after the fact:
| Service name | Full name | What it records or does |
|---|---|---|
| PcaSvc | Program Compatibility Assistant Service | Records program launches into %WINDIR%\appcompat\pca\Pca*.txt (deleted separately, see next section) |
| DPS | Diagnostic Policy Service | Network and hardware diagnostic logs |
| DiagTrack | Connected User Experiences and Telemetry | Windows telemetry pipe, feeds Amcache and related telemetry stores |
| Dnscache | DNS Client service | Local DNS cache, would reveal susano.gg lookups |
| EventLog | Windows Event Log | The catch-all audit source (Application, Security, System, Sysmon and so on). Stopping this is the loudest anti-forensic move on the list. Any forensic sweep would flag an Event Log service stop by itself |
PCA file-delete list
Three UTF-16LE paths in .rdata immediately before the config table (starting at 0x8eb690). All three are the exact files Windows uses to hold program-launch history, and any forensic sweep run after the fact would grep them for the loader's own image name. If Susano runs to completion before a review starts, these files are gone and no program-launch record survives.
C:\Windows\appcompat\pca\PcaAppLaunchDic.txt
C:\Windows\appcompat\pca\PcaGeneralDb0.txt
C:\Windows\appcompat\pca\PcaGeneralDb1.txtProcess interaction list
Seven target processes in the config table as UTF-16LE strings. All except one are critical Windows system processes. The presence of these names in a config table that also holds SeTcbPrivilege and token-manipulation imports is the fingerprint of a loader that impersonates or injects into system processes.
- services.exe. Service Control Manager
- explorer.exe. Windows Explorer
- smartscreen.exe. Windows SmartScreen
- lsass.exe. Local Security Authority Subsystem
- csrss.exe. Client-Server Runtime Subsystem
- dwm.exe. Desktop Window Manager
- winlogon.exe. Windows Logon (listed after the group of 6)
SeTcbPrivilege escalation
SeTcbPrivilege ("act as part of the operating system") is the highest local privilege on Windows. Combined with the token manipulation imports (OpenProcessToken, DuplicateTokenEx, SetThreadToken, SetTokenInformation, GetTokenInformation), this loader is set up to acquire and impersonate SYSTEM- or TCB-level tokens, which is the standard path to make the subsequent driver-load and service-manipulation operations invisible to the current interactive user's token context.
Kernel driver capability
ntdll.NtLoadDriver and ntdll.NtUnloadDriver are imported directly, bypassing the Service Control Manager which is the SCM path most cheats use. Direct Nt* load skips the services.exe event log entries and the SCM-registered ImagePath resolution flow. Since Susano is presumed not to have a valid code-signing certificate for a kernel driver (the outer PE is not signed at all), this capability strongly implies BYOVD (Bring Your Own Vulnerable Driver) where a signed third-party driver with a known LPE is loaded and abused to run unsigned code in ring 0. The exact driver bundled or downloaded is not present in this outer sample. It would arrive from /v2/download.php on a successful handshake.
SOCKS5 support
Plaintext strings "SOCKS5 sub-negotiation response" and "initial SOCKS5 response" appear in the binary. The client has a full SOCKS5 negotiation surface, probably from a bundled libcurl or a custom impl. Purpose is unclear from static analysis alone. Could be a proxy fallback for reaching the C2 through corporate networks or a peer-relay for a distributed cheat network.
Crypto architecture
| Component | Details |
|---|---|
| FUN_1408a69d0 (CryptEncrypt wrapper. The only CryptEncrypt call in the whole binary) | DES 8-byte block. Provider PROV_RSA_FULL (1), algorithm CALG_DES (0x6601), 7-byte input key expanded to an 8-byte parity-adjusted DES key (textbook DES key expansion nibble-shift). One 8-byte block encrypted in place. Used on the initial handshake path, not the main C2 payload. |
| FUN_1408a8290 (SHA-256 KDF) | CryptAcquireContextW with PROV_RSA_AES (0x18), CryptCreateHash with CALG_SHA_256 (0x800c), CryptHashData over the input buffer, CryptGetHashParam HP_HASHVAL (2) into a 32-byte output. Classic SHA-256(input) -> 32-byte digest. Called from 2 sites, the large one at 0x1408a2fa0 (2744 bytes) and a small proxy at 0x14089e090. |
| Software AES tables at 0x1408eb990 | AES S-box, inverse S-box and Rcon at byte-perfect canonical values in the on-disk .rdata. A second copy of the S-box and Rcon also lives in the runtime-decrypted body at 0x1408ec590 and 0x1408ec790, and that second copy IS actively consumed by an AES-256 key schedule (Nk=8, mod-Nk=4 SubBytes branch present). |
| Software SHA-256 constants at 0x1408eb970 | Three separate copies of SHA-256's H0..H7 initial hash values across .rdata (0x8eb970, 0x8f5120, 0x980f10) plus the K[64] round constants at 0x8ebba0. Each statically linked crypto library bundles its own SHA-256 impl. Only one is actually reached. |
The DES 8-byte-block wrapper is worth calling out. It uses a 7-byte input key, expands to 8 bytes with parity nibble-shift (textbook DES key format), builds a PLAINTEXTKEYBLOB in place, calls CryptImportKey with CALG_DES (0x6601) and encrypts exactly 8 bytes. Only used at one call site. Not the main C2 encryption. Likely used to derive an 8-byte token or to seal one field of the handshake.
C2 handshake wire format
The initial handshake POSTs a 176-byte binary body to http://susano.gg/v2/oauth.php. Cloudflare fronts the origin (cf-ray, server: cloudflare, cf-cache-status: DYNAMIC in response headers). The response is 112 bytes of binary served under a mislabelled text/html Content-Type.
| Field | Value |
|---|---|
| Method | POST |
| URL | http://susano.gg/v2/oauth.php |
| Host | susano.gg |
| User-Agent | SusanoUA/1.0 |
| Accept | */* |
| Content-Type | application/x-www-form-urlencoded (misleading, body is raw binary) |
| Content-Length | 176 |
| Response status | HTTP 200 OK |
| Response headers | server: cloudflare, cf-ray: ..., cf-cache-status: DYNAMIC, nel plus report-to: cf-nel |
| Response Content-Type | text/html; charset=UTF-8 (also misleading, response body is raw binary) |
| Response Content-Length | 112 |
Sample request body (hex, 176 bytes):
af56ff55e111107ce29b836b8da3256333dfb7ce5dd8e38c617f29dcf54a4c75af7a753a83ede99599cc135c934289e4391db0a5de41163b09777883e787ae4dda812ce78337ce71c9171c08ed88e85dc49c106a74202a850cc606092d9876644db49c603c02333fe09a369dc25ac7da8b6d96924722554709a79c4f8f7a8181ba6e888aac4565fc726d19a5fbde80c1fd7b4a6a853212c70d2891286204064cb22f9ce73f7c211420f702d5cf5a5c8bSample response body (hex, 112 bytes):
f80c7c4c91bcca1d68fb229bac1efdcef2a2602c7b9d67536a8d2dfb20e6908ada5ceb55032a3e74db6f7d79fcde764fb2f25f0f2d12cda80e6fe14efff2e2514692aecd2e479f79b1b9e8d983117408d566847ecd112704f5543567fd30a82e8c6eac584d65843a07f5673a0cadcc24Replaying the exact same 176-byte request produces a different 112-byte response every time, confirming the server either seeds a per-response nonce or generates fresh session material on each handshake.
Structural observation across multiple captures
Compared across every recorded session, the first 160 bytes of the request body are byte-identical. Only the final 16-byte block varies per session. In hex, the invariant prefix is:
af56ff55e111107ce29b836b8da3256333dfb7ce5dd8e38c617f29dcf54a4c75af7a753a83ede99599cc135c934289e4391db0a5de41163b09777883e787ae4dda812ce78337ce71c9171c08ed88e85dc49c106a74202a850cc606092d9876644db49c603c02333fe09a369dc25ac7da8b6d96924722554709a79c4f8f7a8181ba6e888aac4565fc726d19a5fbde80c1fd7b4a6a853212c70d2891286204064cVariable final-block samples observed in separate captures: cc6fb9864e4ef83add09e1304fd3439f, d0d91a6e147292fb95df47ef28caab7e, 7c4797478f05f6ab7bc47b16b4e1bde6, a4f43400a3f3374c799d37ce2af71984, fcf48ae3e9d312a27688becebeb9800e.
The invariance across sessions means the leading 10 AES blocks are not being freshly derived per handshake. The volatile channel bandwidth per handshake is at most 16 bytes.
The invariant 32-byte prefix IS an AES-256 key
In the running process, an AES-256 key schedule expansion is performed with the master key set to the first 32 bytes of the wire payload above. The 240-byte expansion table (32-byte master + 208 bytes of round keys) lives at a fixed local address in the loader's active stack frame. Independently reproducing the AES-256 schedule on those 32 bytes byte-matches the 240-byte table found in the running process 100%.
In other words: the loader is publishing its own AES-256 master key as the leading 32 bytes of every request it sends. The remaining 144 bytes are then further material (encrypted content plus the volatile 16-byte block) that the server processes with the same key.
The key material is invariant across sessions, meaning it is either compiled in per build or derived deterministically from install-time state before the first HTTP call. The volatile 16-byte block appears to be a per-session sealed value computed after the fixed prefix has already been staged in the send buffer.
The consumer of the expanded round keys is not a stock AES routine. Traced live during response processing, the code path is a hand-rolled dispatcher whose head byte (opcode) is fetched with mov sil, byte ptr [rbx] and compared against a small alphabet: 0x79 selects a 1-byte pointer-chase (mov r12b, [r12]), 0x09 selects a 2-byte chase, 0x6d a 4-byte chase, 0xc1 an 8-byte chase, followed by per-branch XOR whitening with hardcoded constants such as 0x48fa4785, 0x795e9633, 0x3a0befb6. The rbx "opcode stream" is not a contiguous bytecode blob but a scatter of addresses inside the loader's own .text region (observed values: 0x14033407a, 0x14033385a, 0x1403ac175, 0x1403ba430, 0x1403aef78, 0x1403e15b8, 0x1403b94f1, 0x1403db5d3, 0x1403d2326 among others), making the opcode source double as a control-flow-integrity check on the surrounding code.
Walking one full pass of the dispatcher during a live response, the r12 pointer follows the AES ShiftRows byte permutation pattern across the round-key table (reads at offsets 0x00, 0x02, 0x07, 0x09 within each 16-byte round key, advancing by 0x10 each cycle: RK1 0xfd110, 0xfd112, 0xfd117, 0xfd119, then RK2 0xfd120, 0xfd122, 0xfd127, 0xfd129, etc.). Byte-offset pattern {0, 2, 7, 9} combined with the confirmed AES-256 schedule identifies the underlying primitive as AES itself with a custom permutation layer folded over the standard round function. Standard AES-256 modes keyed with this master do not produce readable plaintext from either the request payload or the 112-byte response body, which is consistent with the VM performing that additional permutation before or after the block cipher.
The complete constant table used by the dispatcher for per-branch XOR whitening across the traced code window is 0x48fa4785, 0x3cbdb945, 0x70e268b7, 0x4a0ff44d, 0x793f490f. Dispatch alphabet at the dispatcher opcode fetch is {0x00, 0x09, 0x6d, 0x79, 0xc1}, five handlers total, corresponding to 0-byte, 2-byte, 4-byte, 1-byte and 8-byte pointer chases respectively.
Attempting to replay the dispatcher with a concrete-emulation harness (Triton + full snapshot of registers and reachable memory) reveals the deeper defense: after each dispatcher iteration the loader writes freshly synthesised x86 bytes into the writable range around 0x140154400 and jumps to them, producing near-200,000 memory writes to that same buffer across two hundred thousand emulated instructions with only a single dispatcher iteration completing. In other words the loader is a JIT-generating VM: each virtual opcode materialises a new native code page and executes it in place. That matches the code-based dispatch (opcode source scattered across .text) and explains why straight-line concrete emulation diverges. A faithful analyser needs a JIT-aware lifter (VTIL-Core-style) that recognises the loader's handler shapes and reassembles the semantic operation across many synthesised fragments.
Full crypto scheme recovered (end-to-end verified)
The response body is decrypted in two stages. First an outer XOR unwrapping, then a standard AES-256-CBC decryption with parameters lifted directly out of the same request that carried them. The complete scheme, using slice notation over the 176-byte request body:
KEY = REQ[0:32] # AES-256 master key, invariant across sessions
IV = REQ[32:48] # CBC IV, invariant across sessions
MASK = REQ[48:64] # XOR unwrap mask, invariant across sessions
def decrypt_response(resp_112b):
inner = bytes(a ^ MASK[i % 16] for i, a in enumerate(resp_112b))
return AES.new(KEY, AES.MODE_CBC, IV).decrypt(inner)Concrete constants in this build: KEY=af56ff55e111107ce29b836b8da3256333dfb7ce5dd8e38c617f29dcf54a4c75, IV=af7a753a83ede99599cc135c934289e4, MASK=391db0a5de41163b09777883e787ae4d. All three are the byte-identical leading blocks of every observed request body, meaning they are compiled in per install and re-used across every handshake.
Cross-verified end-to-end: for one recorded session, taking the 112-byte response body, applying the XOR unwrap and the AES-256-CBC decrypt above yields a 112-byte binary plaintext whose leading 32 bytes are 4a840ac9556e2a713c81a9108d8876efaf3068451200d00c759ac18024163ed2, byte-identical to the per-session AES key independently observed via runtime instrumentation on the loader's own key-derivation site during that same session. The remaining 80 bytes of plaintext are per-session opaque state (IV or session tokens for the second-stage endpoint).
/v2/oauth.php is therefore a session-key delivery endpoint. The invariant leading blocks of the request are the client's compiled-in identifier. The server keys off that identifier and returns a fresh 32-byte AES-256 session key plus supporting state (bytes 32-47 IV-shape, bytes 48-63 XOR-mask-shape, bytes 64-111 opaque session token), encrypted under the same identifier.
Request-side plaintext is symmetric: applying the same XOR + AES-256-CBC decryption to the payload region REQ[64:176] reveals the request PT as t=QCMkHCbNYeDvR1Pe&h={56b7558114e09368e8dcab7f0aacb266f39d4da91c6d416092d0c4b1663709b8}&v=lt18&htf=NN(with htf being a per-session counter, the only variable field in the request PT. Everything else is compiled in). Standalone re-encryption of that plaintext under the same scheme reproduces byte-for-byte the observed wire bytes and the origin accepts the forged request, returning fresh session material.
/v2/download.php accepts POST bodies of the same format under both identity-keyed and session-keyed variants and returns 200 OK with an empty body in every observed case, with no discriminating leak. Second-stage retrieval is therefore gated behind additional per-user authorisation state not derivable from the compiled-in identifier alone. The handshake crypto itself is fully broken.
Live memory of the running loader also contains the standard AES-256 S-box at 0x1408ec590 and standard AES Rcon at 0x1408ec790. Byte-perfect canonical values in both cases. The key-schedule loop that consumes those tables is byte-verified as AES-256 (Nk=8, with the mod-Nk=4 SubBytes-only branch that is unique to AES-256's schedule). The schedule appears in the runtime-decrypted body of the loader and is not visible in the on-disk .text at rest.
Backend endpoints
Endpoint enumeration against susano.gg:
| Path | GET | POST | Interpretation |
|---|---|---|---|
| /v2/oauth.php | 403 (CF) | 200 (with 112B body) | Handshake / session establishment. Confirmed live across all 4 builds. |
| /v2/buffer.php | 403 (CF) | 200 (with 5,648,480B body when session-authenticated) | Payload delivery (current). Used by Setup1.exe, Setupuptodate.exe and Setup_1.exe. Returns the encrypted user-mode DLL + kernel driver. |
| /v2/download.php | 403 (CF) | 200 (empty body on wrong-format request) | Payload delivery (legacy). Used by the original Setup.exe. Still responds on the newer builds' backend as a honeypot / kept for backward compat. |
| /v2/loader.php | 403 (CF) | 404 | Does not exist |
| /v2/auth.php | 403 (CF) | 404 | Does not exist |
| /v2/hwid.php | 403 (CF) | 404 | Does not exist |
| /v2/config.php | 403 (CF) | 404 | Does not exist |
| /v2/heartbeat.php | 403 (CF) | 404 | Does not exist |
| /v2/telemetry.php | 403 (CF) | 404 | Does not exist |
| /v2/inject.php | 403 (CF) | 404 | Does not exist |
| /openapi.json | 403 (CF) | - | Does not exist |
| /docs | 403 (CF) | - | Does not exist |
Susano's backend is minimal. Two endpoints, both POST, both 200-with-empty-body when auth fails so an attacker walking the API cannot easily distinguish "endpoint does not exist" from "endpoint exists but you are unauthenticated". This is deliberate.
Payload architecture (5.6 MB blob from /v2/buffer.php)
After the oauth handshake succeeds and the client walks away with a valid session key, the loader makes a second HTTP request. POST /v2/buffer.php with a 640-byte body of the form t={token16}&h={hwid_hash}&v=ltbf&u={userID}&l=0. The body is URL-form plaintext wrapped by the same AES-256-CBC plus XOR mask cipher the oauth request uses. The origin sends back a 5,648,480-byte binary body. Once that is decrypted with the session key the plaintext resolves to a single 5,701,632-byte memory region holding two Windows PE files back-to-back plus a tail of zero padding.
| Field | Value |
|---|---|
| Source | Body of the HTTP response to POST http://susano.gg/v2/buffer.php |
| Wire size | 5,648,480 bytes (5.39 MiB, exact) |
| Decrypted size | 5,701,632 bytes after XOR unwrap + AES-256-CBC decrypt with per-session keys derived from the oauth handshake response |
| Composition | User-mode Susano cheat DLL (2.58 MB) + Windows kernel driver .sys (2.81 MB) + 54 KB zero padding |
| User-mode DLL SHA-256 | cd88aa1dd8b4f59c5dfaaf47d0622de698d7b507cc182d34a8cd2282129d815c |
| Kernel driver SHA-256 | 0aeba1809df1792d36861b70120c2ec5d79aeb978c1c11eb71610b9752557bfb |
| User-mode format | Memory-mapped PE image (VA layout, MZ header zeroed). The loader receives sections at their virtual addresses ready to be handed to the driver for injection |
| Kernel driver format | Standard PE32+, Subsystem = Native (0x1), Machine = x86-64, 7 sections including a section named '.\;d' that appears to be obfuscated code |
| User-mode compile ts | Not present in the dumped image (headers stripped) |
| Kernel driver compile ts | 2026-06-08 12:55 UTC. The driver is a stable component, rebuilt only every few weeks while the loader is rebuilt daily |
Layout of the 5,701,632-byte plaintext region
Offset Size Contents
0x000000 2,705,488 B User-mode Susano cheat DLL
(memory-mapped PE image, MZ header zeroed,
.text starts around 0x1000 relative)
0x294850 2,941,952 B Windows kernel driver .sys
(standard PE32+, valid MZ+PE header,
Subsystem=Native, x86-64, 7 sections)
0x554fb0 54,192 B Zero padding (only 199 non-zero bytes,
tail of AES-CBC output before PKCS7 trim)The layout is deliberate. The loader hands the memory-mapped user-mode image to the driver ready for injection into GTA5.exe (all section VAs already resolved) and keeps the driver PE for its own NtLoadDriver path. This is why the outer PE at offset 0 has a zeroed MZ. It is never intended to be re-parsed as a file on disk, it is handed straight to the driver's process injector.
User-mode Susano DLL
| SHA-256 | cd88aa1dd8b4f59c5dfaaf47d0622de698d7b507cc182d34a8cd2282129d815c |
| Size | 2,705,488 bytes (2.58 MB) |
| Format | Memory-mapped x86-64 PE image (headers stripped) |
| Runtime | MSVC x64, C++ with std::regex (parses FiveM server info JSON), std::string SSO, RTTI enabled |
| Crash symbolication format | Function: susano!sub_0x%X+0x%llX (custom, includes a "susano+0x%llX (RIP: 0x%llX)" walker for stack frames) |
| FiveM server discovery | Compiled-in regex patterns: "hostname"\s*:\s*"([^"]*)", "clients":(\d+), "sv_maxclients"\s*:\s*(\d+). These scrape the FiveM /info.json and /dynamic.json endpoints on target servers directly, likely for population-scoring in a server-picker or for the misc.adminlist / streamproof logic to know when it is safe to render the menu. |
| Config file referenced | dynamic.json (the FiveM server dynamic-info endpoint filename) |
RTTI type descriptors present in the DLL (standard MSVC compiler output confirming C++ exception path with std:: types):
- .?AVinvalid_argument@std@@
- .?AVlength_error@std@@
- .?AVlogic_error@std@@
- .?AVregex_error@std@@
- .?AVruntime_error@std@@
- .?AVout_of_range@std@@
- .?AVbad_alloc@std@@
- .?AVbad_array_new_length@std@@
- .?AVbad_exception@std@@
- .?AVexception@std@@
- .?AVfacet@locale@std@@
- .?AV_Facet_base@std@@
- .?AV_Locimp@locale@std@@
- .?AV?$collate@D@std@@
- .?AV?$ctype@D@std@@
- .?AUctype_base@std@@
- .?AU_Crt_new_delete@std@@
- .?AVtype_info@@
Kernel driver .sys (the real product)
This is the file Susano actually sells. Everything else in the pipeline exists to get it into ring-0 without an EDR catching the delivery. Subsystem is Native (0x1), Machine is x86-64 and it pulls 52 kernel APIs from ntoskrnl.exe covering the entire BYOVD process-injection surface.
| SHA-256 | 0aeba1809df1792d36861b70120c2ec5d79aeb978c1c11eb71610b9752557bfb |
| Size | 2,941,952 bytes (2.81 MB) |
| Format | PE32+, Subsystem = Native, Machine = x86-64, Characteristics = 0x22 (Executable + Large-address-aware) |
| Compile timestamp | 2026-06-08 12:55 UTC (stable, only rebuilt every few weeks unlike the loader) |
| Sections | .text (RVA 0x1000, 0x6f1c), .rdata (0x8000, 0xcc4), .data (0x9000, 0x1914), .pdata (0xb000, 0x330), INIT (0xc000, 0x75c), .\;d (0xd000, 0x2c4f24), .reloc (0x2d2000, 0x124) |
| Obfuscated section | The '.\;d' section (unusual name with a leading dot, backslash and semicolon) holds 2.75 MB of data. Given its size and position after the standard code sections, it is almost certainly the driver's obfuscated payload code region |
| ImageBase | 0x140000000 (standard PE64 default) |
| Entry point RVA | 0x6b20 (inside .text) |
| SizeOfImage | 0x2d3000 (2,961,408) |
Complete import list from ntoskrnl.exe (52 APIs):
- ExAllocatePool
- ExAllocatePoolWithTag
- ExFreePoolWithTag
- ExGetPreviousMode
- IoGetCurrentProcess
- KeAttachProcess
- KeDetachProcess
- KeGetCurrentIrql
- KeQueryPerformanceCounter
- MmCopyVirtualMemory
- MmGetSystemRoutineAddress
- MmHighestUserAddress
- MmIsAddressValid
- NtCreateFile
- NtFsControlFile
- NtQueryEaFile
- NtQuerySystemInformation
- NtSetEaFile
- ObQueryNameString
- ObReferenceObjectByHandle
- ObfDereferenceObject
- PsGetCurrentProcessId
- PsGetProcessExitStatus
- PsGetProcessId
- PsGetProcessPeb
- PsLookupProcessByProcessId
- PsProcessType
- PsTerminateSystemThread
- RtlAppendUnicodeStringToString
- RtlAppendUnicodeToString
- RtlCaptureContext
- RtlCompareUnicodeString
- RtlDowncaseUnicodeChar
- RtlEqualUnicodeString
- RtlGetVersion
- RtlInitUnicodeString
- RtlRandomEx
- SeLocateProcessImageName
- ZwAllocateVirtualMemory
- ZwCreateFile
- ZwDeleteFile
- ZwDeleteValueKey
- ZwEnumerateKey
- ZwEnumerateValueKey
- ZwFreeVirtualMemory
- ZwOpenKey
- ZwProtectVirtualMemory
- ZwQueryDirectoryFile
- ZwQuerySystemInformation
- ZwQueryVirtualMemory
- ZwSetSystemInformation
- ZwTraceControl
Capability inferred per-API cluster:
| API cluster | Operational purpose |
|---|---|
| PsLookupProcessByProcessId + KeAttachProcess/KeDetachProcess | Attach the driver's execution context to any process by PID. Enables reading and writing another process's virtual memory from ring 0 without going through OpenProcess and without triggering the standard OpenProcess ACL check. |
| MmCopyVirtualMemory | Kernel-mode replacement for ReadProcessMemory and WriteProcessMemory. Bypasses handle-based ACLs. This is the primary read/write primitive used to read GTA5.exe game state and write the aimbot / ESP data feeds. |
| ZwProtectVirtualMemory | Change memory page protection on any target process. Used to make read-only game data writable (weapon damage values, spread constants) or to inject small trampoline shellcode into the target process address space. |
| ZwAllocateVirtualMemory + ZwFreeVirtualMemory | Allocate scratch pages in the target process for hook thunks and detour bodies. Cleanup on driver unload. |
| ZwQueryVirtualMemory + MmIsAddressValid + MmHighestUserAddress | Enumerate a target process's memory map safely without triggering an access violation. Used to scan for game-engine module bases. |
| ZwSetSystemInformation | Undocumented but well-known route to unlink the driver from PsLoadedModuleList so that PsLookupThreadByThreadId and toolhelp32 process enumerations do not see it. |
| ObQueryNameString + ObReferenceObjectByHandle + ObfDereferenceObject | Enumerate open kernel handles and dereference by handle. Used to identify target processes by name from the driver side rather than trusting the user-mode caller. |
| NtFsControlFile | IOCTL primitive. The driver serves IOCTL requests from the user-mode DLL over this same interface pattern. This is the driver-to-user IPC surface. |
| ZwEnumerateKey + ZwEnumerateValueKey + ZwDeleteValueKey + ZwOpenKey | Registry cleanup path. The driver walks and deletes registry entries related to its own driver service registration on unload. |
| ZwCreateFile + ZwDeleteFile + NtCreateFile + ZwQueryDirectoryFile | Filesystem primitives. Used to enumerate and delete files from kernel mode (the PCA anti-forensic list from the loader's config table is walked here rather than from user mode where an antivirus filter driver would see the deletes). |
| NtQueryEaFile + NtSetEaFile | Extended Attribute manipulation on NTFS. Extended Attributes are the standard covert-persistence surface (they survive most cleanup passes and are not walked by common EDR file-scanners). Presence of both a query and a set primitive indicates the driver reads and writes EA-hidden data. |
| SeLocateProcessImageName | Get the full image path of a process from a PROCESS pointer. Used to match target processes by full path rather than name only. |
| RtlGetVersion | Runtime OS version detection for per-build gadget selection. Different Windows builds require different KTHREAD/KPROCESS offsets. |
| RtlRandomEx | PRNG. Likely used to randomise the driver's device object name and symbolic link path on load so that consecutive loads produce a different \Device\ name. |
| KeQueryPerformanceCounter | High-resolution timer. Used for either per-request nonce material or to fingerprint timing-side-channel-based anti-analysis tools. |
| PsTerminateSystemThread | Clean driver worker-thread exit path on unload. |
BYOVD architecture confirmation
The driver is not signed with a WHQL cert (Susano does not have one and shipping it under someone else's cert would invalidate the whole product). The loader imports NtLoadDriver and NtUnloadDriver directly from ntdll, bypassing the Service Control Manager. On a machine with Driver Signature Enforcement (DSE) enabled, this driver cannot load on its own. The presence of ci.dll and WdFilter.sys references in the loader's string table (Code Integrity and Windows Defender's filter driver respectively) plus the direct-Nt driver-load path together indicate the loader carries or reaches for a signed third-party vulnerable driver that gets loaded first and abused to disable DSE or map Susano's own driver into memory unsigned. This is textbook BYOVD.
Complete feature inventory (76 config keys, 10 categories)
Every config key sitting in the user-mode DLL's .rdata string table. These are the exact toggle names the menu exposes to the paying user, grouped here by feature category. Every one of them is a live config key on Susano's shipping build.
- aimbot.enabled
- aimbot.drawfov
- aimbot.ignoreveh
- aimbot.peds
- aimbot.prediction
- aimbot.sticky
- aimbot.targetdead
- aimbot.visible
- aimbot.vsmooth
- silent.enabled
- silent.avoidrepeat
- silent.drawfov
- silent.highdmg
- silent.ignoreveh
- silent.magic
- silent.peds
- silent.prediction
- silent.sticky
- silent.targetdead
- silent.visible
- trigger.enabled
- trigger.ignoreveh
- trigger.noroll
- trigger.peds
- trigger.tap
- trigger.targetdead
- esp.armor
- esp.behind
- esp.box
- esp.distance
- esp.dynamic
- esp.friends
- esp.health
- esp.ignoreself
- esp.names
- esp.outlines
- esp.showpeds
- esp.skeleton
- esp.tracers
- esp.vehname
- esp.weapon
- vesp.nametags
- vesp.tracers
- player.antiaim
- player.antihs
- player.expmelee
- player.godmode
- player.incendiary
- player.invisible
- player.noclip
- player.nocol
- player.noragdoll
- player.nowanted
- player.semigod
- player.sjump
- player.solo
- player.stamina
- veh.autorepair
- veh.boost
- veh.bptires
- veh.engine
- veh.godmode
- veh.jump
- weapon.explosive
- weapon.infammo
- weapon.norecoil
- weapon.noreload
- weapon.nospread
- weapon.rapid
- act.armor
- act.heal
- act.revive
- act.rndclothes
- act.tpwp
- misc.adminlist
- misc.crosshair
- misc.streamproof
- misc.watermark
Notable individual toggles worth flagging
- misc.streamproof: the cheat menu is invisible to OBS, Discord screen share and any other tool that reads the framebuffer via the standard DWM path. Renders only into a compositor-hidden overlay. Any capture-based review of a Susano user misses the menu entirely.
- silent.magic: silent-aim with magic-bullet routing. Fires a bullet that visually leaves the muzzle in the player's aim direction but resolves the hit trace against the aimbot target. Bullet trajectory in the network packet points at the target regardless of the shooter's crosshair.
- silent.avoidrepeat: silent-aim will not lock onto the same target twice in a row within a short window, defeating the simplest server-side "same-target consecutive shots" statistical detection.
- silent.highdmg: pairs silent aim with a damage multiplier so kills happen in one shot regardless of weapon.
- trigger.tap: trigger bot fires a single shot per acquisition rather than holding the fire button. Defeats "held-mouse-during-headshot" replay analysis.
- player.antihs: nullifies incoming headshot damage on the local player. Server sees the shot land but the local damage handler skips the multiplier.
- player.expmelee: replaces the local player's melee hit with an explosive hit event. Any punch or kick delivered detonates on impact.
- player.solo: forces a solo session (kicks all other players from the current session). Used to griefer-clear a lobby before farming.
- act.tpwp: one-shot teleport-to-waypoint. Uses the waypoint blip as the destination.
- veh.bptires: vehicle bulletproof tires. Locks all four tire integrity values to max on read/write cycle.
- weapon.norecoil, weapon.nospread, weapon.rapid: recoil zeroing, spread zeroing and fire-rate override. Applied at the weapon-definition table pointer inside GTA5.exe, not per-shot.
- esp.behind: draws ESP through walls (default cheat setting, listed here for completeness).
- esp.dynamic: ESP scales dynamically with distance. Bones and health bars stay legible at range.
- esp.friends: friend-list carve-out (does not aim at or ESP-mark players tagged as friends in the menu).
- esp.ignoreself: obvious, but its presence in .rdata means the operator ships with this defaulted off in some build variants, which is a common menu bug to look for during live inspection.
Anticheat identifier table (17 named + UNKNOWN)
Susano's user-mode DLL carries an identifier table of 18 slots at file offset 0x63750. Slot 0 is the UNKNOWN fallback and slots 1 through 17 are FiveM anticheat names, adjacent in memory and padded to 8-byte or 16-byte boundaries. The identifier runs at cheat startup, scans the target FiveM server's loaded resources and script names, and writes back the matching slot index. A single cmp ecx, 17 bounds check at 0x43ebe gates the write.
| # | AC name | Notes |
|---|---|---|
| 0 | UNKNOWN | Fallback slot the identifier writes when scanning did not match any known AC. |
| 1 | Fiveguard | FiveM's own official anticheat surface (bundled with the client and enforced by CitizenFX). |
| 2 | FiniAC | FiveM community anticheat. |
| 3 | WaveShield | FiveM community anticheat. |
| 4 | PhoenixAC | FiveM community anticheat. |
| 5 | SecurGate | FiveM community anticheat. |
| 6 | ReaperAC | FiveM community anticheat. |
| 7 | ChocoHax | FiveM community anticheat. |
| 8 | Halavista | FiveM community anticheat. |
| 9 | AnvilAC | FiveM community anticheat. |
| 10 | ElectronAC | FiveM community anticheat. |
| 11 | Nb Anticheat | FiveM community anticheat. |
| 12 | Reason Anticheat | FiveM community anticheat. Also referenced twice from a byte-decoder function inside the DLL where its 16-byte name doubles as XOR key material. |
| 13 | Cyber Anticheat | FiveM community anticheat. |
| 14 | Putin Anticheat | FiveM community anticheat. |
| 15 | XeroShield | FiveM community anticheat. |
| 16 | Likizao | FiveM community anticheat. |
| 17 | SniffAC | FiveM community anticheat. |
No per-AC bypass module ships with Susano
We ran an exhaustive reference count over every AC name in the user-mode DLL. Only Reason Anticheat (2 refs, inside a byte-decoder that uses its 16 characters as XOR key material) and Likizao (1 ref, as part of the identifier's stack-array setup) get referenced by code at all. Cyber Anticheat, Putin Anticheat and the other 14 names have zero direct code references. There is no 18-slot function pointer table anywhere in the DLL and no cmp eax, N; je bypass_N switch cluster for values 0 through 17.
The bypass Susano ships is one universal ring-0 memory-manipulation surface, not seventeen. The identifier's output value is used only for the on-screen menu label ("Currently bypassing: Cyber Anticheat"). The actual bypass path is the same for every AC on the list: kernel driver attaches to GTA5.exe via KeAttachProcess, reads and writes the game's memory via MmCopyVirtualMemory, and hides its own driver object via ZwSetSystemInformation. Whichever AC is running gets its detection paths overwritten from ring 0 the same way. Because ring-0 memory reads bypass the OpenProcess ACL and page protections get reflowed via ZwProtectVirtualMemory, a user-mode community AC has no way to see the writes.
Practical takeaway: any FiveM server whose only server-side defence is one of these 17 anticheats has to assume Susano is invisible to it. Independent, kernel-side or process-external monitoring (event log state, PCA/BAM/Prefetch delta against a known-good baseline, unlisted \\Device\\ objects, unexpected PAGE_READWRITE flags on GTA5.exe's read-only sections) is the only surface that stays useful once Susano is on the client.
User-mode hook technique
Susano does not do inline patching of the GTA5.exe or adhesive.dll code pages. The user-mode DLL's IAT and the kernel driver's signature-scan engine together spell out a very deliberate hooking strategy that leaves the targeted code bytes untouched.
| Mechanism | Evidence and consequence |
|---|---|
| Hardware-breakpoint hooks via DR0-DR3 + SetThreadContext + SEH, not inline patching | User-mode DLL IAT carries the exact tuple SuspendThread, ResumeThread, GetThreadContext, SetThreadContext plus RtlCaptureContext, RtlLookupFunctionEntry, RtlVirtualUnwind plus SetUnhandledExceptionFilter. Notably absent: WriteProcessMemory into GTA5, VirtualProtect on foreign pages and FlushInstructionCache. No 0xE9 JMP trampoline bytes. This is the textbook hardware-breakpoint hook: the cheat writes target RIPs into DR0-DR3 with matching DR7 enable bits, catches STATUS_SINGLE_STEP in a vectored exception handler and swaps CONTEXT.Rip on the fault stack. Leaves ZERO bytes altered in the GTA5 or adhesive.dll image. Defeats FiveGuard code-page hash scans and Rockstar Arxan-style code guards because the code pages remain byte-identical to disk. |
| Kernel driver signature-scan engine (IDA-mask style) | Fourteen distinct 'x/?' mask literals inside the driver's obfuscated .\;d section, at offsets 0x6a10, 0x6fb0, 0x7190 and onward. Examples: 'x????xxxxxxxx????xxx????xxx', 'xxx????xxx????xx?????xxxx?????xxxxx????xxx', 'xxxx?xxxx?xxxx?xxxx?xxxxxxxxxxxxx', 'xxxxxx?xxx?xxx?xxx??xxxxxx?xxx?x????xx'. Each mask is a signature scan pattern with wildcards. This is how the driver resolves GTA5.exe function addresses and adhesive.dll internals without hardcoded offsets that break across game patches. |
FiveM in-process module targets
Loader offset 0x8ec060 carries a contiguous UTF-16 list of FiveM in-process DLL names. Immediately before it lie ntdll.dll and API-name strings GetModuleHandleA and NtQuerySystemInformation. That is the resolver stub the loader uses to walk the loaded-module list and match each name.
| Module | Role inside FiveM.exe |
|---|---|
| ntdll.dll | Root API resolver. GetModuleHandleA and NtQuerySystemInformation resolved from here. |
| adhesive.dll | FiveM's FiveGuard AC module. Loaded into every FiveM.exe process at startup. |
| vcruntime140.dll | Visual C++ runtime. Present as a dependency, not a hook target. |
| citizen-scripting-lua.dll | FiveM's Lua5.4 scripting host that runs client-side resource scripts. The Lua VM is where custom AC checks and anti-cheat callbacks live for many FiveM servers. |
| gta-net-five.dll | FiveM's networking backend replacement for Rockstar multiplayer. Hooking here lets the cheat modify network packets before they leave the client. |
| extra-natives-five.dll | FiveM's registrar for extra CFX_ / GET_ / SET_ natives on top of the R* native table. Hooking here neutralises server-side event handlers. |
| gta-streaming-five.dll | FiveM's streaming and resource loader override. Controls which server-side scripts get loaded on the client. |
| dxgi.dll | DirectX Graphics Infrastructure. Classic FiveM DLL-hijack point for menu rendering and the streamproof overlay path. |
GTA V engine data embedded in the user-mode DLL
The user-mode DLL carries a substantial static database of GTA V engine data. Bone-tag tables that drive the aimbot's target selection, weapon and weapon-component name tables that power the ESP labels and give-all-attach features, plus aim-cone and prediction floating-point constants, plus a very large table of GTA5.exe RVAs.
| Table | Offset in DLL | Contents and purpose |
|---|---|---|
| Aim-target bone table (16 entries) | User-mode DLL @ 0x64808 | Sixteen consecutive 4-byte slots holding GTA V ped-skeleton bone tags: 0x796E (SKEL_Head), 0x9995 (SKEL_Neck_1), 0xFCD9 (SKEL_Spine1), 0x29D2 (SKEL_Spine2), 0x60F2 (SKEL_Spine3), 0xDEAD (joke sentinel), 0x49D9, 0x58B7, 0xB1C5 (SKEL_R_UpperArm), 0x9D4D (SKEL_L_UpperArm), 0xE39F, 0xCA72, 0x796E (SKEL_Head repeats to bias the picker), 0x2E28 (SKEL_Pelvis), 0x3779, 0xCC4D. Followed by 4x 0x80000000 (-0.0f) sentinels. This is the aimbot's exact target-bone priority list. Head repeats to weight its selection twice. Presence of 0xDEAD is an attribution fingerprint. |
| Weapon menu label table (102 entries) with joke renames | User-mode DLL @ 0x63038 - 0x63670 | Indexed weapon labels used by the ESP 'Weapon' overlay and the menu weapon picker. Includes CS:GO joke renames: 'AWP' (index 0) is the Sniper Rifle, 'AWP MK II' is the Heavy Sniper MK II, 'M60' is the Combat MG and 'M60 MK II' is the Combat MG MK II. Also covers current-gen DLC weapons (Cayo Perico release): 'Candy Cane', 'Perico Pistol', 'WM29 Pistol', 'Precision Rifle', 'Compact EMP Launcher', 'Military Rifle', 'Tactical Rifle', 'TEC Pistol', 'Stone Hatchet', 'Navy Revolver'. Confirms the current build targets GTA V build 2802 or later. |
| Weapon-component asset name database (323 entries) | User-mode DLL @ 0x601F8..0x62F00 | Full alphabetical table of component_ hash-inputs. Every MK II camo variant 01-10 + ind_01, every clip variant (_clip_armorpiercing, _clip_fmj, _clip_hollowpoint, _clip_incendiary, _clip_tracer, _clip_explosive), every attachment (_at_scope_thermal, _at_scope_nv, _at_muzzle_01..09, _at_ar_supp, _at_pi_flsh_02, _at_ar_afgrip_02, and so on). Susano JOAAT-hashes each and feeds it to GIVE_WEAPON_COMPONENT_TO_PED for the 'give all attachments' feature. |
| Vehicle wheel bone-name table (24 entries) | User-mode DLL @ 0x64C10..0x64DC8 | wheel_lf, wheel_rf, wheel_lr, wheel_rr, wheel_lm1, wheel_rm1, wheel_lm2, wheel_rm2, wheel_lm3, wheel_rm3, wheel_f, wheel_r plus the wheel_[rl][fb][1-3]_dummy expansion for trailers and multi-axle rigs. Followed by three radius floats 15.0f / 255.0f / 1000.0f and eight uint32 wheel-bone indices {0x0B, 0x0C, 0x0D, 0x0F, 0x11, 0x12, 0x13, 0x15}. Powers veh.bptires, veh.autorepair and the 'Burst Tires' primitives. |
| Aim-cone and prediction constants | User-mode DLL @ 0x647E0 | Block A floats: 0.01f (delta), 0.017453292f (PI/180 = DEG_TO_RAD), 0.5235988f (PI/6 = 30 degrees), 1.3089969f (75 degrees = plausible max aim cone), 2.0f, 60.0f, 120.0f, 320.0f. Block B at 0x64B70: 1e-4, 4e-4, 1e-3, 4e-3, 1.6e-2, 0.1f, 0.3f, 0.7f, 0.9f, 5.0f, 6.2831854f (2*PI), 7.0f, 12.0f, 200.0f, 540.0f, 628.3185f (100*2*PI), 960.0f, 1e6, 1e9, FLT_MAX, -1.0f, -2.0f, 0.74f, 3.1415927f (PI). These power aimbot.drawfov, silent.prediction and aimbot.vsmooth. |
| 4614-slot GTA5.exe RVA table (3841 unique values) | User-mode DLL @ 0x64DC8 to 0x2947F0 | Very large post-.rdata table of 16-byte cells each holding one uint32. 3841 unique values in the range 1..0x4F73020 (roughly 1..83.5 MB, matches GTA5.exe binary size). Structure resembles a serialized std::unordered_set<uint32_t>. Interspersed 8-byte bucket hashes at every ~16 entries (0xA352C1B864CAFD33, 0x6DB47AA77FD94E09, 0x07503F7948F491A7, 0x6BC97F4F4BB3C04B, 0x39FF19C64EF7DA5B). One of the largest hardcoded RVA sets in any GTA V cheat. Candidate uses: hook target addresses, scan blacklist, anti-cheat scanner block list, or every native handler entry the cheat wants to redirect. |
Build GUIDs
Two 16-byte GUIDs live inside the Susano binaries as raw byte constants (not documented Microsoft interface or CLSID values). Both are candidate build fingerprints or product namespace UUIDs.
| Role | GUID | Location and notes |
|---|---|---|
| Loader GUID | {6F15AAF2-D208-4E89-9AB4-489535D34F9C} | Sits at loader offset 0x8eb940 at the head of the crypto-constant block, immediately before the SHA-256 IV block and AES SBox. Loaded together with the tables. Not a documented Microsoft interface/CLSID. Almost certainly a Susano build/product GUID used either as a namespace UUID for hashing HWID into a license key or as a mutex/registry-key name. |
| Kernel driver GUID | {54DEA73A-ED1F-42A4-AF71-3E63D056F174} | At driver offset 0x76a0 (VA 0x1400082a0), directly before the FiveM/GTA5 wildcards. Almost certainly the profile/target ID the driver quotes when it reports matches back to user mode. Pivot for correlating kernel telemetry with a specific driver build. |
Crypto constants and hash tables
Beyond the AES SBox / InvSBox / RCON block, the loader carries a second, independent hash surface: full SHA-256 round constants, three copies of the SHA-256 initial IV and an encrypt-and-hash-only Windows CryptoAPI import stack that does NOT include CryptDecrypt.
| Constant / import | Location | What it is used for |
|---|---|---|
| SHA-256 K round constants (256 B) | Loader @ 0x8ebba0 | Standard K[0]..K[63] words, byte-perfect canonical values. Placed right after the AES SBox/InvSBox/RCON block. Proof the loader ships its own inline SHA-256 rather than always going through CryptHashData. |
| SHA-256 IV (H0..H7, 32 B) | Loader @ 0x8eb970, 0x8f5120, 0x980f10 | Three copies in .rdata. Copy #3 sits next to a wall of anti-debug and dynamically-resolved API name strings (NtQueryInformationProcess, TerminateProcess, DbgBreakPoint, kernel32.dll, user32.dll, Advapi32.dll). That co-location fingerprints copy #3 as the seed for an API-name-hash resolver. Classic obfuscation where SHA-256("NtQueryInformationProcess") indexes an IAT slot. |
| Full CryptoAPI import stack (10 fns, no CryptDecrypt) | Loader ADVAPI32 IAT | CryptAcquireContextW, CryptReleaseContext, CryptGenRandom, CryptGetHashParam, CryptCreateHash, CryptHashData, CryptDestroyHash, CryptDestroyKey, CryptImportKey, CryptEncrypt. Notably no CryptDecrypt, no BCrypt, no NCrypt. Encrypt-and-hash-only surface. This is NOT the AES-256-CBC wire cipher (that is inline in the runtime-decrypted VM, keyed by REQ[0:32]). This second CryptoAPI stack is a separate signing/hashing surface used for HWID digest and per-request nonce sealing. |
Anti-analysis probe (XOR-hidden)
The loader carries exactly one XOR-obfuscated string in its whole 10.3 MB image. That string is a registry key path used specifically to check for the presence of a reverse-engineering tool.
| Finding | Detail |
|---|---|
| IDA Pro history registry key check (XOR-obfuscated) | The single XOR-obfuscated string in the loader lives at 0xc4de5. 31 bytes that decode with a byte-wise XOR against 0xd1 to the literal string 'Software\Hex-Rays\IDA\History64'. This is the HKCU key IDA writes to every time an analyst opens a database, so its presence on a machine is a strong tell that the machine has ever had IDA Pro installed. The loader queries it as an active anti-analysis probe. Legitimate paying customers do not have this key. Expected behaviour on hit is a silent bail-out or degraded execution. |
| Hardcoded 32-bit XOR key 0x56D7BB80 for a single 'susano'-tagged blob decoder | At loader offset 0xc4e50: instruction bytes '81 33 80 BB D7 56' (xor dword ptr [rbx], 0x56D7BB80). Occurs exactly once in the whole 10.3 MB loader. Data header at 0xc4dc0 carries a magic (0x88A1F3F228), a length field (0x1F = 31), the tag 'susano\0', and 31 encrypted bytes. The IDA-history probe above is the plaintext that this loop produces (the byte-level XOR 0xd1 is a byte-projection of the 32-bit constant 0x56D7BB80 as it iterates). One decoder, one obfuscated string. |
Loader network stack (beyond plain HTTPS)
The Susano loader ships a much larger client-side network toolkit than a simple HTTPS beacon needs. Everything in the table below is byte-verified against the loader's .rdata and IAT.
| Capability | Location | What it means |
|---|---|---|
| DoH (DNS-over-HTTPS) | Loader @ 0x9848c6 and 0x9848e0 | Full DoH client stack. Content-Type 'application/dns-message' and marker 'DoH AAAA:'. URL-safe base64 alphabet ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_') stored adjacent, which is specifically the encoding for wire-packet-in-GET-URL DoH requests. Means the operator can resolve susano.gg / susano.re / vps93241.serveur-vps.net via public DoH resolvers (Cloudflare 1.1.1.1, Google 8.8.8.8, Quad9) with only application/dns-message packets on the wire. Any defence that inspects OS DNS but not TLS SNI to third-party resolvers misses the C2 lookup. |
| HTTP/2 and HTTP/3 ALPN | Loader @ 0x981a70 | Bytes '68 31 00 00 68 32 00 00 68 33 00 00' pack the three ALPN identifiers 'h1', 'h2', 'h3' back-to-back. The canonical TLS ALPN offer list. Loader can negotiate HTTP/2 (multiplexed over TLS) and HTTP/3 (QUIC over UDP/443). Any hunt that only inspects TCP/443 HTTP/1.1 misses the QUIC leg entirely. |
| HAPPY-EYEBALLS dual-stack racing | Loader @ 0x981980 | Libcurl Happy Eyeballs implementation. Loader races IPv4 vs IPv6 for the C2 hosts and takes whichever answers first. If IPv6 is available to susano.gg the loader may prefer it and the IPv4 defender egress rule is bypassed. |
| HSTS persistent store | Loader @ 0x981b10 | Full HSTS parser and disk-persist writer. Format string '%10s %512s %u %10s %512s %u "%64[^"]" %u %u' at 0x981a80 with 'clear', 'ma', 'persist', 'max-age=', 'includesubdomains' keywords. Once the loader has talked to susano.gg over HTTPS, the HSTS pin is remembered on disk across process launches, which defends the C2 channel against SSL-strip MITM and leaves an on-disk libcurl HSTS cache file as an IOC. |
| SOCKS proxy support | Loader IAT | Full SOCKS4 / SOCKS4a / SOCKS5 / SOCKS5h client stack plus env-var honoring: 'ALL_PROXY', 'HAPROXY', 'HTTP-PROXY', 'SOCKS-PROXYY' along with 'socks4', 'socks4a', 'socks5', 'socks5h' scheme names and 'http_proxy', 'all_proxy', 'no_proxy' env keys. Operator can route the beacon through a chosen SOCKS5 hop and defeat egress-IP-based blocklists. |
| Raw Winsock 2 surface (bind/listen/accept) | Loader WS2_32.dll IAT | Beyond the HTTP client surface the loader imports the full raw Winsock 2 API: bind, listen, accept, select, WSAEventSelect, WSAWaitForMultipleEvents, WSAEnumNetworkEvents plus the async event stack. Means the loader can also RECEIVE inbound connections (server sockets), do non-blocking multi-socket I/O and speak arbitrary raw TCP/UDP. Not consistent with a plain HTTP downloader. |
| AWS SigV4 / S3 signer wired end-to-end | Loader @ 0x984bca..0x984c60 | Not merely a format-string template. Real strings 'aws:amz', '%s4-HMAC-SHA256', '%s4_request', 'UNSIGNED-PAYLOAD', 'x-%s-content-sha256: %s' assembled by an actual signer. Loader is capable of arbitrary S3 PUT/GET with the correct credentials, meaning any customer-supplied AWS key pair could exfil to an S3 bucket the operator does not have to own. |
Persistence and driver install path
How the loader stores its own state and installs the kernel driver. Every string in the table below is byte-verified in the loader binary.
| Mechanism | Evidence |
|---|---|
| HKLM\Software\Microsoft\Windows\CurrentVersion\DevicePath\Configuration (with AdapterConfig value) | The full ASCII path lives at loader offset 0x8ebfca with 'AdapterConfig' at 0x8ebfe8. This is not a legitimate Windows key. Real Windows has a 'DevicePath' REG_EXPAND_SZ VALUE under Setup, not a DevicePath\Configuration SUBKEY. The extra depth plus the AdapterConfig sibling is attacker-created and masqueraded under a Microsoft-shaped path. Loader imports RegCreateKeyExA/W, RegSetValueExA, RegDeleteTreeW and RegSetKeyValueW. Full read/write/tree-delete on this subtree. |
| Driver drop path %s.%s.tmp under %TEMP% | Format string '%s.%s.tmp' at loader offset 0x9847d0 combined with GetTempPathW / GetTempPath2W imports. The .sys file is written to %TEMP%\<rand>.<rand>.tmp. Not a normal service ImagePath. Volatile, non-obvious drop location for a kernel driver. |
| Native SCM-bypass driver install via NtLoadDriver against \Registry\Machine\System\CurrentControlSet\Services\ | Wide strings back-to-back at 0x8f4f00..0x8f5150: 'SYSTEM\CurrentControlSet\Services\', '\??\', 'ImagePath', 'Type', plus imports RtlAdjustPrivilege, NtLoadDriver, NtUnloadDriver. The loader writes the service key directly into the registry hive and calls NtLoadDriver bypassing sc.exe / CreateServiceW / the SCM entirely. Presence of 'ci.dll' string in the same wall implies a Code Integrity / DSE bypass path. RtlAdjustPrivilege(0x14, TRUE, ...) enables SeLoadDriverPrivilege before the Nt call. |
| User-mode execution-history wipe: UserAssist ROT13 Count + MuiCache | UTF-16 strings 'Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist' at 0x8eb410, '\Count' immediately after, and 'Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache' at 0x8eb522. The \Count subkey is where UserAssist stores ROT13-encoded launched-program names. User-mode complement to the driver's kernel-mode BAM/AppCompat/ComDlg32/Prefetch wipe. Any defender who checks UserAssist and MuiCache for evidence of Setup_1.exe execution finds nothing. |
| Full DOS paths for PCA files carried by loader (not just driver) | UTF-16 absolute paths in the loader config table at 0x8eb690: C:\Windows\appcompat\pca\PcaAppLaunchDic.txt, C:\Windows\appcompat\pca\PcaGeneralDb0.txt, C:\Windows\appcompat\pca\PcaGeneralDb1.txt. Confirms a dual-mode user-mode + kernel-mode attack on PCA. User-mode can only touch these once PcaSvc has released its handle, which is why the service kill list stops PcaSvc first. |
Driver targets (FiveM / GTA5 surface)
Every FiveM-specific string embedded in the kernel driver, extracted verbatim from its UTF-16 string table. The driver walks target processes with kernel-mode wildcards (FsRtlIsNameInExpression) and reads or writes the FiveM asset files below directly from ring 0.
| Target string | What it is / how it is used |
|---|---|
| *\GTA5.EXE | FsRtlIsNameInExpression wildcard. The driver identifies GTA5's process image by name, walking every EPROCESS to find it. |
| *\FIVEM*PROCESS.EXE | Wildcard that matches every FiveM*.exe helper process (FiveM.exe, FiveM_b*.exe and the game process itself). |
| *\FIVEM*CHROMEBROWSER | Wildcard that matches the CEF-based Chrome browser helper FiveM ships for its in-game UI. |
| manifest.fingerprint | FiveM's runtime manifest integrity file. Modifying this on disk defeats the file-hash check FiveM performs on its own components at load. |
| font_lib_cfx.gfx | CitizenFX-branded font library file. Presence of this string alongside game-file paths shows the driver knows exactly which FiveM assets to touch. |
| launcher_skip_mtl2 | FiveM launcher flag. Skipping the MTL2 (Rockstar launcher) path lets FiveM start without the parent launcher and its checks. |
| game_files.dat | FiveM's game-file database on disk. |
| fivem_set.bin | FiveM's settings/config binary. |
| nvAppTimestamps | NVIDIA per-application timestamp cache. Cleaning this removes evidence that GTA5/FiveM launched from the graphics driver's own logs. |
| nvlddmkm.sys | NVIDIA display driver. Referenced but not obviously abused, likely used to locate the graphics driver for the streamproof rendering path. |
| win32kfull.sys | Windows graphics kernel. Same GUI-side involvement (menu-render invisibility hooks). |
| clipc.dll | Client License Server Runtime (Windows SPP). Presence here likely relates to the loader's own license/HWID check bypass path, not the game. |
| \PCI, \pci, \USB#, ACPI, \??\PhysicalDrive | Hardware bus enumeration paths. The driver walks these to build its HWID fingerprint independently from what the loader collects. |
| \MMDevices\Audio, Desktop\MuiCached | Audio device enumeration and UI cache. Same fingerprint-collection surface. |
Driver internals (kernel data structures)
The driver names five kernel data-structure or function primitives in its own string table beyond its 52-API import list. Each name gives away one specific ring-0 capability the driver reaches for at runtime rather than statically imports.
| Name | Purpose in a ring-0 cheat |
|---|---|
| KeCapturePersistentThreadState | Referenced string. This function name suggests the driver walks or manipulates persistent-thread state, either to hide its own worker thread or to enumerate other threads for injection targeting. |
| HalPrivateDispatchTable | HAL private dispatch table. Reading this table is a well-known trick for finding undocumented kernel routines. The driver's presence of the string suggests it resolves at least one internal function through the HAL dispatch. |
| Circular Kernel Context Logger | The name of a specific ETW logger. Naming it explicitly means the driver looks for or manipulates that logger (either to disable it, redirect it or hide its own writes to it). |
| FsRtlIsNameInExpression | Kernel filename wildcard matcher. Combined with the FIVEM/GTA5 wildcards, this is the primitive the driver uses to identify target processes by name. |
| ProbeForRead / ProbeForWrite | Standard kernel-mode primitives for validating user-mode pointers passed through the IOCTL surface. Their presence confirms the driver has a real IOCTL handler that accepts user pointers. |
Driver anti-forensic surface
The loader's anti-forensic story is only half the picture. The kernel driver ships its own, larger cleanup path that runs from ring 0 and touches sources the user-mode loader cannot reach without a filter-driver conflict. Every entry in the table below is a verbatim string in the driver's UTF-16 table.
| Target | What it is |
|---|---|
| \??\C:\Windows\Prefetch\ | Windows Prefetch directory. .pf files record every program execution and their timestamps. The driver deletes them from kernel mode, bypassing any user-mode file-system filter driver. |
| \Registry\Machine\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings | Background Activity Moderator (BAM). Windows records every foreground application launch here per user SID. Cleared from ring 0 so no user-mode audit process sees the delete. |
| \Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Store | AppCompat Store. A second application-execution history registry key beyond BAM. |
| \Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU | Explorer's Open/Save dialog MRU list. Removing this hides any recent file-selection evidence. |
| MRUListEx | Generic Most Recently Used list value. Cleared alongside the ComDlg32 MRU. |
| PcaAppLaunchDic.txt, PcaGeneralDb0.txt, PcaGeneralDb1.txt (kernel-mode) | The same PCA files the loader deletes from user mode also get a kernel-mode delete pass from the driver, so any file-system minifilter that would have blocked the user-mode delete gets bypassed. |
Full execution-history wipe
Between the loader's user-mode kill list and the driver's kernel-mode cleanup, Susano covers every routine Windows source of program-execution history. Event Log (services stopped), PCA text files (both user-mode and kernel-mode delete passes), BAM registry (kernel-mode registry delete), AppCompat Compatibility Assistant Store, Explorer ComDlg32 MRU and the Prefetch directory. Any post-hoc review that expects to reconstruct which .exe ran on the machine at what time will come up empty.
Driver IOCTL surface
Seven distinct IOCTL codes appear as 32-bit constants in the driver's .text and .rdata sections, all in the FILE_DEVICE_UNKNOWN (0x22) device family. This is the user-mode-to-kernel-mode command surface the DLL uses to issue reads, writes, process attaches and cleanup requests. Function codes reconstructed from the raw CTL_CODE encoding.
| IOCTL code | Interpretation |
|---|---|
| 0x22220008 | Small function code (fn=0x2, METHOD_BUFFERED, unprivileged access). Likely a driver health-check or handshake IOCTL the user-mode DLL calls first. |
| 0x22220200 | fn=0x80. Larger operation index, plausibly the process-attach primitive (open target by PID). |
| 0x22220600 | fn=0x180. Read primitive candidate (target-process memory read via MmCopyVirtualMemory). |
| 0x22220cb4 | fn=0x32d. Write primitive candidate (target-process memory write). |
| 0x22220dba | fn=0x36e, METHOD_NEITHER access mode. The METHOD_NEITHER selection means the caller passes raw pointers, indicative of a bulk-copy operation. |
| 0x22221500 | fn=0x540. Anti-forensic driver-side cleanup trigger (PCA delete / BAM wipe). |
| 0x22222200 | fn=0x880. Second cleanup or driver-hide IOCTL (unlink from PsLoadedModuleList). |
IOCs
| Type | Value | Notes |
|---|---|---|
| Domain | susano.gg | Primary Susano C2, Cloudflare-fronted, PHP backend on the origin. |
| Domain | susano.re | Fallback C2. Present in the config table. |
| Domain / Origin host | vps93241.serveur-vps.net | Direct VPS origin (French VPS provider). Bypasses Cloudflare. Present in config. |
| Cloudflare IPs | 104.26.15.100, 172.67.70.156, 104.26.14.100 | DNS answers for susano.gg |
| Endpoint | POST /v2/oauth.php | Handshake / session establishment. 176-byte binary request, 112-byte binary response. |
| Endpoint | POST /v2/buffer.php | Payload delivery (the current second-stage path, replaced /v2/download.php in the three newer builds). 640-byte binary request, 5,648,480-byte binary response containing the user-mode DLL + kernel driver. |
| Endpoint (legacy) | POST /v2/download.php | Original payload delivery. Still present as a 200-empty-body honeypot on newer builds. Setup.exe (original) used this path. |
| HTTP header | User-Agent: SusanoUA/1.0 | Constructed at runtime, never stored plaintext in the binary |
| HTTP header | Content-Type: application/x-www-form-urlencoded (with a raw binary body) | Format mismatch is deliberate obfuscation against casual IDS or WAF pattern matches |
| File | SHA-256 65922561c8304fadf5d01c50ca7375f9b2b8afbd2aebac4202657b930d214558 | Setup.exe (original build, HWID-locked) |
| File | SHA-256 4c43f0b310b960623002a60d53f5462fc8595b95c0004adae3118f5edfecea8f | Setup_1.exe (2026-07-15 build, no HWID lock, successfully delivered second-stage payload). 10,796,624 bytes. |
| File | MD5 111bb3f93444d8e873e0b11b0dec2275 | Setup.exe (original build) |
| File | SHA-256 cd88aa1dd8b4f59c5dfaaf47d0622de698d7b507cc182d34a8cd2282129d815c | Susano user-mode cheat DLL (delivered as the first 2.58 MB of the /v2/buffer.php response after decryption) |
| File | SHA-256 0aeba1809df1792d36861b70120c2ec5d79aeb978c1c11eb71610b9752557bfb | Susano kernel driver .sys (delivered as bytes 0x294850-0x554fb0 of the /v2/buffer.php response after decryption). Native subsystem, x86-64, 2.81 MB, 52 ntoskrnl imports. |
| Config marker | The exact ASCII sequence `susano.re\0\0\0\0\0\0\0susano.gg\0\0\0\0\0\0\0vps93241.serveur-vps.net\0` | 16-byte-aligned adjacent domain strings in .rdata. Very distinctive marker for the whole Susano family |
| Config marker (payload) | The exact ASCII cluster `esp.armor` + `esp.behind` + `esp.box` + `esp.distance` + ... in adjacent 16-byte-null-padded slots (see feature inventory above) | The 76 config-key names in the user-mode DLL. Unique to Susano's build. Key-name overlap with any other cheat family is unlikely and any presence of `silent.magic` + `silent.highdmg` + `silent.avoidrepeat` together is a Susano-specific signature. |
| Config marker (payload) | The four ASCII strings `Cyber Anticheat`, `Nb Anticheat`, `Putin Anticheat`, `Reason Anticheat` present together | Anticheat-bypass menu labels. Any cheat DLL containing all four is Susano. |
| Service kill-list | PcaSvc, DPS, DiagTrack, Dnscache, EventLog | Comma-listed here, but adjacent in .rdata at 0x8eb7ec-0x8eb818 as null-padded ASCII |
| PCA delete-list | PcaAppLaunchDic.txt, PcaGeneralDb0.txt, PcaGeneralDb1.txt (UTF-16LE) | At 0x8eb690 and 0x8eb750. The three PCA files hold Windows program-launch history that a forensic sweep would grep |
| Behaviour | NtLoadDriver / NtUnloadDriver imported directly from ntdll | Kernel-driver capability. Confirmed BYOVD (Bring Your Own Vulnerable Driver) chain. Susano's own driver is delivered by /v2/buffer.php and is not code-signed. |
| Behaviour | OpenProcessToken / DuplicateTokenEx / SetThreadToken / SetTokenInformation | Token manipulation for process impersonation and TCB acquisition |
| Behaviour | AWS SigV4-style Authorization: %s4-HMAC-SHA256 Credential=%s/%s, SignedHeaders=%s, Signature=%s template in loader .rdata | Loader carries an AWS Signature V4 code path plus SASL mechanism strings (CRAM-MD5, DIGEST-MD5, SCRAM-SHA-1, SCRAM-SHA-256, SHA-512-256-SESS). Either dead code from a bundled HTTP library or an alternate authentication surface used for a non-observed endpoint. |
| Session identifier (observed) | userID 17943118 (server-assigned) | Server-assigned integer user ID returned on the first oauth call from a new HWID. Used as the u= field in the /v2/buffer.php request. Sequential numbering means the total Susano user population is inferable from an ID rotation observed over time. |
| Driver process wildcard | *\GTA5.EXE (UTF-16LE) | FsRtlIsNameInExpression wildcard the kernel driver uses to identify the GTA V game process by name. |
| Driver process wildcard | *\FIVEM*PROCESS.EXE (UTF-16LE) | Wildcard covering every FiveM helper .exe. |
| Driver process wildcard | *\FIVEM*CHROMEBROWSER (UTF-16LE) | Wildcard covering FiveM's CEF-based Chrome browser helper. |
| Driver-target file | manifest.fingerprint, game_files.dat, fivem_set.bin, font_lib_cfx.gfx (UTF-16LE) | FiveM asset files referenced by name in the kernel driver. Driver reads and can modify them from ring 0. |
| Driver-target file | launcher_skip_mtl2, nvAppTimestamps (UTF-16LE) | FiveM launcher flag file and NVIDIA per-app timestamp cache. Same driver-side reach. |
| Driver anti-forensic path | \??\C:\Windows\Prefetch\ (UTF-16LE) | Prefetch directory. The driver wipes .pf files from ring 0. |
| Driver anti-forensic registry | \Registry\Machine\SYSTEM\CurrentControlSet\Services\bam\State\UserSettings (UTF-16LE) | Background Activity Moderator user settings. The driver clears the BAM record of the loader from ring 0. |
| Driver anti-forensic registry | \Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Store (UTF-16LE) | AppCompat Compatibility Assistant Store. Cleared alongside BAM. |
| Driver anti-forensic registry | \Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU and MRUListEx (UTF-16LE) | Explorer Open/Save dialog MRU list. Cleared to hide file-picker history. |
| Driver IOCTL surface | 0x22220008, 0x22220200, 0x22220600, 0x22220cb4, 0x22220dba, 0x22221500, 0x22222200 | Seven distinct IOCTL codes in the FILE_DEVICE_UNKNOWN family. User-mode DLL to kernel driver command surface. |
| Driver kernel targets | KeCapturePersistentThreadState, HalPrivateDispatchTable, Circular Kernel Context Logger, FsRtlIsNameInExpression (UTF-16LE) | Kernel data structures and functions named in the driver's string table beyond its 52-API static import list. Each name is a specific ring-0 capability the driver reaches for at runtime. |
| Driver-loaded module refs | nvlddmkm.sys, win32kfull.sys, clipc.dll (UTF-16LE) | System modules the driver locates by name. NVIDIA display driver and Windows graphics kernel are the two obvious targets for the streamproof rendering path. |
| Driver hardware enumeration | \PCI, \pci, \USB#, ACPI, \??\PhysicalDrive, \MMDevices\Audio, Desktop\MuiCached (UTF-16LE) | Bus/device enumeration paths. Driver builds its own hardware fingerprint independent of the loader. |
| User-mode AC identifier table | 18 entries at DLL offset 0x63750 (UNKNOWN, Fiveguard, FiniAC, WaveShield, PhoenixAC, SecurGate, ReaperAC, ChocoHax, Halavista, AnvilAC, ElectronAC, Nb Anticheat, Reason Anticheat, Cyber Anticheat, Putin Anticheat, XeroShield, Likizao, SniffAC) | Adjacent null-padded ASCII slots. Cmp ecx, 17 bounds check at 0x43ebe writes the identifier index. Only Reason Anticheat (2 refs, XOR key material) and Likizao (1 ref) get code references. No per-AC bypass module ships. |
| Loader GUID | {6F15AAF2-D208-4E89-9AB4-489535D34F9C} | Raw bytes at loader offset 0x8eb940. Not a Microsoft interface or CLSID. Almost certainly a build/product GUID. |
| Kernel driver GUID | {54DEA73A-ED1F-42A4-AF71-3E63D056F174} | Raw bytes at driver offset 0x76a0, immediately before FiveM/GTA5 wildcards. Candidate profile/target ID. |
| Anti-analysis probe (XOR-obfuscated) | 31-byte ciphertext at loader offset 0xc4de5, XOR each byte with 0xd1 -> 'Software\Hex-Rays\IDA\History64' | The only XOR-obfuscated string in the loader. Actively probes for IDA Pro installation on the target. |
| Loader driver-install format | '%s.%s.tmp' at loader offset 0x9847d0 | Format used to build the %TEMP% path where the .sys is dropped before NtLoadDriver. |
| Loader anti-forensic wipe target (registry) | Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist (UTF-16 at loader 0x8eb410) + \Count sibling + MuiCache path at 0x8eb522 | User-mode complement to the driver's kernel-mode BAM/AppCompat/ComDlg32/Prefetch wipe. |
| Loader custom persistence key | HKLM\Software\Microsoft\Windows\CurrentVersion\DevicePath\Configuration with AdapterConfig value (ASCII at loader 0x8ebfca / 0x8ebfe8) | Attacker-created subkey masqueraded under a Microsoft-shaped path. Real Windows only has a DevicePath REG_EXPAND_SZ value. |
| Loader network stack extras | DoH ('application/dns-message' at 0x9848c6, 'DoH AAAA:' at 0x9848e0), HTTP/2+HTTP/3 ALPN ('h1'\0\0'h2'\0\0'h3'\0\0 at 0x981a70), HAPPY-EYEBALLS at 0x981980, HSTS 'includesubdomains' at 0x981b10, socks4/socks4a/socks5/socks5h, AWS SigV4 'aws:amz' + '%s4-HMAC-SHA256' + 'UNSIGNED-PAYLOAD' | Beyond a plain HTTPS beacon. Enables DoH-hidden C2 lookup, QUIC exfil, dual-stack racing, HSTS pinning on disk, SOCKS relaying and S3 exfil signing. |
| User-mode hook technique | SuspendThread + ResumeThread + GetThreadContext + SetThreadContext + SetUnhandledExceptionFilter in the user-mode DLL IAT | Hardware-breakpoint hooking via DR0-DR3. Leaves ZERO bytes altered in GTA5.exe or adhesive.dll. Defeats code-page hash scans. |
| User-mode aim-target bone table | 16 uint32 slots at DLL offset 0x64808 with bones 0x796E, 0x9995, 0xFCD9, 0x29D2, 0x60F2, 0xDEAD, 0x49D9, 0x58B7, 0xB1C5, 0x9D4D, 0xE39F, 0xCA72, 0x796E, 0x2E28, 0x3779, 0xCC4D | Aimbot target-bone priority list. Head (0x796E) repeats to weight its selection. Joke 0xDEAD sentinel. |
| User-mode weapon menu joke renames | 'AWP' at 0x63038, 'AWP MK II', 'M60', 'M60 MK II' | CS:GO joke labels for Sniper Rifle and Combat MG. Fingerprint for attribution. |
| User-mode weapon-component database | 323 component_ names at DLL offset 0x601F8..0x62F00 | Full GTA V weapon-component asset name enumeration including MK II camos, clip variants, attachments, plus Cayo Perico DLC weapons. Confirms build 2802+ support. |
| User-mode GTA5.exe RVA table | 4614 slots (3841 unique 32-bit values) at DLL offset 0x64DC8..0x2947F0, values range 1..0x4F73020 | Very large hardcoded RVA set. One of the largest observed in any GTA V cheat. Candidate uses: hook target list, scan blacklist, native handler redirect table. |
| Kernel driver signature scan masks | 14 unique 'x/?' mask literals in driver .\;d section at 0x6a10, 0x6fb0, 0x7190 and onward | IDA-style signature-scan engine. Driver locates GTA5.exe function addresses by pattern rather than absolute offset. |
| Loader SHA-256 constants | K round constants (256 B) at 0x8ebba0, H0-H7 IV at 0x8eb970 / 0x8f5120 / 0x980f10 | Full SHA-256 inline. Copy #3 is next to anti-debug and API-name strings, suggests an API-name-hash resolver seeded from the IV. |
| Loader CryptoAPI import set | CryptAcquireContextW, CryptReleaseContext, CryptGenRandom, CryptGetHashParam, CryptCreateHash, CryptHashData, CryptDestroyHash, CryptDestroyKey, CryptImportKey, CryptEncrypt | Encrypt-and-hash-only. No CryptDecrypt. Second cipher surface separate from the AES-256-CBC wire cipher. |
Detection kit (v1 + v2)
Two tiered detection kits for AC operators. Every rule is anchored on multi-signal AND-chains keyed on byte-perfect Susano-branded literals so no legitimate software, Microsoft component, OEM installer, EDR agent, anti-cheat driver or unrelated malware family can trigger them. Both kits run entirely server-side inside Clubhouse AC. The v1 and v2 scanner binaries ship with no indicator data and no rule content, so anyone reverse-engineering the client cannot enumerate what is being matched. The scanner uploads raw evidence to the Clubhouse AC evidence pipeline; the server performs all rule evaluation and returns only the matched detection IDs used to drive follow-up scans and the user report.
v1 kit (broad, easy deployment)
Runs on any FiveM AC or community server with commodity tooling: YARA on-disk scans, Sysmon plus Sigma / KQL for endpoint telemetry, Suricata for HTTP inspection, PowerShell for live-host triage. Uses only signals available without a kernel driver: on-disk PE bytes, registry keys, filesystem paths, standard Sysmon events and cleartext HTTP metadata. Anchor set: SusanoUA/1.0, /v2/oauth.php plus /v2/buffer.php, susano.gg plus susano.re plus vps93241.serveur-vps.net, the .\\;d section name, the DevicePath\\Configuration\\AdapterConfig masquerade and the loader / driver / DLL SHA-1 hashes.
v2 kit (deep, kernel-side or endpoint agent)
Adds compile-time layout fingerprints (static config table adjacency, 5-service kill list packed within a 48-byte window, aim-bone table with the 0xDEAD sentinel), kernel-mode image-load callbacks that gate on .\\;d plus the three FiveM wildcards plus 4-of-7 Susano IOCTLs plus the driver GUID plus 3+ anti-forensic registry references, memory-carved rules for the zeroed-MZ user-mode DLL, byte-perfect AES KEY|IV|MASK 64-byte prefix matching per build, Zeek long-poll cadence rules, and multi-signal SIEM correlations that fuse loader execution + 5-service kill-burst + susano host resolution inside a 60-second window. Similarity hashing (SSDeep / TLSH) is gated by a static-string requirement so entropy collisions on unrelated large installers cannot trigger.
Primary YARA rule (v1 broad), keyed on the co-occurrence of the Susano-branded User-Agent, both v2 endpoints and one of three strong anchors:
import "pe"
rule Susano_Loader_Family_v1_Broad
{
meta:
family = "Susano"
component = "loader"
variant = "v1_broad"
description = "Susano loader dropper family (Setup.exe / Setup1.exe / Setupuptodate.exe / Setup_1.exe). Requires three orthogonal signals: (a) Susano User-Agent, (b) both v2 endpoints, (c) either the masqueraded persistence key or the XOR-obfuscated IDA anti-analysis blob."
imphash = "89279bc839f47ce69afbd562c3637253"
strings:
$ua = "SusanoUA/1.0" ascii fullword
$ep_oauth = "/v2/oauth.php" ascii
$ep_buffer = "/v2/buffer.php" ascii
$reg = "Software\\Microsoft\\Windows\\CurrentVersion\\DevicePath\\Configuration" ascii
$reg_val = "AdapterConfig" ascii fullword
// 31-byte 0xD1-XORed IDA history path constant at loader offset 0xc4de5
$xor_ida = { 82 BE B7 A5 A6 B0 A3 B4 8D 99 B4 A9 FC 83 B0 A8 82 8D 98 95 90 8D 99 B8 82 A5 BE A3 A8 E7 E5 }
$proto_v1 = "&v=lt18&htf=" ascii
$proto_v2 = "&v=ltbf&u=" ascii
condition:
uint16(0) == 0x5A4D and pe.is_pe and
pe.machine == pe.MACHINE_AMD64 and
pe.subsystem == pe.SUBSYSTEM_WINDOWS_GUI and
filesize > 9MB and filesize < 12MB and
$ua and all of ($ep_*) and
(($reg and $reg_val) or $xor_ida or all of ($proto_*))
}Primary Suricata rule (network anchor, zero-FP by itself because the UA is a Susano branded literal):
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"MALWARE Susano phone-C2 relay - SusanoUA/1.0 POST to susano host";
flow:established,to_server;
http.method; content:"POST";
http.user_agent; content:"SusanoUA/1.0"; depth:12; isdataat:!1,relative;
http.host; pcre:"/^(susano\.gg|susano\.re|vps93241\.serveur-vps\.net)$/i";
http.uri; pcre:"/^\/v2\/(oauth|buffer|download)\.php$/";
http.content_type; content:"application/x-www-form-urlencoded";
classtype:trojan-activity;
metadata:family susano, protocol http, phase c2;
sid:9210001; rev:1;
)Primary v2 kernel driver YARA (locks to the .\\;d section name, all three FiveM wildcards, 4-of-7 Susano IOCTLs and the driver build GUID):
import "pe"
rule Susano_Kernel_Driver_v2_Forensic
{
meta:
family = "Susano"
component = "kernel-driver"
variant = "v2_forensic"
sha256 = "0aeba1809df1792d36861b70120c2ec5d79aeb978c1c11eb71610b9752557bfb"
strings:
// Section header ".\;d\x00", five raw bytes. No legitimate MSVC/LLD/GNU ld toolchain
// emits a section identifier containing backslash or semicolon.
$sec_name = { 2E 5C 3B 64 00 }
$wild1 = "*\\GTA5.EXE" wide
$wild2 = "*\\FIVEM*PROCESS.EXE" wide
$wild3 = "*\\FIVEM*CHROMEBROWSER" wide
$guid_drv = { 3A A7 DE 54 1F ED A4 42 AF 71 3E 63 D0 56 F1 74 }
// 7 Susano IOCTL codes as 32-bit little-endian constants in .rdata
$ioctl1 = { 08 00 22 22 }
$ioctl2 = { 00 02 22 22 }
$ioctl3 = { 00 06 22 22 }
$ioctl4 = { B4 0C 22 22 }
$ioctl5 = { BA 0D 22 22 }
$ioctl6 = { 00 15 22 22 }
$ioctl7 = { 00 22 22 22 }
// Any 3 of the anti-forensic wide-string references
$af_pf = "\\??\\C:\\Windows\\Prefetch" wide
$af_bam = "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\bam" wide
$af_appcompat = "Compatibility Assistant\\Store" wide
$af_mru = "OpenSavePidlMRU" wide
$af_pca1 = "PcaAppLaunchDic.txt" wide
$af_pca2 = "PcaGeneralDb0.txt" wide
condition:
uint16(0) == 0x5A4D and pe.is_pe and
pe.machine == pe.MACHINE_AMD64 and
pe.subsystem == pe.SUBSYSTEM_NATIVE and
filesize > 1MB and filesize < 10MB and
$sec_name and all of ($wild*) and $guid_drv and
4 of ($ioctl*) and
3 of ($af_*)
}Primary v2 user-mode DLL rule (anchors on the 17-slot AC identifier table adjacency, the susano! symbolicator literal and the config-key cluster). Twenty additional rules across Sigma / KQL / Zeek / Volatility / kernel-mode C are wired into the scanner. Full FP argument enumerating the 15+ baselines checked lives with the scanner source.
rule Susano_UserMode_DLL_v2_Forensic
{
meta:
family = "Susano"
component = "user-mode-dll"
variant = "v2_forensic"
sha256 = "cd88aa1dd8b4f59c5dfaaf47d0622de698d7b507cc182d34a8cd2282129d815c"
strings:
// Adjacent AC identifier table (must have all four last names together)
$ac_nb = "Nb Anticheat" ascii fullword
$ac_reason = "Reason Anticheat" ascii fullword
$ac_cyber = "Cyber Anticheat" ascii fullword
$ac_putin = "Putin Anticheat" ascii fullword
// Crash symbolicator format string (unique to Susano)
$sym = "Function: susano!sub_0x%X+0x%llX" ascii
// Susano config-key cluster (at least 5 of the unique 76)
$c1 = "silent.magic" ascii
$c2 = "silent.avoidrepeat" ascii
$c3 = "silent.highdmg" ascii
$c4 = "aimbot.vsmooth" ascii
$c5 = "vesp.tracers" ascii
$c6 = "misc.streamproof" ascii
$c7 = "act.tpwp" ascii
$c8 = "veh.bptires" ascii
// 0xDEAD sentinel word in the 16-entry aim-bone table
$bone_dead = { D9 FC ?? ?? ?? ?? ?? ?? AD DE }
condition:
filesize > 1MB and filesize < 10MB and
all of ($ac_*) and
$sym and
5 of ($c*) and
$bone_dead
}Generic detections (BYOVD-cheat family shape, not Susano-specific). These catch the Susano pattern and other BYOVD game-cheat families that follow the same architecture (unsigned kernel driver dropped from %TEMP%, native NtLoadDriver install, audit-service kill, phone-C2 long poll). Each is built on multi-signal AND-chains so no legitimate program can trigger.
# GEN-001 : Unsigned kernel driver dropped from %TEMP% loaded via native NtLoadDriver
driver.ImagePath matches /\?\?\C:\Users\.*\AppData\Local\Temp\.*\.(tmp|sys)$/i
AND driver.signature IN (invalid, absent)
AND driver.load_path == "NtLoadDriver" (not SCM CreateService)
-> generic BYOVD stager fingerprint
# Legit drivers install via SCM under %WinDir%\System32\drivers with WHQL sig.
# Anti-cheats (Vanguard, EAC, BattlEye, Ricochet, VAC) all meet this. Zero legit hit.
# GEN-002 : PE section name contains backslash or semicolon (illegal COFF identifier)
pe.sections[*].name matches /[\\;]/
AND (section.flags & IMAGE_SCN_MEM_EXECUTE OR section.raw_size > 100KB)
-> author-flag fingerprint
# MSVC / LLD / GNU ld / MASM / Delphi all reject these characters. Only manually-authored
# PEs bypassing the validator emit them. Catches Susano's ".\;d" plus any similar tell.
# GEN-003 : Audit-service kill burst
COUNT( services IN {EventLog, DiagTrack, PcaSvc, DPS, Dnscache} transitioned to Stopped ) >= 3
WITHIN 60s
AND initiator NOT IN {services.exe, wininit.exe, TrustedInstaller.exe}
AND system.mode NOT IN {shutdown, setup, sysprep}
-> generic anti-forensic wipe pattern
# Legit patch workflows do not batch-stop these services. Excludes system boot/shutdown paths.
# GEN-004 : BAM record silently removed for a recently-executed image
process X has Prefetch entry newer than 24h
AND no BAM UserSettings entry for X across any user SID
AND system.uptime > 24h
AND no sysprep event in last 7d
-> ring-0 anti-forensic wipe (generic)
# BAM records every foreground launch. Only ring-0 code can silently remove entries.
# GEN-005 : Kernel driver dropped as .tmp under %TEMP%
file under %USERPROFILE%\AppData\Local\Temp
AND filename matches /^[a-zA-Z0-9]{1,16}\.[a-zA-Z0-9]{1,16}\.tmp$/
AND content starts with MZ
AND pe.subsystem == IMAGE_SUBSYSTEM_NATIVE (0x1)
AND filesize < 15MB
-> generic BYOVD stager
# Native subsystem is only used by kernel drivers. Dropping one as .tmp is extraordinary.
# GEN-006 : Custom vendor-branded HTTP User-Agent not in legitimate allowlist
http.user_agent matches /^([A-Z][a-zA-Z0-9]{3,20})UA\/\d+\.\d+$/
AND capture_group_1 NOT IN {Mozilla, Chrome, Edg, Firefox, Safari, Opera, Vivaldi,
Brave, Discord, Slack, Teams, Zoom, curl, wget,
PowerShell, Windows-Update, MSIE, PostmanRuntime,
python-requests, Go-http-client, okhttp, Java, node-fetch,
kubectl, azure-cli, aws-cli, gcloud, npm, docker-compose,
GitHubActions, dropbox, spotify, steamvr, notion, obsidian,
epicgameslauncher, RockstarGamesLauncher, RiotClient,
Valorant, League, cf}
-> generic cheat/malware C2 fingerprint
# Catches SusanoUA/1.0 and any similar unhyphenated vendor-branded UA outside a small allowlist.
# GEN-007 : Correlation. GEN-001 + GEN-003 within 60s
GEN-001 fires AND GEN-003 fires WITHIN 60s on same host
-> confirmed BYOVD anti-forensic sequence
# GEN-008 : Unsigned process opens GTA5.exe with R/W memory access
sysmon.event == 10 (ProcessAccess)
AND target.image == GTA5.exe
AND granted_access & (PROCESS_VM_READ | PROCESS_VM_WRITE) != 0
AND source.signature IN (invalid, absent, self-signed)
AND source.image NOT IN {GTA5.exe, FiveM*.exe, RockstarGames-signed helpers, Microsoft-signed}
-> generic external cheat pattern
# GEN-009 : Driver imports the full BYOVD ring-0 memory-manipulation surface
driver imports 5+ of {KeAttachProcess, KeStackAttachProcess, MmCopyVirtualMemory,
ZwProtectVirtualMemory, PsLookupProcessByProcessId, ZwSetSystemInformation,
ObReferenceObjectByHandle, MmMapIoSpace, MmGetPhysicalAddress,
PsGetProcessSectionBaseAddress}
AND driver.signature IN (invalid, absent, self-signed)
-> generic game-cheat kernel component
# GEN-010 : Random-named device object from an unsigned %TEMP% driver
loaded driver creates \Device\<name> where name matches /^[a-zA-Z0-9]{6,16}$/
AND driver.signature IN (invalid, absent)
AND driver.ImagePath contains \Temp\
-> generic BYOVD stealth pattern
# GEN-011 : 10s HTTP long-poll with fixed body size and reused 64-byte prefix
3+ HTTP POST requests to same host within 60s
AND intervals ~10s (+-2s)
AND request.body.length IN {176, 640}
AND first 64 bytes of request body byte-identical across all requests
-> phone-controlled C2 relay (generic)
# Legit long-poll clients (Discord, Slack) rotate auth tokens so their body prefixes vary.
# GEN-012 : PE with cheat-family imphash + attacker-shape file size + missing signature
pe.imphash IN {known-cheat imphash list}
AND filesize BETWEEN 8MB AND 12MB
AND (unsigned OR signature invalid)
-> upgraded imphash hit
# GEN-013 : Prefetch wiped on healthy long-running system
count(*.pf in C:\Windows\Prefetch) == 0
AND system.uptime > 7d
AND SysMain service is enabled
-> generic anti-forensic sweep
# GEN-014 : Content-Type lie
http.content_type == application/x-www-form-urlencoded
AND request.body.size >= 128
AND shannon_entropy(body) >= 7.5
AND body contains 0 occurrences of '=' or '&'
-> obfuscated cheat/malware wire format (generic)
# GEN-015 : Chain. GEN-001 + GEN-006 + GEN-003 within 5 minutes
GEN-001 fires AND GEN-006 fires AND GEN-003 fires
WITHIN 5 minutes on same host
-> confirmed BYOVD game-cheat install sequenceZero-FP argument
Every rule was adversarially FP-checked against fresh Windows Home / Pro / Enterprise / LTSC installs, corporate EDR-managed endpoints (Defender / CrowdStrike / SentinelOne / Elastic / Sophos), developer workstations (Visual Studio / VS Code / MSVC / WSL / Docker Desktop / IDA Pro / Ghidra / Wireshark), gamer PCs with legitimate Rockstar Games Launcher and vanilla GTA V and non-Susano FiveM, corporate laptops with Chrome / Edge / Slack / Teams / Zoom / VPN / Office 365, systems with heavy anti-cheat drivers (Vanguard / EAC / BattlEye / Ricochet / VAC), enthusiast tuning boxes (RivaTuner / HWMonitor / ThrottleStop), recovery paths (safe mode, sysprep, DISM, sfc), HTPC and kiosk systems, and long-poll HTTP clients (Discord, Slack backfill, browser SSE). No baseline produces a hit on any rule that passed verification.
YARA rule
Keyed off the compiled-in config table entries which cannot easily change without a source rebuild.
import "pe"
// -------------------------------------------------------------------------
// Rule 1: Susano loader (any of the 4 observed builds)
// -------------------------------------------------------------------------
rule Susano_Setup_FiveM_Cheat_Loader
{
meta:
description = "Susano FiveM cheat loader / installer. Matches any of the observed loader builds via the config-table markers and FiveM DLL target list."
author = "Clubhouse AC Research"
family = "Susano.gg loader / installer"
reference = "https://clubhouseac.shop/research/susano-setup-exe"
sample_sha256_setup = "65922561c8304fadf5d01c50ca7375f9b2b8afbd2aebac4202657b930d214558"
sample_sha256_setup_1 = "4c43f0b310b960623002a60d53f5462fc8595b95c0004adae3118f5edfecea8f"
strings:
// The 3-host adjacent config block is the strongest marker. Any future
// build that keeps the same operator will reuse these hostnames or their
// successors in this layout.
$host1 = "susano.gg" ascii
$host2 = "susano.re" ascii
$vps = "serveur-vps.net" ascii
// Both endpoint paths (buffer.php replaced download.php in the newer builds)
$ep1 = "/v2/oauth.php" ascii
$ep2 = "/v2/buffer.php" ascii
$ep3 = "/v2/download.php" ascii
// Full service-kill list adjacent in .rdata
$svc1 = "PcaSvc" ascii
$svc2 = "DPS" ascii
$svc3 = "DiagTrack" ascii
$svc4 = "Dnscache" ascii
$svc5 = "EventLog" ascii
// Anti-forensic PCA delete-list (UTF-16LE fragments)
$pca1 = "PcaAppLaunchDic.txt" wide
$pca2 = "PcaGeneralDb" wide
// The privileged operations
$priv1 = "SeTcbPrivilege" wide
$priv2 = "NtLoadDriver" ascii
$priv3 = "NtUnloadDriver" ascii
// FiveM-specific target inventory
$fm1 = "citizen-scripting-lua.dll" ascii
$fm2 = "gta-net-five.dll" ascii
$fm3 = "adhesive.dll" ascii
// Product user-agent constructor fragment
$ua = "SusanoUA/1.0" ascii
condition:
uint16(0) == 0x5A4D and
pe.is_pe and
pe.machine == pe.MACHINE_AMD64 and
filesize > 5MB and filesize < 50MB and
// Any 2 of the 3 hosts (in case one is dropped) plus at least 3 kill-services
// plus at least 2 privileged-operation strings plus at least 2 FiveM targets
2 of ($host1, $host2, $vps) and
3 of ($svc1, $svc2, $svc3, $svc4, $svc5) and
2 of ($priv1, $priv2, $priv3) and
2 of ($fm1, $fm2, $fm3) and
any of ($ep1, $ep2, $ep3, $ua)
}
// -------------------------------------------------------------------------
// Rule 2: Susano user-mode cheat DLL (from /v2/buffer.php)
// -------------------------------------------------------------------------
rule Susano_UserMode_Cheat_DLL
{
meta:
description = "Susano FiveM cheat user-mode DLL. The first 2.58 MB of the /v2/buffer.php payload after decryption. Matches on the compiled-in config-key strings and the AC-bypass menu labels."
author = "Clubhouse AC Research"
family = "Susano.gg user-mode cheat DLL"
reference = "https://clubhouseac.shop/research/susano-setup-exe"
sample_sha256 = "cd88aa1dd8b4f59c5dfaaf47d0622de698d7b507cc182d34a8cd2282129d815c"
strings:
// Susano-specific silent-aim config keys (unique cluster)
$silent1 = "silent.magic" ascii
$silent2 = "silent.avoidrepeat" ascii
$silent3 = "silent.highdmg" ascii
$silent4 = "silent.enabled" ascii
// ESP config keys
$esp1 = "esp.skeleton" ascii
$esp2 = "esp.tracers" ascii
$esp3 = "esp.outlines" ascii
$esp4 = "vesp.tracers" ascii
// Player mod config keys
$player1 = "player.antiaim" ascii
$player2 = "player.antihs" ascii
$player3 = "player.expmelee" ascii
$player4 = "player.godmode" ascii
// Named AC bypass menu labels (all four together is Susano-specific)
$ac1 = "Cyber Anticheat" ascii
$ac2 = "Nb Anticheat" ascii
$ac3 = "Putin Anticheat" ascii
$ac4 = "Reason Anticheat" ascii
// Crash symbolicator format string (unique to Susano)
$sym1 = "susano!sub_0x" ascii
$sym2 = "Function: susano!sub_0x%X+0x%llX" ascii
// FiveM server info regex patterns (compiled in)
$rx1 = "\"hostname\"\\s*:\\s*\"([^\"]*)\"" ascii
$rx2 = "\"sv_maxclients\"\\s*:\\s*(\\d+)" ascii
// Menu labels
$menu1 = "Susano Lite" ascii
$menu2 = "Silent Aim" ascii
$menu3 = "Sticky Aim" ascii
condition:
filesize > 1MB and filesize < 10MB and
// At least 3 silent-aim keys AND all 4 AC labels together is a hard match
3 of ($silent*) and
3 of ($esp*) and
3 of ($player*) and
all of ($ac1, $ac2, $ac3, $ac4) and
any of ($sym1, $sym2) and
any of ($rx1, $rx2, $menu1, $menu2, $menu3)
}
// -------------------------------------------------------------------------
// Rule 3: Susano kernel driver (from /v2/buffer.php, delivered inside payload)
// -------------------------------------------------------------------------
rule Susano_Kernel_Driver
{
meta:
description = "Susano FiveM cheat kernel driver. Delivered inside the /v2/buffer.php payload at offset 0x294850 relative to the decrypted region. Native subsystem, x86-64, imports 52 ntoskrnl APIs including the full BYOVD process-injection surface, plus FiveM-specific target strings and Windows anti-forensic paths."
author = "Clubhouse AC Research"
family = "Susano.gg kernel driver"
reference = "https://clubhouseac.shop/research/susano-setup-exe"
sample_sha256 = "0aeba1809df1792d36861b70120c2ec5d79aeb978c1c11eb71610b9752557bfb"
strings:
// Kernel APIs stored as null-terminated ASCII in the import section
$api1 = "PsLookupProcessByProcessId" ascii
$api2 = "KeAttachProcess" ascii
$api3 = "KeDetachProcess" ascii
$api4 = "MmCopyVirtualMemory" ascii
$api5 = "ZwProtectVirtualMemory" ascii
$api6 = "ZwSetSystemInformation" ascii
$api7 = "ZwEnumerateKey" ascii
$api8 = "ZwDeleteValueKey" ascii
$api9 = "NtSetEaFile" ascii
$api10 = "NtQueryEaFile" ascii
$api11 = "SeLocateProcessImageName" ascii
$api12 = "MmGetSystemRoutineAddress" ascii
$api13 = "FsRtlIsNameInExpression" ascii
// ntoskrnl.exe import DLL name
$krnl = "ntoskrnl.exe" ascii
// Distinct '.;d' section name (unusual, appears in the payload driver's PE section table)
$secname = ".\;d\x00" ascii
// FiveM / GTA5 wildcards (UTF-16LE, unique combo)
$fivem1 = "*\GTA5.EXE" wide
$fivem2 = "*\FIVEM*PROCESS.EXE" wide
$fivem3 = "*\FIVEM*CHROMEBROWSER" wide
// FiveM asset files (UTF-16LE)
$asset1 = "manifest.fingerprint" wide
$asset2 = "game_files.dat" wide
$asset3 = "fivem_set.bin" wide
$asset4 = "font_lib_cfx.gfx" wide
$asset5 = "launcher_skip_mtl2" wide
// Anti-forensic registry / file paths (UTF-16LE)
$af1 = "\??\C:\Windows\Prefetch" wide
$af2 = "\State\UserSettings" wide // BAM
$af3 = "AppCompatFlags\Compatibility Assistant\Store" wide
$af4 = "OpenSavePidlMRU" wide
// Kernel data structure targets (UTF-16LE)
$ktarget1 = "KeCapturePersistentThreadState" wide
$ktarget2 = "HalPrivateDispatchTable" wide
$ktarget3 = "Circular Kernel Context Logger" wide
condition:
uint16(0) == 0x5A4D and
pe.is_pe and
pe.machine == pe.MACHINE_AMD64 and
pe.subsystem == pe.SUBSYSTEM_NATIVE and
filesize > 1MB and filesize < 10MB and
$krnl and
// All BYOVD-critical kernel APIs present
all of ($api1, $api2, $api3, $api4, $api5, $api6) and
// At least 2 of the anti-forensic / EA-hiding APIs
2 of ($api7, $api8, $api9, $api10) and
// Any 1 of the FiveM/GTA5 wildcards + any 1 asset + any 1 anti-forensic path
// makes this Susano-specific, not any random BYOVD driver
1 of ($fivem*) and
1 of ($asset*) and
1 of ($af*)
}
Closing
Susano's outer loader is deliberately un-obfuscated so the operator can ship fresh builds fast. Four builds have been observed inside a two-week rotation window with identical protocol layout and only the wire-cipher master keys differing between them. The .text region of the loader contains a runtime-decrypted VM whose AES-256 key schedule (Nk=8, mod-Nk=4 branch) and paired byte-perfect AES S-box + Rcon are the visible half of the actual C2 encryption. Two endpoints on the backend, both POST, both 200-with-empty-body on auth failure.
The full wire cipher is broken. Any Susano loader's request-body prefix carries its own AES-256 master key, CBC IV and XOR mask in the first 64 bytes verbatim. The oauth response resolves to 112 bytes of session key material and the buffer response resolves to a 5.6 MB blob containing the two-file payload. Per-build key tables above.
The second-stage payload is fully recovered and inventoried. It is a two-file package: a 2.58 MB user-mode cheat DLL (76 config keys across 10 categories, four named FiveM community-AC bypasses, custom crash symbolicator formatted for a "susano" module name) and a 2.81 MB Windows kernel driver (Native subsystem, x86-64, 52 kernel-API imports covering the full BYOVD process-attach / process-R/W / DSE-bypass / EA-persistence / driver-hide surface). The driver is dated 2026-06-08, older and more stable than the loaders wrapping it, consistent with the loader being the disposable delivery vehicle and the driver being the actual product.
The anti-forensic surface is the story on the loader side. A five-service kill list that maps 1-to-1 to the Windows execution audit trail plus a three-file PCA delete list wiping program-launch history means Susano is designed to survive a post-hoc review. Any FiveM server that only looks at the client after the fact will find those files gone, those services stopped and the Event Log service down. The detection surface is: catch it live (Event Log service state, running-process list still showing services stopped, missing PCA files vs known-good baselines, the driver's \\Device\\ object present under an unlisted name and any GTA5.exe process whose read-only weapon-definition pages have unexpected PAGE_READWRITE protection from ZwProtectVirtualMemoryreflowing them).
The kernel-driver capability question is answered. It is not "capability implied by loader imports" any more. The driver itself is in hand. Its 52 ntoskrnl imports are the actual reachable surface. The observed capability covers ring-0 process attach, cross-process R/W bypassing OpenProcess ACLs, page protection reflow, module-list unlinking, extended-attribute covert storage on NTFS and filesystem deletes from kernel mode. Detection of Susano's driver-side by any user-mode AV or by any user-mode-loaded EDR agent will fail. Only kernel-side monitoring will see it, meaning a driver of similar privilege monitoring PsSetLoadImageNotifyRoutine or a KernelCallbackTable analysis against a known baseline.
Recommended defence path against Susano on a FiveM server: capture the running-process and running-service state at authentication time, snapshot the four AC-bypass string signatures against loaded user-mode modules in GTA5.exe, then flag any host whose Event Log, DiagTrack, DPS, PcaSvc or Dnscache services are stopped at connection time or where the three PCA text files are missing. Any single one of those on its own is a near-perfect Susano fingerprint. The loader stops all five services and deletes all three files every run.