Last updated
Last updated
Beacon is also susceptible to being caught whilst it's running in memory. Some actions, such as lateral movement, will trigger these memory scans; but Defender also carries out routine scans against running processes. Therefore, the time between spawning your Beacon and the time to detection can vary greatly. You can see the "sms" label in the Defender UI, which indicates the alert originated from a memory scan.
Alternatively, Get-MpThreatDetection
labels them as behavior:_process.
Scanning the shellcode payload type with ThreatCheck can be a good way to help find these signatures because although the service binary artifact itself is "clean":
The raw shellcode is not:
This indicates to us that the signature(s) are targeting the reflective loader or the Beacon DLL. The Beacon source code is closed source, so we have no way to access or modify it directly. We could technically write a completely custom reflective loader through the UDRL kit, but that's out of scope for the RTO audience. The easiest way to make modifications to both of these components is by using what's exposed in Malleable C2.
These are the four simple settings that I recommend trying:
Setting userwx
to false tells the reflective loader to allocate memory for the Beacon DLL as RW/RX rather than RWX. Although this does not remove any indications from the Beacon itself, having RX memory is certainly less suspicious than RWX.
Setting cleanup
to true tells Beacon to free the memory associated with the reflective loader after it has been loaded. Once the Beacon is loaded, the reflective loader is no longer required and leaving it in memory just results in indicators sitting there waiting to be spotted. This allows the reflective loader to be freed, thus removing those indicators for the remainder of Beacon's lifetime.
Setting obfuscate
to true does a number of things but the most interesting is that it instructs the reflective loader to load Beacon into memory without its DLL headers. The omission of these headers reduces the number of indicators in memory, which will circumvent signatures target them specifically.
In all cases above, we can see that the "Use" column for Beacon's memory region is blank. This is because the DLL is reflectively loaded from memory, rather than being loaded from disk. Every other legitimate RX region in the process is backed by a DLL on disk, so this makes the Beacon stand out. Setting the module_x64 (and module_x86 for 32-bit payloads) tells the reflective loader to load the specified DLL from disk first and then overwrite the memory allocated for it with Beacon. This has the effect of making it appear as though Beacon's memory region is backed by a legitimate DLL. There are two caveats to consider when choosing a DLL to use.
The DLL size must be equal to or greater than Beacon.
The DLL must not be needed by the application hosting Beacon. This isn't a concern when executing the artifacts, but does become relevant when injecting Beacon shellcode into existing processes.