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.
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.
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 examplestdout
andstderr
).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 thestore
oryara
action. Filenames are replaced with their SHA256 hash.metadata.csv
: Contains the metadata of all files in thestore_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:
- All stored files (using the
store
oryara
action) will be restored by recreating the original file structure in the report directory. This does not apply to files that w - The integrity of all files in the
store_files
directory will be verified using the metadata in themetadata.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:
- 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. - The
report.zip
file will be extracted to the report directory. - All stored files (using the
store
oryara
action) will be restored by recreating the original file structure in the report directory. - The integrity of all files in the
store_files
directory will be verified using the metadata in themetadata.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
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"
Property | Description | Required | Default |
---|---|---|---|
title | The title of the workflow. | Yes | - |
version | The version of the workflow. | Yes | - |
description | A short description of the workflow. | No | - |
author | The 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"]
Property | Description | Required | Default |
---|---|---|---|
os | The operating system(s) the workflow can be executed on. Available values: windows , linux , macos . | Yes | - |
enabled | Can be used to disable a workflow. false will prevent the workflow from being executed, even if all other conditions are met. | No | true |
arch | The architecture(s) the workflow can be executed on. Available values: x86 , x86_64 , aarch64 , arm . | No | ["x86", "x86_64", "aarch64", "arm"] |
is_elevated | If 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. | No | false |
custom_command | Allows 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:
Property | Description | Required | Default |
---|---|---|---|
cmd | The command to be executed. | Yes | - |
args | The arguments for the command. | No | - |
contains_any | The condition is met if at least one of the specified strings is found in the output of the command. | No | - |
contains_all | The condition is met if all of the specified strings are found in the output of the command. | No | - |
contains_regex | The 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 Type | Description |
---|---|
command | Execute a command |
binary | Executes a binary. The path is relative to the custom_files directory. But you can also use absolute paths. |
store | Store files that match a pattern. The pattern can be a glob pattern or a regular expression. See glob for more information. |
yara | Store files that match a YARA rule. You might place them in the custom_files directory. The files to scan do also use glob patterns. |
terminal | Open 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
Property | Description | Required | Default |
---|---|---|---|
cmd | The command to be executed. | Yes | - |
args | The arguments for the command. | No | [] |
cwd | The working directory from which the command is executed. | No | "" (empty string) |
log_to_file | If set to true , the output of the command will be logged to a file. | No | true |
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
Property | Description | Required | Default |
---|---|---|---|
path | The path to the binary file to be executed. | Yes | - |
args | The arguments for the binary file. | No | [] |
log_to_file | If set to true , the output of the binary execution will be logged to a file. | No | true |
Example:
- name: memory_dump
type: binary
attributes:
path: "dumpitforlinux"
args: ["-v", "${LOOT_DIR}/${DEVICE_NAME}.dmp"]
log_to_file: true
3. Store
Property | Description | Required | Default |
---|---|---|---|
case_sensitive | If set to true , the pattern matching will be case-sensitive. | No | true |
patterns | The file patterns or paths to be matched and stored. Multiple patterns can be specified using new lines. | Yes | - |
size_limit | The size limit for the files to be stored. The value should be specified in bytes. | No | Unlimited |
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
Property | Description | Required | Default |
---|---|---|---|
shell | The shell to be used for executing the command. | No | Will use the default shell of the operating system. |
wait | If set to true , the workflow will wait for the terminal to be closed. | No | false |
separate_window | If set to true , a terminal window will be opened. If set to false , an interactive shell will be opened in the current terminal. | No | true |
enable_transcript | If 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. | No | true |
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 istrue
, thenseparate_window
must also be set totrue
. - If the
wait
property isfalse
, thenenable_transcript
must also be set tofalse
. 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
Property | Description | Required | Default |
---|---|---|---|
rules_paths | The 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_scan | The files or directories to be scanned. Multiple paths can be specified using new lines. | Yes | - |
store_on_match | If set to true , any matches found will be stored. | No | true |
num_threads | The number of threads to be used for the scan. | No | 1 |
scan_timeout | The maximum time allowed for the scan, in seconds. | No | 60 |
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
Property | Description | Required | Default |
---|---|---|---|
action | The name of the action to be executed. | Yes | - |
timeout | The maximum time the action is allowed to run. Avaliable for command and binary actions. | No | - |
on_error | The action to be executed if an error occurs. | No | continue |
parallel | This 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. | No | false |
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
Property | Description | Required | Default |
---|---|---|---|
enabled | Specifies whether the zip archive creation is enabled. | No | true |
encryption | Configuration for encrypting the zip archive. Contains the fields: enabled , public_key , and algorithm . | No | See ReportingEncryption Defaults |
compression | Configuration for compressing the zip archive. Contains the fields: enabled and size_limit . | No | See ReportingCompression Defaults |
Encryption
Property | Description | Required | Default |
---|---|---|---|
enabled | Specifies whether encryption is enabled for the zip archive. | No | false |
public_key | The path to the public key file used for encryption. Relative to the keys directory | Yes (if enabled is true ) | - |
algorithm | The encryption algorithm to be used. Available values: AES-128-GCM , CHACHA20-POLY1305 , None . | No | None |
Compression
Property | Description | Required | Default |
---|---|---|---|
enabled | Specifies whether compression is enabled for the zip archive. | No | false |
size_limit | The 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. | No | 100 MB |
Metadata
Property | Description | Required | Default |
---|---|---|---|
mac_times | Specifies whether the MAC times (Modified, Accessed, Created) should be recorded in the metadata.csv for stored files (using store or yara actions). | No | false |
checksums | Specifies whether checksums should be calculated and included in the report. | No | false |
paths | Specifies whether the original file paths should be recorded in the metadata.csv for stored files (using store or yara actions). | No | false |
Variables
The collector replaced all ${VAR_NAME}
variables with the actual values during the execution.
You can use variables in the following places:
- All string values (including lists) in the
actions
section - All string values in the
custom_command
section of thelaunch_conditions
section
Example:
- name: memory_dump
type: binary
attributes:
path: "winpmem_mini_${ARCH}.exe"
args: ["${LOOT_DIR}\\${DEVICE_NAME}.dmp"]
Available Variables
Variable Name | Description | Example |
---|---|---|
BASE_PATH | The base path where the application stores its data. | E:/collector/ |
DEVICE_NAME | The name of the device. | DESKTOP-1234 |
USER_HOME | The path to the user's home directory. | C:/Users/JohnDoe |
USER_NAME | The name of the user. | JohnDoe |
LOOT_DIR | The path to the loot directory. | E:/collector/reports/[NAME]/loot_files/ |
CUSTOM_FILES_DIR | The path to the custom files directory. | E:/collector/custom_files/ |
OS | The operating system. | windows |
ARCH | The 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