FiveM cheat installerAnti-forensic surfaceFull C2 map

Susano Setup.exe

A Susano loader / installer landed on our desk. This write-up covers the full compiled-in config table pulled verbatim from .rdata including the 3-host C2 list, a 5-service kill list that maps 1-to-1 to the Windows execution audit trail, a 3-file PCA delete list that maps directly to the detect.ac screenshare tool's primary forensic source, a 6+1 process interaction list including lsass.exe and winlogon.exe, SeTcbPrivilege acquisition and direct NtLoadDriver / NtUnloadDriver capability. Two backend endpoints confirmed on susano.gg.

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 are all present in .rdata at byte-perfect canonical values but no active AES routine in the binary references them. They are unreferenced dead code from a statically linked crypto lib. The 176-byte body must therefore be encrypted by a non-CryptoAPI custom construction whose key material comes from CryptGenRandom.

Sample identity

FieldValue
Name on diskSetup.exe (as delivered by the Susano landing page)
TypePE32+ EXE, x64, GUI subsystem
Size10,797,648 bytes (10.79 MB)
MD5111bb3f93444d8e873e0b11b0dec2275
SHA-25665922561c8304fadf5d01c50ca7375f9b2b8afbd2aebac4202657b930d214558
LinkerMSVC 14.44 (Visual Studio 2022)
Overlay after last section80 bytes (small padding, plausibly a signature stub)
Manifestlevel='requireAdministrator' uiAccess='false'
Signedno
ImpHash89279bc839f47ce69afbd562c3637253
Product user-agentSusanoUA/1.0 (constructed at runtime, never stored plaintext)
SectionVAVSizeRSizeNotes
.text0x1400010000x008e2fb40x008e30009.06 MB, entropy 7.296 (high, from statically linked crypto libs plus embedded encrypted config)
.rdata0x1408e40000x00115b3a0x00115c001.13 MB, entropy 6.200 (holds the config table plus AES and SHA-256 tables)
.data0x1409fa0000x000491640x00047400295 KB, mostly zero (entropy 0.283)
.pdata0x140a440000x0000b9640x0000ba00SEH unwind info, present (a commercial protector would strip)
.fptable0x140a500000x000001000x00000200Control Flow Guard function table
.rsrc0x140a510000x000001e80x00000200Manifest resource only
.reloc0x140a520000x000010c40x00000000Base relocations present (a commercial protector would strip these)

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

DLLCountNotes
dwmapi.dll1DwmExtendFrameIntoClientArea (composition setup for the overlay)
KERNEL32.dll150CreateFileMappingA, AllocConsole, SetConsoleTextAttribute, VirtualAlloc, service-adjacent helpers, plus 145 others
USER32.dll39DestroyWindow, MessageBoxW, OpenClipboard, GetAsyncKeyState-adjacent, standard cheat UI plus input surface
ADVAPI32.dll37CryptAcquireContextW, CryptEncrypt, CryptImportKey, CryptGenRandom, CryptHashData, CryptCreateHash, CryptGetHashParam, CryptDestroyKey plus token APIs (OpenProcessToken, DuplicateTokenEx, SetThreadToken, GetTokenInformation, SetTokenInformation)
ole32.dll1CoInitializeEx
WS2_32.dll34send, recv, connect, getaddrinfo, WSAStartup, WSASocketW, htons/htonl plus a full SOCKS5 client surface
IMM32.dll4ImmSetCompositionWindow, ImmReleaseContext, ImmGetContext plus one more (IME support for the overlay)
ntdll.dll6NtQueryVirtualMemory, 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.

VAContentPurpose
0x1408eb7b0susano.re (ASCII, null-padded to 16B)Fallback C2 host
0x1408eb7c0susano.gg (ASCII, null-padded to 16B)Primary C2 host
0x1408eb7d0vps93241.serveur-vps.net (ASCII, null-padded to 32B)Direct VPS backup C2 (bypasses Cloudflare, points at the origin server directly)
0x1408eb7ecPcaSvcProgram Compatibility Assistant Service. Windows tracks program launches here
0x1408eb7f4DPSDiagnostic Policy Service. Network and system diagnostic logging
0x1408eb7f8DiagTrackConnected User Experiences and Telemetry. The main Windows telemetry pipe
0x1408eb808DnscacheDNS Client service. Killed to hide C2 lookups from the local DNS cache
0x1408eb818EventLogWindows Event Log. The primary source screenshare tools grep after the fact
0x1408eb828services.exe (UTF-16LE)Target or hooked system process
0x1408eb840explorer.exe (UTF-16LE)Target or hooked
0x1408eb860smartscreen.exe (UTF-16LE)Target. Windows SmartScreen. Interacts to suppress reputation warnings
0x1408eb880lsass.exe (UTF-16LE)Target. LSA. Very sensitive.
0x1408eb8a0csrss.exe (UTF-16LE)Target. Client-Server Runtime Subsystem
0x1408eb8b8dwm.exe (UTF-16LE)Target. Desktop Window Manager
0x1408eb8d8int64[6] = {7, 9, 15, 24, 31}Small integer array. Plausibly PID slots or PROCESS_ACCESS_RIGHTS flags for the six process entries above
0x1408eb900SeTcbPrivilege (UTF-16LE)The 'act as part of the operating system' privilege
0x1408eb920winlogon.exe (UTF-16LE)Target (7th process, listed separately from the six above)
0x1408eb94016 bytes: f2aa156f08d2894e9ab4489535d34f9cUnknown 128-bit constant (IV candidate or fixed nonce)
0x1408eb960double 10.0 (0x4024000000000000)Numeric constant (poll interval or timeout)
0x1408eb97032 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)
0x1408eb990256 bytes = AES S-box (verified 100% match)From a statically linked crypto lib (NOT referenced by any active AES code)
0x1408eba90256 bytes = AES inverse S-boxSame as above
0x1408ebb9110 bytes = AES Rcon (01 02 04 08 10 20 40 80 1b 36)Same
0x1408ebba0256 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 screenshare tool would look after the fact:

Service nameFull nameWhat it records or does
PcaSvcProgram Compatibility Assistant ServiceRecords program launches into %WINDIR%\appcompat\pca\Pca*.txt (deleted separately, see next section)
DPSDiagnostic Policy ServiceNetwork and hardware diagnostic logs
DiagTrackConnected User Experiences and TelemetryWindows telemetry pipe, feeds Amcache and related telemetry stores
DnscacheDNS Client serviceLocal DNS cache, would reveal susano.gg lookups
EventLogWindows Event LogThe catch-all audit source (Application, Security, System, Sysmon and so on). Stopping this is the loudest anti-forensic move. Most screenshare tools flag Event Log stops as-is

PCA file-delete list

Three UTF-16LE paths in .rdata immediately before the config table (starting at 0x8eb690). All three are the exact files the detect.ac / detectfm.exe screenshare tool reads via its own File-source finding type. If Susano runs to completion before a screenshare, these are gone and detect.ac cannot pull program-launch history from them.

C:\Windows\appcompat\pca\PcaAppLaunchDic.txt
C:\Windows\appcompat\pca\PcaGeneralDb0.txt
C:\Windows\appcompat\pca\PcaGeneralDb1.txt

Process 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

ComponentDetails
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 0x1408eb990The AES S-box, inverse S-box and Rcon are all 100% byte-perfect canonical values. Cross-reference scans confirm no active AES routine in the binary calls into this memory range. Dead code from a statically linked crypto lib.
Software SHA-256 constants at 0x1408eb970Three 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.

FieldValue
MethodPOST
URLhttp://susano.gg/v2/oauth.php
Hostsusano.gg
User-AgentSusanoUA/1.0
Accept*/*
Content-Typeapplication/x-www-form-urlencoded (misleading, body is raw binary)
Content-Length176
Response statusHTTP 200 OK
Response headersserver: cloudflare, cf-ray: ..., cf-cache-status: DYNAMIC, nel plus report-to: cf-nel
Response Content-Typetext/html; charset=UTF-8 (also misleading, response body is raw binary)
Response Content-Length112

Sample request body (hex, 176 bytes):

af56ff55e111107ce29b836b8da3256333dfb7ce5dd8e38c617f29dcf54a4c75af7a753a83ede99599cc135c934289e4391db0a5de41163b09777883e787ae4dda812ce78337ce71c9171c08ed88e85dc49c106a74202a850cc606092d9876644db49c603c02333fe09a369dc25ac7da8b6d96924722554709a79c4f8f7a8181ba6e888aac4565fc726d19a5fbde80c1fd7b4a6a853212c70d2891286204064cb22f9ce73f7c211420f702d5cf5a5c8b

Sample response body (hex, 112 bytes):

f80c7c4c91bcca1d68fb229bac1efdcef2a2602c7b9d67536a8d2dfb20e6908ada5ceb55032a3e74db6f7d79fcde764fb2f25f0f2d12cda80e6fe14efff2e2514692aecd2e479f79b1b9e8d983117408d566847ecd112704f5543567fd30a82e8c6eac584d65843a07f5673a0cadcc24

Replaying 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. The body is encrypted with a non-CryptoAPI custom construction keyed off session-scoped CryptGenRandom material passed through the SHA-256 KDF wrapper at 0x1408a8290. Recovering plaintext requires the per-session key material, which the client never emits.

Backend endpoints

Endpoint enumeration against susano.gg:

PathGETPOSTInterpretation
/v2/oauth.php403 (CF)200 (with 112B body)Handshake / session establishment. Confirmed live.
/v2/download.php403 (CF)200 (empty body without valid auth)Payload delivery. Confirmed to exist. Returns empty on wrong-format request.
/v2/loader.php403 (CF)404Does not exist
/v2/auth.php403 (CF)404Does not exist
/v2/hwid.php403 (CF)404Does not exist
/v2/config.php403 (CF)404Does not exist
/v2/heartbeat.php403 (CF)404Does not exist
/v2/telemetry.php403 (CF)404Does not exist
/v2/inject.php403 (CF)404Does not exist
/openapi.json403 (CF)-Does not exist
/docs403 (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.

IOCs

TypeValueNotes
Domainsusano.ggPrimary Susano C2, Cloudflare-fronted, PHP backend on the origin.
Domainsusano.reFallback C2. Present in the config table.
Domain / Origin hostvps93241.serveur-vps.netDirect VPS origin (French VPS provider). Bypasses Cloudflare. Present in config.
Cloudflare IPs104.26.15.100, 172.67.70.156, 104.26.14.100DNS answers for susano.gg
EndpointPOST /v2/oauth.phpHandshake / session establishment. 176-byte binary request, 112-byte binary response.
EndpointPOST /v2/download.phpPayload delivery. POST returns 200, GET returns 403 CF-blocked, wrong-payload POST returns 200 with an empty body suggesting auth-gated.
HTTP headerUser-Agent: SusanoUA/1.0Constructed at runtime, never stored plaintext in the binary
HTTP headerContent-Type: application/x-www-form-urlencoded (with a raw binary body)Format mismatch is deliberate obfuscation against casual IDS or WAF pattern matches
FileSHA-256 65922561c8304fadf5d01c50ca7375f9b2b8afbd2aebac4202657b930d214558The installer itself
FileMD5 111bb3f93444d8e873e0b11b0dec2275same
Config markerThe 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
Service kill-listPcaSvc, DPS, DiagTrack, Dnscache, EventLogComma-listed here, but adjacent in .rdata at 0x8eb7ec-0x8eb818 as null-padded ASCII
PCA delete-listPcaAppLaunchDic.txt, PcaGeneralDb0.txt, PcaGeneralDb1.txt (UTF-16LE)At 0x8eb690 and 0x8eb750. The three PCA files that detect.ac's screenshare tool reads for program-launch forensic evidence
BehaviourNtLoadDriver / NtUnloadDriver imported directly from ntdllKernel-driver capability. Likely a BYOVD (Bring Your Own Vulnerable Driver) chain since Susano is not a signed kernel driver
BehaviourOpenProcessToken / DuplicateTokenEx / SetThreadToken / SetTokenInformationToken manipulation for process impersonation and TCB acquisition

YARA rule

Keyed off the compiled-in config table entries which cannot easily change without a source rebuild.

import "pe"

rule Susano_Setup_FiveM_Cheat_Config_Table
{
    meta:
        description = "Susano FiveM cheat installer (Setup.exe). Identifies via the adjacent domain strings in .rdata and the FiveM DLL target list"
        author      = "Clubhouse AC Research"
        family      = "Susano.gg loader / installer"
        reference   = "https://clubhouseac.shop/research/susano-setup-exe"
        sample_sha256 = "65922561c8304fadf5d01c50ca7375f9b2b8afbd2aebac4202657b930d214558"

    strings:
        // The 3-host adjacent config block is the strongest marker. Any future Susano
        // 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

        // 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

    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)
}

Closing

Susano's outer shell is deliberately un-obfuscated so the operator can ship fresh builds fast, but the operational config is compiled in and the AES tables are a red herring left over from a statically linked crypto lib the sample does not call. The actual C2 encryption is a custom construction keyed off CryptGenRandom-derived material passed through the SHA-256 KDF wrapper at 0x1408a8290. Two endpoints on the backend, both POST, both 200-with-empty-body on auth failure.

The anti-forensic surface is the story here. A five-service kill list that maps 1-to-1 to the Windows execution audit trail plus a three-file PCA delete list that maps directly to the detect.ac screenshare tool's File-source finding type means Susano is designed to survive a screenshare. Any FiveM server that relies on detect.ac for post-hoc evidence against a Susano user 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).

Kernel-driver capability via direct NtLoadDriver and SeTcbPrivilege acquisition plus token manipulation imports points at BYOVD as the plausible ring-0 path. The actual driver is not in this outer sample. It would be delivered by /v2/download.php on a successful handshake.

Susano Setup.exe, C2 Map + Config Table + Anti-Forensic Surface on a FiveM Cheat Installer ยท Clubhouse AC