GRR On The Command Line With GRRShell
What is GRR?
GRR Rapid Response (or GRR) is an incident response framework focused on remote live forensics. It is a tool that communicates with its deployed endpoint agents to collect and deliver forensics artifacts to an incident responder for analysis from one machine or thousands. This article assumes you’re already familiar with using GRR in a production environment.
GRR is GRReat! But...
GRR is a beneficial tool to have available, but it does have some limitations:
- Browsing the Virtual File System (VFS) In the Web UI can be time consuming for in-depth analysis. Upon browsing to a directory, a new ListDirectory flow is launched, and the operator must wait for that flow to complete before continuing. For repeated directory navigations, this time adds up.
- Finding a file of an unknown location requires a ClientFileFinder flow. The exact syntax can be challenging to remember, resulting in needing to check the documentation frequently.
- Launching artifact collection flows is located in a separate section of the Web UI than VFS browsing.
- Artifacts collected are downloaded via a different method to files collected via the VFS in the Web UI.
- Some people, including myself, just prefer the command line instead of a web browser.
GRRShell is a command line REPL utility and it should be familiar to anyone who has used sftp or similar utilities in Linux. Designed for interacting with a single remote client, GRRShell fetches a TimelineFlow from the client, which is used to populate an in-memory representation of the client file system called the Emulated File System (EFS) - so named to differentiate it from the VFS in the Web UI. The operator can navigate the EFS with immediate speed rather than waiting for ListDirectory flows to complete.
Our analysis shows that a ListDirectory flow takes anywhere between 5 and 20 seconds, while a TimelineFlow takes approximately 1 minute to return a result to the engineer. As such, after approximately 7 directory changes, a single TimelineFlow used to populate the EFS is more time efficient. Front-loading that wait time for an engineer solves the first limitation above. Of course, timelines can become stale as files and artifacts change on the client, so fresh timelines can be requested within the tool from the client during your investigation.
The remaining points are addressed as follows:
- Finding a location of a file can be near-instantaneous with the EFS, and can support more standardized filename patterns via regex.
- Artifact collections (ArtifactCollectorFlow) are issued at the same command prompt as file collections (ClientFileFinder).
- ArtifactCollector and ClientFileFinder flows download results to the same location on the engineers workstation.
- No web browser - it's a CLI tool!
GRRShell In Action
At launch, GRRShell will (in the following order of preference) use a TimelineFlow specified by the operator, a recent existing TimelineFlow (up to 12 hours old), or request a new TimelineFlow, and use the result to populate a navigable EFS.
Typical usage may look like the following:
In addition to startup, the above shows artifact collection (supporting British and American English spelling) including autocomplete for both the command and selection of the artifact to collect. Artifacts that download files are performed asynchronously in the background. Artifacts that display a result like the above example are synchronous and will block until complete (or the user hits CTRL+C).
Some GRRShell Limitations
GRRShell aims to provide support for most of the GRR Web UI features to navigate a file system and collect artifacts. GRRShell does not have any support for GRR Hunts, so you'll still need the Web UI for those.
Additionally, GRRShell is not primarily designed for collecting artifacts from multiple machines. It does however provide a couple of non-interactive commands that allow you to collect the same artifact or files for multiple hosts. For example:
$ cat clients | while read client; do grrshell artifact --grr-server http://address --username admin --password password --client $client --artifact BrowserHistory --local-path .; done
For a more comprehensive list of options see the appendix or the output of grrshell help
GRRShell can be installed via pip: $ pip install grrshell
The source is available on Github. Bugs and feature requests can of course be raised at that same location.
GRRShell is designed for incident responders who prefer working on a command line instead of a web browser, for collecting files and artifacts from client machines to a consistent local location. GRRShell aims to be more time efficient for navigating, and finding files within, a client file system.
Appendix: Full Shell Commands List
- help (aliases h, ?) - Display help text. help <command> displays extended help for the command, where available
- artefact (alias artifact) - Perform an ArtifactCollector flow. The flow is performed synchronously or asynchronously, depending on the artifact requested
- cd <path> - Change working directory
- clear - Clear the terminal screen
- collect <path> - Collect remote files via a ClientFileFinder flow. CFF syntax is supported, which is documented here
- detail <flowid> - Displays detailed information on a specific flow
- exit (alias quit, <CTRL+D>) - Exit the shell
- find <regex> - Search the EFS for a filename matching a regex
- flows - List flows launched in the GRRShell session. Specify --all for all flows launched on the client.
- info <path> (alias hash) - Display file information.
- --offline - Display the values in the EFS instead of a launching a flow
- --ads - Include the Alternate Data Stream
- ls - List entries in a directory. Adjust sorting with -S, -t and -r
- pwd - Display the current working directory
- refresh - Schedule a new TimelineFlow, and update the EFS with the result. An optional path can be specified for a Timeline root for refreshing only a subdirectory, if required
- resume <flowid> - Reattach an existing completed or in progress flow to this GRRShell session
- set <name> <value> - Set a shell variable. Currently, only one variable is supported:
- max-file-size - Specify a max file size for file collections