Nighthawk 0.2.4 – Taking Out the Trash

Introduction

Congratulations to our new king and in honour of the coronation, we proudly present Nighthawk 0.2.4.

Our last Nighthawk public post was for our 0.2.1 release in November and while several months have passed, we’ve continued to be busy in the background releasing new versions and features to customers, as well as beginning a separate and parallel development stream on a design re-architecture.

With our latest 0.2.4 minor release, we’ve decided to recap a little on some of the additions we’ve brought to Nighthawk.

Encrypting the CLR Garbage

One of the major new features included in our 0.2.4 release we’ve dubbed “OpSec CLR”. Nighthawk leverages the CLR in a number of areas, including in the Custom C2, custom agent traffic encoders and within our inproc-execute-assembly .NET assembly harness. These features have been around since the very first release of Nighthawk and they facilitate the execution of .NET assemblies in process for performing various tasks.

There are however some drawbacks to executing .NET assemblies in process. Firstly the CLR and its dependencies must be loaded in to your process; Nighthawk is able to evade the indicators associated with this by leveraging the dark loading capability we included in our 0.2.1 release. However, once the CLR is loaded it is somewhat difficult to completely unload without causing instability in the process, therefore most CLR harnesses will typically just destroy a custom app domain after execution. While this approach works nicely, it does often leave some artifacts relating to the assembly in the process, primarily because the CLR uses its own internal memory management and garbage collection routines. Unfortunately this meant that we were not able to take advantage Nighthawk’s custom and encrypted private heap, leaving some artifacts from the .NET assembly lingering in the memory of the process. Consequently, this meant that memory signatures could be built for detecting common assemblies in memory, or worse if the blue team performed a memory acquisition of your beacon process they would get greater insight in to some of the actions performed.

While assemblies could of course be obfuscated, we wanted to empower our customers by providing some built-in protections. Following extensive research, we discovered a somewhat supported means by which it was possible to implement your own private allocation routines within the CLR. As of 0.2.4 and as another first for Nighthawk in the implant space, Nighthawk now supports the possibility for .NET memory sleep encryption, using a custom allocator to protect and encrypt not only the executed .NET assembly but also any of its allocations during runtime. All allocations and modifications to page permissions take advantage of Nighthawk’s configuration strategy for syscall execution. In addition to this, when the assembly is passed to Nighthawk, the assembly metadata will be parsed and mangled before execution to further limit the risks of memory scanning.

In the video below, we show memory analysis of two beacons both executing Seatbelt, one with the CLR sleep encryption enabled and the other without:

Extra Life

A key design consideration in beacon development is the “in-process” vs “fork and run” model. With a fork and run model, you can afford to give much less consideration to the stability of your post-exploitation tooling because they will execute inside a surrogate process that exits on completion. This however comes at the price of OpSec, with the process of spawning a new surrogate, injecting in to it and capturing the output creating many points for detection.

However, when operating in a in-process architecture, null and invalid pointers, unhandled exceptions, executing unmapped memory and other subtle bugs in post-exploitation tooling can lead to instability in the beacon process. Nighthawk offers a number of harnesses to execute post-exploitation tooling in-process, including PEs (execute-exe), .NET assemblies (inproc-execute-assembly) and BOFs (execute-bof) and while we’ve attempted to implement rigid exception handling in each of the harnesses, it is difficult to ensure this is all encompassing.

With the 0.2.4 release we’ve now included a feature we’ve dubbed “extra life” in hommage to the awesome new Super Mario Bros film. When extra life is enabled, Nighthawk will deploy a hook to the exception dispatcher and a custom exception handler to unwind any threads in the process. Should an unhandled exception occur that would normally result in unexpected behaviour and potentially process instability, Nighthawk will attempt to catch the exception and revive the beacon by reloading a copy of itself in-process. This feature brings significant confidence to the in-process model, in particular when executing an array of different post-exploitation tooling.

Extra life is available by configuring the extra-life configuration option, which supports three different options, inprocess, spawn or inject, which will load Nighthawk in the current process, by spawn injecting or via cross process injection.

Let’s take a look at extra life in action when touching invalid memory using a “bad” PE with our execute-exe harness:

Reverse Port Forward

In our 0.2.2 release we added one of the features most requested by our customers, a reverse port forward. This post-exploitation features allows traffic routed from the beacon network to be sent over the c2 channel and out of the teamserver to an arbitrary location. Although it can be helpful for many things, this feature is particularly useful in authentication coercion attacks which are becoming ever popular (we did a Twitter thread about some of these recently:

Exploitation of classic SMB relaying with Nighthawk therefore might look something like this:

To start a reverse port forwarding session, Nighthawk now supports the rportfwd-start which takes the bind interface, port and forward host/port as arguments. Let’s take a look at this in practice:

Hidden Desktop Improvements

In November’s 0.2.1 release we introduced the Hidden Desktop, a post-exploitation feature that allows you to create a virtual desktop on the user’s endpoint and interact with thick client applications while remaining invisible to the user. This feature has been a game changer for many of our users as it allows them to take advantage of the user context to interact with thick client applications. There are however some considerations when using the hidden desktop, including the use of browser applications. Due to how many browsers broker their processes, opening a new instance of the browser could inadvertently lead to a tab being spawned on the real user’s desktop if they had the browser open. This is clearly less than ideal, as such with 0.2.2 we introduced a new configuration option to hidden desktop, alongside a new custom start menu painted by Nighthawk. The custom start menu contains start items for spawning a variety of browsers which when clicked, would lead to the user’s browser context being cloned on disk and the cloned profile being used by the hidden desktop browser. This now provides the benefits of leveraging the real user context, including session cookies and saved credentials, for browsing. In addition to this, we also made some minor improvements to the hidden desktop, including support for non-standard taskbar locations.

In the video below, we use the hidden desktop to access Chrome as the user which remains invisible to them:

Token Querying

Another feature that was frequently requested by our customers was the ability to retrieve some basic information about a token. That is, if a token has been stolen and retained in the Nighthawk token store using the steal-token command, it may be valuable to find out more information about the token such as the domain and user it belongs to or when the token expires. In the 0.2.2 release we added a new query-token command that will retrieve information about a token based on its handle, an example of this is shown below:

Shared Credential Store

Another highly requested feature was the ability to save credentials captured during the op inside a store shared by all operators. In our 0.2.2 release we added the credential store to the Nighthawk UI. This store allows operators to manually add any credentials they discover such that they are recorded and accessible to all users in the operation. It also allows notes to be manually added to the credentials so additional context can be stored alongside the credentials:

Profile Linter Nighthawk is highly configurable, with a plethora of options available to the user to change the beacons behaviour or the c2 traffic. As such, the JSON configuration used by the beacon can be quite complex and error prone. In our 0.2.2 release we added a linter for the profile format to the supporting tools repository, allowing operators to validate profiles and c2 traffic match the expected format before deploying them.

Miscellaneous Minor Improvements

In addition to various bug fixes across the beacon, UI and API, several other minor improvements were introduced across these versions, including:

  • Added support for the X-Forwarded-For header to report external IP,
  • Added support for Cobalt Strike’s BOF download API,
  • Improvements to our syscall unhooking in both syswow64 and x64 processes,
  • Upgraded notes and colouring inside UI to be shared across all operators
updated_at 01-05-2023