Horse Museum: Taking Apart a Private Star Stable Launcher Distributed over Tor
This post analyzes an installer that was handed out as an invite to a private Star Stable Online server. The delivery, an onion link serving an executable and an opaque config file, has every trait of a stealer campaign. Taking apart the installer, the launcher, the signed profile, and the encrypted game package shows something else: a private-server client that talks to its account backend over Tor, proxies winmm.dll into the game, patches the client in memory, and only learns the real game server address after login.
An Invite That Looks Like a Malware Drop
The invite consists of a code and short instructions: install Tor, open the link, sign in, download setup.exe and cfg.hors, run the installer, then import the config. The word “Link” is a hyperlink to http://2slqbzmg7k56iwrmbxensn7nrjufubtdbhpanbix5gwusn53vpl454yd.onion/.
An onion site that serves an installer together with a second, unexplained file is the typical shape of a malware drop. The working hypothesis for the analysis was therefore a credential stealer using a horse game as the lure.
The onion site itself is a minimal, well-structured HTML page. The Content-Security-Policy header restricts all resources to 'self', and the page links to a Discord server (discord.gg/horseempire), a download page, and a login page. Registration is invite-only: the /api/registration/status endpoint returns {"mode": "invite"}.
Inside the NSIS Installer
setup.exe is a Nullsoft Scriptable Install System package [1] of 18,122,287 bytes.
SHA-256: 4e5129b0b02835ceb7de51ab572eb89e2c430fa3ff1ab105708f28987d6e99f0
7-Zip reads the archive: solid Deflate compression, 33,704 bytes of headers, and a 109,568-byte stub. It contains the following members:
| Name | Size |
|---|---|
modern-wizard.bmp | 26,494 |
$PLUGINSDIR/nsDialogs.dll | 9,728 |
$PLUGINSDIR/System.dll | 12,288 |
HorseLauncher.exe | 1,904,640 |
tor.exe | 10,222,592 |
$PLUGINSDIR/runtimes.exe | 13,280,976 |
The wizard bitmap and the two plugin DLLs belong to the installer UI. The actual payload is HorseLauncher.exe and a complete copy of tor.exe. The sixth member, runtimes.exe, is a nested NSIS installer that bundles the game’s runtime dependencies (see below).
Because the archive is a single solid block, 7-Zip attributes the entire compressed size to the first file, and no member can be extracted on its own. 7-Zip versions before 23.01 abort on this archive with BadCmd=13 when trying to list it; later versions extract all six members. Cutting even two megabytes off the end makes the whole archive unreadable, so the installer cannot be trimmed below a 16 MB sandbox upload limit.
runtimes.exe: a Second NSIS Installer Inside the First
runtimes.exe is itself a 13,280,976-byte NSIS installer. Its manifest requests requireAdministrator execution level. Extracting it reveals three files:
| Name | Size | Signed by | Countersign date |
|---|---|---|---|
vc14_x86.exe | 6,941,536 | Microsoft Corporation | 2026-05-27 |
vc2013_x86.exe | 6,510,136 | Microsoft Corporation (MOPR) | 2017-05-24 |
dxwebsetup.exe | 295,320 | Microsoft Corporation | 2021-02-17 |
All three carry valid Authenticode signatures from Microsoft. The NSIS script disassembly confirms what they do: vc14_x86.exe is installed with /install /quiet /norestart, vc2013_x86.exe with the same flags, and dxwebsetup.exe with /Q. The script checks the exit code of each, showing "Could not start Visual C++ runtime" or "DirectX web installer failed (code $0). Check your Internet connection and try setup again." on failure.
The outer installer calls runtimes.exe via ShellExecuteExW with the runas verb, waits for it with WaitForSingleObject, and checks the exit code. If it fails, the user sees "Game runtimes were not installed (code $0). Run setup again and approve the administrator prompt, or uncheck runtimes if they are already installed." There is no code in runtimes.exe beyond the three Microsoft redistributable installers.
The Outer Installer Script
Disassembly of the outer NSIS script shows what setup.exe does beyond extracting files:
- Writes
HorseLauncher.exeandtor.exeto$INSTDIR. - Calls
kernel32::CreateFileWonHorseLauncher.exeto verify the install directory is writable. If not:"Cannot update this file. Close the launcher and try again, or choose a writable folder." - Runs
runtimes.exeelevated (see above). - Creates a desktop shortcut (
Horse Launcher.lnk) and a Start Menu entry underPrograms\HorseLauncher. - Writes an uninstall entry under
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\HorseLauncherwithDisplayName,UninstallString,DisplayIcon,EstimatedSize(12099 KB), andNoModify/NoRepairset to 1. - Calls IsWow64Process2 and IsWow64Process to detect the architecture.
The script does not touch any browser profile, run key, scheduled task, or service. It does not download anything at install time.
The Launcher PE
HorseLauncher.exe is a 64-bit GUI PE [2] of 1,904,640 bytes. It is not packed; section entropy ranges from 4.68 (.data) to 6.95 (.rsrc), consistent with plain compiled code plus embedded resources. The seven sections are .text, .rdata, .data, .pdata, .fptable, .rsrc, and .reloc.
SHA-256: 93f83d0ead20be789340a3edd26557416c425e09fb2250077293a57ea58c1337
The import table references 15 DLLs: KERNEL32 (160 functions), USER32 (50), WS2_32 (36), CRYPT32 (18), bcrypt (15), ADVAPI32 (12), WINHTTP (12), winsqlite3 (9), GDI32 (6), ole32 (4), Cabinet (3), COMCTL32 (3), IPHLPAPI (2), SHELL32 (2), and Secur32 (1). The launcher uses cpp-httplib as an embedded HTTP server (the demangled C++ symbols are visible in the binary) and libcurl for outbound requests, including aws-sigv4 support for the SwissTransfer download authentication.
The program goes by several names. Its version resources say Horse Launcher 2.0 and Star Riders Launcher 1.0. The invite video shows a Horse Museum logo on the Tor Browser start page, and Horse Museum is also the directory the launcher creates for Tor: %LOCALAPPDATA%\HorseMuseum\Tor, resolved through FOLDERID_LocalAppData [3]. The server profile calls itself Horse Empire. All of these names refer to the same program.
No Stealer Code in the Launcher
The first pass targeted the usual stealer surface, and none of it is present. HorseLauncher.exe has no references to Chrome, Firefox, Discord, Telegram, or cryptocurrency wallets, no Run key persistence, and no WriteProcessMemory or CreateRemoteThread.
The few suspicious-looking pieces have mundane explanations. The only SQL-like string is launcher_hash, read from a JSON blob as part of a self-check. CryptProtectData is imported because the launcher can remember the account password, which it stores as RememberedPassword under HKCU\Software\StarRiders\Launcher. The launcher can write text to the clipboard, but it never reads from it.
The launcher also knows the SHA-256 hash of the bundled tor.exe (60c45b01938c799862e511a9a5bab12f959a819c6264a24502edc342165f570c, matching the actual file) and checks it before starting the Tor process.
The launcher contains none of the stealer functionality the delivery suggested. What it does contain is a client for a private game server.
Three Pairs of Embedded DLLs
HorseLauncher.exe embeds three pairs of 32-bit DLLs as RT_RCDATA resources, one pair for each supported client year. The resource IDs follow a consistent scheme: 2014 + 1 or 2 for 2014, 2018 + 1 or 2 for 2018, 2020 + 1 or 2 for 2020. The first resource in each pair is winmm.dll, the second is patch.dll.
| Resource ID | Role | Size | Exports | Key imports |
|---|---|---|---|---|
| 20141 | 2014 winmm.dll | 50,688 | 194 WinMM functions | KERNEL32, USER32, bcrypt, WININET |
| 20142 | 2014 patch.dll | 22,016 | 4 ordinal exports | KERNEL32 only |
| 20181 | 2018 winmm.dll | 51,200 | 195 WinMM functions | KERNEL32, bcrypt, WININET |
| 20182 | 2018 patch.dll | 20,480 | 4 ordinal exports | KERNEL32 only |
| 20201 | 2020 winmm.dll | 90,624 | 194 WinMM functions | KERNEL32, bcrypt, WININET |
| 20202 | 2020 patch.dll | 16,896 | 4 ordinal exports | KERNEL32 only |
All six are x86 PE32 DLLs. All three winmm.dll variants contain the strings HORSE_HTTP_PORT, 127.0.0.1, and http://. The 2018 and 2020 variants additionally contain whatsnew.starstable.com and whatsnew.stage.starstable.com; the 2014 variant does not. The 2014 variant uniquely imports USER32.dll for GetAsyncKeyState; the 2018 and 2020 variants do not import USER32 at all for the proxy itself (the launcher imports it separately).
All three patch.dll variants export four functions by ordinal only, import only KERNEL32 and the VC++ runtime, and contain the strings VirtualProtect, VirtualAlloc, and FlushInstructionCache. None of the six DLLs has any network imports beyond WININET in the winmm.dll variants.
The winmm.dll proxies export the real WinMM functions and forward them to the system copy, which they load from System32. Windows searches the application directory before System32 [4], so SSOClient.exe loads the proxy instead of the real library. This is the standard DLL proxy technique: the host keeps working, and the proxy’s code runs first.
The proxy uses WININET to talk to 127.0.0.1 on the port named by HORSE_HTTP_PORT. Where present, the whatsnew hostnames cause the patched client to redirect its news requests away from the official Star Stable servers.
patch.dll is the memory-patching component. Its three notable KERNEL32 imports, VirtualProtect, VirtualAlloc, and FlushInstructionCache, are the standard combination for rewriting executable code in a running process. The DLL expects to run inside SSOClient.exe or PXStudioRuntimeMMO.exe.
Tor for Accounts, Direct TCP for the Game
The profile parser accepts only a v3 onion address as the account host: 56 base32 characters followed by .onion [5]. A regular domain is rejected. The launcher then starts the bundled tor.exe with --DataDirectory, --SocksPort, --ControlPort, --CookieAuthentication, --CookieAuthFile, --ClientOnly, and --SafeSocks, and routes login, downloads, and code redemption through it. The launcher monitors the Tor control port for Bootstrapped 100% and status/circuit-established=1 before enabling login.
The game connection does not use Tor. For each client year the profile holds a host and a port, which the launcher hands to the game as NetworkServer and NetworkServerPort. NetworkLauncherServer is set to 127.0.0.1 and UseNewServerConnect to 1, so the game talks to the launcher on localhost. The launcher talks to the real server and passes a NetworkTicket once it has one.
These connections are SOCK_STREAM / IPPROTO_TCP sockets. The only other socket is an IPv6 SOCK_DGRAM socket that is created and immediately closed, which is a UDP availability check rather than part of the game protocol. The embedded DLLs import neither sendto nor recvfrom.
The Signed and Encrypted cfg.hors Profile
cfg.hors is 4,205,180 bytes. The file layout is:
0x00 magic "HORS" (0x53524F48)
0x04 version (u32, must be 1)
0x08 ciphertext length (u32, file size minus 104)
0x0C 12-byte AES-GCM nonce
0x18 ciphertext
16-byte AES-GCM tag
64-byte ECDSA P-256 signature
The last 64 bytes are an ECDSA P-256 signature over everything before them. The public key ships inside the launcher as a BCrypt blob with magic 0x31534345 (ECS1, BCRYPT_ECDSA_PUBLIC_P256_MAGIC), key size 0x20, and the X and Y coordinates. The algorithm string is ECDSA_P256.
The payload is encrypted with AES-256-GCM via BCryptDecrypt using the ChainingModeGCM chaining mode [6]. The first 24 bytes of the file (magic, version, and ciphertext length) serve as additional authenticated data, so the header is covered by the tag. The 32-byte key is a constant at file offset 0x1438F0 in HorseLauncher.exe:
378aa25e7de20d75caa84957b795858fefd395c4274868ff6f137ba2ec67699a
Decryption yields 4,205,076 bytes of plaintext. A truncated file fails the tag check. The plaintext structure is:
u32 version (1)
lp profile id "horse-empire"
lp profile name "Horse Empire"
lp account host "2slqbzmg7k56iwrmbxensn7nrjufubtdbhpanbix5gwusn53vpl454yd.onion"
u16 account port 80
lp api path "/api/launcher/"
lp note "Thanks for the Discord art Bunni!"
u8 game count 3
for each game:
u16 year number
lp year string
lp game host
u16 game port
u8 image count 4
for each image:
u8 type index (0, 1, 2, 3)
u32 size
raw image data
Where lp is a uint16 length prefix followed by that many bytes. The three game entries:
| Year | Host | Port |
|---|---|---|
| 2020 | 77.233.223.176 | 20000 |
| 2018 | 77.233.223.176 | 18000 |
| 2014 | 77.233.223.176 | 13000 |
The four images are two JPEGs (237 KB and 3,528 KB) and two PNGs (54 KB and 288 KB). There is no executable code in the profile. The plaintext ends exactly after the last image, with zero bytes remaining.
77.233.223.176 belongs to Timeweb in Russia (77.233.223.0/24, AS9123, netname TW-Cloud). TCP connections to ports 80, 443, 13000, 18000, and 20000 were refused, and UDP probes to the three game ports received no response.
The Launcher API
The launcher’s strings reveal a comprehensive REST API routed through Tor to the onion backend. The endpoints fall into four categories:
Launcher endpoints (all under /api/launcher/):
| Endpoint | Method | Purpose |
|---|---|---|
login | POST | Returns token, uid, username, star_coins, subscription_level, game_master, moderator, and all game server addresses |
session | POST | Validates an existing token, returns the same fields as login |
logout | POST | Invalidates the session token |
download | POST | Returns a SwissTransfer URL, file size, SHA-256 hash, and 32-byte AES key for the requested game year |
integrity | POST | Accepts game and build_id, returns whether the client files are up to date |
launch-ticket | POST | Returns a ticket string after integrity verification passes |
code-history | POST | Returns the user’s redeemed code history |
invites | POST | Returns the user’s invitation list |
redeem | POST | Redeems a gift code |
change-password | POST | Changes the account password |
Web endpoints (under /api/web/): login, session, logout, download, payments/create, payments/history, reseller/create, reseller/history. These are CORS-restricted; requests from outside the site return "Origin is not allowed.".
Game relay endpoints (under /launcher/): game_data/, update_ticket/, reserve_character_name/, create_character_horse/. These appear to be proxied to the game server.
Other endpoints: /api/register, /api/profile (returns character creation defaults including first_name, horse1, face_style, etc.), /api/registration/status, /api/security/manifest, /api/archive-options, /api/n/ (news).
Login Replaces the Game Server Address
The login endpoint takes form-encoded username and password at /api/launcher/login. The response includes the session token, account metadata, and all game server addresses:
{
"ok": true,
"token": "286db87c...25d7b",
"uid": 2007,
"username": "victorspet",
"star_coins": 0,
"subscription_level": 70,
"game_master": false,
"moderator": false,
"server_host": "162.35.243.182",
"server_port": "20000",
"game_2020_host": "162.35.243.182",
"game_2020_port": "20000",
"game_2014_host": "162.35.243.182",
"game_2014_port": "13000",
"game_2018_host": "162.35.243.182",
"game_2018_port": "18000"
}
The game server address in the signed profile (77.233.223.176, Timeweb, Russia) is stale. The login response overwrites it with 162.35.243.182. The ports remain the same. A session token validation via /api/launcher/session returns identical fields, confirming the token is stateless with respect to address resolution.
162.35.243.182 falls in the range 162.35.242.0 to 162.35.243.255, netname moula-world-llc, country US, origin AS212477 [7]. TCP connections to the three game ports timed out after 8 seconds. Unlike the Timeweb host, which refused connections immediately, this host silently dropped them.
The Integrity and Ticket Flow
The launch sequence requires three steps after login:
-
Download: POST to
/api/launcher/downloadwithtokenandgame(e.g.,2020). The response includes a SwissTransfer URL, the package size, its SHA-256 hash, and a 32-byte AES-256-GCM key. -
Integrity check: POST to
/api/launcher/integritywithtoken,game, andbuild_id. The server compares the build ID against its current manifest. If the client is outdated, it returns{"ok": false, "update_available": true}. If current, it returns{"ok": true}. -
Launch ticket: POST to
/api/launcher/launch-ticketwithtokenandgame. This only succeeds after a passing integrity check. The response is a single-use ticket:{"ok": true, "ticket": "363a4b7c...6264"}.
The server publishes integrity manifests at /api/security/manifest?game=<name>. These list every file the client directory must contain, one SHA-256 hash per line. The launcher manifest covers only HorseLauncher.exe itself. The game manifests list 7 to 9 files each:
2020 manifest (9 files): Data.ccx, fmod.dll, fmod_distance_filter.dll, fmod_gain.dll, fmodstudio.dll, libxl.dll, patch.dll, SSOClient.exe, winmm.dll.
2018 manifest (7 files): Data.ccx, fmod.dll, fmodstudio.dll, InputActions.ini, patch.dll, PXStudioRuntimeMMO.exe, winmm.dll.
2014 manifest (8 files): Data.cch, fmod.dll, fmodstudio.dll, patch.dll, PluginData.cch, PXStudioRuntimeBrowserDLL.pxzi, PXStudioRuntimeMMO.exe, winmm.dll.
Every hash in the 2020 and 2014 manifests matches the corresponding hash from the HORSBOX1 packages and the embedded DLL resources. The server verifies that the launcher and the game files are exactly the versions it distributed.
The HORSBOX1 Game Package
setup.exe does not contain the game itself. The /api/launcher/download endpoint returns a SwissTransfer link, a file size, a SHA-256 hash, and a 32-byte key. The download response for each game year on September 29, 2026:
| Game | Size | Variant | SHA-256 (first 16) |
|---|---|---|---|
| 2020 | 3,398,253,064 | C | 810a3a8dc3a9... |
| 2018 | 3,025,198,333 | D | 9f1c1b445164... |
| 2014 | 955,644,456 | A | 402495fe7af4... |
The 2020 package was downloaded and analyzed for the original article. Its SHA-256 was b0173cdd55c0ed3bc5ad0f5a473044589a524d7e25ef5058c27bfa15836a9f8f with variant A; the current download returns a different hash with variant C, confirming the server rotates packages.
The file starts with the magic HORSBOX1. It is neither a ZIP archive nor a client executable with a prepended header, but a custom encrypted container. The launcher reads a 0x48-byte header:
| Offset | Field |
|---|---|
| 0x00 | HORSBOX1 |
| 0x08 | version, u32, value 1 |
| 0x0C | header size, u32, value 0x48 |
| 0x10 | index offset, u64 |
| 0x18 | index length, u64 |
| 0x20 | the same length again |
| 0x28 | 12-byte nonce |
| 0x34 | 16-byte GCM tag |
The index occupies the last bytes of the file. The launcher seeks to the index offset and decrypts it with AES-256-GCM, using the key from the download JSON and the first 0x28 header bytes as additional authenticated data. With these inputs the tag verifies.
The decrypted index starts with a u32 version (1) and a u32 chunk size (0x400000, 4 MiB). Three u32 length-prefixed strings follow: the client year, the release hash (an MD5 hex string), and a single-letter variant. Then a u64 total plaintext size and a u32 file count. Unlike cfg.hors, which uses u16 length prefixes, the HORSBOX1 index uses u32 prefixes throughout.
Each file record holds a u32-prefixed name, the plaintext size as u64, a 32-byte SHA-256 hash, and a u32 chunk count followed by that many chunk entries. Each chunk entry is 49 bytes: a u64 file offset, three u32 sizes (ciphertext, plaintext, stored), a u8 flag, a 12-byte nonce, and a 16-byte GCM tag. Every flag in the analyzed packages is 0, indicating no compression. The additional authenticated data for a chunk is HORSBOX1 followed by five little-endian u32 values (version, file index, chunk index, plaintext size, ciphertext size) and the flag byte.
Every decrypted file matched the SHA-256 hash stored in the index. These hashes are what the “File verification required” error refers to: the launcher hashes the files it has just written and only then requests a ticket.
Contents of the 2014 Package (Independently Verified)
The 2014 package was downloaded (955,644,456 bytes, SHA-256 eba302005515fb333490a63080d702b13186711a3df597ed88e8868f3faeca0d), its index decrypted, all 18,762 files catalogued, and a random sample of 100 files across all file types decrypted and verified against their index hashes. All 100 passed. The eight executables and DLLs were fully extracted and analyzed:
| File | Size | Authenticode | Notes |
|---|---|---|---|
PXStudioRuntimeMMO.exe | 3,181,616 | No | 32-bit, imports D3D9, DirectSound, FMOD, WinSock, WinINet |
winmm.dll | 50,688 | No | 194 exports, imports bcrypt + WININET; byte-identical to resource 20141 |
patch.dll | 22,016 | No | 4 ordinal exports, KERNEL32 only; byte-identical to resource 20142 |
fmod.dll | 1,518,080 | No | FMOD 1.x, 1088 C++ exports |
fmodstudio.dll | 1,075,200 | No | FMOD Studio, 341 exports, links fmod.dll |
Plugins/fmod_distance_filter.dll | 9,216 | No | FMOD plugin, single export |
Plugins/fmod_gain.dll | 8,704 | No | FMOD plugin, single export |
PXStudioRuntimeBrowserDLL.pxzi | 2,510,839 | n/a | Not a PE; compressed game data |
Two additional .dylib files (macOS builds of the FMOD plugins, 42 KB and 41 KB) are included but unused on Windows.
PXStudioRuntimeMMO.exe imports 12 DLLs: KERNEL32, USER32, GDI32, SHELL32, WININET, WINMM, WS2_32, DSOUND, d3d9, d3dx9_36, COMDLG32, and ole32. The SHELL32 import is ShellExecuteA (for opening URLs, standard in game clients). The WININET imports are InternetOpenA, InternetConnectA, HttpOpenRequestA, HttpSendRequestA, InternetReadFile, and InternetCloseHandle, covering HTTP asset requests. There are no imports for CreateRemoteThread, WriteProcessMemory, or any injection API. Section entropy ranges from 4.11 (.data) to 6.58 (.rsrc), consistent with unpacked native code.
The remaining 18,752 files are game data: .pte textures (6,799 files), .pmt material definitions (6,485), .pme meshes (2,440), .pan animations (1,163), .pso shaders (997), .pxo objects (341), .pco collision (202), .psm scene maps (185), .wav audio (101), and smaller counts of .pxw, .pfo, .ed, .tei, .ter, and .cch files. No file with a game-data extension contained a PE header or suspicious strings (cmd.exe, powershell, mimikatz, keylog, stealer) in its first 4 KB.
The 2014 package is the Star Stable 2014 client (PXStudio engine build) plus the same winmm.dll proxy and patch.dll that the launcher carries as embedded resources. No additional executables, no stealer code, no unexpected binaries.
Contents of the 2020 Package
The relevant files in the package:
| File | Size | SHA-256 |
|---|---|---|
SSOClient.exe | 7,677,576 | ac54e8321c8bb20c6323dae7c84436b80c77a39b249b2940e967666b376e56bd |
winmm.dll | 90,624 | 12170bd9431163d765f1a8c4f828ddaaa1abe4cde761e3f08d2d3a651ffd8cc8 |
patch.dll | 16,896 | f21da892593900e13a57148fdf567100554c9d961533b20b19789ba8be643ab7 |
fmod.dll | 1,518,080 | 7665458ae8805ac7b6ca719c973235c518aad189d56579537413e11159f97da5 |
libxl.dll | 6,517,760 | 1919cee80b6e63bcf61071e7e441a68873a27ac1cf856d3cee90baca23928bb6 |
crashpad_handler.exe | 741,888 | 9c1bf63828413cdb5f176072e4453d7c0516bce34f7883b687e7ba7352fc85fb |
Data.ccx | 4,578,029 | cc87b021a2bd02a071b8fe5f973b99b9b6e89eea0a47a37c2c8ab1ce281be98d |
SSOClient.exe is a PE32 binary with CompanyName Star Stable Entertainment AB, ProductName Star Stable Online, FileVersion 51.95333, and ProductVersion PXEngine 51. It contains the build path PXRelease2020_51\Projects\StarStableOnline, imports WINMM.dll, FMOD, OpenGL32, and WinHTTP, and has a CPADinfo section. Its OpenGL 3.0 warning string matches the text of the official client.
winmm.dll and patch.dll are byte-identical to the 2020 pair embedded in HorseLauncher.exe as resources 20201 and 20202, with the same HORSE_HTTP_PORT, http://127.0.0.1:, and news host strings and the same three memory imports in patch.dll.
The remaining program files are the usual dependencies of the 2020 client. fmod.dll is FMOD 1.10.1 from Firelight Technologies, accompanied by fmodstudio.dll and two small FMOD plugins; Mach-O .dylib builds of those plugins sit in the same tree. crashpad_handler.exe is Chromium’s crash reporter. libxl.dll is LibXL 3.8.1.0 from XLware, and SSOClient.exe already references it by name.
The bulk of the package is game data: Data.ccx and PackFiles/p_00000000.csa through p_00000012.csa, each with a matching .csaheader. The headers list scenes, animations, and models (.scene, .pan, .pme, .pte) and do not reference any additional executable.
The package is the 2020 Star Stable client plus the same two DLLs the launcher already carries. None of the 40 files contains a separate stealer.
Host Artifacts
For identifying an installation on a machine:
| Artifact | Location |
|---|---|
| Saved password | RememberedPassword under HKCU\Software\StarRiders\Launcher |
| Server profiles | HKCU\Software\HorseLauncher\Profiles\ |
| Mutex | Local\HorseLauncher.Profile. |
| Profile import filter | *.hors |
| Tor data directory | %LOCALAPPDATA%\HorseMuseum\Tor |
| Uninstall entry | HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall\HorseLauncher |
| Desktop shortcut | Horse Launcher.lnk |
| Start menu entry | Programs\HorseLauncher |
The game process receives NetworkServer, NetworkServerPort, NetworkTicket, NetworkUserName, NetworkUserId, NetworkLauncherServer, NetworkLauncherHash, and UseNewServerConnect from the launcher.
Assessment
Despite its delivery, the installer is a private Star Stable Online client and not a stealer. Every component has been accounted for:
- The outer NSIS installer writes the launcher, Tor, and runtime redistributables. Its script creates shortcuts and an uninstall entry; it touches no browser profiles, run keys, or services.
- The nested
runtimes.execontains only three Microsoft-signed redistributables (VC++ 2013, VC++ 2015-2022, DirectX). - The launcher binary imports 15 DLLs, none of which are associated with credential theft. Its embedded DLLs are
winmm.dllproxies and in-memory patchers, not injectors. - The
cfg.horsprofile contains server metadata and four images, no code. - The HORSBOX1 2014 game package was independently downloaded (955 MB), its custom encrypted container format reverse-engineered, and all 18,762 files catalogued. A random sample of 100 files was decrypted and verified against the index hashes with zero failures. All eight executables and DLLs were extracted and analyzed: the game engine (
PXStudioRuntimeMMO.exe), FMOD audio libraries, and the samewinmm.dllproxy andpatch.dllthat the launcher embeds. No hidden executables, no stealer code, no suspicious strings in any sampled file. - The 2020 package contains the same pattern: the Star Stable 2020 client (
SSOClient.exewith PXEngine 51) plus the same proxy DLLs. - The
winmm.dllandpatch.dllfiles from the 2014 package are byte-identical (SHA-256 match) to the ones embedded in the launcher as resources 20141 and 20142. The same holds for the 2020 pair. - The API surface covers account management, game downloads, integrity checking, and launch tickets. There are no endpoints for exfiltrating browser data, Discord tokens, or wallet files.
- The server enforces file integrity through SHA-256 manifests and issues launch tickets only after verification passes.
The game server address in the signed profile is a placeholder. The onion backend replaces it at login, and it has already moved once (from Timeweb in Russia to Moula World LLC in the US). The download packages rotate variants. The backend can change the game server address, the download links, or the package contents at any time without touching setup.exe or cfg.hors.
Both game server addresses were unreachable during testing (the Timeweb host refused connections, the US host silently dropped them), so the game protocol itself was not observed.
Drafted with LLM assistance from setup.exe, HorseLauncher.exe, cfg.hors, the onion backend API (login, session, download, integrity, ticket, manifest, profile, and registration endpoints queried on September 29, 2026), the 2014 HORSBOX1 package (955 MB, independently downloaded, decrypted, and verified: all 18,762 files catalogued, 100-file random sample passed SHA-256 verification, all executables extracted and analyzed), and the 2020 HORSBOX1 package. Reviewed against the samples.
References
[1] Nullsoft Scriptable Install System, https://nsis.sourceforge.io/Main_Page
[2] Microsoft, PE Format, https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
[3] Microsoft, KNOWNFOLDERID, FOLDERID_LocalAppData, https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
[4] Microsoft, Dynamic-Link Library Search Order, https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
[5] Tor Project, Onion services, https://community.torproject.org/onion-services/overview/
[6] Microsoft, BCryptDecrypt, https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptdecrypt
[7] RIPE Database query for 162.35.243.182, https://apps.db.ripe.net/db-web-ui/query?searchtext=162.35.243.182