Martin's Blog

Appendix F: IOC Catalogue

This catalogue turns the reconstruction into defensive leads. It covers the RCS operator/backend platform and the deployment edge visible in the examined source. It is not a universal signature for HackingTeam products, and it does not claim to identify every implant, customer configuration, successor product, or later version.

An indicator’s value depends on where it is observed. A TLS issuer can be seen on a network sensor. A REST path normally requires TLS termination. A service name requires host telemetry or a forensic image. A MongoDB collection shape requires database access. The tables preserve that sensor position together with provenance and false-positive limits.

Confidence has the following meaning:

Do not block or attribute solely on a low-confidence item. Even a high- confidence technical match identifies software or infrastructure, not the customer, operator, legal authority, target, or successful use.

Highest-value combinations

CombinationSensorProvenanceConfidenceWhy it matters
Default CA issuer containing both Root Certification Authority and ACME Corp, long-lived leaf, and adjacent RCS REST/WSS behaviorTLS/networkSOURCE + LABHigh for an unchanged defaultThe issuer fields are generic separately; service behavior supplies specificity
Cleartext X-Auth-Frontend on an internal HTTP flow to a collector, corroborated by collector/database topologyNetwork or proxy logSOURCEHighThe header names an RCS frontend trust mechanism; redact its credential value
C:\RCS\DB with RCSMasterConfig, RCSMasterRouter, or RCSShard, plus matching Mongo service pathsWindows hostSOURCEHighExact root, service names, and process layout form a distinctive installer cluster
RCS licence YAML schema beside database launchers and certificate-generation sourceFile scan/forensic imageSOURCEHighMulti-field content rules avoid relying on a generic filename
evidence.<target-id>, aggregate.<target-id>, and paired grid.<target-id>.files/.chunks collections beside items, audit, and signaturesMongoDB/backupSOURCE + LABHighThe coordinated target-scoped family is much stronger than MongoDB alone
Several RCS-specific REST nouns in one authenticated session, such as /agent/filesystems, /collector/del_logs, /backuparchive, /injector/add_rule, and /shardTLS-terminated HTTPSOURCE + LABHighRoute clustering is stronger than /auth/login or JSON field names alone

These combinations are starting points for confirmation. Preserve surrounding transactions, process state, certificates, database metadata, and timestamps before taking disruptive action.

Network and service topology

Port or relationshipExpected roleProvenanceStandalone confidenceCaveat
TCP 443Database HTTPS REST; also collector-to-database loginSOURCE + LABLowOrdinary HTTPS; configurable
TCP 444Database WSS, normally REST port plus oneSOURCE + LABLow to medium as a pairPort is non-unique and may be proxied
TCP 442Worker evidence ingressSOURCE + LABLow by port; higher with framing and host evidenceLab keeps it internal; exposure is deployment-dependent
TCP 80Collector public listener and backend-to-collector frontend requestsSOURCELowNo collector was run; HTTP is ubiquitous
TCP 4499 on loopbackCollector-to-network-controller serviceSOURCEMedium on a matching collector hostConfigurable; remote exposure would differ from the examined default
TCP 27017/27018/27019Mongo router, shard server, and configuration serverSOURCE + LABMedium as a co-located trioStandard MongoDB roles; network placement varies

The book’s host ports 127.0.0.1:44443 and 127.0.0.1:44444 are lab mappings, not original RCS indicators. Likewise, container names such as rcs-db-lab:9.2, the private Compose network, and port 8080 belong to the reconstruction only.

TLS and HTTP

IndicatorProvenanceConfidenceCompanion evidenceFalse-positive or evasion note
CA subject includes CN=Root Certification Authority and O=ACME CorpSOURCE; lab-generated exampleMedium alone; high in combinationTen-year leaf, RCS ports/routes, host artifactsOperators can replace certificates; both strings occur elsewhere
Database leaf common name set to configured server name/addressSOURCELowIssuer cluster and adjacent WSSFully configurable
Collector certificate common name collectorSOURCELow to mediumMatching CA, component login, host roleGeneric word
Certificate validity of 3,650 daysSOURCELowDefault issuer and RCS topologyCommon in old appliances
Every backend REST response sets Server: nginx although the application is EventMachineSOURCE + LABLow aloneRCS route, error body, TLS and process evidenceReal nginx and many applications use the same banner
Sparse nginx-styled 403/404 body from the backendSOURCE + LABLowBanner plus application-specific route behaviorEasily copied and affected by proxies
X-Auth-Frontend request headerSOURCEHighDirection from database toward collector; topology recordsHeader value is a credential and should not be retained in ordinary alerts
Collector empty status 444/connection close after invalid trafficSOURCELowRepeated behavior, collector host evidence, RCS-specific trafficOrdinary nginx configurations use 444; wire outcome can be only a close
Collector HACK ALERT logs after unauthorized privileged methods or traversal attemptsSOURCEMedium to high on hostCollector configuration/process and matching network timeLog strings can be copied or disabled

The old WebSocket stack also has a case-sensitive handshake quirk: proxied Connection: Upgrade works where a lowercase value can be dropped. It was reproduced while building the web port. Treat it as a version-specific diagnostic clue, not a durable network signature; intermediaries routinely normalize headers.

REST and application behavior

The original REST shape is /<controller>/<action>[/<id>]. A login request is POST /auth/login with user, pass, and version JSON fields. That pattern is only medium confidence and normally invisible without TLS termination. Stronger hunting looks for several of these less common paths in one service:

Route or behaviorMeaningProvenanceCaution
/agent/status first synchronization followed by an agent name ending in (N)Factory-to-agent clone lifecycleSOURCE + LABA request or name shows backend registration, not real-device attribution
/agent/filesystems, /agent/exec, /agent/upload, /agent/downloadQueued operator request surfacesSOURCE + LABA queued request proves intent, not delivery or execution
/evidence, /evidence/body, /grid/<id>?target_id=...Evidence metadata/body and target GridFS accessSOURCE + LABRequires authorization and sensor visibility
/collector/log/<id>, /collector/del_logs, topology tasksFrontend monitoring and log lifecycleSOURCE + WEB PORTUI rendering alone does not prove edge services ran
/injector/add_rule, /injector/logs/<id>Network Injector configuration/log surfaceSOURCE + WEB PORTDo not infer a successful injection from stored rules
/connector with a changing queue-derived statusEvidence export stateSOURCE + WEB PORTA connector record may be disabled or synthetic
/shard and /shard/<id> returning raw Mongo shard/dbStats structureBackend topology viewSOURCE + LABDatabase-administration tools can expose similar nouns
/evidence/sync_history returning a 404 while adjacent 9.6 console calls it9.2.3/9.6 pairing gapSOURCE + LABNarrow version fingerprint, not universal RCS behavior

Successful sessions use a UUID-like session cookie. Failed login bodies such as INVALID_ACCOUNT and EXPIRED_ACCOUNT are product clues but should not be actively elicited on an unknown system. An authentication attempt changes server state and can notify or disconnect an operator.

Collector and anonymizer leads

The collector defaults to database host name rcs-server, database port 443, public port 80, controller port 4499, and 30-second heartbeat/controller intervals. Candidate configuration commonly refers to config.yaml, a database certificate, a server-signature file, a public directory, local cache, and component logs.

The examined anonymizer source uses the program name bbproxy, compile-time prefix /opt/bbproxy, and tunable files named version, cookie, key, proxyport, and nexthop. It adds X-Forwarded-For and X-Proxy-Version when those headers are absent. The RCS manual instead documents an installed /opt/rcsanon service listening on port 443. That difference is a version/package clue: search for both families and preserve the exact executable and configuration before deciding which snapshot fits.

Neither X-Forwarded-For nor X-Proxy-Version is unique. The source proxy preserves client-supplied versions, so their values are also weak attribution evidence unless a trusted upstream sanitized them.

Implant-side source describes short encrypted authentication posts and build- randomized URI/cookie names. Because no implant-to-collector session was run, this catalogue does not promote body length or a “static-looking site” into a standalone production signature. Use those traits only as scoped hunting hypotheses with corroborating collector evidence.

Windows backend host artifacts

ArtifactProvenanceConfidenceNotes
C:\RCS\DB, with adjacent C:\RCS\Ruby, C:\RCS\Collector, C:\RCS\Java, or C:\RCS\PythonSOURCE installer/manualHigh as a clusterA research copy can reproduce the path
Services RCSMasterConfig, RCSMasterRouter, RCSShardSOURCE installerHighCombine with Mongo image paths under the RCS root
Firewall group RCS Firewall Rules and rule prefix RCS_FWDSOURCE installerHighPreserve full rule command, creator, and timestamps
AppCompat Layers value for C:\RCS\Ruby\bin\ruby.exe with DisableNXShowUISOURCE installerHighEncoded in a Sigma rule in Appendix G
config/, certs/, cores/, exploits/, log/err/, backup/, and Mongo data/config trees under the RCS installationSOURCE + MANUALMedium to high as a structureIndividual directory names are generic
rcs.lic beside RCS configuration and service filesSOURCEMedium by name; high by schemaMatch content schema, not filename alone
Bundled HASP support files and installerSOURCEMediumHardware-licence path is optional

The original source contains embedded licence and dongle material. The book does not repeat secret values as IOCs. On a seized authorized host, hash and restrict those files; do not copy credential values into shared alerting systems.

Licence and configuration schema

The RCS 9 licence is YAML with a distinctive combination of fields including serial, maintenance, platform entitlements, collector/anonymizer limits, hostname synchronization, correlation, deletion, signature, and integrity. The accompanying YARA rule requires several fields together and bounds file size.

Default backend configuration includes names for the CA, database certificate and key, listening port, heartbeat interval, backup directory, and shard. Most names are individually generic. Their value is in co-location with licence, service, certificate, and MongoDB evidence.

The default bootstrap administrator name and password are security findings, not recommended detection probes. Do not attempt them against a candidate. The presence of a default account in a preserved database can support a finding after authorized offline analysis, but an interactive login mutates sessions and audit state.

MongoDB and evidence storage

RCS target data forms coordinated collection families:

evidence.<24-hex-target-id>
aggregate.<24-hex-target-id>
grid.<24-hex-target-id>.files
grid.<24-hex-target-id>.chunks

Evidence collections use shard key {type, da, aid}, and aid is stored as a string in the original model. Binary evidence metadata points into the paired target GridFS bucket. These are high-value forensic indicators when found with global collections such as items, users, groups, sessions, audit, signatures, status, collectors, injectors, connectors, and task or alert queues.

Collection names alone still require care. A researcher could recreate them, and a backup may contain a partial or migrated database. Confirm indexes, field shape, ObjectId relationships, application files, and version evidence. Use read-only queries against a forensic clone; do not compact, repair, restore, or recalculate statistics on original evidence.

Behavioral and state indicators

Two lab-observed behaviors can assist diagnosis:

Both are low-confidence outside an already corroborated installation. Many systems enforce one session per user, and monitoring bugs are common. They are most useful for explaining observations, not finding RCS from scratch.

Explicit non-indicators

Do not treat any of the following as sufficient evidence:

The last group prevents the lab itself from contaminating historical hunts. Maintain explicit allowlists for authorized reconstruction systems and keep research traffic out of production detection corpora where possible.

Triage sequence

  1. Preserve the triggering event and its sensor position.
  2. Add one independent layer: network, host, database, certificate, or source artifact.
  3. Compare the exact version and deployment mode with the fidelity map.
  4. Exclude authorized research and forensic replay.
  5. Acquire passively before any login or API request.
  6. Separate platform identification, platform compromise, target compromise, and attribution.
  7. Record absent expected evidence and plausible configuration changes.

The source rule files and current validation status are reproduced in Appendix G. They remain experimental until their target engines and representative negative corpora have been exercised.

Sources and evidence

↑ HackingTeam's RCS: Bringing a Commercial Spyware Platform Back to Life