Skip to content

Commit

Permalink
Public release
Browse files Browse the repository at this point in the history
  • Loading branch information
nbareil committed Jun 26, 2024
0 parents commit 7cb5a7d
Show file tree
Hide file tree
Showing 81 changed files with 3,255 additions and 0 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use nix
78 changes: 78 additions & 0 deletions .github/workflows/nix_shell_bundle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: "nix-shell.tar.gz"
on:
workflow_dispatch:

env:
NIXPKGS_ALLOW_INSECURE: "1"
NIXPKGS_ALLOW_UNFREE: "1"

jobs:
build:
runs-on: [ Linux, self-hosted ]
steps:
- uses: actions/checkout@v3

- name: "Add Nix to path if already installed"
run: |
if [ -d "/nix/var/nix/profiles/default/bin" ]; then
echo "/nix/var/nix/profiles/default/bin" > "$GITHUB_PATH"
fi
- uses: CERT/install-nix-action@v25

- name: "Install the deploy key"
env:
DEPLOY_KEY: "${{ secrets.DEPLOY_KEY }}"
run: |
mkdir -p ~/.ssh
ssh_agent_vars=$(ssh-agent -s)
eval "$ssh_agent_vars"
echo "$ssh_agent_vars" | fgrep '=' | cut -d';' -f1 >> "$GITHUB_ENV"
echo "$DEPLOY_KEY" | ssh-add -
ssh-keyscan github.cert.corp >> ~/.ssh/known_hosts
cat ~/.ssh/known_hosts | sort -u > ~/.ssh/known_hosts.new
mv ~/.ssh/known_hosts.new ~/.ssh/known_hosts
- name: "Build nix-shell derivation"
run: nix-build shell.nix
- name: "Export closure"
run: |
mkdir tmp
cd tmp
nix-store --export $(nix-store --query --requisites ../result) | bzip2 > nix-shell.nar.bz2
- name: "Write 'nix-shell.sh'"
run: |
cd tmp
cat <<'EOF' > nix-shell.sh
#!/usr/bin/env bash
set -o pipefail
if [ -f "nix-shell.nar.bz2" ]; then
echo "[+] Detected 'nix-shell.nar.bz2, importing..."
cat nix-shell.nar.bz2 | bunzip2 | nix-store --import
if [ $? -ne 0 ]; then
echo "An error happened while importing the NAR file, exiting..."
exit 1
fi
rm nix-shell.nar.bz2
fi
p="$PATH"
EOF
nix-shell --pure ../shell.nix --run 'export' | grep -F -e 'declare -x PATH=' -e 'declare -x PYTHONPATH=' -e 'declare -x PERL5LIB=' -e 'declare -x shellHook=' >> nix-shell.sh
cat <<'EOF' >> nix-shell.sh
export PATH="$p:$PATH"
export PS1="\[\033[00;32m\][\u@nix-shell:\w]\$ \[\033[00m\]"
bash --noprofile -i --rcfile <(echo "\$shellHook")
EOF
- uses: actions/upload-artifact@v3
with:
name: nix-shell
path: tmp/*
71 changes: 71 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: "Testing"
on:
pull_request:
push:
branches: [ "main" ]

env:
NIXPKGS_ALLOW_INSECURE: "1"
NIXPKGS_ALLOW_UNFREE: "1"

jobs:
build:
runs-on: [ Linux, self-hosted ]
steps:
- uses: actions/checkout@v3

- name: "Add Nix to path if already installed"
run: |
if [ -d "/nix/var/nix/profiles/default/bin" ]; then
echo "/nix/var/nix/profiles/default/bin" > "$GITHUB_PATH"
fi
- uses: CERT/install-nix-action@v25

- name: "Install the deploy key"
env:
DEPLOY_KEY: "${{ secrets.DEPLOY_KEY }}"
run: |
mkdir -p ~/.ssh
ssh_agent_vars=$(ssh-agent -s)
eval "$ssh_agent_vars"
echo "$ssh_agent_vars" | fgrep '=' | cut -d';' -f1 >> "$GITHUB_ENV"
echo "$DEPLOY_KEY" | ssh-add -
ssh-keyscan github.cert.corp >> ~/.ssh/known_hosts
cat ~/.ssh/known_hosts | sort -u > ~/.ssh/known_hosts.new
mv ~/.ssh/known_hosts.new ~/.ssh/known_hosts
- name: "Build nix-shell derivation"
run: nix-build shell.nix

tests:
runs-on: [ Linux, self-hosted ]
needs: build
steps:
- uses: actions/checkout@v3

- name: "Add Nix to path if already installed"
run: |
if [ -d "/nix/var/nix/profiles/default/bin" ]; then
echo "/nix/var/nix/profiles/default/bin" > "$GITHUB_PATH"
fi
- uses: CERT/install-nix-action@v25

- name: "Install the deploy key"
env:
DEPLOY_KEY: "${{ secrets.DEPLOY_KEY }}"
run: |
mkdir -p ~/.ssh
ssh_agent_vars=$(ssh-agent -s)
eval "$ssh_agent_vars"
echo "$ssh_agent_vars" | fgrep '=' | cut -d';' -f1 >> "$GITHUB_ENV"
echo "$DEPLOY_KEY" | ssh-add -
ssh-keyscan github.cert.corp >> ~/.ssh/known_hosts
cat ~/.ssh/known_hosts | sort -u > ~/.ssh/known_hosts.new
mv ~/.ssh/known_hosts.new ~/.ssh/known_hosts
- name: "Run test suite"
run: |
cd tests
bash run_tests.sh
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/result
78 changes: 78 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# nix-forensics

Spawn a complete forensics environment in a reproducible way.

## Usage

### In a nix-enabled, CERT-connected environment

```
$ nix-shell
```

This will build all required tools, both public and private ones, and put you in a shell where they're all ready to use.

```
$ bash export-shell.sh user@remote-server
```

This will copy all derivations required to run the environment to the remote server. Only missing derivations will be copied: this is potentially very fast. **Nix must be installed** on the remote server!

A script to enter the environment will be written at `~/nix-shell.sh` on the remote host.

### Building a Docker image containing all tools

```
$ nix-build . -A docker
```

Will generate a Docker image which, when instanciated, drops you in a shell similar to what you would get with the first option.

Import the Docker image like so:

```
$ docker load <result
```

### Using a ready-made bundle on a remote server

In the [Actions](actions/workflows/nix_shell_bundle.yml) tab, go to the latest action summary, and download the `nix-shell` artefact. Run the action manually if needed, in order to build the bundle for the latest commit. These bundles are not built for every single commit due to size constraints (each bundle is around 500MB).

Unzip the resulting file on the remote server, and run `nix-shell.sh`. This will automatically import the required derivations and drop you in a shell.

This still requires Nix to be installed on the server!


## Troubleshooting

### error: cannot add path XXX because it lacks a valid signature

This error happens because the remote user you are using is not part of Nix's "trusted group". Importing closures can be a potential security risk, so you need to manually allow your user to do it.

Edit `/etc/nix/nix.conf` on the remote machine and add the following line:

```
trusted-users = YOUR_USERNAME
```

Then, restart the Nix daemon:

```
$ sudo systemctl restart nix-daemon
```

### error: package is marked as insecure, refusing to evaluate

This shell uses Python 2.7, which is (rightly) marked as insecure. You can tell Nix "I understand the risks" by setting the following environment variables:

```
export NIXPKGS_ALLOW_INSECURE=1
```

### error: package is marked as unfree, refusing to evaluate

This shell uses Volatility 3, which uses a custom software licence, and as such is not free software. If you accept to taint your computer with proprietary software, set the following environment variable:

```
export NIXPKGS_ALLOW_UNFREE=1
```
112 changes: 112 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# nixos-23.11 - 2023-12-19
{ pkgs ? (import (fetchTarball "https://github.com/nixos/nixpkgs/archive/1e2e384c5b7c50dbf8e9c441a9e58d85f408b01f.tar.gz") {})}:
with pkgs;
rec {
my-python-registry = python3Packages.python-registry.overridePythonAttrs {
src = fetchFromGitHub {
owner = "nbareil";
repo = "python-registry";
rev = "f4cddbc4ce77b0ca3682474e10d130c624a96349";
hash = "sha256-CUOC3UxgD7zUf0OmOh4fpa/oqKsT3hkr4ZGHHKCA/nQ=";
};
};


libcerror = callPackage ./pkgs/libcerror.nix {};
libcthreads = callPackage ./pkgs/libcthreads.nix { inherit libcerror; };
libcnotify = callPackage ./pkgs/libcnotify.nix { inherit libcerror; };
libcdatetime = callPackage ./pkgs/libcdatetime.nix { inherit libcerror; };
libcsplit = callPackage ./pkgs/libcsplit.nix { inherit libcerror; };
libclocale = callPackage ./pkgs/libclocale.nix { inherit libcerror; };
libcdata = callPackage ./pkgs/libcdata.nix { inherit libcerror libcthreads; };
libuna = callPackage ./pkgs/libuna.nix { inherit libcerror libcthreads libcnotify libcdatetime libclocale; };
libcfile = callPackage ./pkgs/libcfile.nix { inherit libcerror libcthreads libuna libclocale libcnotify; };
libcpath = callPackage ./pkgs/libcpath.nix { inherit libcerror libcthreads libuna libclocale libcsplit; };
libbfio = callPackage ./pkgs/libbfio.nix { inherit libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libuna; };
libfcache = callPackage ./pkgs/libfcache.nix { inherit libcdata libcerror libcthreads; };
libfdata = callPackage ./pkgs/libfdata.nix { inherit libcdata libcerror libcnotify libcthreads libfcache; };
libfdatetime = callPackage ./pkgs/libfdatetime.nix { inherit libcerror; };
libfguid = callPackage ./pkgs/libfguid.nix { inherit libcerror; };
libfusn = callPackage ./pkgs/libfusn.nix { inherit libcerror libcnotify libfdatetime libuna; };
libfwnt = callPackage ./pkgs/libfwnt.nix { inherit libcdata libcerror libcnotify libcthreads; };
libhmac = callPackage ./pkgs/libhmac.nix { inherit libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libuna; };
libfsntfs = callPackage ./pkgs/libfsntfs.nix { inherit fuse python3 libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfdatetime libfguid libfusn libfwnt libhmac libuna; };
libfmapi = callPackage ./pkgs/libfmapi.nix { inherit libcdata libcerror libcnotify libcthreads libfdatetime libfguid libfwnt libuna; };
libfvalue = callPackage ./pkgs/libfvalue.nix { inherit libcdata libcerror libcnotify libcthreads libfdatetime libfguid libfwnt libuna ; };
libmapidb = callPackage ./pkgs/libmapidb.nix { inherit libcerror libcnotify; };
libesedb = callPackage ./pkgs/libesedb.nix { inherit fuse python3 libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfdatetime libfguid libfmapi libfvalue libfwnt libmapidb libuna; };
libvshadow = callPackage ./pkgs/libvshadow.nix { inherit fuse python3 libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfdatetime libfguid libuna;};
libcdirectory = callPackage ./pkgs/libcdirectory.nix { inherit libcerror libclocale libuna; };
libexe = callPackage ./pkgs/libexe.nix { inherit libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfdatetime libuna; };
libfwevt = callPackage ./pkgs/libfwevt.nix { inherit libcdata libcerror libcnotify libcthreads libfdatetime libfguid libfwnt libuna; };
libregf = callPackage ./pkgs/libregf.nix { inherit libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfdatetime libfwnt libuna; };
libwrc = callPackage ./pkgs/libwrc.nix { inherit libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libexe libfcache libfdata libfdatetime libfguid libfvalue libfwnt libuna; };
libevtx = callPackage ./pkgs/libevtx.nix { inherit fuse python3 libbfio libcdata libcdirectory libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libexe libfcache libfdata libfdatetime libfguid libfvalue libfwevt libfwnt libregf libuna libwrc;};
libvmdk = callPackage ./pkgs/libvmdk.nix { inherit fuse python3 libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfvalue libuna;};
libvhdi = callPackage ./pkgs/libvhdi.nix { inherit fuse python3 libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfcache libfdata libfguid libuna;};
libfole = callPackage ./pkgs/libfole.nix { inherit libcerror; };
libmsiecf = callPackage ./pkgs/libmsiecf.nix { inherit fuse python3 libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfdatetime libfguid libfole libfvalue libuna;};
libfwps = callPackage ./pkgs/libfwps.nix { inherit libcdata libcerror libclocale libcnotify libcthreads libfdatetime libfguid libuna; };
libfwsi = callPackage ./pkgs/libfwsi.nix { inherit libcdata libcerror libclocale libcnotify libcthreads libfdatetime libfguid libfole libfwps libuna; };
liblnk = callPackage ./pkgs/liblnk.nix { inherit fuse python3 libbfio libcdata libcerror libcfile libclocale libcnotify libcpath libcsplit libcthreads libfdatetime libfguid libfole libfwps libfwsi libuna;};

shellbags = ps: callPackage ./pkgs/shellbags.nix { python2Packages = ps; };
INDXParse = callPackage ./pkgs/INDXParse.nix {};
INDXRipper = callPackage ./pkgs/INDXRipper.nix {};
dfir_ntfs = callPackage ./pkgs/dfir_ntfs.nix {};
yarp = callPackage ./pkgs/yarp.nix {};
cimlib = callPackage ./pkgs/cimlib.nix {};
shimCacheParser = callPackage ./pkgs/shimCacheParser.nix {};
#mftspy = callPackage ./pkgs/mftspy.nix { inherit libfsntfs; };
regrippy = callPackage ./pkgs/regrippy.nix {};
regipy = callPackage ./pkgs/regipy.nix { inherit libfwsi; };
netstructlib = callPackage ./pkgs/netstructlib.nix {};
CobaltStrikeParser = callPackage ./pkgs/CobaltStrikeParser.nix { inherit netstructlib; };
domaintoolslib = callPackage ./pkgs/domaintoolslib.nix {};
pymisplib = callPackage ./pkgs/pymisplib.nix {};
splunklib = callPackage ./pkgs/splunklib.nix {};
pdoclib = callPackage ./pkgs/pdoclib.nix {};
huntlib = callPackage ./pkgs/huntlib.nix { inherit splunklib domaintoolslib pymisplib; };
evtxTools = callPackage ./pkgs/evtxTools.nix {};
usnrs = callPackage ./pkgs/usnrs.nix {};
liblnk-python = python3Packages.toPythonModule liblnk;
timeliner = callPackage ./pkgs/timeliner.nix {};
libevtx-python = python3Packages.toPythonModule libevtx;
#srum-dump = callPackage ./pkgs/srum-dump.nix { inherit libesedb; };
amcacheparser = callPackage ./pkgs/amcacheparser.nix {};
bits_parser = callPackage ./pkgs/bits_parser.nix {};
at_jobs_carver = callPackage ./pkgs/at_jobs_carver.nix {};
ccm_rua_finder = callPackage ./pkgs/ccm_rua_finder.nix {};
registryFlush = python3Packages.callPackage ./pkgs/registryFlush.nix { inherit yarp; };
forensicslab = callPackage ./pkgs/forensicslab.nix {};

customPython = pkgs.python3.withPackages (ps: with ps; [
requests
python_magic
grpcio
dateutil
pandas
requests_ntlm
google-api-python-client
pandas
pytest-vcr

jinja2
lxml
yara-python
fuse
evtx
progressbar
]
++ [
pdoclib
huntlib
splunklib
pytest
libevtx-python
liblnk-python
]);


docker = callPackage ./docker.nix { nixForensicsShell = import ./shell.nix; };
}
6 changes: 6 additions & 0 deletions docker.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{ dockerTools
, nixForensicsShell
}:
dockerTools.buildNixShellImage {
drv = nixForensicsShell;
}
Loading

0 comments on commit 7cb5a7d

Please sign in to comment.