5 minute read

What is Nemesis?

Nemesis is an offensive data enrichment pipeline that is designed to help operators with common tasks on engagements. It can ingest structured data produced during offensive security engagements, process it, and give insights about the data including identifying vulnerabilities, credentials, and metadata about the output.

According to the README it’s aim is to automate a number of repetitive tasks operators encounter on engagements, empower operators analytic capabilities, and collective knowledge, and create structured and unstructed data stores of as much operational data as possible to help guide future research and facilitate offensive data analysis.

Why are you writing this?

If you take a look at the setup instructions it can look a bit intimidating. So I wanted to write a no-frills guide that outlines exactly what commands to run in order to get a basic Nemesis setup running. Just run the commands exactly as I outlined, and you’ll have a Nemesis server you can connect to your favorite C2 platform.



sudo apt update && sudo apt install git curl -y

sudo mkdir /etc/apt/keyrings/ 2>/dev/null

curl -fsSL https://get.docker.com -o get-docker.sh

sudo sh get-docker.sh

sudo apt-get install -y docker-compose

# Allow your user to run docker w/o being root
sudo usermod -aG docker <user>

Next logout of your shell and log back in, we’ll go ahead and confirm docker can be run as a non-root user

docker ps



curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

kubectl version --client



Next we need to install Kubernetes

curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

sudo install minikube-linux-amd64 /usr/local/bin/minikube

minikube config set memory 12288

minikube config set cpus 3

minikube start


Now let’s make sure it’s working as expected, you can probably skip these steps but it never hurts to make sure.

First we check the status to make sure it’s up:

minikube status


Next we can go ahead confirm we’re running the right version, it should be greater than 1.26

minikube version


Now let’s run a few commands on the host to make sure it has internet access:

# First log into minikube 
minikube ssh

# Next let's ping an IP we know should be live
ping -c 4

# finally let's just confirm DNS resolution
nslookup google.com


If all these work, we can move onto the next step!


curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list

sudo apt-get update

sudo apt-get install -y helm

You can confirm it’s working by running the command:

helm list



skaffold config set --global collect-metrics false

Next we’ll need to update your ~\.bashrc file, we’ll just add all the lines we’re going to add now don’t worry about errors for now. Just add the following lines to the bottom of your ~\.bashrc file


export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

export PATH="$HOME/.local/bin:$PATH"

Next we’ll just reload it you can do this by either logging out and logging back in or running this command:

source ~\.bashrc

You’ll see an error about pyenv not being installed, don’t worrry, we’ll resolve that in a minute.


Python, PyEnv, and Poetry

Nemesis was coded specifically with Python 3.11 in mind, so we’re going to go ahead and make sure we’re using the right version. In addition, it uses PyEnv and Poetry for it’s package management so we need to install those also.

# Install prerquisites for pyenv
sudo apt update; sudo apt install build-essential libssl-dev zlib1g-dev \
		libbz2-dev libreadline-dev libsqlite3-dev curl \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

# Install pyenv
curl https://pyenv.run | bash

We’ll want to re-load our bash profile again, this time those errors should be resolved

source ~.\bashrc


Next we’ll setup our python environment

# Install Python 3.11
pyenv install 3.11.2

# Set our active Python version to 3.11
pyenv global 3.11.2

Next confirm that worked by running the following:

python --version


Now that Python is ready to go, let’s set up Poetry

python3 -c 'from urllib.request import urlopen; print(urlopen("https://install.python-poetry.org").read().decode())' | python3 -



Finally, we’re done with the pre-requisites, and we can get to the actual Nemesis setup.

First grab the Nemesis repo:

git clone https://github.com/SpecterOps/Nemesis

We’ll need to install one of the enrichment commands first, since Nemesis relies on it:

cd Nemesis/

poetry -C ./cmd/enrichment/ install


Next install some pre-requisites that the nemesis-cli.py script requires:

pip3 install boto3 vyper-config passlib

Next let’s configure Nemesis, luckily for us it comes with an example config file we can start from

cp nemesis.config.example nemesis.config

Edit the nemesis config, for a basic setup, you’ll only need to change the nemesis_http_server which you’ll set to use the IP of the machine you’re running this on. Everything else you can keep as default if you want, or edit it to your specifications. We’re going to keep it mostly default for now.

When you’re finished run the following command:

python nemesis-cli.py --config nemesis.config

Press enter and accept the default values for now, unless you want to specify the credentials yourself. If not, nemesis will autogenerate random credentials.

Take note of these, and store them somewhere safe.

The nemesis documentation recommends running

skaffold run -m nemesis --port-forward=user

However, they also note that you may encounter some timeout issues when running this command on slower internet speeds. So to skip the middle man, go ahead and run these commands instead:


skaffold build

Get comfortable, this should take a minute. If the skaffold build command fails for some reason, just re-run it, it should succeed the second time.

This performs the 2 steps the previous command ran manually, while eliminating the risk of it timing out.

Finally, we should be able to run

skaffold run -m nemesis --port-forward=user

Like the documentation says, and get a fully stood up nemesis. You should see the following on your screen assuming everything set up properly.


You should now be able to log into the Nemesis interface at http://your.ip.add.ress:8080


Enter the Nemesis basic auth credentials that were spit out when you ran the nemesis-cli.py script and you should see a pretty minimal UI.


Click Dashboard and you’ll be brought to the main Nemesis Dashboard, which you can authenticate using the dashboard_user and dashboard_password from before.


Congratulations, you now have a basic Nemesis set up that you can begin testing against!

Future posts about this I’ll likely talk about using it operationally with my favorite red team tools.