The Sleep Mask Kit

The default sleep mask performs the following operations for Beacon:

Depending on the operation being performed Beacon will set up two parameters sleepMaskInfo and functionCall and call the entry point.

NOTE:

FUNCTION_CALL is NULL unless it is a beacon gate call.

void sleep_mask(PSLEEPMASK_INFO sleepMaskInfo, PFUNCTION_CALL functionCall);

The PSLEEPMASK_INFO, PFUNCTION _CALL, and additional data structures are large structures making it difficult to document in the user guide. Instead, examples will be provided to show how to customize your own sleep mask. The first example is provided in the Arsenal Kit and supports the same operations as the default sleep mask along with additional examples of other evasive operations that are not provided by the default sleep mask. The second example is provided in the Sleepmask-VS repo and will support the operations except for the cleanup memory along with changing the development environment to use Visual Studio to provide a different tool set.

Both examples define the data structures used by the sleep mask function in the sleepmask.h, beacon_gate.h, and beacon.h files. It is recommended to review these header files to understand the structures before going through the code.

To access the Arsenal Kit, go to Help -> Arsenal to download the Arsenal Kit which includes the Sleep Mask Kit. Your license key is required for this example.

For more information on the Sleep Mask Kit see the arsenal-kit/README.md and arsenal-kit/kits/sleepmask/README.md files.

Obfuscate Beacon

The operation to obfuscate beacon in memory will use a data structure named ALLOCATED_MEMORY which defines the memory locations for the PE sections of beacon. The code will process each section and mask or unmask the memory based on the information for the section.

Each PE section will have a memory protection set to RWX, RW, or RX, which depends on the ‘stage.userwx’ configuration setting.

When the setting is ‘true’ all sections will have the protection of RWX which will support masking and unmasking.

When the setting is set to ‘false’ all sections except for the ‘.text’ section will be set to RW which will support masking and unmasking. The ‘.text’ section will be set to RX which does not support masking and unmasking. In this case the ‘.text’ section will need to modify the current protection to RW prior to masking and back to RX after unmasking. To change the protection the standard Windows API VirtualProtect will be used. This operation is new with the 4.10 default sleep mask but has been available in the Arsenal Kit for previous versions.

In addition to the PE sections the memory allocated on the heap will also be processed. The heap memory locations are provided to the sleep mask through the BEACON_INFO data structure as a contiguous block of memory of HEAP_RECORD data structures. The memory block is terminated with a zeroed-out HEAP_RECORD entry.

If you are using a UDRL the memory protections on the sections are defined by the UDRL code as it does not have to honor the ‘stage.userwx’ setting.

Proxied WinAPIs

The sleep mask will also handle Windows API calls that are configured to use the BeaconGate. See Beacon Gate for a list of supported Windows APIs.

When a Windows API is proxied through the BeaconGate the sleep mask will perform the following steps.

  • Execute the obfuscate logic to mask beacon
  • Execute the Windows API call
  • Execute the obfuscate logic to unmask beacon
NOTE:

Masking/unmasking will be automatically disabled when you task Beacon to become interactive (< 3s) to avoid CPU spikes.

Cleanup on Exit

When the ‘exit’ command is used to terminate the Beacon session the sleep mask function will be called when the following conditions are configured.

  • The exit method is set to ExitThread
  • Module stomping is not configured
  • Beacon Gate is configured with All, Cleanup, or ExitThread

In this case Beacon will call the BeaconGate for the ExitThread Windows API. In the sleep mask function prior to executing ExitThread the code will call a function and release the memory defined in the ALLOCATED_MEMORY data structure which contains information about how the memory should be released.

In the ALLOCATED_MEMORY structure there is an ALLOCATED_MEMORY_PURPOSE field and when it is set to PURPOSE_SLEEPMASK_MEMORY that memory will not be released by the sleep mask function. This is because it is not possible to release the memory you are currently executing without doing something custom like using a timer.

When the exit method is set to ExitProcess then the process is terminated which will release all the memory and calling the sleep mask function is not necessary.

 

Related Topics