GEMS

August 3, 2025 · View on GitHub

The Ground Equipment Monitoring Service (GEMS) plugin for Caldera provides adversary emulation abilities specific to the OMG-GEMS communication protocol.

v1.0.0 released 6 Aug 2025

Overview

The GEMS plugin provides 9 abilities specific to the GEMS protocol. Variants of each ability are provided for both the XML and ASCII message formats defined by the GEMS specification. Adversary emulation is accomplished not through exploitation, but rather by leveraging native functionality within the protocol. The specification for the GEMS protocol is available free of charge from OMG-GEMS.

The following table outlines MITRE ATT&CK for ICS coverage provided by the GEMS plugin.

DiscoveryCollectionImpair-Process-Control
Remote System DiscoveryPoint & Tag IdentificationModify Parameter
Brute Force I/O
Unauthorized Command Message

Ability Overview Table

The following table lists each plugin ability by their corresponding tactic.

NameTacticTechniqueTechnique Id
GEMS - PingdiscoveryRemote System DiscoveryT0846
GEMS - Get ParametercollectionPoint & Tag IdentificationT0861
GEMS - Get All ParameterscollectionPoint & Tag IdentificationT0861
GEMS - Get Configuration ListcollectionPoint & Tag IdentificationT0861
GEMS - Set Parameterimpair-process-controlModify ParameterT0836
GEMS - Save Configurationimpair-process-controlUnauthorized Command MessageT0855
GEMS - Load Configurationimpair-process-controlModify ParameterT0836
GEMS - Send Directiveimpair-process-controlUnauthorized Command MessageT0855
GEMS - Send Directive with Argumentsimpair-process-controlUnauthorized Command MessageT0855

Architecture

This section describes the main components of the plugin and how they interface.

Block Diagram

block diagram

The GEMS plugin exposes several new protocol specific abilities to your Caldera instance. The abilities are executed from a host running a Caldera agent via the corresponding payload. Abilities must target devices that support the GEMS protocol to achieve described effects.

Payloads

The GEMS plugin includes one payload, compiled for 3 different architectures, to implement the abilities in the plugin.

  • gems-client.exe: Windows executable
  • gems-client: Linux executable
  • gems-client_darwin: macOS (ARM) executable

Libraries

The following libraries were used to build the GEMS payloads:

LibraryVersionLicense
cobrav1.8.0Apache 2.0

Usage

This section describes how to initially deploy and execute the abilities present within the GEMS Plugin.

Deployment

  1. Identify the target system you would like to communicate with via the GEMS protocol.
  2. Identify a viable host for the Caldera agent that will be sending GEMS messages to the target system.
  3. Deploy the Caldera agent to the identified host.
  4. Use the Caldera server to execute GEMS plugin abilities to achieve the desired effect.
Each ability contains optional parameters if needed to customize the connection
to the GEMS device. These allow you to set the GEMS version, connection token,
target device, and choose to connect using TLS.
Reference the Caldera training plugin for a step-by-step tutorial on how to
deploy an agent and run abilities via an operation.

Sample Fact Source YAML File

The plugin includes a sample fact source (also copied below) to demonstrate how to save information about your environment to use as arguments to abilities.

id: eb1ba869-176a-46cb-a2f1-f47cc735ed68
name: GEMS Sample Facts
facts:
- trait: gems.device.addr
  value: localhost:12345
- trait: gems.device.psm
  value: ascii
- trait: gems.device.psm
  value: xml 
- trait: gems.device.user
  value: none
- trait: gems.device.password
  value: none
- trait: gems.config.name
  value: ExampleConfig 
- trait: gems.parameter.names
  value: Example,Parameter,Names
- trait: gems.parameter.value
  value: ExampleIntValue:int=1024
- trait: gems.parameter.value
  value: ExampleStringValue:string=HelloWorld
- trait: gems.directive.name
  value: ExampleDirectiveName 

GEMS Authentication

The GEMS specification defines a very basic, optional authentication scheme. If configured by the GEMS device (server), the user must identify themselves with a username and password in the initial ConnectMessage. This information is passed to the device in the token field of the GEMS message header. In this plugin, the abilities are designed to allow the input of a username and password by default. If your device does not require authentication, set "none" as the value for the #{gems.device.user} and #{gems.device.password} facts. Alternatively, arbitrary token values can be sent in the ConnectMessage header by setting the value of the --token flag.

Abilities

GEMS - Ping

Connect to a GEMS server and send a PingMessage.
The PingMessage provides a method for determining if a GEMS device is responding to messages.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe ping #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client ping #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin ping #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Get Parameter

Connect to a GEMS server and send a GetConfigMessage.
The GetConfigMessage requests the value of a parameter in the current configuration from the GEMS device.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe get #{gems.device.psm} #{gems.device.addr} --names #{gems.parameter.names} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client get #{gems.device.psm} #{gems.device.addr} --names #{gems.parameter.names} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin get #{gems.device.psm} #{gems.device.addr} --names #{gems.parameter.names} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string
gems.parameter.namesdesired parameter namescomma separated list of strings

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Get All Parameters

Connect to a GEMS server and send a GetConfigMessage.
The GetConfigMessage with no parameters specified requests the values of all parameters in the current configuration from the GEMS device.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe get #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client get #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin get #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Set Parameter

Connects to a GEMS server and sends a SetConfigMessage.
The SetConfigMessage contains a list of parameters to set and their new values. Parameters are passed using the -p or --param flag and must be formatted as defined by GEMS ASCII.

The ability is configured to set one parameter at a time, but the `--param` flag
can be repeated to set more than one parameter in a single message.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe set #{gems.device.psm} #{gems.device.addr} --param #{gems.parameter.value} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client set #{gems.device.psm} #{gems.device.addr} --param #{gems.parameter.value} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin set #{gems.device.psm} #{gems.device.addr} --param #{gems.parameter.value} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string
gems.parameter.valuea GEMS parameter formatted as defined by GEMS ASCIIstring

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Save Configuration

Connects to a GEMS server and sends a SaveConfigMessage.
The SaveConfigMessage saves the configuration as the provided name. The configuration name is an alphanumeric string with no spaces.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe save #{gems.device.psm} #{gems.device.addr} #{gems.config.name} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client save #{gems.device.psm} #{gems.device.addr} #{gems.config.name} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin save #{gems.device.psm} #{gems.device.addr} #{gems.config.name} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string
gems.config.namename to assign to the configurationstring

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Load Configuration

Connects to a GEMS server and sends a LoadConfigMessage.
The LoadConfigMessage loads the configuration with the provided name. The configuration name is an alphanumeric string with no spaces.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe load #{gems.device.psm} #{gems.device.addr} #{gems.config.name} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client load #{gems.device.psm} #{gems.device.addr} #{gems.config.name} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin load #{gems.device.psm} #{gems.device.addr} #{gems.config.name} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string
gems.config.namename of the configuration to loadstring

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Get Configuration List

Connects to a GEMS server and sends a GetConfigListMessage.
The GetConfigListMessage retrieves all configurations available on the GEMS device.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe get-config-list #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client get-config-list #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin get-config-list #{gems.device.psm} #{gems.device.addr} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Send Directive

Connects to a GEMS server and sends a DirectiveMessage.
The DirectiveMessage invokes an action on the GEMS device.

To send arguments along with a directive, use the [GEMS - Send Directive with Arguments](#gems---send-directive-with-arguments) ability.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe directive #{gems.device.psm} #{gems.device.addr} #{gems.directive.name} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client directive #{gems.device.psm} #{gems.device.addr} #{gems.directive.name} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin directive #{gems.device.psm} #{gems.device.addr} #{gems.directive.name} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string
gems.directive.namename of the directive to callstring

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

GEMS - Send Directive with Arguments

Connects to a GEMS server and sends a DirectiveMessage.
The DirectiveMessage invokes an action on the GEMS device. The message may contain contain a list of parameter arguments. Parameters are passed using the --params flag and must be formatted as defined by GEMS ASCII. Multiple parameters must be separated by the pipe character (|).

The pipe character (`|`) may need to be escaped with a backslash (`\|`) depending on the shell in use by the agent.

Ability Command:

Windows (cmd/psh)
.\gems-client.exe directive #{gems.device.psm} #{gems.device.addr} #{gems.directive.name} --params #{gems.parameter.value} --user #{gems.device.user} --pass #{gems.device.password}
Linux (sh)
./gems-client directive #{gems.device.psm} #{gems.device.addr} #{gems.directive.name} --params #{gems.parameter.value} --user #{gems.device.user} --pass #{gems.device.password}
Darwin (sh)
./gems-client_darwin directive #{gems.device.psm} #{gems.device.addr} #{gems.directive.name} --params #{gems.parameter.value} --user #{gems.device.user} --pass #{gems.device.password}

Facts:

NameDescriptionType
gems.device.psmmessage format used by the device ('ascii' or 'xml')string
gems.device.addraddress of the device in "host:port" formatstring
gems.device.userusername for authentication (send 'none' for no authentication)string
gems.device.passwordpassword for authentication (send 'none' for no authentication)string
gems.directive.namename of the directive to callstring
gems.parameter.valueGEMS parameter(s) formatted as defined by GEMS ASCIIstring

Optional Flags:

FlagDescriptionTypeDefault
--versionset the GEMS versionstring1.4
--targetname of the target devicestring-
--tokenGEMS connection tokenstring-
--tlsconnect using TLSnonefalse
--insecureallow self-signed certificates when connecting using TLSnonefalse

Source Code

The source code for the plugin payloads can be found inside this plugin's src directory.

GEMS® is a registered trademark of Object Management Group, 9C Medway Road, PMB 274, Milford, MA 01757, USA.

This Caldera plugin is named GEMS in order to describe its scope and purpose. This plugin is not produced by or affiliated with Object Management Group.