Blueteam operational triage registry hunting/forensic tool.
I hope to incorporate more than just registry triage and hunting. I'd love to see this tool become a standalone triage / hunt tool for all Windows persistence mechanisms.
Demo and misc. information on Registry Hunter via Forensic Lunch podcast: https://www.youtube.com/watch?v=_lKinL7f7ak&t=2s
Thank you to https://twitter.com/Hexacorn and https://twitter.com/SBousseaden for their open research. Many of the explicit registry keys and values defined in this tool came from their graciously shared hard work.
Thanks to https://github.com/lilopkins and https://github.com/gentoo90 for the Lnk and Registry Rust crates.
Output is in JSON line delimited.
If you just want the tool, download the reg_hunter_x32.exe and/or reg_hunter_x64.exe binary. Note that you'll want to run the 64 bit binary on a 64 bit OS so that it will not be partially blinded by Windows WOW64 redirection.
Registry key "last_write_time" is included in Registry JSON logs.
The "tags" field is an array populated by any hunts that are a positive match.
I needed a self-contained tool, as when I'm triaging an event, the less files I have to push to a remote device the better. Adding in new hunts and recompiling is simple as well. I also wanted a tool that was not dependent on having a minimum .Net version installed.
NOTE: The "parent_data_type" field specifies the "data_type" that caused the generation of this data type. E.g. If a Lnk file was found in a registry value, this will generate a "ShellLink" data_type with a parent_data_type of "Registry". Then a data_type of "File" with a parent_data_type of "ShellLink" will be generated if the file that the Lnk file points to is found/exists. I.e. Registry --> ShellLink --> File
A file/lnk's meta data will only be collected once no matter how many times it is referenced in registry values.
Add Rust 32 bit target build environment:
rustup toolchain install stable-i686-pc-windows-msvc
rustup target add i686-pc-windows-msvc
rustup target add x86_64-pc-windows-gnu
To compile; install Rust and the MSVC 32 and/or 64 bit environment:
x32: cargo build --release --target i686-pc-windows-msvc
x64: cargo build --release --target x86_64-pc-windows-msvc
Linux x64: sudo apt update && sudo apt install mingw-w64
cargo build --release --target x86_64-pc-windows-gnu
Reg Hunter
Author: Brian Kellogg
License: MIT
Many thanks: @Hexacorn and @SBousseaden
Disclaimer:
This tool comes with no warranty or support.
If anyone chooses to use it, you accept all responsibility and liability.
Usage:
reg_hunter --help
reg_hunter [options]
reg_hunter --explicit -f -n [--ip <ip> --port <port>]
reg_hunter --all [-bcefimnorsuwyz] [--ip <ip> --port <port>] [--limit]
reg_hunter -a --regex <regex> --path --name --value
reg_hunter -a -y [--start <start_time> --end <end_time>]
Options:
Registry context (one required):
-a, --all Examine all the registry; HKLM and HKU
-x, --explicit Examine only more often forensically interesting keys and values
This option will always report out all
value names and values unless values are empty/null
-k, --key <path> Only examine a specified reg path. [default: NONE]
All sub keys will be examined as well.
Searches both HKLM and HKU hives
format: SOFTWARE\Microsoft\Windows\CurrentVersion
Hunts:
-b, --binary Find possible MZ headers in REG_BINARY values
and possible Base64 encoded MZ headers - e.g. 'TVq'
Tag: MzHeader
-c, --shell Find command shells (cmd.exe, powershell.exe, ...)
Tag: Shell
-e, --encoding Find possibly encoded values
Tag: Encoding
-f, --file Find files referenced in registry values
and collect lnk/file metadata. If a lnk file is found,
metadata on both the lnk and file it points to will be
reported.
Tag: File
-g, --link Hunt for registry symbolic links
WORK IN PROGRESS
-i, --ip Search for IPv4 addresses
Tag: IPv4
-l, --rightleft Hunt for RightToLeft override
Tag: RightToLeft
-m, --email Find email addresses
Tag: Email
-n, --null Hunt for null prefixed value names
Tag: NullPrefixedName
-o, --obfuscation Find possibly obfuscated values
Tag: Obfuscation
-r, --script Find script files
Tag: Script
-s, --shellcode Find possible shellcode
Tag: Shellcode
-u, --unc Find UNC paths
Tag: UNC
-w, --url Find URLs
Tag: URL
-y, --suspicious Find various suspicious substrings
e.g. iex, invoke-expression, etc.
Tag: Suspicious
-z, --everything Run ALL the hunts
Time window:
This option will compare the specified date window to the registry key's
last_write_time and only output logs where the last_write_time falls
within that window. Window start is inclusive, window end is exclusive.
NOTE: key last_write_time can be timestomped.
--start <UTC_start_time> Start of time window: [default: 0000-01-01T00:00:00]
format: YYYY-MM-DDTHH:MM:SS
--end <UTC_end_time> End of time window: [default: 9999-12-31T23:59:59]
format: YYYY-MM-DDTHH:MM:SS
Custom hunts (regex and/or hex required):
NOTE: A limitation of the regex hunt is that only REG_BINARY values
that can be successfully converted to a string will be searched.
-q, --regex <regex> Custom regex [default: $^]
Does not support look aheads/behinds/...
Uses Rust regex crate (case insensitive and multiline)
Any match will add 'Custom' to the tags field
Tag: RegexHunt
--hex <string> Hex search string [default: FF]
Hex string length must be a multiple of two
format: 0a1b2c3d4e5f
Tag: HexHunt
-j, --path Search reg key path
-t, --name Search value name
-v, --value Search reg value
Network output:
-d, --destination <ip> IP address to send output to [default: NONE]
-p, --port <port> Destination port to send output to [default: 80]
Misc:
-h, --help Show this screen
--limit Try to minimize CPU use as much as possible
--print Always output log whether a hunt matched or not
--outfile <file> Send output to a line delimted file [default: NONE]
If the file exists, it will be appended to
--debug Print error logs
e.g. access denied to a registry key
failure opening a registry key
Note:
If not run as an administrator some telemetry cannot be harvested.
Only logs that are matched by a hunt are printed out unless the --print
or --explicit argument is used.
An error log with tag of 'HiddenKey' will be generated if any registry key
that fails to open is identified as a maliciously hidden key.
e.g. Key path ends with a unicode null character.
The output is mostly meant to be fed into some hunting backend. But,
there are some built in hunts; --null, --binary, ...
Depending on the options used, considerable output can be generated.
To capture output remotely, start a netcat listener on your port of choice.
Use the -k option with netcat to prevent netcat from closing after a TCP connection is closed.
Files larger than 256MB will not be hashed.
reg_hunter --all --null
- Search the entire registry for null hidden keys
reg_hunter --all --print --start 2022-11-01T00:00:00
- Print out all changed registry keys since November 1st 2022
- Great tactic for finding malicious entries when you know the start date of a possible compromise
reg_hunter --key "system\CurrentControlSet\Services" --print
- Print out all registry keys and values found under the given registry location
reg_hunter --key "system\CurrentControlSet\Services" --everything
- Run all hunts against the given registry location
reg_hunter --explicit --everything
- Run all hunts against just the more forensically interesting registry keys and values
reg_hunter -abcsy
- Run the following hunts against the entire registry: binary, shell, shellcode, suspicious
{
"parent_data_type": "",
"data_type": "Registry",
"timestamp": "2020-11-24T17:29:48.822",
"device_name": "DESKTOP-NDPUHM4",
"device_domain": "DESKTOP-NDPUHM4",
"device_type": "Windows 10",
"registry_hive": "HKEY_LOCAL_MACHINE",
"registry_key": "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
"registry_value_name": "evil_too",
"registry_type": "REG_SZ",
"registry_value": "C:\\Temp\\evil.txt.lnk",
"last_write_time": "2020-11-24T17:24:30.515",
"tags": [
"File"
]
}
{
"parent_data_type":"",
"data_type":"Registry",
"timestamp":"2020-11-24T17:29:48.813",
"device_name":"DESKTOP-NDPUHM4",
"device_domain":"DESKTOP-NDPUHM4",
"device_type":"Windows 10",
"registry_hive":"HKEY_LOCAL_MACHINE",
"registry_key":"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
"registry_value_name":"evil",
"registry_type":"REG_BINARY",
"registry_value":"[00, 00, 00, 4d, 5a, 90, 00, 00, 00, 00, 00]",
"last_write_time":"2020-11-24T17:24:30.515",
"tags":[
"MzHeader",
"HexHunt"
],
"error":""
}
{
"parent_data_type": "Registry",
"data_type": "ShellLink",
"timestamp": "2020-11-24T17:29:48.818",
"path": "c:\\temp\\evil.txt.lnk",
"target_path": "C:\\evil.txt",
"last_access_time": "2020-11-24T17:29:48.818",
"last_write_time": "2020-11-07T14:14:08.711",
"creation_time": "2020-11-07T14:13:06.694",
"size": 769,
"hidden": true,
"arguments": "",
"hotkey": "NO_MODIFIER-NoKeyAssigned"
}
{
"parent_data_type": "Registry",
"data_type": "File",
"timestamp": "2020-11-24T17:29:48.822",
"path": "c:\\temp\\evil.txt.lnk",
"md5": "0fcba6e9dd09e1cb497454f0b256b490",
"mime_type": "application/octet-stream",
"last_access_time": "2020-11-24T17:29:48.818",
"last_write_time": "2020-11-07T14:14:08.711",
"creation_time": "2020-11-07T14:13:06.694",
"size": 769,
"hidden": true
}
{
"parent_data_type": "ShellLink",
"data_type": "File",
"timestamp": "2020-11-24T17:29:48.821",
"path": "C:\\evil.txt",
"md5": "1df1eae8c6c44484a840a40a0543cc59",
"mime_type": "text/plain",
"last_access_time": "2020-11-24T17:29:48.820",
"last_write_time": "2020-11-24T17:23:26.245",
"creation_time": "2020-11-24T17:23:17.173",
"size": 16,
"hidden": true
}
{
"parent_data_type": "Error",
"data_type": "Registry",
"timestamp": "2020-12-06T20:56:42.113",
"device_name": "DESKTOP-NDPUHM4",
"device_domain": "DESKTOP-NDPUHM4",
"device_type": "Windows 10",
"registry_hive": "HKEY_LOCAL_MACHINE",
"registry_key": "SOFTWARE\\WOW6432Node\\Systems Internals\\Can't touch me!\u0000",
"registry_value_name": "ERROR_READING",
"registry_type": "REG_ERROR",
"registry_value": "ERROR_READING",
"last_write_time": "",
"tags": [
"HiddenKey"
],
"error": "The system cannot find the file specified. (os error 2)"
}