From c503c3d504cdf92ec9b88ae5181135135873ed6a Mon Sep 17 00:00:00 2001 From: <> Date: Wed, 26 Jul 2023 11:50:27 +0000 Subject: [PATCH] Deployed 1b604b0 with MkDocs version: 1.4.3 --- .nojekyll | 0 404.html | 1326 ++++ advanced/cyclone/index.html | 1363 ++++ advanced/enchanter/index.html | 1363 ++++ advanced/index.html | 1350 ++++ advanced/necromancer/index.html | 1361 ++++ animator/index.html | 1414 ++++ animator/jobs/index.html | 1457 ++++ animator/run/index.html | 1433 ++++ assets/images/favicon.png | Bin 0 -> 1870 bytes assets/img/animator-logo.png | Bin 0 -> 56253 bytes assets/img/crucible-icon-c-alpha.svg | 1 + assets/img/ghosts.png | Bin 0 -> 28157 bytes assets/img/npc-types.png | Bin 0 -> 66681 bytes assets/javascripts/bundle.220ee61c.min.js | 29 + assets/javascripts/bundle.220ee61c.min.js.map | 8 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.hy.min.js | 1 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.kn.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + assets/javascripts/lunr/min/lunr.sa.min.js | 1 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.te.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++ .../workers/search.74e28a9f.min.js | 42 + .../workers/search.74e28a9f.min.js.map | 8 + assets/screens/pandora.gif | Bin 0 -> 2041657 bytes assets/stylesheets/main.eebd395e.min.css | 1 + assets/stylesheets/main.eebd395e.min.css.map | 1 + assets/stylesheets/palette.ecc896b0.min.css | 1 + .../stylesheets/palette.ecc896b0.min.css.map | 1 + content/index.html | 1397 ++++ content/pandora/index.html | 1532 ++++ content/social/index.html | 1387 ++++ core/api/index.html | 1500 ++++ core/api/timelines/index.html | 1479 ++++ core/client/index.html | 1733 +++++ core/handlers/blog_helper/index.html | 1358 ++++ core/handlers/browser/index.html | 1418 ++++ core/handlers/clicks/index.html | 1356 ++++ core/handlers/cmd/index.html | 1356 ++++ core/handlers/excel/index.html | 1363 ++++ core/handlers/index.html | 1406 ++++ core/handlers/notepad/index.html | 1356 ++++ core/handlers/npc_system/index.html | 1356 ++++ core/handlers/outlook/index.html | 1358 ++++ core/handlers/pidgin/index.html | 1356 ++++ core/handlers/powerpoint/index.html | 1363 ++++ core/handlers/print/index.html | 1356 ++++ core/handlers/rdp/index.html | 1356 ++++ core/handlers/reboot/index.html | 1356 ++++ core/handlers/sftp/index.html | 1356 ++++ core/handlers/sharepoint_helper/index.html | 1358 ++++ core/handlers/ssh/index.html | 1356 ++++ core/handlers/watcher/index.html | 1356 ++++ core/handlers/wmi/index.html | 1356 ++++ core/handlers/word/index.html | 1363 ++++ index.html | 1457 ++++ new/index.html | 1415 ++++ quickstart/index.html | 1454 ++++ search/search_index.json | 1 + sitemap.xml | 3 + sitemap.xml.gz | Bin 0 -> 127 bytes spectre/index.html | 1477 ++++ stylesheets/extra.css | 3 + 89 files changed, 60455 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 advanced/cyclone/index.html create mode 100644 advanced/enchanter/index.html create mode 100644 advanced/index.html create mode 100644 advanced/necromancer/index.html create mode 100644 animator/index.html create mode 100644 animator/jobs/index.html create mode 100644 animator/run/index.html create mode 100644 assets/images/favicon.png create mode 100644 assets/img/animator-logo.png create mode 100644 assets/img/crucible-icon-c-alpha.svg create mode 100644 assets/img/ghosts.png create mode 100644 assets/img/npc-types.png create mode 100644 assets/javascripts/bundle.220ee61c.min.js create mode 100644 assets/javascripts/bundle.220ee61c.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hy.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.kn.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sa.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.te.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.74e28a9f.min.js create mode 100644 assets/javascripts/workers/search.74e28a9f.min.js.map create mode 100644 assets/screens/pandora.gif create mode 100644 assets/stylesheets/main.eebd395e.min.css create mode 100644 assets/stylesheets/main.eebd395e.min.css.map create mode 100644 assets/stylesheets/palette.ecc896b0.min.css create mode 100644 assets/stylesheets/palette.ecc896b0.min.css.map create mode 100644 content/index.html create mode 100644 content/pandora/index.html create mode 100644 content/social/index.html create mode 100644 core/api/index.html create mode 100644 core/api/timelines/index.html create mode 100644 core/client/index.html create mode 100644 core/handlers/blog_helper/index.html create mode 100644 core/handlers/browser/index.html create mode 100644 core/handlers/clicks/index.html create mode 100644 core/handlers/cmd/index.html create mode 100644 core/handlers/excel/index.html create mode 100644 core/handlers/index.html create mode 100644 core/handlers/notepad/index.html create mode 100644 core/handlers/npc_system/index.html create mode 100644 core/handlers/outlook/index.html create mode 100644 core/handlers/pidgin/index.html create mode 100644 core/handlers/powerpoint/index.html create mode 100644 core/handlers/print/index.html create mode 100644 core/handlers/rdp/index.html create mode 100644 core/handlers/reboot/index.html create mode 100644 core/handlers/sftp/index.html create mode 100644 core/handlers/sharepoint_helper/index.html create mode 100644 core/handlers/ssh/index.html create mode 100644 core/handlers/watcher/index.html create mode 100644 core/handlers/wmi/index.html create mode 100644 core/handlers/word/index.html create mode 100644 index.html create mode 100644 new/index.html create mode 100644 quickstart/index.html create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz create mode 100644 spectre/index.html create mode 100644 stylesheets/extra.css diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..8fde7e8c --- /dev/null +++ b/404.html @@ -0,0 +1,1326 @@ + + + + + + + + + + + + + + + + + + GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/advanced/cyclone/index.html b/advanced/cyclone/index.html new file mode 100644 index 00000000..295ab003 --- /dev/null +++ b/advanced/cyclone/index.html @@ -0,0 +1,1363 @@ + + + + + + + + + + + + + + + + + + + + + + Cyclone - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS CYCLONE Overview

+
+Unreleased +

Coming soon

+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/advanced/enchanter/index.html b/advanced/enchanter/index.html new file mode 100644 index 00000000..4363c542 --- /dev/null +++ b/advanced/enchanter/index.html @@ -0,0 +1,1363 @@ + + + + + + + + + + + + + + + + + + + + + + Enchanter (Keysender) - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS ENCHANTER Overview

+
+Unreleased +

Coming soon

+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/advanced/index.html b/advanced/index.html new file mode 100644 index 00000000..3389c930 --- /dev/null +++ b/advanced/index.html @@ -0,0 +1,1350 @@ + + + + + + + + + + + + + + + + + + + + + + GHOSTS Advanced Features Overview - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS Advanced Features Overview

+

The SEI is a research institute, and so we often are thinking about how to use GHOSTS in new ways to drive insight for our customers. Some of this work makes it here, with the caveat that it might be early beta editions or require some amount of engineer hand-holding in its current state. Some call it pre-release, we call it advanced features.

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/advanced/necromancer/index.html b/advanced/necromancer/index.html new file mode 100644 index 00000000..7fc15b8f --- /dev/null +++ b/advanced/necromancer/index.html @@ -0,0 +1,1361 @@ + + + + + + + + + + + + + + + + + + + + Necromancer - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS NECROMANCER Overview

+
+Unreleased +

Coming soon

+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/animator/index.html b/animator/index.html new file mode 100644 index 00000000..9e30ab5c --- /dev/null +++ b/animator/index.html @@ -0,0 +1,1414 @@ + + + + + + + + + + + + + + + + + + + + + + GHOSTS ANIMATOR Overview - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS ANIMATOR Overview

+
+GHOSTS ANIMATOR Source Code +

The GHOSTS ANIMATOR Source Code Repository is hosted on GitHub

+
+

Animator brings NPCs to life in two ways:

+
    +
  1. +

    Initial Creation

    +

    Animator creates the initial NPC profile, including details such as name, address, career, finances, and family members. Based on configuration, it can place users in a multi-level organizational structure, and establish relationships between users.

    +
  2. +
  3. +

    Animation Jobs

    +

    Via jobs that can be run during training and exercise events, Animator can update the NPC's preferences, beliefs, and relationships. This enables dynamic NPCs that change over time.

    +
  4. +
+

At its core, Animator is a realistic user detail generator. Its primary function is to create sufficiently realistic identities and accompanying verbose portfolios of personal information. Each generated user, or NPC (Non-Player Character) as we call them, has numerous categories of details associated with them, and a great deal of metadata that define who they are. Each piece of information is generated using sourced datasets in an attempt to distribute characteristics realistically. We like to say it creates, "NPCs so real, they sell for a premium on the dark web."1

+

Quick Start

+
git clone <https://github.com/cmu-sei/GHOSTS-ANIMATOR>
+cd ghosts-animator/src
+docker build . -t ghosts/animator
+docker compose up -d
+
+

or if you don't want to build and just run the latest docker-compose file:

+
mkdir ghosts-animator
+cd ghosts-animator
+curl https://github.com/cmu-sei/GHOSTS-ANIMATOR/blob/master/src/docker-compose.yml -o docker-compose.yml
+docker compose up -d
+
+

Now browse to http://localhost:5000/

+

Using Animator to Create NPCs

+

The data generated by Animator can be leveraged in multiple areas, but is particularly applicable in four key areas:

+
    +
  1. +

    Training Machine Learning Algorithms - Animator creates larges sets of hyper-realistic user data. It can be leveraged to generate data sets that can be used for training machine learning algorithms. This enables the rapid training of anthropology-related ML algorithms that can leverage one or more of the hundred-plus data points generated by Animator.2

    +
  2. +
  3. +

    Honeypot Payloads - NPC details generated by Animator are designed to be as realistic as possible given the available relevant open source information. This makes the user data convincingly real while still being completely fabricated. Therefore, the data is ideal for use in applications like honeypots, where the goal is to trick an attacker into thinking they are compromising an asset with real user data. This data is also perfect for any other application that would benefit from extremely realistic user information.

    +
  4. +
  5. +

    Insider Threat Modeling - Each Animator NPC is given an Insider Threat Profile. This profile determines how likely it is that the NPC is an insider threat by incorporating the CDSE's Insider Threat Potential Indicators. As we continue developing Animator, it will be possible to configure NPCs to be more or less likely to be insider threats based on factors like their finances, criminal history, foreign contacts, and mental health.

    +
  6. +
  7. +

    Social Network and Relationship Modeling - Animator can establish relationships between the NPCs it generates. As we increase the fidelity of inter-NPC relationships, Animator NPCs create larger and more realistic social networks. By leveraging Animator's ability to quickly generate thousands of inter-related NPCs, Animator can easily be used to perform social networking modeling and research.

    +
  8. +
+

How Creating NPCs Works

+
    +
  • Once Animator receives a request to create NPCs, it starts by creating an empty NPC Profile.
  • +
  • Animator then iterates through all 100+ data points for the NPC and generates synthetic data to be associated with that NPC.
  • +
  • Example data points are name, address, mental health, career, finances, and family members.
  • +
  • Data points are either generated at random or are generated using weighted randomization. Weighted randomization involves leveraging verified datasets to influence the distribution of randomly generated data points to match much more closely to reality.
  • +
  • Animator will complete this process for as many users as were selected by the request. This information can be exported through the API, or stored in a local database
  • +
+

Animator currently supports storing NPC data in a local Mongo Database. This feature is still being actively improved.

+
+
+
    +
  1. +

    The GHOSTS development team highly recommends Nick Bilton's book American Kingpin for insight into the early days of the dark web. 

    +
  2. +
  3. +

    A key developer from the Animator team went on to a position in the SEI's AI division. AI models need data. You connect the dots. 

    +
  4. +
+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/animator/jobs/index.html b/animator/jobs/index.html new file mode 100644 index 00000000..e5610b97 --- /dev/null +++ b/animator/jobs/index.html @@ -0,0 +1,1457 @@ + + + + + + + + + + + + + + + + + + + + + + Animation Jobs - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Animation Jobs

+

So, now we have Animator-generated NPCs, and they have profile information and preferences.

+

Animator has a job system that might enables us to push our simulation further:

+
    +
  • What motivates an agent?
  • +
  • What does an agent know and how did they learn that? How does their knowledge grow over time?
  • +
  • What relationships does an agent have off-network? How might this influence what they do on the computer?
  • +
  • What does an agent believe? How did they come to that belief?
  • +
+

Jobs operate on a "per cycle" or "step" basis. For each cycle, the job processes a list of agents, and the actions or determinations programmed for each.

+

Decision-Making Framework

+

We can use any combination of the following to drive agent decision-making:

+

Motivation

+

We implement the Reiss Motivational Profile (RMP) - which is a mathematical framework for reasoning about agent comparative motivations - agent A is twice as motivated by X than agent B - that is baselined every few years.

+

Relationships

+

Agents build relationships with other agents in the cohort. These get better or worse over time.

+

How this works is that each agent has the potential to interact with n other agents (they can also potentially transfer knowledge as a result). The more an agent knows about a particular subject, maybe the more likely they are to transfer information to another agent.

+

Knowledge

+

Agents build knowledge across an array of subjects that may alter their preferences. Within Animator, there are two main ways to learn:

+
    +
  • Independently through study or by utilizing resources such as books or videos
  • +
  • Through relationships with others at the coffee counter, through mentorship, or group-based learning (a classroom or team for example). Here NPCs learn via interactions with other agents, and the system tracks what was learned and from whom.
  • +
+

Belief

+

What an agent believes can directly influence their behavior. Beliefs shape understanding of the world and guide decision-making and problem-solving. Agents come to belief utilizing Bayes Theorem, which is a mathematical framework for reasoning about probability of evidence.

+
+

So what does this all mean? Here is an example where an agent shares bits of information on social media:

+

Some tweets contain no insight about the agent. Some disclose some bit of information:

+
    +
  • Agent knows X fact
  • +
  • Agent interacted with Y agent
  • +
  • Agent decided to disclose some personal detail Z
  • +
+

Other agents — and adversaries — can see and infer from this information!

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/animator/run/index.html b/animator/run/index.html new file mode 100644 index 00000000..6c0b0bb8 --- /dev/null +++ b/animator/run/index.html @@ -0,0 +1,1433 @@ + + + + + + + + + + + + + + + + + + + + + + Running Animations - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + Skip to content + + +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Running Animator Animations

+

Animator is a simulation of a population of agents. Animator runs in cycles, and for each cycle, the agents make decisions based on their attributes, preferences, motivations, and behaviors.

+

Setup

+
    +
  • Get the Animator API up and running as outlined here
  • +
  • Edit the appsettings.json file to enable Animations:
  • +
+
"ApplicationSettings": {
+    "GhostsApiUrl": "http://localhost:52388/",        // this should be root url of your ghosts API server
+    "Animations": {
+      "IsEnabled": false,                             // set this to true to enable animation jobs
+      "SocialGraph": {
+        "IsEnabled": false,                           // set this to true to enable the entire module (inc. web gui access)
+        "IsInteracting": false,                       // set this to true to actually run the interactions
+        "MaximumSteps": 4000,                         // animator stops when it reaches this many steps 
+        "TurnLength": 900,                            // by default, a step is a cpu cycle, the higher this number, the slower the simulation 
+        "ChanceOfKnowledgeTransfer": 0.3,
+        "Decay": {
+          "StepsTo": 10,
+          "ChanceOf": 0.05
+        }
+      },
+      "SocialSharing": {
+        "IsEnabled": false,                          // set this to true to enable the entire module (inc. web gui access)
+        "IsInteracting": false,                      // set this to true to actually run the interactions
+        "IsSendingTimelinesToGhostsApi": false,      // set this to true to actually send the timeline commands to the ghosts API
+        "IsChatGptEnabled": false,                   // this is still under development, here be dragons
+        "SocializerUrl": "http://socializer.com",    // change this to the root url of your in-game social server
+        "MaximumSteps": 14000,
+        "TurnLength": 9000                           // by default, a step is a cpu cycle, the higher this number, the slower the simulation 
+      },
+      "SocialBelief": {
+        "IsEnabled": false,                         // set this to true to enable the entire module (inc. web gui access)
+        "IsInteracting": false,                     // set this to true to actually run the interactions
+        "MaximumSteps": 14000,
+        "TurnLength": 9000
+      }
+    }
+  },
+  ...
+
+

After you update the appsettings.json file, you will need to restart the Animator API server via:

+
docker restart animator-api
+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf13b9f9d978896599290a74f77d5dbe7d1655c GIT binary patch literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ literal 0 HcmV?d00001 diff --git a/assets/img/animator-logo.png b/assets/img/animator-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e374d92d99b0c62fcbc208e1d0c00f843f6e9ba7 GIT binary patch literal 56253 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 \ No newline at end of file diff --git a/assets/img/ghosts.png b/assets/img/ghosts.png new file mode 100644 index 0000000000000000000000000000000000000000..a2546349621892d968311ccaf79059cf08327ec7 GIT binary patch literal 28157 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 literal 0 HcmV?d00001 diff --git a/assets/img/npc-types.png b/assets/img/npc-types.png new file mode 100644 index 0000000000000000000000000000000000000000..13c0ab46e776922f080f0fa38e0ba67e84ff4f60 GIT binary patch literal 66681 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[qDk)t+H!LhgaLUSP1B|7oqwXwUUg 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 U3#f5E0}wx{Z}Q@mUkw8P2dl6XkpKVy literal 0 HcmV?d00001 diff --git a/assets/javascripts/bundle.220ee61c.min.js b/assets/javascripts/bundle.220ee61c.min.js new file mode 100644 index 00000000..116072a1 --- /dev/null +++ b/assets/javascripts/bundle.220ee61c.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Ci=Object.create;var gr=Object.defineProperty;var Ri=Object.getOwnPropertyDescriptor;var ki=Object.getOwnPropertyNames,Ht=Object.getOwnPropertySymbols,Hi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,nn=Object.prototype.propertyIsEnumerable;var rn=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&rn(e,r,t[r]);if(Ht)for(var r of Ht(t))nn.call(t,r)&&rn(e,r,t[r]);return e};var on=(e,t)=>{var r={};for(var n in e)yr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&Ht)for(var n of Ht(e))t.indexOf(n)<0&&nn.call(e,n)&&(r[n]=e[n]);return r};var Pt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Pi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ki(t))!yr.call(e,o)&&o!==r&&gr(e,o,{get:()=>t[o],enumerable:!(n=Ri(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Ci(Hi(e)):{},Pi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var sn=Pt((xr,an)=>{(function(e,t){typeof xr=="object"&&typeof an!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(O){return!!(O&&O!==document&&O.nodeName!=="HTML"&&O.nodeName!=="BODY"&&"classList"in O&&"contains"in O.classList)}function f(O){var Qe=O.type,De=O.tagName;return!!(De==="INPUT"&&s[Qe]&&!O.readOnly||De==="TEXTAREA"&&!O.readOnly||O.isContentEditable)}function c(O){O.classList.contains("focus-visible")||(O.classList.add("focus-visible"),O.setAttribute("data-focus-visible-added",""))}function u(O){O.hasAttribute("data-focus-visible-added")&&(O.classList.remove("focus-visible"),O.removeAttribute("data-focus-visible-added"))}function p(O){O.metaKey||O.altKey||O.ctrlKey||(a(r.activeElement)&&c(r.activeElement),n=!0)}function m(O){n=!1}function d(O){a(O.target)&&(n||f(O.target))&&c(O.target)}function h(O){a(O.target)&&(O.target.classList.contains("focus-visible")||O.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(O.target))}function v(O){document.visibilityState==="hidden"&&(o&&(n=!0),Y())}function Y(){document.addEventListener("mousemove",N),document.addEventListener("mousedown",N),document.addEventListener("mouseup",N),document.addEventListener("pointermove",N),document.addEventListener("pointerdown",N),document.addEventListener("pointerup",N),document.addEventListener("touchmove",N),document.addEventListener("touchstart",N),document.addEventListener("touchend",N)}function B(){document.removeEventListener("mousemove",N),document.removeEventListener("mousedown",N),document.removeEventListener("mouseup",N),document.removeEventListener("pointermove",N),document.removeEventListener("pointerdown",N),document.removeEventListener("pointerup",N),document.removeEventListener("touchmove",N),document.removeEventListener("touchstart",N),document.removeEventListener("touchend",N)}function N(O){O.target.nodeName&&O.target.nodeName.toLowerCase()==="html"||(n=!1,B())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),Y(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var cn=Pt(Er=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},s=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(B,N){d.append(N,B)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(O){throw new Error("URL unable to set base "+c+" due to "+O)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,Y=!0,B=this;["append","delete","set"].forEach(function(O){var Qe=h[O];h[O]=function(){Qe.apply(h,arguments),v&&(Y=!1,B.search=h.toString(),Y=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var N=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==N&&(N=this.search,Y&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},s=i.prototype,a=function(f){Object.defineProperty(s,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){a(f)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er)});var qr=Pt((Mt,Nr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Mt=="object"&&typeof Nr=="object"?Nr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Mt=="object"?Mt.ClipboardJS=r():t.ClipboardJS=r()})(Mt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Ai}});var s=i(279),a=i.n(s),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(T){return!1}}var d=function(T){var E=p()(T);return m("cut"),E},h=d;function v(j){var T=document.documentElement.getAttribute("dir")==="rtl",E=document.createElement("textarea");E.style.fontSize="12pt",E.style.border="0",E.style.padding="0",E.style.margin="0",E.style.position="absolute",E.style[T?"right":"left"]="-9999px";var H=window.pageYOffset||document.documentElement.scrollTop;return E.style.top="".concat(H,"px"),E.setAttribute("readonly",""),E.value=j,E}var Y=function(T,E){var H=v(T);E.container.appendChild(H);var I=p()(H);return m("copy"),H.remove(),I},B=function(T){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},H="";return typeof T=="string"?H=Y(T,E):T instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(T==null?void 0:T.type)?H=Y(T.value,E):(H=p()(T),m("copy")),H},N=B;function O(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?O=function(E){return typeof E}:O=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},O(j)}var Qe=function(){var T=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},E=T.action,H=E===void 0?"copy":E,I=T.container,q=T.target,Me=T.text;if(H!=="copy"&&H!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&O(q)==="object"&&q.nodeType===1){if(H==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(H==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Me)return N(Me,{container:I});if(q)return H==="cut"?h(q):N(q,{container:I})},De=Qe;function $e(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(E){return typeof E}:$e=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},$e(j)}function Ei(j,T){if(!(j instanceof T))throw new TypeError("Cannot call a class as a function")}function tn(j,T){for(var E=0;E0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof I.action=="function"?I.action:this.defaultAction,this.target=typeof I.target=="function"?I.target:this.defaultTarget,this.text=typeof I.text=="function"?I.text:this.defaultText,this.container=$e(I.container)==="object"?I.container:document.body}},{key:"listenClick",value:function(I){var q=this;this.listener=c()(I,"click",function(Me){return q.onClick(Me)})}},{key:"onClick",value:function(I){var q=I.delegateTarget||I.currentTarget,Me=this.action(q)||"copy",kt=De({action:Me,container:this.container,target:this.target(q),text:this.text(q)});this.emit(kt?"success":"error",{action:Me,text:kt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(I){return vr("action",I)}},{key:"defaultTarget",value:function(I){var q=vr("target",I);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(I){return vr("text",I)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(I){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return N(I,q)}},{key:"cut",value:function(I){return h(I)}},{key:"isSupported",value:function(){var I=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof I=="string"?[I]:I,Me=!!document.queryCommandSupported;return q.forEach(function(kt){Me=Me&&!!document.queryCommandSupported(kt)}),Me}}]),E}(a()),Ai=Li},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,f){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(f))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof m=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(m))return c(m,d,h);if(s.nodeList(m))return u(m,d,h);if(s.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return a(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),s=f.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var f=this;function c(){f.off(i,c),s.apply(a,arguments)}return c._=s,this.on(i,c,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=a.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var rs=/["'&<>]/;Yo.exports=ns;function ns(e){var t=""+e,r=rs.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(s)throw s.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||a(m,d)})})}function a(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof et?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){a("next",m)}function u(m){a("throw",m)}function p(m,d){m(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function pn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Ee=="function"?Ee(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(s){return new Promise(function(a,f){s=e[i](s),o(a,f,s.done,s.value)})}}function o(i,s,a,f){Promise.resolve(f).then(function(c){i({value:c,done:a})},s)}}function C(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var It=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Ee(s),f=a.next();!f.done;f=a.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var u=this.initialTeardown;if(C(u))try{u()}catch(v){i=v instanceof It?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=Ee(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{ln(h)}catch(v){i=i!=null?i:[],v instanceof It?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new It(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ln(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Sr=Ie.EMPTY;function jt(e){return e instanceof Ie||e&&"closed"in e&&C(e.remove)&&C(e.add)&&C(e.unsubscribe)}function ln(e){C(e)?e():e.unsubscribe()}var Le={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Sr:(this.currentObservers=null,a.push(r),new Ie(function(){n.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new xn(r,n)},t}(F);var xn=function(e){ie(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Sr},t}(x);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ie(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,f=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Wt);var Sn=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Dt);var Oe=new Sn(wn);var M=new F(function(e){return e.complete()});function Vt(e){return e&&C(e.schedule)}function Cr(e){return e[e.length-1]}function Ye(e){return C(Cr(e))?e.pop():void 0}function Te(e){return Vt(Cr(e))?e.pop():void 0}function zt(e,t){return typeof Cr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Nt(e){return C(e==null?void 0:e.then)}function qt(e){return C(e[ft])}function Kt(e){return Symbol.asyncIterator&&C(e==null?void 0:e[Symbol.asyncIterator])}function Qt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Yt=zi();function Gt(e){return C(e==null?void 0:e[Yt])}function Bt(e){return un(this,arguments,function(){var r,n,o,i;return $t(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,et(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,et(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,et(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Jt(e){return C(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(qt(e))return Ni(e);if(pt(e))return qi(e);if(Nt(e))return Ki(e);if(Kt(e))return On(e);if(Gt(e))return Qi(e);if(Jt(e))return Yi(e)}throw Qt(e)}function Ni(e){return new F(function(t){var r=e[ft]();if(C(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function qi(e){return new F(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?A(function(o,i){return e(o,i,n)}):de,ge(1),r?He(t):Dn(function(){return new Zt}))}}function Vn(){for(var e=[],t=0;t=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new x}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,f=a===void 0?!0:a;return function(c){var u,p,m,d=0,h=!1,v=!1,Y=function(){p==null||p.unsubscribe(),p=void 0},B=function(){Y(),u=m=void 0,h=v=!1},N=function(){var O=u;B(),O==null||O.unsubscribe()};return y(function(O,Qe){d++,!v&&!h&&Y();var De=m=m!=null?m:r();Qe.add(function(){d--,d===0&&!v&&!h&&(p=$r(N,f))}),De.subscribe(Qe),!u&&d>0&&(u=new rt({next:function($e){return De.next($e)},error:function($e){v=!0,Y(),p=$r(B,o,$e),De.error($e)},complete:function(){h=!0,Y(),p=$r(B,s),De.complete()}}),U(O).subscribe(u))})(c)}}function $r(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function z(e,t=document){let r=ce(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ce(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),V(e===_e()),J())}function Xe(e){return{x:e.offsetLeft,y:e.offsetTop}}function Kn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>Xe(e)),V(Xe(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>rr(e)),V(rr(e)))}var Yn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!Wr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),va?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!Wr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ba.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Gn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Jn=typeof WeakMap!="undefined"?new WeakMap:new Yn,Xn=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=ga.getInstance(),n=new La(t,r,this);Jn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Xn.prototype[e]=function(){var t;return(t=Jn.get(this))[e].apply(t,arguments)}});var Aa=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:Xn}(),Zn=Aa;var eo=new x,Ca=$(()=>k(new Zn(e=>{for(let t of e)eo.next(t)}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ye(e){return Ca.pipe(S(t=>t.observe(e)),g(t=>eo.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(()=>he(e)))),V(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var to=new x,Ra=$(()=>k(new IntersectionObserver(e=>{for(let t of e)to.next(t)},{threshold:0}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function sr(e){return Ra.pipe(S(t=>t.observe(e)),g(t=>to.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function ro(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),J())}var cr={drawer:z("[data-md-toggle=drawer]"),search:z("[data-md-toggle=search]")};function no(e){return cr[e].checked}function Ke(e,t){cr[e].checked!==t&&cr[e].click()}function Ue(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),V(t.checked))}function ka(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ha(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(V(!1))}function oo(){let e=b(window,"keydown").pipe(A(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:no("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),A(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!ka(n,r)}return!0}),pe());return Ha().pipe(g(t=>t?M:e))}function le(){return new URL(location.href)}function ot(e){location.href=e.href}function io(){return new x}function ao(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)ao(e,r)}function _(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)ao(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function so(){return location.hash.substring(1)}function Dr(e){let t=_("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Pa(e){return L(b(window,"hashchange"),e).pipe(l(so),V(so()),A(t=>t.length>0),X(1))}function co(e){return Pa(e).pipe(l(t=>ce(`[id="${t}"]`)),A(t=>typeof t!="undefined"))}function Vr(e){let t=matchMedia(e);return er(r=>t.addListener(()=>r(t.matches))).pipe(V(t.matches))}function fo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(V(e.matches))}function zr(e,t){return e.pipe(g(r=>r?t():M))}function ur(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(fe(()=>M),g(r=>r.status!==200?Ot(()=>new Error(r.statusText)):k(r)))}function We(e,t){return ur(e,t).pipe(g(r=>r.json()),X(1))}function uo(e,t){let r=new DOMParser;return ur(e,t).pipe(g(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),X(1))}function pr(e){let t=_("script",{src:e});return $(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(g(()=>Ot(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),R(()=>document.head.removeChild(t)),ge(1))))}function po(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function lo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(po),V(po()))}function mo(){return{width:innerWidth,height:innerHeight}}function ho(){return b(window,"resize",{passive:!0}).pipe(l(mo),V(mo()))}function bo(){return G([lo(),ho()]).pipe(l(([e,t])=>({offset:e,size:t})),X(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(ee("size")),o=G([n,r]).pipe(l(()=>Xe(e)));return G([r,t,o]).pipe(l(([{height:i},{offset:s,size:a},{x:f,y:c}])=>({offset:{x:s.x-f,y:s.y-c+i},size:a})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(s=>{let a=document.createElement("script");a.src=i,a.onload=s,document.body.appendChild(a)})),Promise.resolve())}var r=class extends EventTarget{constructor(n){super(),this.url=n,this.m=i=>{i.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:i.data})),this.onmessage&&this.onmessage(i))},this.e=(i,s,a,f,c)=>{if(s===`${this.url}`){let u=new ErrorEvent("error",{message:i,filename:s,lineno:a,colno:f,error:c});this.dispatchEvent(u),this.onerror&&this.onerror(u)}};let o=document.createElement("iframe");o.hidden=!0,document.body.appendChild(this.iframe=o),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS Content Servers Overview

+

GHOSTS content servers are an evolving part of the framework. They exist for several reasons:

+
    +
  1. On an air-gapped network, where we are simulating some subset of the internet, we want more types of browsable content within that range — documents, spreadsheets, presentations, pdf files, streamed movies, and the like.
  2. +
  3. We want a broad range of URLs within a site we are representing in the range.
  4. +
  5. We want to simulate a document store, such as SharePoint, OneCloud, or similar, but without the hassle of installing and maintaining those actual systems.
  6. +
+
+

Research by Global WebIndex claims that globally, 59% of the world's population uses social media, and that the average daily use is 2 hours and 29 minutes (July 2022).

+
+

Air-gaps

+

Many ranges are air-gapped, which means they have no access to the wider internet. In these cases, recreating a reasonable facsimile of the internet is key to the training experience. While there are many systems that do this well, we often want to augment the scenario with a wider array of URL traffic, or we want to introduce more of certain kinds of content going across the wire. PANDORA was created to address these concerns. Shortly later, we added a social server as well.

+

Having to know valid URLs

+

The other problem is that the internet works by the client having to “know” the location of some resource via:

+
    +
  • Actually knowing the URL
  • +
  • Being referred from another page - I might know google.com and search for something, which gives me a reference to another page I was not aware of previously.
  • +
  • Inferring the URL from some like resource - If one is poking around and looking for something on a server, a slight change of URL often gives hints that get you to where you wanted to go.
  • +
  • Guessing - the proliferation of .com domains means that for something new, it's often fruitful to just try that thing.com and see if it works!
  • +
+

The problem here is that currently, clients must know valid URLs that actually exist out in a simulated greyspace (via TopGen, GreyBox, or otherwise), which limits the array of potential requests and creates range work to maintain. So we created GHOSTS PANDORA, which serves whatever clients ask for - if the request is for a doc file, the server creates a random doc file on the fly — in memory — and serves it back to the client. Pandora serves the following content types:

+
    +
  • html
  • +
  • css
  • +
  • js
  • +
  • doc|x
  • +
  • ppt|x
  • +
  • xls|x
  • +
  • mp4
  • +
  • pdf
  • +
  • gif
  • +
  • jpg
  • +
  • png
  • +
  • zip
  • +
  • msi
  • +
  • iso
  • +
  • other binary formats, etc.
  • +
+

Pandora has generic request handlers for each HTTP verb (GET, POST, etc.) and is deployed as a simple docker container. We configure it to handle a particular IP on a multiple-IP-enabled host machine. It works off any URL, but part of the solution involved introducing more randomness in the GHOSTS clients as well. Those clients now support a creative parameter-built URL system that can be configured to look something like this:

+
sharepoint.hello.com/{org}/{report_type}/{uuid}/{file_name}.{file_type}
+
+

These variables are processed at runtime, and produce a final url that might look something like:

+
sharepoint.hello.com/operations/maintenance/80e6af4e-5107-43b5-832f-0d8027efbd76/report.docx
+
+

In addition, Pandora supports “bad” payloads via configuration. Here the server responds to specific configured URLs to deploy planted injects. So clients can download malware in an exercise in a manner that is hard to differentiate based on URLs already seen within the event. The configuration looks like:

+
[payloads]
+1=/bad/payload/url/,some_bad.zip,application/zip
+
+

Where id=url,payload file, MIME response type.

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/content/pandora/index.html b/content/pandora/index.html new file mode 100644 index 00000000..d8098513 --- /dev/null +++ b/content/pandora/index.html @@ -0,0 +1,1532 @@ + + + + + + + + + + + + + + + + + + + + + + Pandora - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS PANDORA SERVER Overview

+
+Pandora is part of GHOSTS +

Pandora is within the GHOSTS Source Code Repository hosted on GitHub.

+
+

GHOSTS PANDORA is a web server that responds to a myriad of request types with randomized content generated in real-time. Used in conjunction with GHOSTS NPCs, the two can provide for agents that are periodically downloading content other than simple HTML and associated image, CSS, and js files.

+

Pandora

+

Running this server

+

As a Docker Container

+

Docker is the preferred way to run Pandora - mostly because this is how we run and test it before version releases.

+
    +
  1. Review the repository docker-compose.yml file
  2. +
  3. Run the following in your terminal
  4. +
+
mkdir ghosts-pandora
+cd ghosts-pandora
+curl https://raw.githubusercontent.com/cmu-sei/GHOSTS/master/src/ghosts.pandora/docker-compose.yml -o docker-compose.yml
+docker-compose up -d
+
+

Bare metal

+

This assumes the host server is a common Linux distribution. For images to render correctly, PIL or the more recent Pillow library is necessary. See here for more information on Pillow installation and configuration.

+
    +
  1. Using a Python 3 distribution >= 3.6.2
  2. +
  3. In the terminal run: pip install -r requirements.txt
  4. +
  5. Then run python app.py
  6. +
+

Capabilities

+

Handling requests by directory

+
    +
  • /api - All requests beginning with /api automatically respond with json. This includes:
      +
    • /api/users
    • +
    • /api/user/a320f971-b3d9-4b79-bb8d-b41d02572942
    • +
    • /api/reports/personnel
    • +
    +
  • +
  • /csv - All requests beginning with /csv automatically respond with csv. Like the above, this includes urls such as:
      +
    • /csv/users
    • +
    • /csv/user/winx.jalton
    • +
    • /csv/reports/HR/payroll
    • +
    +
  • +
  • /i, /img, /images - All requests beginning with these directories automatically respond with a random image of type [gif, jpg, png]. Examples:
      +
    • /i/v1/a9f6e2b7-636c-4821-acf4-90220f091351/f8f8b1f0-9aa5-4fc7-8880-379e3192748e/small
    • +
    • /images/products/184f3515-f49b-4e07-8c8b-7f978666df0e/view
    • +
    • /img/432.png
    • +
    +
  • +
  • /pdf - All requests respond with a random pdf document. Examples:
      +
    • /pdf/operations/SOP_Vault/a7f48bd5-84cb-43a1-8d3d-cd2c732ddff6
    • +
    • /pdf/products
    • +
    +
  • +
  • /docs - All requests respond with a random word document
  • +
  • /slides - All requests respond with a random powerpoint document
  • +
  • /sheets - All requests respond with a random excel document
  • +
+

Handling requests by type

+

For requests indicating a specific file type, there are several specific handlers built to respond with that particular kind of file, such as:

+
    +
  • .csv
  • +
  • Image requests [.gif, .ico, .jpg, .jpeg, .png]
  • +
  • .json
  • +
  • Office document requests
  • +
  • .doc, .docx
  • +
  • .ppt, .pptx
  • +
  • .xls, .xlsx
  • +
  • .pdf
  • +
+

So that a URL such as /users/58361185-c9f2-460f-ac45-cb845ba88574/profile.pdf would return a pdf document typically rendered right in the browser.

+

All unhandled request types, urls without a specific file indicator, or requests made outside specifically handled directories (from the preceding section) are returned as html, including:

+
    +
  • /docs/by_department/operations/users
  • +
  • /blog/d/2022/12/4/blog_title-text
  • +
  • /hello/index.html
  • +
+

Hiding malicious payloads for red-teaming

+

Pandora also can hide payloads in a particular request for things like red-teaming and such. This is done in the configuration file, and looks like this:

+
[payloads]
+1=/1/,a.zip,application/zip
+2=/2/users,b.zip,application/zip
+3=/3/some/report/url,c.zip,application/zip
+
+

Each record must be an incrementing integer with no duplication. The values are:

+
    +
  • The URL that this payload responds to
  • +
  • The local file (stored in ./payloads/) to be returned
  • +
  • The MIME type of the response
  • +
+

So for 1 in the example above, requests to /1/ return the a.zip file as an application/zip file.

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/content/social/index.html b/content/social/index.html new file mode 100644 index 00000000..1935f39c --- /dev/null +++ b/content/social/index.html @@ -0,0 +1,1387 @@ + + + + + + + + + + + + + + + + + + + + + + Pandora Social - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS PANDORA SOCIAL Overview

+
+PANDORA SOCIAL is still very early beta +

Here be dragons

+
+

The place where GHOSTS agents come to share their thoughts and information.

+

In the spirit of the original PANDORA, this server also responds to a very broad array of URLs but enables clients to POST/PUT/DELETE to it as well, for example:

+ + + + + + + + + + + + + + + + + + + + + +
RequestResponse
POST /images responds with a url to the saved image file
POST / responds with a randomly-generated streamed video
POST /users/michelle_smith/af2d00aa-4a89-4af3-baff-1746b556e7a1/ responds with a reply to the original user's social post
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/api/index.html b/core/api/index.html new file mode 100644 index 00000000..c13876f8 --- /dev/null +++ b/core/api/index.html @@ -0,0 +1,1500 @@ + + + + + + + + + + + + + + + + + + + + + + GHOSTS Core API Overview - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS Core API Overview

+
+GHOSTS Source Code +

The GHOSTS Source Code Repository is hosted on GitHub.

+
+

The GHOSTS API enables the control and orchestration of non-player characters (NPCs) within a deployment. It supports logging, reporting, and managing individual, groups of, or entire deployments of client installs.

+

Installation

+
    +
  1. Install 🐳 Docker
  2. +
  3. Install Docker Compose
  4. +
  5. Run the following commands - we'll use this docker-compose.yml file
  6. +
+
mkdir ghosts
+cd ghosts
+curl https://raw.githubusercontent.com/cmu-sei/GHOSTS/master/src/Ghosts.Api/docker-compose.yml -o docker-compose.yml
+docker-compose up -d
+
+

The required containers will be downloaded and configured automatically.

+

Once the last command completes, if you open http://localhost:5000/api/home in your browser, you should see the initial API page outlining the version of the install, and a few test machine entries. If this page renders, your API is up, running, and available.

+

You will still need to set up Grafana. Beware that you must often chown the host location of the container as listed in the docker-compose file or the container will just continually restart in error due to insufficient permissions.

+

Configuring the API

+

The API generally has good defaults to get you up and running quickly, but there are some considerations in the appconfig.json file:

+
    "ClientSettings": {
+        "OfflineAfterMinutes": 30, ...
+        "MatchMachinesBy": null,
+
+

Can be fqdn|host|resolvedhost|null - null tells the API to match incoming requests with machine records by the machine name. For installations where multiple domains are reporting into the same API, you probably want to use FQDN in order to avoid machines being duplicated.

+
"QueueSyncDelayInSeconds": 10,
+"NotificationsQueueSyncDelayInSeconds": 10,
+
+

This is how often the synch job runs. Incoming machine requests are not real-time in order to best bundle like records together.

+

Configuring Grafana

+
    +
  • Grafana will be running (if containerized) on port 3000, and we can access it via the same URL we use for the API.
  • +
  • The default login is admin/admin.
  • +
  • The first step is to set up a datasource named "ghosts" to the ghosts Postgres database.
  • +
  • Now import your choice of the grafana json files in this repository. It creates the default GHOSTS dashboard.
  • +
+

Webhooks

+

The GHOSTS API provides webhook callbacks based on the configuration on the endpoint: /api/webhooks. The payload for creating a webhook is in the format:

+
{
+  "status": 0,
+  "description": "some description",
+  "postbackUrl": "http://localhost/endpoint:port",
+  "postbackMethod": 0, (0 == get, 1 == post)
+  "postbackFormat": "see below"
+}
+
+

Payloads can be any format — here is a sample:

+
{
+ 'machine':'[machinename]',
+ 'created':'[datetime.utcnow]',
+ 'type':'[messagetype]',
+ 'payload':'[messagepayload]'
+}
+
+

On send, the payload will be converted into the correct JSON format:

+
{
+ "machine":"some_guid",
+ "created":"some_datetime",
+ "type":"some_message",
+ "payload":"some_payload"
+}
+
+

If the postback method is POST, the payload will be sent as the message body. If the postback method is GET, the payload will be sent as part of the querystring value ?message=payload.

+

The following events are reported via webhooks:

+
    +
  1. Timeline delivered (with the timeline that was delivered as payload) to a machine via API (original API posting of timeline only holds timeline in wait - the client still must check-in in order for that timeline to be delivered)
  2. +
  3. Machine requested updates ("checked in") from API
  4. +
  5. Machine posted results to API
  6. +
+

Troubleshooting

+
+

Is the API up and running?

+
+
    +
  • Go to /api/home in the browser, it should return the current API version and the number of machines and groups under management. If it says relationship not found, restart the API application and it should create the database automatically.
  • +
  • Run docker ps --all and see that all containers are running normally. If one or more is not running, look at the logs for that machine via docker logs [machine name].
  • +
+
+

The ClientId, ClientResults, and other Client* endpoints are failing.

+
+

The Client* endpoints are for the Clients to use only. There are specific header values set by the client in the request that is used to authenticate the request. If you are not using the client, you will not have these headers set, and these endpoints will fail.

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/api/timelines/index.html b/core/api/timelines/index.html new file mode 100644 index 00000000..755d68ca --- /dev/null +++ b/core/api/timelines/index.html @@ -0,0 +1,1479 @@ + + + + + + + + + + + + + + + + + + + + + + Managing Timelines - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Managing Timelines

+

One of the primary capabilities of the API is to manage multiple client timelines. Timelines are the mechanism for clients to perform actions on behalf of a user. For example, a client might execute a timeline to browse a website, create a document, or other Handler activities.

+

Clients are configured to check in periodically with the API to report their current state and to check if any updates are available. We can have the API hold an update for the next time a client, group of clients, or all clients check in. That update will then be processed by the client and the client will report back to the API that the update has been processed. This allows the API to manage the state of the client and to ensure that the client is always up to date. So the process is:

+
    +
  1. We configure an update for a client or group of clients in the API.
  2. +
  3. Clients check in and are told that an update is available.
  4. +
  5. The client processes the update and reports back to the API that the update has been processed.
  6. +
+

Configuring a Timeline for a Client

+

Client timelines are updated via POST to /api/timelines in the following format:

+
{
+  "machineId": "3fa85f64-5717-4562-b3fc-2c963f66afaf",
+  "type": 0,
+  "activeUtc": "2023-03-08T16:38:04.002Z",
+  "status": 0,
+  "update": {
+    "status": 0,
+    "timeLineHandlers": [
+      {
+        "handlerType": 0,
+        "initial": "string",
+        "utcTimeOn": {
+          "ticks": 0
+        },
+        "utcTimeOff": {
+          "ticks": 0
+        },
+        "handlerArgs": {
+          "additionalProp1": "string",
+          "additionalProp2": "string",
+          "additionalProp3": "string"
+        },
+        "loop": true,
+        "timeLineEvents": [
+          {
+            "trackableId": "string",
+            "command": "string",
+            "commandArgs": [
+              "string"
+            ],
+            "delayAfter": 0,
+            "delayBefore": 0
+          }
+        ]
+      }
+    ]
+  }
+}
+
+

The key values to consider here are: The machine ID that you want to update, the other key value is the type of timeline. The type is an integer value that represents the type of update. The following are the types of updates that are currently supported:

+
    +
  • Timeline = 0 // this
  • +
  • Health = 1
  • +
  • TimelinePartial = 10 // this the agent is currently doing off its default timeline
  • +
  • RequestForTimeline = 20
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDTypeDescription
0TimelineReplaces the client's default timeline stored within ./config/timeline.json
1HealthThis updates a client's health instructions
10TimelinePartialDoes not replace the default timeline, rather this timeline is executed immediately on separate threads from whatever
20RequestForTimelineUse this to instruct the client to send its current default timeline up to the API
+

The remainder of the settings are for the timeline - basically what we are doing here is sending a client a new timeline, with the above values to indicate, which machine and what to change in the update node.

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/client/index.html b/core/client/index.html new file mode 100644 index 00000000..d5181a9b --- /dev/null +++ b/core/client/index.html @@ -0,0 +1,1733 @@ + + + + + + + + + + + + + + + + + + + + + + GHOSTS Core Client Overview - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS Core Client Overview

+
+GHOSTS Source Code +

The GHOSTS Source Code Repository is hosted on GitHub.

+
+

The GHOSTS client simulates what anyone might do at a computer given their particular role or membership within some team. It creates documents, browses websites, downloads files, and uses all sorts of popular applications on many versions of Windows and Linux machines. Whether you're a friendly administrator or a powerful cyber adversary, GHOSTS can replicate your expected behavior.

+

Types of NPCs

+

GHOSTS has many use cases in cyber training and exercises, most notably for bringing non-player characters (NPCs) to life, but it can also be used for other purposes where realistic activity on a computer or network is needed - testing or generating datasets, for example.

+
+Do I need the API? +

Although clients are fully functional without the API server, the latter enables logging, reports, and remote administration capabilities. Without the API, changes to clients must be managed in some other manner.

+
+

The client's configuration and command system are file-based, so if you do not wish to use the API, you can manage these through some other tool, such as Ansible or similar. All of these files are under the client's install location.

+
+Run as the NPC you're representing +

The GHOSTS client should typically be run as a user, and not as administrator or root - training or exercising teams will notice this immediately.

+
+

The Windows Client

+

GHOSTS on Windows (Win10 and Win7 currently supported) is a .NET Console application that performs user activity on client workstations - web browsing, working with office documents, using the command prompt or PowerShell, etc. Our team typically installs the client in an out-of-game directory (c:\exercise\ghosts\), where no event or injects will originate. It is recommended you verify one working client before deploying to multiple machines. You will need the base URL from the API installation for the client to communicate home.

+

Windows Installation

+ +

Unzip to your client machine in a directory such as c:\exercise\ghosts. You will need to adjust the configuration in config/application.json for your client to talk to your an installed instance of the GHOSTS API server.

+
+Additional configuration required for web browsing +

For any client utilizing the Firefox or Chrome web browser, an automation driver is necessary to be included in the same folder as the GHOSTS binary. For Firefox, download the appropriate 🦎  Geckodriver for your version of the browser here . For Chrome, download the appropriate Chromedriver for your version of the browser here .

+
+
+Additional configuration required for email +

Using the Windows client email functions requires the use of Redemption which provides robust Outlook automation. The full Redemption library should be found in /lib.

+
+

Linux Client

+

Your client Linux machine will need to have the latest Microsoft dotnetcore runtime installed (Note that for the GHOSTS client, there are versions for dotnetcoreapp3.1 - this will eventually go away — and dotnet6.0, which is long term support (LTS) and will stick around for a while). Again, note that you only need the runtime installed, not the full SDK.

+

Linux Installation

+ +

Unzip to a folder such as ~/ghosts for the user that you want GHOSTS to run as.

+

Note that on Linux machines running the client as root and utilizing web browsing may result in failures due to Gecko/Chromedriver display issues.

+

Client Directory Structure

+
+Do not copy the instance folder +

You should never copy the instance folder from one machine to another.

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
FolderDescription
config/configuration files are stored here.
instance/generated files and information relative to this particular installed instance of ghosts is stored here. This folder should never be copied from one machine to another
lib/third-party libraries used by ghosts are stored here
logs/output logs for the installed instance (logs/app.log), and logs that are transferred to the server (logs/clientupdates.log)
+

Configuration Quick Start

+

After unzipping the GHOSTS client, we can simply double-click it to run. Note that the console window likely printed a few messages, but then disappeared. This is normal, in production mode GHOSTS hides itself. We can see it in the Windows Task Manager, however, and we can kill the process from there. We can also run the included kill-ghosts.bat file that closes the application and any applications it might control.

+

Beyond this initial step of verifying that the client will run, there are two files that we might need to adjust to fit many deployments:

+

application.json

+

In this file, often all we need to change are the URLs for the API, IdUrl, ClientResultsUrl, ClientUpdatesUrl, and the like. Change the hostname to your installed API location, and GHOSTS should check in as expected.

+
{
+    "IdEnabled": true,                                                      //enabled in order to command and control from api (C2) server
+    "IdUrl": "http://yourapiurl.com/api/clientid",                          //url for API endpoint to get clientid
+    "ClientResultsEnabled": true,                                           //enabled to report results to C2
+    "ClientResultsUrl": "http://yourapiurl.com/api/clientresults",          //url for API endpoint to report results
+    "ClientResultsCycleSleep": 90,                                          //report results every x ms
+    "ClientUpdatesEnabled": true,                                           //enabled to get updates from C2
+    "ClientUpdatesUrl": "http://yourapiurl.com/api/clientupdates",          //url for API endpoint to get updates
+    "ClientUpdatesCycleSleep": 90,                                          //check for updates every x ms
+    "Survey": {                                                             //survey is a local report of processes running, etc.
+        "IsEnabled": true,                                                  //on/off
+        "Frequency": "once",                                                //how often to survey
+        "MaxAgeInHours": 168,                                               //how long to wait until new survey
+        "OutputFormat": "indent"                                            //compact/fancy(indent)
+    },
+    "HealthIsEnabled": true,                                                //enable local health checks
+    "HandlersIsEnabled": true,                                              //enable local timeline activity
+    "ChromeExtensions": "",                                                 //comma separated local extensions (used for injects in the past)
+    "FirefoxInstallLocation": "",                                           //geckodriver needs this for non-standard installs (is pesky)
+    "FirefoxMajorVersionMinimum": 48,                                       //geckodriver is picky about versions
+    "OfficeDocsMaxAgeInHours": 6,                                           //cleanup kills docs in the documents folder older than this setting
+}
+
+

timeline.json

+

The other file we may want to adjust is the default timeline. This is what the agent does all day, including browsing the internet, creating documents, and similar. The defaults hopefully give you a good idea of what is possible, and of course, the array of configurations here is endless - be creative!

+

The primary item is the HandlerType. This tells GHOSTS to run a command (Command), use Firefox to browse an array of websites (BrowserFirefox), create Excel documents (Excel) and so on. Some of the other items related to a handler's configuration are:

+
    +
  • Initial: The initial command for a handler to execute. For a web browser, you might enter either a URL or "about:blank".
  • +
  • UtcTimeOn | UtcTimeOff: "00:00:00": "24:00:00" to not shut off. Otherwise, enter an on and an off time to simulate things such as office hours of 9-5, etc. There are 30 minutes of jitter plus or minus from the time entered.
  • +
  • Loop: Set this to true to continue to execute this same command on a loop, or false to execute something just one time.
  • +
+
{
+   "HandlerType": "Command",
+   "Initial": "",
+   "UtcTimeOn": "00:00:00",
+   "UtcTimeOff": "24:00:00",
+   "Loop": "True",
+   "TimeLineEvents": [
+      {
+         "Command": "NETSTAT",    
+         "CommandArgs": [],
+         "DelayAfter": 900000,
+         "DelayBefore": 0
+      }
+   ]
+}
+
+

To access a network share file, the command might be: net use X:\SERVER\Share

+

To RDP to another machine: mstsc.exe {ConnectionFile | /v:ServerName[:Port]} [/console] [/f] [/w:Width/h:Height]

+

/v - specifies the remote computer and port (optional) you wish to connect to +/console – connects to the console of a Windows Server 2003 based system +/f – starts the remote desktop connection in full screen mode +/w & /h – specifies the width and height of the remote desktop connection

+

Actions can also be created for standard copy/move/deletion of files via their respective commands.

+

Chrome

+

We have to pass the browser window an initial value. If we don't want it to go anywhere at start, we could pass about:blank, otherwise we'd pass a url. These can be http or https.

+
{
+   "HandlerType": "BrowserChrome",
+   "Initial": "http://google.com",
+   "UtcTimeOn": "00:00:00",
+   "UtcTimeOff": "24:00:00",
+   "Loop": "True",
+   "TimeLineEvents": [
+      {
+         "Command": "random",
+         "CommandArgs": [
+            "http://google.com",
+            "http://facebook.com",
+         ],
+         "DelayAfter": 1000,
+         "DelayBefore": 0
+      }
+   ]
+}
+
+

Excel, PowerPoint, Word

+
{
+   "HandlerType": "Word",
+   "Initial": "",
+   "UtcTimeOn": "00:00:00",
+   "UtcTimeOff": "24:00:00",
+   "Loop": "True",
+   "TimeLineEvents": [
+      {
+         "Command": "create",
+         "CommandArgs": [ "%homedrive%%homepath%\\Documents" ],
+         "DelayAfter": 900000,
+         "DelayBefore": 0
+      }
+   ]
+}
+
+

Trackables

+

For specific Timeline Events where the outcome is needed to be tracked, like for example, a client machine spawned inject, use a Trackable (via TrackableId in the following example):

+
{
+    "TimeLineHandlers": [
+        {
+            "HandlerType": "BrowserChrome",
+            "Initial": "about:blank",
+            "UtcTimeOn": "00:00:00",
+            "UtcTimeOff": "24:00:00",
+            "Loop": false,
+            "TimeLineEvents": [
+                {
+                    "Command": "browse",
+                    "CommandArgs": [ "https://dl.dafont.com/dl/?f=italian_breakfast" ],
+                    "DelayAfter": 0,
+                    "DelayBefore": 0
+                },
+                {
+                    "Command": "download",
+                    "CommandArgs": [ "//a[contains(@class, 'dl')]" ],
+                    "TrackableId": "<guid id from trackables table/>",
+                    "DelayAfter": 0,
+                    "DelayBefore": 0
+                }
+            ]
+        },
+        {
+            "HandlerType": "Command",
+            "Initial": "",
+            "UtcTimeOn": "00:00:00",
+            "UtcTimeOff": "24:00:00",
+            "Loop": false,
+            "TimeLineEvents": [
+                {
+                    "Command": "cd %homedrive%%homepath%\\Downloads",
+                    "CommandArgs": [
+                        "powershell expand-archive -Path italian_breakfast.zip -destinationpath x",
+                        "cd x",
+                        "dir"
+                    ],
+                    "TrackableId": "<guid id from trackables table/>",
+                    "DelayAfter": 10,
+                    "DelayBefore": 10000
+                }
+            ]
+        }
+    ]
+}
+
+

Troubleshooting

+
+

Clients aren't running (immediately exiting, throwing copious exceptions, or similar)

+
+
    +
  • Is the dotnet framework runtime 4.x installed on the machine?
  • +
  • If GPO is doing white-listing of what apps can run, is ghosts.exe white-listed?
  • +
  • Will the client run by simply double-clicking on the exe?
  • +
  • Does it report anything to the windows application event logs?
  • +
  • What's in logs/app.log?
  • +
  • Is the ghosts executable set to execute automatically when the machine restarts?
  • +
+
+

Clients aren't reporting their activity to the API

+
+
    +
  • Is the client running correctly? (if not, see above)
  • +
  • Is there entries in the logs/clientupdates.log?
  • +
  • If there are, is the file too large? (Try removing it, ghosts might be hung trying to process a lot of log data)
  • +
  • If the folder instance created? Does the file instance/id.json exist? (If it does and has an ID within, then ghosts has reported home to the api at least once)
  • +
  • The file logs/app.log indicating any fatal issues? (Logging can be ratcheted up and down via nlog configuration)
  • +
+
+

Can I update what clients are doing?

+
+
    +
  • Clients operate off their config/timeline.json file and this can be updated via Powershell, Ansible, or other means - it's just a file.
  • +
  • Clients can also do just-in-time activities via the instance/timeline/in folder. Anything placed here will be picked up, executed, and moved to the corresponding out folder once complete. This does not affect any activity currently controlled with the default timeline file.
  • +
+
+

Can I reset a client on a box?

+
+
    +
  • Yes, launching a new instance of Ghosts kills the previous one and all associated tasks from the timeline (any instances of Word, PowerShell, etc.). Only one instance of Ghosts will be running on a client box at any time. We can also run the .bat script kill-ghosts.bat included in the distribution to clean everything up.
  • +
+
+

What is the easiest way to determine the running version of the client?

+
+
    +
  • run the version flag: ghosts.exe --version
  • +
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/blog_helper/index.html b/core/handlers/blog_helper/index.html new file mode 100644 index 00000000..8fb41ce7 --- /dev/null +++ b/core/handlers/blog_helper/index.html @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + + + Blogs/Drupal - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Blogs/Drupal

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/browser/index.html b/core/handlers/browser/index.html new file mode 100644 index 00000000..0b6638fd --- /dev/null +++ b/core/handlers/browser/index.html @@ -0,0 +1,1418 @@ + + + + + + + + + + + + + + + + + + + + + + Web Browsers (Firefox|Chrome) - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Web Browser (Firefox|Chrome) Configuration

+

A sample timeline for each browser is available in a code repository directory of the same name.

+

Timeline URL Variables

+

An example of a URL using variables is:

+
http://craigslist.org/{org}/{group}/{uuid}/{verb}/{type}/{n}?{c}={now}
+
+

All variables are in the format {variable}. There are several standard variables:

+
    +
  • {now} = short datetime (mm/dd/yyyy format)
  • +
  • {uuid} = uuid
  • +
  • {c} = a single character from a-z and A-Z
  • +
  • {n} = number between 1 and 1000
  • +
+

We can also configure additional variables by adding the following to a browser handler in a timeline:

+
"url-replace": [
+          {"verb": ["order", "enable", "engage"]},
+          {"group": ["operations", "logistics", "medical"]},
+          {"org": ["army", "command", "brigade", "battalion"]},
+          {"type": ["document", "doc", "files", "vault", "filevault"]}
+        ]
+
+

Therefore:

+
https://www.cmu.edu/{org}/{group}/{verb}/{type}/{uuid}/version_{n}?{c}={now}
+
+

might be rendered as:

+
https://www.cmu.edu/command/operations/order/doc/bcc396b5-47d0-4665-93c8-0a314cec13e1/version_55?d=6/21/2022
+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/clicks/index.html b/core/handlers/clicks/index.html new file mode 100644 index 00000000..21c67203 --- /dev/null +++ b/core/handlers/clicks/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Clicks - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Clicks

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/cmd/index.html b/core/handlers/cmd/index.html new file mode 100644 index 00000000..0dbcee7a --- /dev/null +++ b/core/handlers/cmd/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Cmd - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Cmd

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/excel/index.html b/core/handlers/excel/index.html new file mode 100644 index 00000000..5d8d3ec8 --- /dev/null +++ b/core/handlers/excel/index.html @@ -0,0 +1,1363 @@ + + + + + + + + + + + + + + + + + + + + + + Excel - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Excel Configuration

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/index.html b/core/handlers/index.html new file mode 100644 index 00000000..e92f171e --- /dev/null +++ b/core/handlers/index.html @@ -0,0 +1,1406 @@ + + + + + + + + + + + + + + + + + + + + + + Basic Configuration - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Basic Handler Configuration

+

The following is the format for a basic timeline handler:

+
"TimeLineHandlers": [
+    {
+      "HandlerType": "Watcher",
+      "UtcTimeOn": "00:00:00",
+      "UtcTimeOff": "24:00:00",
+      "Loop": true,
+      "TimeLineEvents": [
+        {
+          "Command": "folder",
+          "CommandArgs": [ "path:%HOMEDRIVE%%HOMEPATH%\\Downloads", "size:2000", "deletionApproach:oldest" ],
+          "DelayAfter": 0,
+          "DelayBefore": 0
+        }
+      ]
+    }
+]
+
+

Some of the key-value pairs are self-explanatory, but let's review a few important ones:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
KeyValue
HandlerTypeThe application or major function we want to control. This could be FireFox, the Cmd terminal, or Word.
UtcTimeOnThe time the handler will begin to run. To simulate an agent coming into the office at 0900, we set this to your time zone's UTC value.
UtcTimeOffThe time the handler will stop. To simulate an agent leaving the office at 1700, we set this to your time zone's UTC value.
Looptrue or false - a handler could be repeated or just run one-time.
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/notepad/index.html b/core/handlers/notepad/index.html new file mode 100644 index 00000000..5f349b73 --- /dev/null +++ b/core/handlers/notepad/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Notepad - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Notepad

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/npc_system/index.html b/core/handlers/npc_system/index.html new file mode 100644 index 00000000..262c1f3f --- /dev/null +++ b/core/handlers/npc_system/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + NPCSystem - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

NPCSystem

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/outlook/index.html b/core/handlers/outlook/index.html new file mode 100644 index 00000000..1779df62 --- /dev/null +++ b/core/handlers/outlook/index.html @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + + + Outlook - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Outlook

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/pidgin/index.html b/core/handlers/pidgin/index.html new file mode 100644 index 00000000..6df7c13a --- /dev/null +++ b/core/handlers/pidgin/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Pidgin - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Pidgin

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/powerpoint/index.html b/core/handlers/powerpoint/index.html new file mode 100644 index 00000000..d5e70df0 --- /dev/null +++ b/core/handlers/powerpoint/index.html @@ -0,0 +1,1363 @@ + + + + + + + + + + + + + + + + + + + + + + PowerPoint - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

PowerPoint Configuration

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/print/index.html b/core/handlers/print/index.html new file mode 100644 index 00000000..e6075276 --- /dev/null +++ b/core/handlers/print/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Print - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Print

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/rdp/index.html b/core/handlers/rdp/index.html new file mode 100644 index 00000000..579f2cfb --- /dev/null +++ b/core/handlers/rdp/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + RDP - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

RDP

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/reboot/index.html b/core/handlers/reboot/index.html new file mode 100644 index 00000000..4e3e1edb --- /dev/null +++ b/core/handlers/reboot/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Reboot - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Reboot

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/sftp/index.html b/core/handlers/sftp/index.html new file mode 100644 index 00000000..b17aaaa1 --- /dev/null +++ b/core/handlers/sftp/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Sftp - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Sftp

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/sharepoint_helper/index.html b/core/handlers/sharepoint_helper/index.html new file mode 100644 index 00000000..7f81640d --- /dev/null +++ b/core/handlers/sharepoint_helper/index.html @@ -0,0 +1,1358 @@ + + + + + + + + + + + + + + + + + + + + + + Sharepoint - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Sharepoint

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/ssh/index.html b/core/handlers/ssh/index.html new file mode 100644 index 00000000..31df3349 --- /dev/null +++ b/core/handlers/ssh/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Ssh - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Ssh

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/watcher/index.html b/core/handlers/watcher/index.html new file mode 100644 index 00000000..fcfaa382 --- /dev/null +++ b/core/handlers/watcher/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Watcher - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Watcher

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/wmi/index.html b/core/handlers/wmi/index.html new file mode 100644 index 00000000..52f93b56 --- /dev/null +++ b/core/handlers/wmi/index.html @@ -0,0 +1,1356 @@ + + + + + + + + + + + + + + + + + + + + + + Wmi - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Wmi

+ + + + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/core/handlers/word/index.html b/core/handlers/word/index.html new file mode 100644 index 00000000..3da8e623 --- /dev/null +++ b/core/handlers/word/index.html @@ -0,0 +1,1363 @@ + + + + + + + + + + + + + + + + + + + + + + Word - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Word Configuration

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..4b54d2da --- /dev/null +++ b/index.html @@ -0,0 +1,1457 @@ + + + + + + + + + + + + + + + + + + + + GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

The GHOSTS NPC Framework

+

Developed by Carnegie Mellon University's Software Engineering Institute (SEI), The GHOSTS Framework is an open-source (OSS) software framework that enables creating, deploying, and orchestrating complex non-player character (NPC) activity within training, exercise, simulation, and educational environments. Within GHOSTS there are several systems and applications, all of which are modular and extendable to fit a wide array of use cases and needs.

+

If you've never seen GHOSTS in action, watch this quick three-minute introductory video on YouTube:

+ + +

Documentation

+

This is the GHOSTS documentation site for the framework and all of its components. Each major component's detail is accessible from the main navigation. If anything is unclear or you still have questions, please do not hesitate to start a discussion — our community is growing and eager to help!

+

Cyber Ranges and Crucible

+

GHOSTS is typically run on machines within a virtualized network, often referred to as "the range". This network can be as simple or as complex as required for training and exercise purposes.

+

CERT's Cyber Workforce Development (CWD) team has a great deal of experience in building cyber ranges for training and exercise, captured in our technical report Foundation of Cyber Ranges. The report details the design considerations and execution plan for building high-fidelity, realistic virtual cyber ranges that deliver maximum training and exercise value for cyberwarfare participants.

+
+Run GHOSTS on the Crucible Framework +

Crucible Logo +GHOSTS runs very well within the SEI's Crucible Framework (Source Code and Docs) - which we use extensively for training and exercise here at Carnegie Mellon University (CMU)'s Software Engineering Institute, and particularly, within CERT.

+

Building a sufficiently complex range for training and exercise purposes is often challenging. Crucible is a modular framework for creating, deploying, and managing virtual environments to support training, education, and exercises. Crucible is designed to be easy to use, extensible, and customizable to meet the needs of a wide variety of use cases.

+
+

Philosophy

+

GHOSTS evolved in our quest to create more realistic NPCs within cyberwarfare training and exercise. In 2018, we outlined our thoughts in a technical report entitled GHOSTS in the Machine: A Framework for Cyber-Warfare Exercise NPC Simulation.1 In that report, we outline how the GHOSTS framework accomplishes the creation of simulations in which NPCs realistically represent a vast array of possible encounters and outcomes. We have continued to follow our initial path since. The litmus has always been that if we looked over someone's shoulder while they were using a computer, that is what GHOSTS should look like.2

+

Since then the framework has expanded to include tools that serve content in simulated environments, create NPCs with details about them that we can programmatically use to drive their decision-making, and machine learning agent preference engines. If it is related to replicating human behavior within a cyber training or exercise scenario, we are interested in how GHOSTS can contribute within that space.

+

Reporting Bugs

+

Found a bug? Please report all bugs - including bugs for the individual components - in the cmu-sei/ghosts issue tracker. Include as much detail as possible including steps to reproduce, the specific components involved, and any error messages you may have found.

+

Requesting Features

+

Have a good idea for a new feature? Submit all new feature requests through the cmu-sei/ghosts issue tracker. Include the reasons why you're requesting the new feature and how it might benefit other users.

+

License

+

[DISTRIBUTION STATEMENT A] This material has been approved for public release and unlimited distribution.

+

Copyright 2018 Carnegie Mellon University. See the LICENSE.md file for details.

+
+
+
    +
  1. +

    This paper is influenced by our previous paper R-EACTR: A Framework for Designing Realistic Cyber Warfare Exercises which outlines a design framework for cyber warfare exercises. It ensures that designs of team-based exercises factor realism into all aspects of the participant experience. Both of these papers are natural extensions to The CERT Approach to Cybersecurity Workforce Development

    +
  2. +
  3. +

    There is also a GHOSTS video presentation from FloCon 2021 that provides a general introduction to the framework. 

    +
  4. +
+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/new/index.html b/new/index.html new file mode 100644 index 00000000..a1ec12f3 --- /dev/null +++ b/new/index.html @@ -0,0 +1,1415 @@ + + + + + + + + + + + + + + + + + + + + + + What's New - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

What's New

+

Welcome to what's new in the GHOSTS framework. Use this page to review the latest changes.

+

GHOSTS Core v7.0

+
    +
  • 10+ significant features built by 6+ contributors!
  • +
  • We surpassed 175 issues/discussions!
  • +
  • These new docs are hosted on GitHub Pages
  • +
  • GHOSTS PANDORA - a new tool for delivering randomized content within a range
  • +
  • GHOSTS PANDORA SOCIAL - a new tool for managing social media content within a range
  • +
+

In the Core Client, v7 Improves:

+
    +
  • Performance
  • +
  • The Clean up of created artifacts
  • +
  • Logging
  • +
  • Cron-like scheduling (in development for all handlers)
  • +
  • New handlers for Firefox and Chrome Browsers
  • +
  • Complete forms
  • +
  • Post payloads (images, files, etc.)
  • +
  • Better UA string handling
  • +
  • SharePoint
  • +
  • Drupal Blog Management
  • +
  • Jabber (XMPP)
  • +
  • RDP
  • +
  • sFTP
  • +
  • SSH
  • +
  • Client Now Supports AutoIT
  • +
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/quickstart/index.html b/quickstart/index.html new file mode 100644 index 00000000..35d98940 --- /dev/null +++ b/quickstart/index.html @@ -0,0 +1,1454 @@ + + + + + + + + + + + + + + + + + + + + + + Quick Start - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

Quick Start

+
+No Compilers Necessary +

This section details the installation and configuration of GHOSTS from precompiled binaries for both the server and the client.

+
+

If you are just checking out the project for the first time and want to see NPCs performing activities, skip to the client section below. Otherwise, it is easier to install the API first and then a client that will connect to that installed API instance.

+

GHOSTS API Server

+

Easy installation requires:

+
    +
  1. Install 🐳 Docker
  2. +
  3. Install Docker Compose
  4. +
  5. +

    We'll use this docker-compose.yml file in the following command block which will download the required containers will automatically. The commands to stand up the GHOSTS API containers is:

    +
    mkdir ghosts-api
    +cd ghosts-api
    +curl https://raw.githubusercontent.com/cmu-sei/GHOSTS/master/src/Ghosts.Api/docker-compose.yml -o docker-compose.yml
    +docker-compose up -d
    +
    +
  6. +
  7. +

    Once the command completes, if you open http://localhost:5000/api/home in your browser, you should see the initial API page outlining the version of the install, and a few test machine entries. If this page renders, your API is up, running, and available. If the page does not render, follow the advice in the API troubleshooting section.

    +
  8. +
+

You will still need to set up Grafana. Beware that you must often chown g_data, which is the host location for the Graphana container as listed in the docker-compose file. Otherwise, the Grafana container will just continually restart in error due to insufficient permissions (detailed in API troubleshooting).

+

GHOSTS Clients

+

For any of the clients utilizing the browser, an automation driver is necessary to be included in the same folder as the GHOSTS binary. For Firefox, download the appropriate 🦎 Geckodriver for your version of the browser here. For Chrome, download the appropriate Chromedriver for your version of the browser here.

+

Note there are additional configuration steps for Outlook email automation.

+

The GHOSTS client should typically be run as a specific user, and not as an administrator or root account.

+

Windows Client

+
    +
  1. Your client machine will need to have (at least) the Microsoft DotNet 4.6.1 runtime installed. You do not need the full SDK.
  2. +
  3. Download the latest Windows client.
  4. +
  5. Unzip to your client machine in a directory such as c:\exercise\ghosts. You will need to adjust the configuration in config/application.json for your client to talk to the already installed API server from above.
  6. +
+

Linux Client

+
    +
  1. Your client Linux machine will need to have the latest Microsoft dotnetcore runtime installed (Note that for the GHOSTS client, there are versions for dotnetcoreapp3.1 - this will eventually go away — and dotnet6.0, which is LTS and should stick around for a while). Again, note that you only need the runtime installed, not the full SDK.
  2. +
  3. Download the latest Linux client zip file. Unzip to a folder such as ~/ghosts for the user that you want GHOSTS to run as.
  4. +
+

Note that on Linux machines running the client as root and utilizing web browsing may result in failures due to Gecko/Chromedriver display issues.

+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 00000000..e3efcca3 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"The GHOSTS NPC Framework","text":"

Developed by Carnegie Mellon University's Software Engineering Institute (SEI), The GHOSTS Framework is an open-source (OSS) software framework that enables creating, deploying, and orchestrating complex non-player character (NPC) activity within training, exercise, simulation, and educational environments. Within GHOSTS there are several systems and applications, all of which are modular and extendable to fit a wide array of use cases and needs.

If you've never seen GHOSTS in action, watch this quick three-minute introductory video on YouTube:

"},{"location":"#documentation","title":"Documentation","text":"

This is the GHOSTS documentation site for the framework and all of its components. Each major component's detail is accessible from the main navigation. If anything is unclear or you still have questions, please do not hesitate to start a discussion \u2014 our community is growing and eager to help!

"},{"location":"#cyber-ranges-and-crucible","title":"Cyber Ranges and Crucible","text":"

GHOSTS is typically run on machines within a virtualized network, often referred to as \"the range\". This network can be as simple or as complex as required for training and exercise purposes.

CERT's Cyber Workforce Development (CWD) team has a great deal of experience in building cyber ranges for training and exercise, captured in our technical report Foundation of Cyber Ranges. The report details the design considerations and execution plan for building high-fidelity, realistic virtual cyber ranges that deliver maximum training and exercise value for cyberwarfare participants.

Run GHOSTS on the Crucible Framework

GHOSTS runs very well within the SEI's Crucible Framework (Source Code and Docs) - which we use extensively for training and exercise here at Carnegie Mellon University (CMU)'s Software Engineering Institute, and particularly, within CERT.

Building a sufficiently complex range for training and exercise purposes is often challenging. Crucible is a modular framework for creating, deploying, and managing virtual environments to support training, education, and exercises. Crucible is designed to be easy to use, extensible, and customizable to meet the needs of a wide variety of use cases.

"},{"location":"#philosophy","title":"Philosophy","text":"

GHOSTS evolved in our quest to create more realistic NPCs within cyberwarfare training and exercise. In 2018, we outlined our thoughts in a technical report entitled GHOSTS in the Machine: A Framework for Cyber-Warfare Exercise NPC Simulation.1 In that report, we outline how the GHOSTS framework accomplishes the creation of simulations in which NPCs realistically represent a vast array of possible encounters and outcomes. We have continued to follow our initial path since. The litmus has always been that if we looked over someone's shoulder while they were using a computer, that is what GHOSTS should look like.2

Since then the framework has expanded to include tools that serve content in simulated environments, create NPCs with details about them that we can programmatically use to drive their decision-making, and machine learning agent preference engines. If it is related to replicating human behavior within a cyber training or exercise scenario, we are interested in how GHOSTS can contribute within that space.

"},{"location":"#reporting-bugs","title":"Reporting Bugs","text":"

Found a bug? Please report all bugs - including bugs for the individual components - in the cmu-sei/ghosts issue tracker. Include as much detail as possible including steps to reproduce, the specific components involved, and any error messages you may have found.

"},{"location":"#requesting-features","title":"Requesting Features","text":"

Have a good idea for a new feature? Submit all new feature requests through the cmu-sei/ghosts issue tracker. Include the reasons why you're requesting the new feature and how it might benefit other users.

"},{"location":"#license","title":"License","text":"

[DISTRIBUTION STATEMENT A] This material has been approved for public release and unlimited distribution.

Copyright 2018 Carnegie Mellon University. See the LICENSE.md file for details.

  1. This paper is influenced by our previous paper R-EACTR: A Framework for Designing Realistic Cyber Warfare Exercises which outlines a design framework for cyber warfare exercises. It ensures that designs of team-based exercises factor realism into all aspects of the participant experience. Both of these papers are natural extensions to The CERT Approach to Cybersecurity Workforce Development.\u00a0\u21a9

  2. There is also a GHOSTS video presentation from FloCon 2021 that provides a general introduction to the framework.\u00a0\u21a9

"},{"location":"new/","title":"What's New","text":"

Welcome to what's new in the GHOSTS framework. Use this page to review the latest changes.

"},{"location":"new/#ghosts-core-v70","title":"GHOSTS Core v7.0","text":"
  • 10+ significant features built by 6+ contributors!
  • We surpassed 175 issues/discussions!
  • These new docs are hosted on GitHub Pages
  • GHOSTS PANDORA - a new tool for delivering randomized content within a range
  • GHOSTS PANDORA SOCIAL - a new tool for managing social media content within a range

In the Core Client, v7 Improves:

  • Performance
  • The Clean up of created artifacts
  • Logging
  • Cron-like scheduling (in development for all handlers)
  • New handlers for Firefox and Chrome Browsers
  • Complete forms
  • Post payloads (images, files, etc.)
  • Better UA string handling
  • SharePoint
  • Drupal Blog Management
  • Jabber (XMPP)
  • RDP
  • sFTP
  • SSH
  • Client Now Supports AutoIT
"},{"location":"quickstart/","title":"Quick Start","text":"No Compilers Necessary

This section details the installation and configuration of GHOSTS from precompiled binaries for both the server and the client.

If you are just checking out the project for the first time and want to see NPCs performing activities, skip to the client section below. Otherwise, it is easier to install the API first and then a client that will connect to that installed API instance.

"},{"location":"quickstart/#ghosts-api-server","title":"GHOSTS API Server","text":"

Easy installation requires:

  1. Install \ud83d\udc33 Docker
  2. Install Docker Compose
  3. We'll use this docker-compose.yml file in the following command block which will download the required containers will automatically. The commands to stand up the GHOSTS API containers is:

    mkdir ghosts-api\ncd ghosts-api\ncurl https://raw.githubusercontent.com/cmu-sei/GHOSTS/master/src/Ghosts.Api/docker-compose.yml -o docker-compose.yml\ndocker-compose up -d\n
  4. Once the command completes, if you open http://localhost:5000/api/home in your browser, you should see the initial API page outlining the version of the install, and a few test machine entries. If this page renders, your API is up, running, and available. If the page does not render, follow the advice in the API troubleshooting section.

You will still need to set up Grafana. Beware that you must often chown g_data, which is the host location for the Graphana container as listed in the docker-compose file. Otherwise, the Grafana container will just continually restart in error due to insufficient permissions (detailed in API troubleshooting).

"},{"location":"quickstart/#ghosts-clients","title":"GHOSTS Clients","text":"

For any of the clients utilizing the browser, an automation driver is necessary to be included in the same folder as the GHOSTS binary. For Firefox, download the appropriate \ud83e\udd8e Geckodriver for your version of the browser here. For Chrome, download the appropriate Chromedriver for your version of the browser here.

Note there are additional configuration steps for Outlook email automation.

The GHOSTS client should typically be run as a specific user, and not as an administrator or root account.

"},{"location":"quickstart/#windows-client","title":"Windows Client","text":"
  1. Your client machine will need to have (at least) the Microsoft DotNet 4.6.1 runtime installed. You do not need the full SDK.
  2. Download the latest Windows client.
  3. Unzip to your client machine in a directory such as c:\\exercise\\ghosts. You will need to adjust the configuration in config/application.json for your client to talk to the already installed API server from above.
"},{"location":"quickstart/#linux-client","title":"Linux Client","text":"
  1. Your client Linux machine will need to have the latest Microsoft dotnetcore runtime installed (Note that for the GHOSTS client, there are versions for dotnetcoreapp3.1 - this will eventually go away \u2014 and dotnet6.0, which is LTS and should stick around for a while). Again, note that you only need the runtime installed, not the full SDK.
  2. Download the latest Linux client zip file. Unzip to a folder such as ~/ghosts for the user that you want GHOSTS to run as.

Note that on Linux machines running the client as root and utilizing web browsing may result in failures due to Gecko/Chromedriver display issues.

"},{"location":"advanced/","title":"GHOSTS Advanced Features Overview","text":"

The SEI is a research institute, and so we often are thinking about how to use GHOSTS in new ways to drive insight for our customers. Some of this work makes it here, with the caveat that it might be early beta editions or require some amount of engineer hand-holding in its current state. Some call it pre-release, we call it advanced features.

"},{"location":"advanced/cyclone/","title":"GHOSTS CYCLONE Overview","text":"Unreleased

Coming soon

"},{"location":"advanced/enchanter/","title":"GHOSTS ENCHANTER Overview","text":"Unreleased

Coming soon

"},{"location":"advanced/necromancer/","title":"GHOSTS NECROMANCER Overview","text":"Unreleased

Coming soon

"},{"location":"animator/","title":"GHOSTS ANIMATOR Overview","text":"GHOSTS ANIMATOR Source Code

The GHOSTS ANIMATOR Source Code Repository is hosted on GitHub

Animator brings NPCs to life in two ways:

  1. Initial Creation

    Animator creates the initial NPC profile, including details such as name, address, career, finances, and family members. Based on configuration, it can place users in a multi-level organizational structure, and establish relationships between users.

  2. Animation Jobs

    Via jobs that can be run during training and exercise events, Animator can update the NPC's preferences, beliefs, and relationships. This enables dynamic NPCs that change over time.

At its core, Animator is a realistic user detail generator. Its primary function is to create sufficiently realistic identities and accompanying verbose portfolios of personal information. Each generated user, or NPC (Non-Player Character) as we call them, has numerous categories of details associated with them, and a great deal of metadata that define who they are. Each piece of information is generated using sourced datasets in an attempt to distribute characteristics realistically. We like to say it creates, \"NPCs so real, they sell for a premium on the dark web.\"1

"},{"location":"animator/#quick-start","title":"Quick Start","text":"
git clone <https://github.com/cmu-sei/GHOSTS-ANIMATOR>\ncd ghosts-animator/src\ndocker build . -t ghosts/animator\ndocker compose up -d\n

or if you don't want to build and just run the latest docker-compose file:

mkdir ghosts-animator\ncd ghosts-animator\ncurl https://github.com/cmu-sei/GHOSTS-ANIMATOR/blob/master/src/docker-compose.yml -o docker-compose.yml\ndocker compose up -d\n

Now browse to http://localhost:5000/

"},{"location":"animator/#using-animator-to-create-npcs","title":"Using Animator to Create NPCs","text":"

The data generated by Animator can be leveraged in multiple areas, but is particularly applicable in four key areas:

  1. Training Machine Learning Algorithms - Animator creates larges sets of hyper-realistic user data. It can be leveraged to generate data sets that can be used for training machine learning algorithms. This enables the rapid training of anthropology-related ML algorithms that can leverage one or more of the hundred-plus data points generated by Animator.2

  2. Honeypot Payloads - NPC details generated by Animator are designed to be as realistic as possible given the available relevant open source information. This makes the user data convincingly real while still being completely fabricated. Therefore, the data is ideal for use in applications like honeypots, where the goal is to trick an attacker into thinking they are compromising an asset with real user data. This data is also perfect for any other application that would benefit from extremely realistic user information.

  3. Insider Threat Modeling - Each Animator NPC is given an Insider Threat Profile. This profile determines how likely it is that the NPC is an insider threat by incorporating the CDSE's Insider Threat Potential Indicators. As we continue developing Animator, it will be possible to configure NPCs to be more or less likely to be insider threats based on factors like their finances, criminal history, foreign contacts, and mental health.

  4. Social Network and Relationship Modeling - Animator can establish relationships between the NPCs it generates. As we increase the fidelity of inter-NPC relationships, Animator NPCs create larger and more realistic social networks. By leveraging Animator's ability to quickly generate thousands of inter-related NPCs, Animator can easily be used to perform social networking modeling and research.

"},{"location":"animator/#how-creating-npcs-works","title":"How Creating NPCs Works","text":"
  • Once Animator receives a request to create NPCs, it starts by creating an empty NPC Profile.
  • Animator then iterates through all 100+ data points for the NPC and generates synthetic data to be associated with that NPC.
  • Example data points are name, address, mental health, career, finances, and family members.
  • Data points are either generated at random or are generated using weighted randomization. Weighted randomization involves leveraging verified datasets to influence the distribution of randomly generated data points to match much more closely to reality.
  • Animator will complete this process for as many users as were selected by the request. This information can be exported through the API, or stored in a local database

Animator currently supports storing NPC data in a local Mongo Database. This feature is still being actively improved.

  1. The GHOSTS development team highly recommends Nick Bilton's book American Kingpin for insight into the early days of the dark web.\u00a0\u21a9

  2. A key developer from the Animator team went on to a position in the SEI's AI division. AI models need data. You connect the dots.\u00a0\u21a9

"},{"location":"animator/jobs/","title":"Animation Jobs","text":"

So, now we have Animator-generated NPCs, and they have profile information and preferences.

Animator has a job system that might enables us to push our simulation further:

  • What motivates an agent?
  • What does an agent know and how did they learn that? How does their knowledge grow over time?
  • What relationships does an agent have off-network? How might this influence what they do on the computer?
  • What does an agent believe? How did they come to that belief?

Jobs operate on a \"per cycle\" or \"step\" basis. For each cycle, the job processes a list of agents, and the actions or determinations programmed for each.

"},{"location":"animator/jobs/#decision-making-framework","title":"Decision-Making Framework","text":"

We can use any combination of the following to drive agent decision-making:

"},{"location":"animator/jobs/#motivation","title":"Motivation","text":"

We implement the Reiss Motivational Profile (RMP) - which is a mathematical framework for reasoning about agent comparative motivations - agent A is twice as motivated by X than agent B - that is baselined every few years.

"},{"location":"animator/jobs/#relationships","title":"Relationships","text":"

Agents build relationships with other agents in the cohort. These get better or worse over time.

How this works is that each agent has the potential to interact with n other agents (they can also potentially transfer knowledge as a result). The more an agent knows about a particular subject, maybe the more likely they are to transfer information to another agent.

"},{"location":"animator/jobs/#knowledge","title":"Knowledge","text":"

Agents build knowledge across an array of subjects that may alter their preferences. Within Animator, there are two main ways to learn:

  • Independently through study or by utilizing resources such as books or videos
  • Through relationships with others at the coffee counter, through mentorship, or group-based learning (a classroom or team for example). Here NPCs learn via interactions with other agents, and the system tracks what was learned and from whom.
"},{"location":"animator/jobs/#belief","title":"Belief","text":"

What an agent believes can directly influence their behavior. Beliefs shape understanding of the world and guide decision-making and problem-solving. Agents come to belief utilizing Bayes Theorem, which is a mathematical framework for reasoning about probability of evidence.

So what does this all mean? Here is an example where an agent shares bits of information on social media:

Some tweets contain no insight about the agent. Some disclose some bit of information:

  • Agent knows X fact
  • Agent interacted with Y agent
  • Agent decided to disclose some personal detail Z

Other agents \u2014 and adversaries \u2014 can see and infer from this information!

"},{"location":"animator/run/","title":"Running Animator Animations","text":"

Animator is a simulation of a population of agents. Animator runs in cycles, and for each cycle, the agents make decisions based on their attributes, preferences, motivations, and behaviors.

"},{"location":"animator/run/#setup","title":"Setup","text":"
  • Get the Animator API up and running as outlined here
  • Edit the appsettings.json file to enable Animations:
\"ApplicationSettings\": {\n\"GhostsApiUrl\": \"http://localhost:52388/\",        // this should be root url of your ghosts API server\n\"Animations\": {\n\"IsEnabled\": false,                             // set this to true to enable animation jobs\n\"SocialGraph\": {\n\"IsEnabled\": false,                           // set this to true to enable the entire module (inc. web gui access)\n\"IsInteracting\": false,                       // set this to true to actually run the interactions\n\"MaximumSteps\": 4000,                         // animator stops when it reaches this many steps \n\"TurnLength\": 900,                            // by default, a step is a cpu cycle, the higher this number, the slower the simulation \n\"ChanceOfKnowledgeTransfer\": 0.3,\n\"Decay\": {\n\"StepsTo\": 10,\n\"ChanceOf\": 0.05\n}\n},\n\"SocialSharing\": {\n\"IsEnabled\": false,                          // set this to true to enable the entire module (inc. web gui access)\n\"IsInteracting\": false,                      // set this to true to actually run the interactions\n\"IsSendingTimelinesToGhostsApi\": false,      // set this to true to actually send the timeline commands to the ghosts API\n\"IsChatGptEnabled\": false,                   // this is still under development, here be dragons\n\"SocializerUrl\": \"http://socializer.com\",    // change this to the root url of your in-game social server\n\"MaximumSteps\": 14000,\n\"TurnLength\": 9000                           // by default, a step is a cpu cycle, the higher this number, the slower the simulation \n},\n\"SocialBelief\": {\n\"IsEnabled\": false,                         // set this to true to enable the entire module (inc. web gui access)\n\"IsInteracting\": false,                     // set this to true to actually run the interactions\n\"MaximumSteps\": 14000,\n\"TurnLength\": 9000\n}\n}\n},\n...\n

After you update the appsettings.json file, you will need to restart the Animator API server via:

docker restart animator-api\n
"},{"location":"content/","title":"GHOSTS Content Servers Overview","text":"

GHOSTS content servers are an evolving part of the framework. They exist for several reasons:

  1. On an air-gapped network, where we are simulating some subset of the internet, we want more types of browsable content within that range \u2014 documents, spreadsheets, presentations, pdf files, streamed movies, and the like.
  2. We want a broad range of URLs within a site we are representing in the range.
  3. We want to simulate a document store, such as SharePoint, OneCloud, or similar, but without the hassle of installing and maintaining those actual systems.

Research by Global WebIndex claims that globally, 59% of the world's population uses social media, and that the average daily use is 2 hours and 29 minutes (July 2022).

"},{"location":"content/#air-gaps","title":"Air-gaps","text":"

Many ranges are air-gapped, which means they have no access to the wider internet. In these cases, recreating a reasonable facsimile of the internet is key to the training experience. While there are many systems that do this well, we often want to augment the scenario with a wider array of URL traffic, or we want to introduce more of certain kinds of content going across the wire. PANDORA was created to address these concerns. Shortly later, we added a social server as well.

"},{"location":"content/#having-to-know-valid-urls","title":"Having to know valid URLs","text":"

The other problem is that the internet works by the client having to \u201cknow\u201d the location of some resource via:

  • Actually knowing the URL
  • Being referred from another page - I might know google.com and search for something, which gives me a reference to another page I was not aware of previously.
  • Inferring the URL from some like resource - If one is poking around and looking for something on a server, a slight change of URL often gives hints that get you to where you wanted to go.
  • Guessing - the proliferation of .com domains means that for something new, it's often fruitful to just try that thing.com and see if it works!

The problem here is that currently, clients must know valid URLs that actually exist out in a simulated greyspace (via TopGen, GreyBox, or otherwise), which limits the array of potential requests and creates range work to maintain. So we created GHOSTS PANDORA, which serves whatever clients ask for - if the request is for a doc file, the server creates a random doc file on the fly \u2014 in memory \u2014 and serves it back to the client. Pandora serves the following content types:

  • html
  • css
  • js
  • doc|x
  • ppt|x
  • xls|x
  • mp4
  • pdf
  • gif
  • jpg
  • png
  • zip
  • msi
  • iso
  • other binary formats, etc.

Pandora has generic request handlers for each HTTP verb (GET, POST, etc.) and is deployed as a simple docker container. We configure it to handle a particular IP on a multiple-IP-enabled host machine. It works off any URL, but part of the solution involved introducing more randomness in the GHOSTS clients as well. Those clients now support a creative parameter-built URL system that can be configured to look something like this:

sharepoint.hello.com/{org}/{report_type}/{uuid}/{file_name}.{file_type}\n

These variables are processed at runtime, and produce a final url that might look something like:

sharepoint.hello.com/operations/maintenance/80e6af4e-5107-43b5-832f-0d8027efbd76/report.docx\n

In addition, Pandora supports \u201cbad\u201d payloads via configuration. Here the server responds to specific configured URLs to deploy planted injects. So clients can download malware in an exercise in a manner that is hard to differentiate based on URLs already seen within the event. The configuration looks like:

[payloads]\n1=/bad/payload/url/,some_bad.zip,application/zip\n

Where id=url,payload file, MIME response type.

"},{"location":"content/pandora/","title":"GHOSTS PANDORA SERVER Overview","text":"Pandora is part of GHOSTS

Pandora is within the GHOSTS Source Code Repository hosted on GitHub.

GHOSTS PANDORA is a web server that responds to a myriad of request types with randomized content generated in real-time. Used in conjunction with GHOSTS NPCs, the two can provide for agents that are periodically downloading content other than simple HTML and associated image, CSS, and js files.

"},{"location":"content/pandora/#running-this-server","title":"Running this server","text":""},{"location":"content/pandora/#as-a-docker-container","title":"As a Docker Container","text":"

Docker is the preferred way to run Pandora - mostly because this is how we run and test it before version releases.

  1. Review the repository docker-compose.yml file
  2. Run the following in your terminal
mkdir ghosts-pandora\ncd ghosts-pandora\ncurl https://raw.githubusercontent.com/cmu-sei/GHOSTS/master/src/ghosts.pandora/docker-compose.yml -o docker-compose.yml\ndocker-compose up -d\n
"},{"location":"content/pandora/#bare-metal","title":"Bare metal","text":"

This assumes the host server is a common Linux distribution. For images to render correctly, PIL or the more recent Pillow library is necessary. See here for more information on Pillow installation and configuration.

  1. Using a Python 3 distribution >= 3.6.2
  2. In the terminal run: pip install -r requirements.txt
  3. Then run python app.py
"},{"location":"content/pandora/#capabilities","title":"Capabilities","text":""},{"location":"content/pandora/#handling-requests-by-directory","title":"Handling requests by directory","text":"
  • /api - All requests beginning with /api automatically respond with json. This includes:
    • /api/users
    • /api/user/a320f971-b3d9-4b79-bb8d-b41d02572942
    • /api/reports/personnel
  • /csv - All requests beginning with /csv automatically respond with csv. Like the above, this includes urls such as:
    • /csv/users
    • /csv/user/winx.jalton
    • /csv/reports/HR/payroll
  • /i, /img, /images - All requests beginning with these directories automatically respond with a random image of type [gif, jpg, png]. Examples:
    • /i/v1/a9f6e2b7-636c-4821-acf4-90220f091351/f8f8b1f0-9aa5-4fc7-8880-379e3192748e/small
    • /images/products/184f3515-f49b-4e07-8c8b-7f978666df0e/view
    • /img/432.png
  • /pdf - All requests respond with a random pdf document. Examples:
    • /pdf/operations/SOP_Vault/a7f48bd5-84cb-43a1-8d3d-cd2c732ddff6
    • /pdf/products
  • /docs - All requests respond with a random word document
  • /slides - All requests respond with a random powerpoint document
  • /sheets - All requests respond with a random excel document
"},{"location":"content/pandora/#handling-requests-by-type","title":"Handling requests by type","text":"

For requests indicating a specific file type, there are several specific handlers built to respond with that particular kind of file, such as:

  • .csv
  • Image requests [.gif, .ico, .jpg, .jpeg, .png]
  • .json
  • Office document requests
  • .doc, .docx
  • .ppt, .pptx
  • .xls, .xlsx
  • .pdf

So that a URL such as /users/58361185-c9f2-460f-ac45-cb845ba88574/profile.pdf would return a pdf document typically rendered right in the browser.

All unhandled request types, urls without a specific file indicator, or requests made outside specifically handled directories (from the preceding section) are returned as html, including:

  • /docs/by_department/operations/users
  • /blog/d/2022/12/4/blog_title-text
  • /hello/index.html
"},{"location":"content/pandora/#hiding-malicious-payloads-for-red-teaming","title":"Hiding malicious payloads for red-teaming","text":"

Pandora also can hide payloads in a particular request for things like red-teaming and such. This is done in the configuration file, and looks like this:

[payloads]\n1=/1/,a.zip,application/zip\n2=/2/users,b.zip,application/zip\n3=/3/some/report/url,c.zip,application/zip\n

Each record must be an incrementing integer with no duplication. The values are:

  • The URL that this payload responds to
  • The local file (stored in ./payloads/) to be returned
  • The MIME type of the response

So for 1 in the example above, requests to /1/ return the a.zip file as an application/zip file.

"},{"location":"content/social/","title":"GHOSTS PANDORA SOCIAL Overview","text":"PANDORA SOCIAL is still very early beta

Here be dragons

The place where GHOSTS agents come to share their thoughts and information.

In the spirit of the original PANDORA, this server also responds to a very broad array of URLs but enables clients to POST/PUT/DELETE to it as well, for example:

Request Response POST /images responds with a url to the saved image file POST / responds with a randomly-generated streamed video POST /users/michelle_smith/af2d00aa-4a89-4af3-baff-1746b556e7a1/ responds with a reply to the original user's social post"},{"location":"core/api/","title":"GHOSTS Core API Overview","text":"GHOSTS Source Code

The GHOSTS Source Code Repository is hosted on GitHub.

The GHOSTS API enables the control and orchestration of non-player characters (NPCs) within a deployment. It supports logging, reporting, and managing individual, groups of, or entire deployments of client installs.

"},{"location":"core/api/#installation","title":"Installation","text":"
  1. Install \ud83d\udc33 Docker
  2. Install Docker Compose
  3. Run the following commands - we'll use this docker-compose.yml file
mkdir ghosts\ncd ghosts\ncurl https://raw.githubusercontent.com/cmu-sei/GHOSTS/master/src/Ghosts.Api/docker-compose.yml -o docker-compose.yml\ndocker-compose up -d\n

The required containers will be downloaded and configured automatically.

Once the last command completes, if you open http://localhost:5000/api/home in your browser, you should see the initial API page outlining the version of the install, and a few test machine entries. If this page renders, your API is up, running, and available.

You will still need to set up Grafana. Beware that you must often chown the host location of the container as listed in the docker-compose file or the container will just continually restart in error due to insufficient permissions.

"},{"location":"core/api/#configuring-the-api","title":"Configuring the API","text":"

The API generally has good defaults to get you up and running quickly, but there are some considerations in the appconfig.json file:

    \"ClientSettings\": {\n\"OfflineAfterMinutes\": 30, ...\n\"MatchMachinesBy\": null,\n

Can be fqdn|host|resolvedhost|null - null tells the API to match incoming requests with machine records by the machine name. For installations where multiple domains are reporting into the same API, you probably want to use FQDN in order to avoid machines being duplicated.

\"QueueSyncDelayInSeconds\": 10,\n\"NotificationsQueueSyncDelayInSeconds\": 10,\n

This is how often the synch job runs. Incoming machine requests are not real-time in order to best bundle like records together.

"},{"location":"core/api/#configuring-grafana","title":"Configuring Grafana","text":"
  • Grafana will be running (if containerized) on port 3000, and we can access it via the same URL we use for the API.
  • The default login is admin/admin.
  • The first step is to set up a datasource named \"ghosts\" to the ghosts Postgres database.
  • Now import your choice of the grafana json files in this repository. It creates the default GHOSTS dashboard.
"},{"location":"core/api/#webhooks","title":"Webhooks","text":"

The GHOSTS API provides webhook callbacks based on the configuration on the endpoint: /api/webhooks. The payload for creating a webhook is in the format:

{\n\"status\": 0,\n\"description\": \"some description\",\n\"postbackUrl\": \"http://localhost/endpoint:port\",\n\"postbackMethod\": 0, (0 == get, 1 == post)\n\"postbackFormat\": \"see below\"\n}\n

Payloads can be any format \u2014 here is a sample:

{\n'machine':'[machinename]',\n'created':'[datetime.utcnow]',\n'type':'[messagetype]',\n'payload':'[messagepayload]'\n}\n

On send, the payload will be converted into the correct JSON format:

{\n\"machine\":\"some_guid\",\n\"created\":\"some_datetime\",\n\"type\":\"some_message\",\n\"payload\":\"some_payload\"\n}\n

If the postback method is POST, the payload will be sent as the message body. If the postback method is GET, the payload will be sent as part of the querystring value ?message=payload.

The following events are reported via webhooks:

  1. Timeline delivered (with the timeline that was delivered as payload) to a machine via API (original API posting of timeline only holds timeline in wait - the client still must check-in in order for that timeline to be delivered)
  2. Machine requested updates (\"checked in\") from API
  3. Machine posted results to API
"},{"location":"core/api/#troubleshooting","title":"Troubleshooting","text":"

Is the API up and running?

  • Go to /api/home in the browser, it should return the current API version and the number of machines and groups under management. If it says relationship not found, restart the API application and it should create the database automatically.
  • Run docker ps --all and see that all containers are running normally. If one or more is not running, look at the logs for that machine via docker logs [machine name].

The ClientId, ClientResults, and other Client* endpoints are failing.

The Client* endpoints are for the Clients to use only. There are specific header values set by the client in the request that is used to authenticate the request. If you are not using the client, you will not have these headers set, and these endpoints will fail.

"},{"location":"core/client/","title":"GHOSTS Core Client Overview","text":"GHOSTS Source Code

The GHOSTS Source Code Repository is hosted on GitHub.

The GHOSTS client simulates what anyone might do at a computer given their particular role or membership within some team. It creates documents, browses websites, downloads files, and uses all sorts of popular applications on many versions of Windows and Linux machines. Whether you're a friendly administrator or a powerful cyber adversary, GHOSTS can replicate your expected behavior.

GHOSTS has many use cases in cyber training and exercises, most notably for bringing non-player characters (NPCs) to life, but it can also be used for other purposes where realistic activity on a computer or network is needed - testing or generating datasets, for example.

Do I need the API?

Although clients are fully functional without the API server, the latter enables logging, reports, and remote administration capabilities. Without the API, changes to clients must be managed in some other manner.

The client's configuration and command system are file-based, so if you do not wish to use the API, you can manage these through some other tool, such as Ansible or similar. All of these files are under the client's install location.

Run as the NPC you're representing

The GHOSTS client should typically be run as a user, and not as administrator or root - training or exercising teams will notice this immediately.

"},{"location":"core/client/#the-windows-client","title":"The Windows Client","text":"

GHOSTS on Windows (Win10 and Win7 currently supported) is a .NET Console application that performs user activity on client workstations - web browsing, working with office documents, using the command prompt or PowerShell, etc. Our team typically installs the client in an out-of-game directory (c:\\exercise\\ghosts\\), where no event or injects will originate. It is recommended you verify one working client before deploying to multiple machines. You will need the base URL from the API installation for the client to communicate home.

"},{"location":"core/client/#windows-installation","title":"Windows Installation","text":"
  • Your client Windows machine will need to have (at least) the Microsoft DotNet 4.6.1 runtime installed . Again, note that you only need the runtime, not the full SDK. We continue to use 4.6.1 on Windows to maintain backward compatibility.

  • Download the appropriate latest client

Unzip to your client machine in a directory such as c:\\exercise\\ghosts. You will need to adjust the configuration in config/application.json for your client to talk to your an installed instance of the GHOSTS API server.

Additional configuration required for web browsing

For any client utilizing the Firefox or Chrome web browser, an automation driver is necessary to be included in the same folder as the GHOSTS binary. For Firefox, download the appropriate \ud83e\udd8e\u00a0 Geckodriver for your version of the browser here . For Chrome, download the appropriate Chromedriver for your version of the browser here .

Additional configuration required for email

Using the Windows client email functions requires the use of Redemption which provides robust Outlook automation. The full Redemption library should be found in /lib.

"},{"location":"core/client/#linux-client","title":"Linux Client","text":"

Your client Linux machine will need to have the latest Microsoft dotnetcore runtime installed (Note that for the GHOSTS client, there are versions for dotnetcoreapp3.1 - this will eventually go away \u2014 and dotnet6.0, which is long term support (LTS) and will stick around for a while). Again, note that you only need the runtime installed, not the full SDK.

"},{"location":"core/client/#linux-installation","title":"Linux Installation","text":"
  • Download the latest Linux client

Unzip to a folder such as ~/ghosts for the user that you want GHOSTS to run as.

Note that on Linux machines running the client as root and utilizing web browsing may result in failures due to Gecko/Chromedriver display issues.

"},{"location":"core/client/#client-directory-structure","title":"Client Directory Structure","text":"Do not copy the instance folder

You should never copy the instance folder from one machine to another.

Folder Description config/ configuration files are stored here. instance/ generated files and information relative to this particular installed instance of ghosts is stored here. This folder should never be copied from one machine to another lib/ third-party libraries used by ghosts are stored here logs/ output logs for the installed instance (logs/app.log), and logs that are transferred to the server (logs/clientupdates.log)"},{"location":"core/client/#configuration-quick-start","title":"Configuration Quick Start","text":"

After unzipping the GHOSTS client, we can simply double-click it to run. Note that the console window likely printed a few messages, but then disappeared. This is normal, in production mode GHOSTS hides itself. We can see it in the Windows Task Manager, however, and we can kill the process from there. We can also run the included kill-ghosts.bat file that closes the application and any applications it might control.

Beyond this initial step of verifying that the client will run, there are two files that we might need to adjust to fit many deployments:

"},{"location":"core/client/#applicationjson","title":"application.json","text":"

In this file, often all we need to change are the URLs for the API, IdUrl, ClientResultsUrl, ClientUpdatesUrl, and the like. Change the hostname to your installed API location, and GHOSTS should check in as expected.

{\n\"IdEnabled\": true,                                                      //enabled in order to command and control from api (C2) server\n\"IdUrl\": \"http://yourapiurl.com/api/clientid\",                          //url for API endpoint to get clientid\n\"ClientResultsEnabled\": true,                                           //enabled to report results to C2\n\"ClientResultsUrl\": \"http://yourapiurl.com/api/clientresults\",          //url for API endpoint to report results\n\"ClientResultsCycleSleep\": 90,                                          //report results every x ms\n\"ClientUpdatesEnabled\": true,                                           //enabled to get updates from C2\n\"ClientUpdatesUrl\": \"http://yourapiurl.com/api/clientupdates\",          //url for API endpoint to get updates\n\"ClientUpdatesCycleSleep\": 90,                                          //check for updates every x ms\n\"Survey\": {                                                             //survey is a local report of processes running, etc.\n\"IsEnabled\": true,                                                  //on/off\n\"Frequency\": \"once\",                                                //how often to survey\n\"MaxAgeInHours\": 168,                                               //how long to wait until new survey\n\"OutputFormat\": \"indent\"                                            //compact/fancy(indent)\n},\n\"HealthIsEnabled\": true,                                                //enable local health checks\n\"HandlersIsEnabled\": true,                                              //enable local timeline activity\n\"ChromeExtensions\": \"\",                                                 //comma separated local extensions (used for injects in the past)\n\"FirefoxInstallLocation\": \"\",                                           //geckodriver needs this for non-standard installs (is pesky)\n\"FirefoxMajorVersionMinimum\": 48,                                       //geckodriver is picky about versions\n\"OfficeDocsMaxAgeInHours\": 6,                                           //cleanup kills docs in the documents folder older than this setting\n}\n
"},{"location":"core/client/#timelinejson","title":"timeline.json","text":"

The other file we may want to adjust is the default timeline. This is what the agent does all day, including browsing the internet, creating documents, and similar. The defaults hopefully give you a good idea of what is possible, and of course, the array of configurations here is endless - be creative!

The primary item is the HandlerType. This tells GHOSTS to run a command (Command), use Firefox to browse an array of websites (BrowserFirefox), create Excel documents (Excel) and so on. Some of the other items related to a handler's configuration are:

  • Initial: The initial command for a handler to execute. For a web browser, you might enter either a URL or \"about:blank\".
  • UtcTimeOn | UtcTimeOff: \"00:00:00\": \"24:00:00\" to not shut off. Otherwise, enter an on and an off time to simulate things such as office hours of 9-5, etc. There are 30 minutes of jitter plus or minus from the time entered.
  • Loop: Set this to true to continue to execute this same command on a loop, or false to execute something just one time.
{\n\"HandlerType\": \"Command\",\n\"Initial\": \"\",\n\"UtcTimeOn\": \"00:00:00\",\n\"UtcTimeOff\": \"24:00:00\",\n\"Loop\": \"True\",\n\"TimeLineEvents\": [\n{\n\"Command\": \"NETSTAT\",    \"CommandArgs\": [],\n\"DelayAfter\": 900000,\n\"DelayBefore\": 0\n}\n]\n}\n

To access a network share file, the command might be: net use X:\\SERVER\\Share

To RDP to another machine: mstsc.exe {ConnectionFile | /v:ServerName[:Port]} [/console] [/f] [/w:Width/h:Height]

/v - specifies the remote computer and port (optional) you wish to connect to /console \u2013 connects to the console of a Windows Server 2003 based system /f \u2013 starts the remote desktop connection in full screen mode /w & /h \u2013 specifies the width and height of the remote desktop connection

Actions can also be created for standard copy/move/deletion of files via their respective commands.

Chrome

We have to pass the browser window an initial value. If we don't want it to go anywhere at start, we could pass about:blank, otherwise we'd pass a url. These can be http or https.

{\n\"HandlerType\": \"BrowserChrome\",\n\"Initial\": \"http://google.com\",\n\"UtcTimeOn\": \"00:00:00\",\n\"UtcTimeOff\": \"24:00:00\",\n\"Loop\": \"True\",\n\"TimeLineEvents\": [\n{\n\"Command\": \"random\",\n\"CommandArgs\": [\n\"http://google.com\",\n\"http://facebook.com\",\n],\n\"DelayAfter\": 1000,\n\"DelayBefore\": 0\n}\n]\n}\n

Excel, PowerPoint, Word

{\n\"HandlerType\": \"Word\",\n\"Initial\": \"\",\n\"UtcTimeOn\": \"00:00:00\",\n\"UtcTimeOff\": \"24:00:00\",\n\"Loop\": \"True\",\n\"TimeLineEvents\": [\n{\n\"Command\": \"create\",\n\"CommandArgs\": [ \"%homedrive%%homepath%\\\\Documents\" ],\n\"DelayAfter\": 900000,\n\"DelayBefore\": 0\n}\n]\n}\n
"},{"location":"core/client/#trackables","title":"Trackables","text":"

For specific Timeline Events where the outcome is needed to be tracked, like for example, a client machine spawned inject, use a Trackable (via TrackableId in the following example):

{\n\"TimeLineHandlers\": [\n{\n\"HandlerType\": \"BrowserChrome\",\n\"Initial\": \"about:blank\",\n\"UtcTimeOn\": \"00:00:00\",\n\"UtcTimeOff\": \"24:00:00\",\n\"Loop\": false,\n\"TimeLineEvents\": [\n{\n\"Command\": \"browse\",\n\"CommandArgs\": [ \"https://dl.dafont.com/dl/?f=italian_breakfast\" ],\n\"DelayAfter\": 0,\n\"DelayBefore\": 0\n},\n{\n\"Command\": \"download\",\n\"CommandArgs\": [ \"//a[contains(@class, 'dl')]\" ],\n\"TrackableId\": \"<guid id from trackables table/>\",\n\"DelayAfter\": 0,\n\"DelayBefore\": 0\n}\n]\n},\n{\n\"HandlerType\": \"Command\",\n\"Initial\": \"\",\n\"UtcTimeOn\": \"00:00:00\",\n\"UtcTimeOff\": \"24:00:00\",\n\"Loop\": false,\n\"TimeLineEvents\": [\n{\n\"Command\": \"cd %homedrive%%homepath%\\\\Downloads\",\n\"CommandArgs\": [\n\"powershell expand-archive -Path italian_breakfast.zip -destinationpath x\",\n\"cd x\",\n\"dir\"\n],\n\"TrackableId\": \"<guid id from trackables table/>\",\n\"DelayAfter\": 10,\n\"DelayBefore\": 10000\n}\n]\n}\n]\n}\n
"},{"location":"core/client/#troubleshooting","title":"Troubleshooting","text":"

Clients aren't running (immediately exiting, throwing copious exceptions, or similar)

  • Is the dotnet framework runtime 4.x installed on the machine?
  • If GPO is doing white-listing of what apps can run, is ghosts.exe white-listed?
  • Will the client run by simply double-clicking on the exe?
  • Does it report anything to the windows application event logs?
  • What's in logs/app.log?
  • Is the ghosts executable set to execute automatically when the machine restarts?

Clients aren't reporting their activity to the API

  • Is the client running correctly? (if not, see above)
  • Is there entries in the logs/clientupdates.log?
  • If there are, is the file too large? (Try removing it, ghosts might be hung trying to process a lot of log data)
  • If the folder instance created? Does the file instance/id.json exist? (If it does and has an ID within, then ghosts has reported home to the api at least once)
  • The file logs/app.log indicating any fatal issues? (Logging can be ratcheted up and down via nlog configuration)

Can I update what clients are doing?

  • Clients operate off their config/timeline.json file and this can be updated via Powershell, Ansible, or other means - it's just a file.
  • Clients can also do just-in-time activities via the instance/timeline/in folder. Anything placed here will be picked up, executed, and moved to the corresponding out folder once complete. This does not affect any activity currently controlled with the default timeline file.

Can I reset a client on a box?

  • Yes, launching a new instance of Ghosts kills the previous one and all associated tasks from the timeline (any instances of Word, PowerShell, etc.). Only one instance of Ghosts will be running on a client box at any time. We can also run the .bat script kill-ghosts.bat included in the distribution to clean everything up.

What is the easiest way to determine the running version of the client?

  • run the version flag: ghosts.exe --version
"},{"location":"core/handlers/","title":"Basic Handler Configuration","text":"

The following is the format for a basic timeline handler:

\"TimeLineHandlers\": [\n{\n\"HandlerType\": \"Watcher\",\n\"UtcTimeOn\": \"00:00:00\",\n\"UtcTimeOff\": \"24:00:00\",\n\"Loop\": true,\n\"TimeLineEvents\": [\n{\n\"Command\": \"folder\",\n\"CommandArgs\": [ \"path:%HOMEDRIVE%%HOMEPATH%\\\\Downloads\", \"size:2000\", \"deletionApproach:oldest\" ],\n\"DelayAfter\": 0,\n\"DelayBefore\": 0\n}\n]\n}\n]\n

Some of the key-value pairs are self-explanatory, but let's review a few important ones:

Key Value HandlerType The application or major function we want to control. This could be FireFox, the Cmd terminal, or Word. UtcTimeOn The time the handler will begin to run. To simulate an agent coming into the office at 0900, we set this to your time zone's UTC value. UtcTimeOff The time the handler will stop. To simulate an agent leaving the office at 1700, we set this to your time zone's UTC value. Loop true or false - a handler could be repeated or just run one-time."},{"location":"core/api/timelines/","title":"Managing Timelines","text":"

One of the primary capabilities of the API is to manage multiple client timelines. Timelines are the mechanism for clients to perform actions on behalf of a user. For example, a client might execute a timeline to browse a website, create a document, or other Handler activities.

Clients are configured to check in periodically with the API to report their current state and to check if any updates are available. We can have the API hold an update for the next time a client, group of clients, or all clients check in. That update will then be processed by the client and the client will report back to the API that the update has been processed. This allows the API to manage the state of the client and to ensure that the client is always up to date. So the process is:

  1. We configure an update for a client or group of clients in the API.
  2. Clients check in and are told that an update is available.
  3. The client processes the update and reports back to the API that the update has been processed.
"},{"location":"core/api/timelines/#configuring-a-timeline-for-a-client","title":"Configuring a Timeline for a Client","text":"

Client timelines are updated via POST to /api/timelines in the following format:

{\n\"machineId\": \"3fa85f64-5717-4562-b3fc-2c963f66afaf\",\n\"type\": 0,\n\"activeUtc\": \"2023-03-08T16:38:04.002Z\",\n\"status\": 0,\n\"update\": {\n\"status\": 0,\n\"timeLineHandlers\": [\n{\n\"handlerType\": 0,\n\"initial\": \"string\",\n\"utcTimeOn\": {\n\"ticks\": 0\n},\n\"utcTimeOff\": {\n\"ticks\": 0\n},\n\"handlerArgs\": {\n\"additionalProp1\": \"string\",\n\"additionalProp2\": \"string\",\n\"additionalProp3\": \"string\"\n},\n\"loop\": true,\n\"timeLineEvents\": [\n{\n\"trackableId\": \"string\",\n\"command\": \"string\",\n\"commandArgs\": [\n\"string\"\n],\n\"delayAfter\": 0,\n\"delayBefore\": 0\n}\n]\n}\n]\n}\n}\n

The key values to consider here are: The machine ID that you want to update, the other key value is the type of timeline. The type is an integer value that represents the type of update. The following are the types of updates that are currently supported:

  • Timeline = 0 // this
  • Health = 1
  • TimelinePartial = 10 // this the agent is currently doing off its default timeline
  • RequestForTimeline = 20
ID Type Description 0 Timeline Replaces the client's default timeline stored within ./config/timeline.json 1 Health This updates a client's health instructions 10 TimelinePartial Does not replace the default timeline, rather this timeline is executed immediately on separate threads from whatever 20 RequestForTimeline Use this to instruct the client to send its current default timeline up to the API

The remainder of the settings are for the timeline - basically what we are doing here is sending a client a new timeline, with the above values to indicate, which machine and what to change in the update node.

"},{"location":"core/handlers/browser/","title":"Web Browser (Firefox|Chrome) Configuration","text":"

A sample timeline for each browser is available in a code repository directory of the same name.

"},{"location":"core/handlers/browser/#timeline-url-variables","title":"Timeline URL Variables","text":"

An example of a URL using variables is:

http://craigslist.org/{org}/{group}/{uuid}/{verb}/{type}/{n}?{c}={now}\n

All variables are in the format {variable}. There are several standard variables:

  • {now} = short datetime (mm/dd/yyyy format)
  • {uuid} = uuid
  • {c} = a single character from a-z and A-Z
  • {n} = number between 1 and 1000

We can also configure additional variables by adding the following to a browser handler in a timeline:

\"url-replace\": [\n{\"verb\": [\"order\", \"enable\", \"engage\"]},\n{\"group\": [\"operations\", \"logistics\", \"medical\"]},\n{\"org\": [\"army\", \"command\", \"brigade\", \"battalion\"]},\n{\"type\": [\"document\", \"doc\", \"files\", \"vault\", \"filevault\"]}\n]\n

Therefore:

https://www.cmu.edu/{org}/{group}/{verb}/{type}/{uuid}/version_{n}?{c}={now}\n

might be rendered as:

https://www.cmu.edu/command/operations/order/doc/bcc396b5-47d0-4665-93c8-0a314cec13e1/version_55?d=6/21/2022\n
"},{"location":"core/handlers/excel/","title":"Excel Configuration","text":""},{"location":"core/handlers/powerpoint/","title":"PowerPoint Configuration","text":""},{"location":"core/handlers/word/","title":"Word Configuration","text":""},{"location":"spectre/","title":"GHOSTS SPECTRE Overview","text":"GHOSTS SPECTRE Source Code

The GHOSTS SPECTRE Source Code Repository is hosted on GitHub

SPECTRE is our attempt to reduce that agent browsing patterns appear as \"computer random\".1 This module modifies user web browser timelines so that they more closely match that agent's preferences over time. We expect this simple model of ML to be used for other types of agent activity in the future.

Agent browsing patterns are no longer random and match different types of users on a network. These patterns improve over time.

Also, this simple model of ML can now be used for other types of agent activity. This makes for an exciting future on the GHOSTS platform.

Using Machine Learning to Increase NPC Fidelity with Dynamic Preferences Used in Forward-Looking Decisions

As GHOSTS agents make more informed, and hopefully, more complex decisions, there is a need for each agent to have a system of preferences existing at the time the agent is created, and for an ability to update those preferences over time as the agent continues to make decisions and measure the outcome of those decisions afterwards.

SPECTRE provides GHOSTS enables agents to make preferenced decisions and to use the outcome of those decisions to learn and evaluate future choices more intelligently.

"},{"location":"spectre/#how-it-works","title":"How it works","text":"

SPECTRE currently has two components:

"},{"location":"spectre/#preference-engine","title":"Preference Engine","text":"
  1. An administrator creates the types of personas they wish to have GHOSTS agents represent
  2. GHOSTS agents report in their browser history to the GHOSTS C2 API
  3. If the agent has no persona, SPECTRE assigns one at random
  4. The persona assignment randomly creates different preferences for the agent based on persona settings (not unlike character creation in D&D)
  5. Preferences are a preference and its numeric value (-100 to 100) which roughly represents how much an agent likes or dislikes something
  6. Preferences can be any key:value pair, such as: \"sports\":50 \"kali\":35 \"127.0.0.1\":77
  7. Preferences of 0 mean that the agent is indifferent (or has no preference)
  8. All preference history is stored so that in the (near) future we can track an agent's preferences over time
  9. It is assumed that high negative preferences would have agents avoiding those values (e.g. for \"onions\":-100 one would assume an agent is avoiding eating onions at all costs.)
"},{"location":"spectre/#machine-learning","title":"Machine Learning","text":"

The incoming GHOSTS agent browsing activity can be attenuated to individual agent preferences after they are assigned some number of preferences based on default persona profiles. SPECTRE will aggregate this information periodically and perform model training and testing against that browsing activity, and recommend new browsing patterns for that agent to execute. This creates a new activity timeline for the agent. This cycle is referred to as a \"Test\". After any given test, that information would be used to inform the next round of ML testing to be done.

"},{"location":"spectre/#installation","title":"Installation","text":"

SPECTRE installs alongside an existing GHOSTS installation as a separate docker container. With a few configuration changes, you should be up and running in minimal time.

There are only two configuration settings, both contained within appsettings.json:

\"DefaultConnection\": \"Host=localhost;Port=5432;Database=preferences;User Id=ghosts;Password=scotty@1;Pooling=true;Command Timeout=9900\",\n\"GhostsApiUrl\": \"http://localhost:5000\"\n

The first setting is for your connection to a necessary Postgres database, which SPECTRE will use for its operations. It is fine to host this on the same machine or container that you might be using for GHOSTS itself. In this case, either use the same user as GHOSTS or create a new user for SPECTRE.

The second setting is for SPECTRE to access the GHOSTS API endpoints. This is used to get information about machines and to update their timelines, based on SPECTRE findings and executions.

"},{"location":"spectre/#quick-start","title":"Quick Start","text":"

Spectre is rather like an add-on -- it sits alongside the core API and uses that system to get its initial agent information, process their timelines, and then post updated timelines back to the API for dissemination to the clients.

  • There is one setting in the spectre appsettings.json file that may need updating based on the install - it is how Spectre will connect to the GHOSTS Core API: \"GhostsApiUrl\": \"http://host.docker.internal:52388\" \u2014\u00a0update this to your core API host and port.
  • Now go to Spectre's host:port/swagger to bring up the API.
  • GET /Agents will show you what you have under SPECTRE control - at the start, it is likely no agents. We need to sync with core GHOSTS Core API to get its agents into SPECTRE.
  • So, we need to run POST /Agents/sync once to pull the agents in the core API over to SPECTRE.
  • Now Spectre's GET /Agents will show you the same agents from ghosts Core API.
  • You can now run a browse recommendations job.
  1. This work is detailed in the technical report Using Machine Learning to Increase NPC Fidelity. Some of the team also discussed this project in an SEI podcast episode, entitled ML-Driven Decision-Making in Realistic Cyber Exercises.\u00a0\u21a9

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 00000000..0f8724ef --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..0313cdfd58bd7cf3df05b49c040e46ae920b448a GIT binary patch literal 127 zcmV-_0D%7=iwFpV2*G3m|8r?{Wo=<_E_iKh04<9_3V)_WXo8&M?ytk3HC}0~zlG)Vu + + + + + + + + + + + + + + + + + + + + Spectre - GHOSTS Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + +
+ +
+ + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + +

GHOSTS SPECTRE Overview

+
+GHOSTS SPECTRE Source Code +

The GHOSTS SPECTRE Source Code Repository is hosted on GitHub

+
+

SPECTRE is our attempt to reduce that agent browsing patterns appear as "computer random".1 This module modifies user web browser timelines so that they more closely match that agent's preferences over time. We expect this simple model of ML to be used for other types of agent activity in the future.

+

Agent browsing patterns are no longer random and match different types of users on a network. These patterns improve over time.

+

Also, this simple model of ML can now be used for other types of agent activity. This makes for an exciting future on the GHOSTS platform.

+

Using Machine Learning to Increase NPC Fidelity with Dynamic Preferences Used in Forward-Looking Decisions

+

As GHOSTS agents make more informed, and hopefully, more complex decisions, there is a need for each agent to have a system of preferences existing at the time the agent is created, and for an ability to update those preferences over time as the agent continues to make decisions and measure the outcome of those decisions afterwards.

+

SPECTRE provides GHOSTS enables agents to make preferenced decisions and to use the outcome of those decisions to learn and evaluate future choices more intelligently.

+

How it works

+

SPECTRE currently has two components:

+

Preference Engine

+
    +
  1. An administrator creates the types of personas they wish to have GHOSTS agents represent
  2. +
  3. GHOSTS agents report in their browser history to the GHOSTS C2 API
  4. +
  5. If the agent has no persona, SPECTRE assigns one at random
  6. +
  7. The persona assignment randomly creates different preferences for the agent based on persona settings (not unlike character creation in D&D)
  8. +
  9. Preferences are a preference and its numeric value (-100 to 100) which roughly represents how much an agent likes or dislikes something
  10. +
  11. Preferences can be any key:value pair, such as: + "sports":50 + "kali":35 + "127.0.0.1":77
  12. +
  13. Preferences of 0 mean that the agent is indifferent (or has no preference)
  14. +
  15. All preference history is stored so that in the (near) future we can track an agent's preferences over time
  16. +
  17. It is assumed that high negative preferences would have agents avoiding those values (e.g. for "onions":-100 one would assume an agent is avoiding eating onions at all costs.)
  18. +
+

Machine Learning

+

The incoming GHOSTS agent browsing activity can be attenuated to individual agent preferences after they are assigned some number of preferences based on default persona profiles. SPECTRE will aggregate this information periodically and perform model training and testing against that browsing activity, and recommend new browsing patterns for that agent to execute. This creates a new activity timeline for the agent. This cycle is referred to as a "Test". After any given test, that information would be used to inform the next round of ML testing to be done.

+

Installation

+

SPECTRE installs alongside an existing GHOSTS installation as a separate docker container. With a few configuration changes, you should be up and running in minimal time.

+

There are only two configuration settings, both contained within appsettings.json:

+
"DefaultConnection": "Host=localhost;Port=5432;Database=preferences;User Id=ghosts;Password=scotty@1;Pooling=true;Command Timeout=9900",
+"GhostsApiUrl": "http://localhost:5000"
+
+

The first setting is for your connection to a necessary Postgres database, which SPECTRE will use for its operations. It is fine to host this on the same machine or container that you might be using for GHOSTS itself. In this case, either use the same user as GHOSTS or create a new user for SPECTRE.

+

The second setting is for SPECTRE to access the GHOSTS API endpoints. This is used to get information about machines and to update their timelines, based on SPECTRE findings and executions.

+

Quick Start

+

Spectre is rather like an add-on -- it sits alongside the core API and uses that system to get its initial agent information, process their timelines, and then post updated timelines back to the API for dissemination to the clients.

+
    +
  • There is one setting in the spectre appsettings.json file that may need updating based on the install - it is how Spectre will connect to the GHOSTS Core API: "GhostsApiUrl": "http://host.docker.internal:52388" — update this to your core API host and port.
  • +
  • Now go to Spectre's host:port/swagger to bring up the API.
  • +
  • GET /Agents will show you what you have under SPECTRE control - at the start, it is likely no agents. We need to sync with core GHOSTS Core API to get its agents into SPECTRE.
  • +
  • So, we need to run POST /Agents/sync once to pull the agents in the core API over to SPECTRE.
  • +
  • Now Spectre's GET /Agents will show you the same agents from ghosts Core API.
  • +
  • You can now run a browse recommendations job.
  • +
+
+
+
    +
  1. +

    This work is detailed in the technical report Using Machine Learning to Increase NPC Fidelity. Some of the team also discussed this project in an SEI podcast episode, entitled ML-Driven Decision-Making in Realistic Cyber Exercises

    +
  2. +
+
+ + + + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/stylesheets/extra.css b/stylesheets/extra.css new file mode 100644 index 00000000..34d19a1f --- /dev/null +++ b/stylesheets/extra.css @@ -0,0 +1,3 @@ +:root > * { --md-primary-fg-color: green; } +img[alt="Crucible Logo"] {width:4.5%; float:left; margin-right:7px; } +img[alt="Animator Logo"] {width: 4.5%; } \ No newline at end of file