*** Modified spyre project to add some feature:***
- yara match indicate information strings matched
- process get informations (path, child, parent, cmdline, pe-sieve)
- process can be killed by yara rule
- registry scan ioc (excepted HKCU of not current user already opened by system)
- event windows scan by yara rules (event by event)
- linux/unix log scan by yara rules (line by line)
- netstat scan ioc
- autorun scan ioc (from autorunsc sysinternals for windows only)
- logonsession (get all session user)
- get return of command (option timeout and get files/dir created) - multithread
- try connect to host:port
- get KB installed (only windows)
- get user is member of admin local (windows only)
- get local IP routed
- get installed software
- change order of scan (ioc->mem->evtx->fs)
- jsonl result by default
- crypt with RSA public key output (use extra/uncrypt.go to uncrypt)
...a simple, self-contained modular host-based IOC scanner
Spyre is a simple host-based IOC scanner built around the YARA pattern matching engine and other scan modules. The main goal of this project is easy operationalization of YARA rules and other indicators of compromise.
Users need to bring their own rule sets. The awesome-yara repository gives a good overview of free yara rule sets out there.
Spyre is intended to be used as an investigation tool by incident responders. It is not meant to evolve into any kind of endpoint protection service.
Using Spyre is easy:
-
Add YARA signatures. Per default, YARA rules for file scans are read from
filescan.yar
,procscan.yar
,evtxscan.yar
for file scans, process memory scans, event windows scans respectively. The following options exist for providing rules files to Spyre (and will be tried in this order):- Add the rule files to ZIP file and append that file to the binary.
- Add the rule files to a ZIP file name
$PROGRAM.zip
: If the Spyre binary is calledspyre
orspyre.exe
, usespyre.zip
. - Put the rule files into the same directory as the binary.
ZIP file contents may be encrypted using the password
infected
(AV industry standard) to prevent antivirus software from mistaking parts of the ruleset as malicious content and preventing the scan.YARA rule files may contain
include
statements. -
Deploy, run the scanner
-
Collect report
Run-time options can be either passed via command line parameters or
via file that params.txt
. Empty lines and lines starting with the
#
character are ignored. Every line is interpreted as a single
command line argument.
If a ZIP file has been appended to the Spyre binary, configuration and other files such as YARA rules are only read from this ZIP file. Otherwise, they are read from the directory into which the binary has been placed.
Some options allow specifying a list of items. This can be done by
separating the items using a semicolon (;
).
Normally (unless this switch is enabled), Spyre instructs the OS scheduler to lower the priorities of CPU time and I/O operations, in order to avoid disruption of normal system operation.
Explicitly set the hostname that will be used in the log file and in the report. This is usually not needed.
Set the log level. Valid: trace, debug, info, notice, warn, error, quiet.
Set one or more report targets, separated by a semicolon (;
).
Default: spyre.log
in the current working directory, using the plain
format.
A different output format can be specified by appending
,format=FORMAT
. The following formats are currently supported:
plain
, the default, a simple human-readable text formattsjson
, a JSON document that can be imported into Timesketch
Set one or more specific filesystem paths to scan. Default: /
(Unix)
or all fixed drives (Windows).
Set list of YARA rule files for scanning files on the system. Default:
Use filescan.yar
from appended ZIP file, $PROGRAM.ZIP
, or current
working directory.
Set list of YARA rule files for scanning processes' memory
regions. Default: Use procscan.yar
from appended ZIP file,
$PROGRAM.ZIP
, or current working directory.
Set list of YARA rule files for scanning events windows'. Default:
Use evtxscan.yar
from appended ZIP file,
$PROGRAM.ZIP
, or current working directory.
Set list of YARA rule files for scanning linux/unix logs'. Default:
Use logsscan.yar
from appended ZIP file,
$PROGRAM.ZIP
, or current working directory.
Set maximum size for files to be scanned using YARA. Default: 32MB
Option only for windows, Yara FS scan only on:
- windir
- SystemRoot
- ProgramFiles
- ProgramFiles(x86)
- ProgramData
- ALLUSERSPROFILE
- profile directory (eg: c:\users) Default: True
Default: False
Set path line by line that will not be scanned.
Default: Use ignorepath.txt
from current working directory.
Set names of processes that will not be scanned.
Set path of public rsa key to crypt log file.
Use extra/uncrypt.go to uncrypt log file.
Set number of worker to run command. Default: 2
YARA is configured with default settings, plus the following explicit
switches (cf. 3rdparty.mk
):
--disable-magic
--disable-cuckoo
--enable-dotnet
--enable-macho
--enable-dex
Spyre can be built for 32bit and 64bit Linux and Windows targets.
On a Debian/buster system (or a chroot) in which the following packages have been installed:
- make
- gcc
- gcc-multilib
- gcc-mingw-w64
- autoconf
- automake
- libtool
- pkg-config
- wget
- patch
- sed
- golang-$VERSION-go, e.g. golang-1.8-go. The Makefile will
automatically select the newest version unless
GOROOT
has been set. - git-core
- ca-certificates
- zip
This describes the build environment that is exercised regularly via CI.
The same build has also been successfully tried on Fedora 30 with the following packages installed:
- make
- gcc
- mingw{32,64}-gcc
- mingw{32,64}-winpthreads-static
- autoconf
- automake
- libtool
- pkgconf-pkg-config
- wget
- patch
- sed
- golang
- git-core
- ca-certificates
- zip
Once everything has been installed, just type make
. This should
download archives for musl-libc, openssl, yara, build those and
then build spyre.
The bare spyre binaries are created in _build/<triplet>/
.
Running make release
creates a ZIP file that contains those binaries
for all supported architectures.
You can use variable informations passed to yara:
- filename: name of file
- filepath: full path
- extension: file extension
If rule name contains "_keepfile" then the content of file added to report in base64.
You can use variables informations passed to yara:
- pid: pid number (String)
- pathexe: executable path (String)
- cmdline: command line for start process (String)
- executable: name of process (String)
- username: username who runned process
- cwd: cwd where command started (String)
- foreground: process foreground mode (String: true|false)
- connexions: connexions used by process (String)
- handle_files: files used by process (String)
- ppid: parent pid (String)
- ppathexe: parent executable path (String)
- pcmdline: command line for start parent process (String)
- pexecutable: name of parent process
- pusername: username who runned parent process
- cpathexe: children executable path - separed by "|" (String)
- ccmdline: command line for start children process - separed by "|" (String)
- cexecutable: name of children process - separed by "|" (String)
- cusername: username who runned children process - separed by "|" (String)
- psieve_total: pe sieve result (Int)
- psieve_patched: pe sieve result (Int)
- psieve_replaced: pe sieve result (Int)
- psieve_unreachable_file: pe sieve result (Int)
- psieve_implanted_pe: pe sieve result (Int)
- psieve_implanted_shc: pe sieve result (Int)
- psieve_other: pe sieve result (Int)
- psieve_iat_hooked: pe sieve result (Int)
- psieve_hdr_modified: pe sieve result (Int)
- psieve_results: pe sieve result Json (String)
You can kill processus matched by yara rule if you rename rule with prefix "kill_", e.g.: kill_emotet {} .
E.G:
rule windows_defender {
meta:
description = "Windows defender detect malware."
author = "Lionel PRAT"
date = "2020-12-28"
strings:
/* Plain strings */
$id01 = "EventID\x22:\x221005\x22" ascii nocase
$id02 = "EventID\x22:\x221006\x22" ascii nocase
$id03 = "EventID\x22:\x221007\x22" ascii nocase
$id04 = "EventID\x22:\x221008\x22" ascii nocase
$id05 = "EventID\x22:\x221009\x22" ascii nocase
$id06 = "EventID\x22:\x221010\x22" ascii nocase
$id07 = "EventID\x22:\x221016\x22" ascii nocase
$id08 = "EventID\x22:\x221017\x22" ascii nocase
$id09 = "EventID\x22:\x221018\x22" ascii nocase
$id10 = "EventID\x22:\x221019\x22" ascii nocase
$id11 = "EventID\x22:\x221021\x22" ascii nocase
$id12 = "EventID\x22:\x221116\x22" ascii nocase
$id13 = "EventID\x22:\x221117\x22" ascii nocase
$id14 = "EventID\x22:\x221120\x22" ascii nocase
$chan = "Microsoft-Windows-Windows Defender" ascii nocase
condition:
1 of ($id*) and $chan
}
You can use variable informations passed to yara:
- filename: name of file logs
- filepath: full path of file logs
- extension: file extension of file logs (ex: ".log" or ".gz")
E.G:
rule remote_session_ssh {
meta:
description = "Remote ssh session opened."
author = "Lionel PRAT"
date = "2023-01-03"
strings:
/* Plain strings */
$ssh = "ssh" ascii nocase
$open1 = "session opened for" ascii nocase
$open2 = "Accepted" ascii nocase
condition:
filename matches /auth\.log/i and $ssh and any of ($open*)
}
- Command is executed according by order of declaration
- "command": is variable of path of command to run
- "commandargs": is args of command
- "description": is description of rule indicated in stdout
- "InputFile": if you need to import file to execute on target (gzip+b64)
- "InputFileName": name for inputfile (put in tempdir), you cannot choose if you want to make random name
- "timeout": max time to run before kill command
- "YaraRulesOnStdout": yara rules on match to stdout to keep information in log
- "KeepResultInFile": keep stdout result to use in other command (created in tempdir if not path specified)
- "Getfiles": files or/and directories to extract in log (zip->b64)
- "Level": level of execution command if you need require another command finished before E.G:
{
"command":
[
{
"command": "c:\\windows\\System32\\ipconfig.exe",
"commandargs": ["/displaydns"],
"description":"cache DNS",
"timeout": "60"
},
{
"command": "$INPUTFILE$",
"KeepResultInFile": "piplist_result.txt",
"YaraRulesOnStdout": "rule test { meta: author = \"Lionel PRAT\" strings: $a = \"LSM_API\" fullword condition: $a }",
"InputFile": "base64(gzip(file_to_extract))",
"InputFileName": "piplist.exe",
"commandargs": ["/accepteula"],
"description":"piplist",
"timeout":"60"
},
{
"command": "/usr/bin/zip",
"commandargs": ["-r", "/tmp/data.zip", "/data"],
"description":"dump /data",
"timeout": "60",
"getfiles": ["/tmp/data.zip"],
"Level": 0
},
{
"command": "/usr/bin/ls",
"commandargs": ["-l", "/tmp/"],
"description":"ls /tmp/data.zip",
"timeout": "60",
"Level": 1
}
],
"connect":
[
{
"ip": "www.google.fr",
"port": "80",
"protocol": "tcp",
"send": "GET / HTTP/1.0\r\n\r\n",
"timeout": "2s",
"description":"google_443"
}
],
"autorun":
[
{
"value":".*",
"type":2,
"description":"Get all autorun"
}
],
"registry-keys":
[
{
"key": "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SilentProcessExit\\**",
"name": "",
"value": "",
"description": "Detects persistence registry keys SilentProcessExit on mmc",
"type": 0
},
{
"key": "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\**",
"name": "Debugger",
"value": "",
"description": "Detects persistence registry keys Debugger",
"type": 1
},
{
"key": "HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Session Manager\\AppCertDlls",
"name": "",
"value": "(?i)(C:\\\\Windows\\\\Temp\\\\|C:\\\\ProgramData\\\\|C:\\\\$Recycle.bin\\\\|C:\\\\Temp\\\\|C:\\\\Users\\\\Public\\\\|C:\\\\Users\\\\Default\\\\|\\\\AppData\\\\|%AppData%)",
"description": "Detects persistence registry keys Debugger on mmc",
"type": 6
}
],
"netstat":
[
{
"dip": [],
"sip": [],
"sport": [],
"dport": [14444, 49636],
"pname": [],
"notpname": [],
"state": [],
"proto": "*",
"description": "Potential wannamine"
},
{
"dip": [],
"sip": [],
"sport": [49636],
"dport": [],
"pname": [],
"notpname": [],
"state": [],
"proto": "*",
"description": "Potential wannamine"
}
]
}
You can use wildcard keys "**". You can use type search:
- 0: just key
- 1: Key + Name
- 2: Key + Real name contains name
- 3: Key + Name + Contains value
- 4: Key + Name + Regex value
- 5: Key + Contains value (check all names under key)
- 6: Key + Regex value (check all names under key)
You can use type search: - 0: contains value - 1: not contains value - 2: match regexp (value) - 3: not match regexp (value)
See HACKING.md
Copyright 2018-2020 DCSO Deutsche Cyber-Sicherheitsorganisation GmbH
Copyright 2020-2021 Spyre Project Authors (see: AUTHORS.txt)
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
See the LICENSE file for the full license text.