Introduction

IR-Toolkit is a portable framework to automate your scripts and tools using workflows. It is designed to assist incident responders and digital forensic analysts in data aquisition.

banner

Installation

Download the latest release

Download the latest release from the releases page and extract the contents.

You can store the toolkit on a USB drive or network share. The directory structure has to be preserved!

Configuration

1. Define your workflows

Workflows are defined in the /workflows directory. You can use the provided examples as a starting point.

ir-toolkit/
└── workflows/
    ├── workflow1.yaml
    └── workflow2.yaml

You can also structure your workflows in subdirectories. The toolkit will recursively search for workflows in the /workflows directory.

See the workflow chapter for more information on how to define workflows.

2. Use custom tools

Tools like Autoruns or FTK Imager can be placed in the custom_files directory. Within the workflow, you can run these tools by specifying the relative path to the executable.

For example, if you have custom_files/windows_tools/autorunsc.exe, you can use the following action in your workflow:

- name: autorunsc
  type: binary
  attributes:
    path: "windows_tools/autorunsc.exe"

Note: You can use both \\ and / as path separators.

3. Configure the toolkit

The configuration file config.yaml is located in the root directory of the toolkit. The settings apply to all workflows. You can adjust the following settings:

time:
  ## The time zone to use for the timestamps in the report.
  ## e.g. "UTC", "Europe/Berlin", "Etc/GMT+2" or "UTC"
  ## For a list of time zones see: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
  time_zone: "UTC"

  ## Enable NTP time to ensure that the system time is correct.
  ## WARNING: Enabling NTP time will delay the start of the workflow
  ##
  ## According to Federal Office for Information Security (BSI) in Germany,
  ##   changing the system time itself, e.g. to cover tracks, can be an incident
  ##   to be verified, both the hardware-based time from the RTC and the system
  ##   time must be recorded and compared with one from an independent time source.
  ## See: https://www.bsi.bund.de/EN/Themen/Oeffentliche-Verwaltung/Sicherheitspruefungen/IT-Forensik/forensik_node.html
  ntp_enabled: false
  ## Time in seconds to wait for an NTP server to respond.
  ## If the NTP server does not respond within this time,
  ##   the next server in ntp_servers will be tried.
  ## If set to 0, no timeout is used.
  ntp_timeout: 2
  ntp_servers: ["0.pool.ntp.org:123", "1.pool.ntp.org:123"]

## If set to true, the collector will attempt to elevate its privileges
## If set to false, the collector will run with the privileges of the user executing it
elevate: false

4. (Optional) Generate a new public/private key pair

If you want authenticated encryption for the report, you can generate a new public/private key pair using the keygen tool, which is located in the bin directory.

[keygen-binary].exe --private private_key.pem --public public_key.pem --size 2048

Move the public key to the /keys directory and reference it in the workflow.

reporting:
  zip_archive:
    enabled: true
    encryption:
      enabled: true
      public_key: "example_public.pem"
      algorithm: CHACHA20-POLY1305

Warning: Do not put the private key in the toolkit directory. Keep it in a secure location.

The encrypted report can be decrypted using the unpacker tool, which is also located in the bin directory.

See the report chapter for more information on how to generate and locate the report.

Acquisition

Execute the collector

The collector is compiled for different operating systems and architectures. Each version is located in the bin directory. To make the execution easier, you can use the run.ps1 script on Windows or the run.sh script on Linux/macOS. The scripts will automatically execute the collector for the current operating system.

ir-toolkit/
├── run.ps1
├── run.sh
└── bin/
    ├── windows/
    │   ├── keygen-x86_64-pc-windows-msvc.exe
    │   ├── unpacker-x86_64-pc-windows-msvc.exe
    │   └── collector-x86_64-pc-windows-msvc.exe
    ├── linux/...
    └── macos/...

The collector will then search for all definied workflow files. Each workflow that meets the launch condition for the current system will be executed.

how_it_works

Report

Each workflow creates one report. You can specify the report format in the workflow configuration. This includes:

  • Enabling or disabling the ZIP compression
  • Enabling or disabling the encryption
  • Specifying the encryption algorithm
  • Metadata to collect (MAC times, checksums)

The console output of the collector is seperate from the reports and is stored in the /reports directory as a .log file.

Report structure

The report is structured as follows:

reports/
└── MYPC_Windows_Example_2024-08-12_13-45-20/
    ├── action_output/...
    ├── loot_files/...
    ├── store_files/...
    └── metadata.csv
  • action_output/: Contains the output of each action in the workflow (for example stdout and stderr).
  • loot_files/: Contains all files you placed there manually during the workflow. This should be the output directory for your disk images or memory dumps.
  • store_files/: Contains all files that were stored using the store or yara action. Filenames are replaced with their SHA256 hash.
  • metadata.csv: Contains the metadata of all files in the store_files directory. The metadata includes the SHA256 hash, the file path, the file size, and the MAC times (modified, accessed, created), etc.

If the report is encrypted, everything inside the report directory is archived in a report.zip file. The encryption.json file contains the encryption algorithm and the (encrypted) symmetric key:

reports/
└── MYPC_Windows_Example_2024-08-12_13-45-20/
    ├── report.zip
    └── encryption.json

1. Locate the generated report

The generated report is located in the /reports directory.

2. Unpacking/Decrypion

The unpacker tool, which is located in the bin directory, automatically detects if the report was encrypted or archived.

Run the unpacker tool with the --help flag to see the available options.

2.1. Unpacking a report without encryption or compression

[unpacker-binary].exe -i reports/MYPC_Example_2024-08-12_13-45-20 --restore --verify

This will do the following:

  1. All stored files (using the store or yara action) will be restored by recreating the original file structure in the report directory. This does not apply to files that w
  2. The integrity of all files in the store_files directory will be verified using the metadata in the metadata.csv file.

2.2. Unpacking a report with compression and encryption

[unpacker-binary].exe -i reports/MYPC_Example_2024-08-12_13-45-20 -k key/private_key.pem --restore --verify

This will do the following:

  1. The report.zip will be decrypted using the private key specified with the -k flag. The process will fail if the file was tampered with or the key is incorrect.
  2. The report.zip file will be extracted to the report directory.
  3. All stored files (using the store or yara action) will be restored by recreating the original file structure in the report directory.
  4. The integrity of all files in the store_files directory will be verified using the metadata in the metadata.csv file.

How does a workflow work?

A workflow is a set of actions that are executed in a specific order. It is structured as follows:

# workflows/example.yaml

properties:
# Name, description, and author of the workflow

launch_conditions:
# Conditions that must be met for the workflow to be executed

actions:
# Definition and configuration of the actions that are used in the next section

workflow:
# The order in which the actions are executed, error handling and timeouts

reporting:
# Use of ZIP compression, encryption, and metadata collection

how_it_works

Creating a workflow

In the following pages, you will learn how to create a workflow. See the examples chapter for some examples.

Properties

properties:
  title: "Linux Example"
  version: "1.0"
  description: "This is an example configuration file for Linux"
  author: "John Doe"
PropertyDescriptionRequiredDefault
titleThe title of the workflow.Yes-
versionThe version of the workflow.Yes-
descriptionA short description of the workflow.No-
authorThe author of the workflow.No-
?You can add additional properties to the workflow configuration with string values.No-

Launch Conditions

launch_conditions:
  os: ["windows"]
  enabled: false
  arch: ["x86", "x86_64", "aarch64", "arm"]
  is_elevated: false
  custom_command:
    cmd: "cmd"
    args: ["/c", "dir", "${USER_HOME}"]
    contains_any: ["Downloads", "Documents"]
PropertyDescriptionRequiredDefault
osThe operating system(s) the workflow can be executed on. Available values: windows, linux, macos.Yes-
enabledCan be used to disable a workflow. false will prevent the workflow from being executed, even if all other conditions are met.Notrue
archThe architecture(s) the workflow can be executed on. Available values: x86, x86_64, aarch64, arm.No["x86", "x86_64", "aarch64", "arm"]
is_elevatedIf set to true, the workflow will only be executed if the user has elevated privileges. If set to false, it is not necessary to have elevated privileges.Nofalse
custom_commandAllows the execution of a custom command. The command is executed in the shell of the operating system.No-

Custom Commands

This condition allows the execution of a custom command. The following properties are available:

PropertyDescriptionRequiredDefault
cmdThe command to be executed.Yes-
argsThe arguments for the command.No-
contains_anyThe condition is met if at least one of the specified strings is found in the output of the command.No-
contains_allThe condition is met if all of the specified strings are found in the output of the command.No-
contains_regexThe condition is met if the regular expression is found in the output of the command.No-

You must specify at least one of the properties contains_any, contains_all, or contains_regex.

If you specify for example contains_any: ["abc", "def"] and contains_all: ["ghi", "jkl"], the condition is met if both contains_any and contains_all are true.

Actions

You can define all actions and use them in the next chapter. The defined actions are not executed until they are used in the workflow.

actions:
  - name: whoami
    type: command
    attributes:
      cmd: "cmd"
      args: ["/c", "whoami"]
      log_to_file: true

  - name: executables
    type: store
    attributes:
      case_sensitive: false
      patterns: |
        ${USER_HOME}/Downloads/**/*.exe
      size_limit: 10 GB

  - name: memory_dump
    type: binary
    attributes:
      path: "winpmem_mini_${ARCH}.exe"
      args: ["${LOOT_DIR}\\${DEVICE_NAME}.dmp"]
      log_to_file: true

The variables ${USER_HOME}, ${LOOT_DIR}, ${DEVICE_NAME}, and ${ARCH} are replaced with the actual values during the execution of the collector. See the variables section for more information.

Available Actions

Action TypeDescription
commandExecute a command
binaryExecutes a binary. The path is relative to the custom_files directory. But you can also use absolute paths.
storeStore files that match a pattern. The pattern can be a glob pattern or a regular expression. See glob for more information.
yaraStore files that match a YARA rule. You might place them in the custom_files directory. The files to scan do also use glob patterns.
terminalOpen a terminal window to execute arbitrary commands. A transcript of the terminal session is stored in the action_output directory of the report.

Hint: For glob patterns, path separators (/ and \\) are valid on all operating systems.

1. Command

PropertyDescriptionRequiredDefault
cmdThe command to be executed.Yes-
argsThe arguments for the command.No[]
cwdThe working directory from which the command is executed.No"" (empty string)
log_to_fileIf set to true, the output of the command will be logged to a file.Notrue

Example:

  - name: disable_network
    type: command
    attributes:
      cmd: "sh"
      args: ["-c", "ip link set $(ip route get 1.1.1.1 | awk '{print $5; exit}') down"]
      log_to_file: true

2. Binary

PropertyDescriptionRequiredDefault
pathThe path to the binary file to be executed.Yes-
argsThe arguments for the binary file.No[]
log_to_fileIf set to true, the output of the binary execution will be logged to a file.Notrue

Example:

  - name: memory_dump
    type: binary
    attributes:
      path: "dumpitforlinux"
      args: ["-v", "${LOOT_DIR}/${DEVICE_NAME}.dmp"]
      log_to_file: true

3. Store

PropertyDescriptionRequiredDefault
case_sensitiveIf set to true, the pattern matching will be case-sensitive.Notrue
patternsThe file patterns or paths to be matched and stored. Multiple patterns can be specified using new lines.Yes-
size_limitThe size limit for the files to be stored. The value should be specified in bytes.NoUnlimited

Example:

  - name: browser
    type: store
    attributes:
      case_sensitive: false
      patterns: |
        /home/*/.mozilla/firefox/*.default-release/places.sqlite
        /home/*/.config/google-chrome/Default/History
      size_limit: 5 GB

4. Terminal

PropertyDescriptionRequiredDefault
shellThe shell to be used for executing the command.NoWill use the default shell of the operating system.
waitIf set to true, the workflow will wait for the terminal to be closed.Nofalse
separate_windowIf set to true, a terminal window will be opened. If set to false, an interactive shell will be opened in the current terminal.Notrue
enable_transcriptIf set to true, the output of the terminal will be captured and stored. This uses the script command on Linux and macOS and the Start-Transcript cmdlet on Windows.Notrue

Note:

  • On Windows the conhost process will be opened in a separate window.
  • On macOS the Terminal.app will be opened in a separate window.
  • On Linux a list of known terminal apps will be checked and the first one found will be used. If no known terminal app is found, the default shell will be used and the separate_window property will be ignored.

There are some limitations when using the terminal action:

  • If the wait property is true, then separate_window must also be set to true.
  • If the wait property is false, then enable_transcript must also be set to false. This is because the workflow might have already finishes when the transcript file will be saved.

Example:

  - name: terminal
    type: terminal
    attributes:
      shell: "bash"
      wait: true
      separate_window: true
      enable_transcript: true

5. Yara

PropertyDescriptionRequiredDefault
rules_pathsThe path to the Yara rules file(s). Multiple paths can be specified using new lines. The paths are relative to the custom_files directory.Yes-
files_to_scanThe files or directories to be scanned. Multiple paths can be specified using new lines.Yes-
store_on_matchIf set to true, any matches found will be stored.Notrue
num_threadsThe number of threads to be used for the scan.No1
scan_timeoutThe maximum time allowed for the scan, in seconds.No60

Example:

  - name: pdf_files
    type: yara
    attributes:
      rules_paths: |
        yara/*.yara
      files_to_scan: |
        ${USER_HOME}/Downloads/**/*
      store_on_match: true
      scan_timeout: 4s

Workflow

workflow:
  - action: disable_network
  - action: memory_dump
    timeout: 10m
    on_error: abort
  - action: activities
    on_error:
      goto: browser
  - action: disk_image
    timeout: 10s
  - action: browser

The workflow section defines the order in which the actions are executed. Each action is defined by its name and can have additional properties like timeout and on_error.

Hint: All actions must be defined in the actions section.

Action Properties

PropertyDescriptionRequiredDefault
actionThe name of the action to be executed.Yes-
timeoutThe maximum time the action is allowed to run. Avaliable for command and binary actions.No-
on_errorThe action to be executed if an error occurs.Nocontinue
parallelThis action will run in the background. The next action will be executed immediately. If the workflow finishes, the collector will wait for the parallel actions to finish before creating the report. Available for command, binary and terminal actions.Nofalse

Error Handling

The on_error property defines what should happen if an error occurs during the execution of an action. An action is considered to have failed if:

  • A childprocess returns a non-zero exit code.
  • A timeout occurs.
  • An error occurs during the execution of the action.

The following options are available:

  • continue: Continue with the next action. This is the default behavior.
  • abort: Stop the workflow and do not execute any further actions. This will wait for all parallel actions to finish before creating the report.
  • goto: Jump to a specific action. The action must be defined in the workflow. This is useful if you want to skip actions that are not necessary in case of an error.

Example:

workflow:
  - action: 1
    on_error: continue
  - action: 2
    on_error:
      goto: 4
  - action: 3
    on_error: abort
  - action: 4

Report

reporting:
  zip_archive:
    enabled: false
    encryption:
      enabled: false
      public_key: "example_public.pem"
      algorithm: CHACHA20-POLY1305
    compression:
      enabled: true
      size_limit: 100 MB
  metadata:
    mac_times: true
    checksums: true
    paths: true

Archive

PropertyDescriptionRequiredDefault
enabledSpecifies whether the zip archive creation is enabled.Notrue
encryptionConfiguration for encrypting the zip archive. Contains the fields: enabled, public_key, and algorithm.NoSee ReportingEncryption Defaults
compressionConfiguration for compressing the zip archive. Contains the fields: enabled and size_limit.NoSee ReportingCompression Defaults

Encryption

PropertyDescriptionRequiredDefault
enabledSpecifies whether encryption is enabled for the zip archive.Nofalse
public_keyThe path to the public key file used for encryption. Relative to the keys directoryYes (if enabled is true)-
algorithmThe encryption algorithm to be used. Available values: AES-128-GCM, CHACHA20-POLY1305, None.NoNone

Compression

PropertyDescriptionRequiredDefault
enabledSpecifies whether compression is enabled for the zip archive.Nofalse
size_limitThe maximum size limit for specific files to be compressed. If a file exceeds this limit, it will only be stored inside the archive without compression.No100 MB

Metadata

PropertyDescriptionRequiredDefault
mac_timesSpecifies whether the MAC times (Modified, Accessed, Created) should be recorded in the metadata.csv for stored files (using store or yara actions).Nofalse
checksumsSpecifies whether checksums should be calculated and included in the report.Nofalse
pathsSpecifies whether the original file paths should be recorded in the metadata.csv for stored files (using store or yara actions).Nofalse

Variables

The collector replaced all ${VAR_NAME} variables with the actual values during the execution.

You can use variables in the following places:

  1. All string values (including lists) in the actions section
  2. All string values in the custom_command section of the launch_conditions section

Example:

  - name: memory_dump
    type: binary
    attributes:
      path: "winpmem_mini_${ARCH}.exe"
      args: ["${LOOT_DIR}\\${DEVICE_NAME}.dmp"]

Available Variables

Variable NameDescriptionExample
BASE_PATHThe base path where the application stores its data.E:/collector/
DEVICE_NAMEThe name of the device.DESKTOP-1234
USER_HOMEThe path to the user's home directory.C:/Users/JohnDoe
USER_NAMEThe name of the user.JohnDoe
LOOT_DIRThe path to the loot directory.E:/collector/reports/[NAME]/loot_files/
CUSTOM_FILES_DIRThe path to the custom files directory.E:/collector/custom_files/
OSThe operating system.windows
ARCHThe architecture.x86_64

Examples

Windows

properties:
  title: "Windows Example"
  description: "This is an example configuration file for Windows"
  author: "John Doe"
  version: "1.0"

launch_conditions:
  os: ["windows"]
  enabled: true
  arch: ["x86", "x86_64"]
  is_elevated: true

actions:
  - name: disable_network
    type: command
    attributes:
      cmd: "cmd"
      args: ["/c", "${CUSTOM_FILES_DIR}\\disable_network.bat"]
      log_to_file: true

  - name: memory_dump
    type: binary
    attributes:
      path: "winpmem_mini_${ARCH}.exe"
      args: ["${LOOT_DIR}\\${DEVICE_NAME}.dmp"]
      log_to_file: true

  - name: clipboard
    type: command
    attributes:
      cmd: "powershell"
      args: ["-c", "Get-Clipboard"]
      log_to_file: true

  - name: disk_image
    type: binary
    attributes:
      path: "ftk/FTK Imager.exe"
      log_to_file: true

  - name: registry_dump
    type: command
    attributes:
      cmd: "cmd"
      args: ["/c", "reg save HKLM\\SYSTEM ${LOOT_DIR}\\registry_dump.reg"]
      log_to_file: true

  - name: event_log
    type: command
    attributes:
      cmd: "powershell"
      args: ["-c", "wevtutil epl System ${LOOT_DIR}\\system.evtx"]
      log_to_file: true

  - name: browser
    type: store
    attributes:
      case_sensitive: false
      patterns: |
        ${USER_HOME}/AppData/Local/Google/Chrome/User Data/Default/History
        ${USER_HOME}/AppData/Roaming/Mozilla/Firefox/Profiles/*/places.sqlite
      size_limit: 5 GB

workflow:
  - action: disable_network
  - action: memory_dump
  - action: clipboard
  - action: disk_image
  - action: registry_dump
  - action: event_log
  - action: browser

reporting:
  zip_archive:
    enabled: false
    encryption:
      enabled: false
      public_key: "example_public.pem"
      algorithm: CHACHA20-POLY1305
    compression:
      enabled: true
      size_limit: 100 MB
  metadata:
    mac_times: true
    checksums: true
    paths: true

Linux

properties:
  title: "Linux Example"
  description: "This is an example configuration file for Linux"
  author: "John Doe"
  version: "1.0"

launch_conditions:
  os: ["linux"]
  enabled: true
  arch: ["x86", "x86_64"]
  is_elevated: true

actions:
  - name: disable_network
    type: command
    attributes:
      cmd: "sh"
      args: ["-c", "ip link set $(ip route get 1.1.1.1 | awk '{print $5; exit}') down"]
      log_to_file: true

  - name: memory_dump
    type: binary
    attributes:
      path: "dumpitforlinux"
      args: ["-v", "${LOOT_DIR}/${DEVICE_NAME}.dmp"]
      log_to_file: true

  - name: activities
    type: command
    attributes:
      cmd: "sh"
      args: ["-c", "ps aux > ${LOOT_DIR}/processes.txt && netstat -tulnp > ${LOOT_DIR}/network_connections.txt && lsof > ${LOOT_DIR}/open_files.txt"]
      log_to_file: true

  - name: disk_image
    type: command
    attributes:
      cmd: "sh"
      args: ["-c", "${CUSTOM_FILES_DIR}/dc3dd if=$(df / | tail -1 | awk '{print $1}') of=${LOOT_DIR}/root_partition.img"]
      log_to_file: true

  - name: browser
    type: store
    attributes:
      case_sensitive: false
      patterns: |
        /home/*/.mozilla/firefox/*.default-release/places.sqlite
        /home/*/.config/google-chrome/Default/History
      size_limit: 5 GB

workflow:
  - action: disable_network
  - action: memory_dump
  - action: activities
  - action: disk_image
  - action: browser

reporting:
  zip_archive:
    enabled: false
    encryption:
      enabled: false
      public_key: "example_public.pem"
      algorithm: CHACHA20-POLY1305
    compression:
      enabled: true
      size_limit: 100 MB
  metadata:
    mac_times: true
    checksums: true
    paths: true

macOS

properties:
  title: "macOS Example"
  description: "This is an example configuration file for macOS"
  author: "John Doe"
  version: "1.0"

launch_conditions:
  os: ["macos"]
  enabled: true
  arch: ["x86", "x86_64", "aarch64", "arm"]
  is_elevated: true

actions:
  - name: disable_network
    type: command
    attributes:
      cmd: "sh"
      args: ["-c", "networksetup -setairportpower en0 off"]
      log_to_file: true

  - name: activities
    type: command
    attributes:
      cmd: "sh"
      args: ["-c", "ps -e > ${LOOT_DIR}/processes.txt && lsof -i > ${LOOT_DIR}/open_files.txt"]
      log_to_file: true

  - name: disk_image
    type: command
    attributes:
      cmd: "sh"
      args: ["-c", "hdiutil create -srcdevice $(df / | tail -1 | awk '{print $1}') -format UDRW ${LOOT_DIR}/disk_image.dmg"]
      log_to_file: true

  - name: email_chat
    type: store
    attributes:
      case_sensitive: false
      patterns: |
        /Users/*/Library/Mail/**/*
        /Users/*/Library/Messages/**/*
      size_limit: 5 GB

  - name: browser
    type: store
    attributes:
      case_sensitive: false
      patterns: |
        /Users/*/Library/Safari/History.db
        /Users/*/Library/Application Support/Google/Chrome/Default/History
      size_limit: 5 GB

workflow:
  - action: disable_network
  - action: activities
  - action: disk_image
  - action: email_chat
  - action: browser

reporting:
  zip_archive:
    enabled: false
    encryption:
      enabled: false
      public_key: "example_public.pem"
      algorithm: CHACHA20-POLY1305
    compression:
      enabled: true
      size_limit: 100 MB
  metadata:
    mac_times: true
    checksums: true
    paths: true