Intro to Using GScript for Red Teams
Hey all, I wanted to talk about why and how to use gscript for Red Team operations. I introduced gscript before, but in this post I will cover details about how to start using it and some of its cool features. Before we get into the technical details, I want to talk about why we built gscript and how we'd traditionally been deploying implants collaboratively. The rest of this post will cover how to embed payloads into gscript, embedding multiple payloads into a gscript implant, and debugging gscripts during development. Let's start by taking a deeper look at the history of gscript and how it’s useful as a post exploitation tool.
Gscript is the evolution of GENESIS, a dynamic dropper of multiple post exploitation payloads. This “cluster bomb” or dropper idea was inspired by a coworker's custom dropper for *nix systems. During the engagement, you'd send him your payloads and how they needed to be dropped and he'd stage and write it into the script. We knew this was unsustainable when it became a rush to collect and embed as many of the payloads into a dropper as we could at game time. Instead we wanted an implant designed from the ground-up to easily bundle and drop other payloads, in a semi-effortless manner. The first solution to this was an SMB share team members could drop payloads in and later collect a single binary or staged one-liner. After that, we experimented with using JSON based manifest files (similar to JAR manifests) describing how to instrument each embedded payload. Ultimately Alex arrived at gscript, or using a JavaScript virtual machine to instrument precompiled dropper functions at runtime. The idea here is team members can define their "gscripts" that specifies exactly how they want to drop, call, and/or persist their payload. Further, gscript is cross-platform and compiles final binaries for Windows, Linux, and OS X. The built-in functions are, by in large, platform independent. We did this to allow red teamers to learn the core of gscript, and be able to produce scripts for any platform. If the original Jerricho dropper could be described as a cluster bomb, then gscript is more like a MIRV.
Let's start by getting you setup with gscript. First, you'll want to download one of the releases and place this in your PATH. On Windows, I also recommend using Cygwin or another terminal emulator for better compatibility. Now, let’s write our first gscript and include an agent to embed.
In the above image you can see an “import” declaration, followed by a file path. This works by importing the binary from the specified location at compile time. The compiler packages this file into the final binary and can be referenced within gscript using the Asset("filename") function. If a binary is not at a location defined in the import declaration than the gscript compile command will fail. In the screenshot below we use the short name for the compile command, c.
In the above image you can see a user compiling a Merlin gscript into a final payload. Check out some of the example scripts, including these showing how to get started by embedding Merlin agents into a dropper payload. If you’re looking for more examples of how to use the functions, checkout the function tests, as that will provide working gscript syntax.
Next, let's look at how to bundle multiple gscripts into a single binary. When you run the gscript compile command, you can specify n number of gscripts as arguments. Each gscript will be enumerated, parsed for dependencies, and bundled into the final binary. This is the bread and butter of gscript, embedding lots of post exploitation payloads, with detailed execution instructions, into a single dropper binary.
We also see in the previous example how easy it is to build gscript dropper payloads for multiple architectures, just wrapping and bundling our favorite post-exploitation payloads into platform specific dropper builds. In this screenshot above, we compile final payloads for OS X, Linux, and Windows, each with three or more post exploitation implants embedded inside.
By now, you're probably wondering how to test your gscripts. The gscript compiler has another command gscript run custom.gs that lets you execute a gscript with debug tracing enabled. This tracing is always turned off on the final compiled binary, so the run command really helps you through development. If your developing some gscripts and they have errors you may want to debug them, including the underlying built-in functions. This will print errors and debug statements anywhere we’ve defined “e.LogInfo” or “e.LogError” in the code.
In this post we covered why you may want to use gscript, how to embedded other payloads into your gscripts, how to compile multiple gscripts into your final payload, and how to debug your gscripts. Remember, gscript is still in active development, so things here are subject to change rapidly. We hope you enjoy using this tool, feel free to leave feedback and send PRs!