Harnessing the Power of Cobalt Strike Profiles for EDR Evasion – Part 2

This blog post is a continuation of the previous entry “Harnessing the Power of Cobalt Strike Profiles for EDR Evasion“, we covered the malleable profile aspects of Cobalt Strike and its role in security solution evasion. Since the release of version 4.9, Cobalt Strike has introduced a number of significant updates aimed at improving operator flexibility, evasion techniques, and custom beacon implementation. In this post, we’ll dive into the latest features and enhancements, examining how they impact tradecraft and integrate into modern adversary simulation workflows.We will build an OPSEC-safe malleable C2 profile that incorporates the latest best practices and features. All codes and scripts referenced throughout this post are available on our GitHub repository. CS 4.9 – Post-Exploitation DLLs Cobalt Strike 4.9 introduces a new malleable C2 option, post-ex.cleanup. This option specifies whether or not to clean up the post-exploiation reflective loader memory when the DLL is loaded.Our initial attempt was to extract the post-exploitation DLLs within the Cobaltstrike JAR file: Upon checking for strings, nothing was detected as the DLLs are encrypted.When checking the documentation, we stumbled upon the POSTEX_RDLL_GENERATE hook. This hook takes place when the beacon is tasked to perform a post exploitation task such as keylogging, taking a screenshot, run Mimikatz, etc. According to the documentation, the raw Post-ex DLL binary is passed as the second argument. So we created a simple script, to save its value to the disk: Load the CNA script to the Cobal Strike client, and task the beacon to perform a post-exploitation task (this case a screenshot): Tasking the beacon with all the possible post-exploitation tasks, will provided us all the 10 post-ex DLLs: After extracting the DLLs, find all the strings within. We come up with the following set of profile configuration (shortened for readability) on preventing any potential static detection: The full profile with all the found strings can be found here. Note: It is highly recommended to replace the plaintext strings with something meaningful to the operator, since the changes will be outputted during or after the post-exploitation job. For example, in the image below we modified the string to show them in reverse during a port scan: Beacon Data Store Beacon data store allows us to stored items to be executed multiple times without having to resend the item. The default data store size is 16 entries, although this can be modified by configuring the stage.data_store_size option within your Malleable C2 profile to match your needs: WinHTTP Support Even though there is a new profile option to set a default internet library, we will not be including the option in our profile. The reason is that both libraries are heavily monitored from security solutions and there is no difference in terms of evasion between the libraries. What matters, is a good red team infrastructure which bypasses the network and memory detection.However, if you prefer to using a specific library (in this case winhttp.dll), the following option can be applied to the profile: CS 4.10 – BeaconGate BeaconGate is a feature that instructs Beacon to intercept supported API calls via a custom Sleep Mask. This allows the developer to implement advanced evasion techniques without having to gain control over Beacon’s API calls through IAT hooking in a UDRL, a method that is both complex and difficult to execute. It is recommended that you have the profile configured to proxy all the 23 functions that Cobalt Strike currently supports (as of 4.11). This can be done by setting the new stage.beacon_gate Malleable C2 option, as demonstrated below: The profile will also enable the use of BeaconGate where we later start playing with it. This is crucial, otherwise the changes will not be applied to exported Beacons. To get started, we need to work with Sleepmask-VS project from Fortra’s repository. If you prefer the Linux environment for development, you can use the Artifact Kit template instead. The BeaconGateWrapper function in /library/gate.cpp is where these API calls are handled. The following demo code checks if the the VirtualAlloc function is called. This enabled us to intercept the execution flow and add the evasion mechanism(s): The same can be applied for all the other supported high-level API functions. In this example, we are going to implement callback spoofing mechanism. Since the goal of this blog is to explain how the BeaconGate implementation works, we will use the HulkOperator’s code for the spoofing mechanism. The custom SetupConfig function expects a function pointer to spoof. This can be achieved by utilizing the functionCall structure. The functionPtr field holds the pointer to the WinAPI function you want to hook. To access the function’s name, you can use functionCall->function, and for the number of arguments, use functionCall->numOfArgs. Individual argument values can be retrieved via functionCall->args[i]. Here’s a proof of concept showing how the final code looks: Next time you export a Beacon, the spoof mechanism will be applied. The final implementation code can be found here. CS 4.11 – Novel Process Injection Cobalt Strike 4.11 introduced a custom process injection technique, ObfSetThreadContext. This injection technique, bypasses the modern detection of injected threads (where the start address of a thread is not backed by a Portable Executable image on disk) by making the use of various gadgets to redirect execution. By default, this new option will automatically set the injected thread start address as the (legitimate) remote image entry point, but can be additionally configured with custom module and offset as shown below: The option above sets ObfSetThreadContext as the default process injection technique. The next injection techniques servers as a backup when the default injection technique fails. This happens on certain cases (i.e. x86 -> x64 injection, self-injection etc.) CS 4.11 – sRDI with evasion capabilities According to Fortra, the version 4.11 ports Beacon’s default reflective loader to a new prepend/sRDI style loader with several new evasive features added. sRDI enables the transformation of DLL files into position-independent shellcode. It functions as a comprehensive PE loader, handling correct section permissions, TLS callbacks, and various integrity