Cobalt Strike Infrastructure Downtime - March 2024

 

The Cobalt Strike download infrastructure will be down for a short while on Wednesday 13th March for routine maintenance.

Work will begin around 15:00 GMT (10:00 EST). We expect the maintenance to be completed in under 30 minutes. Downloads and updates will be unavailable while this work is carried out. Apologies for any inconvenience that this maintenance causes.

Cobalt Strike Infrastructure Maintenance - January 2024

 

We will be making a small change to the Cobalt Strike infrastructure next week. This will not result in any downtime but will affect updates using old copies of the update application.

TLS Certificate Update

verify.cobaltstrike.com hosts a text file with SHA256 hashes for the licensed Cobalt Strike product and distribution packages for Windows, Linux and MacOS. The update application queries this server during the update process. One of the validation checks performed during an update is to check that the TLS certificate hashes pinned by the update application match the certificate on that server, as well as the one on download.cobaltstrike.com. If the values are not what the update application expects, it will warn you that the server cannot be trusted. This is by design, and is to ensure that you are getting the update from Fortra.

We will be updating the TLS certificates used by our infrastructure on Wednesday January 24th. You will need to download and extract the distribution package for your platform to get the latest version of the update program (20240112) in order to run warning-free updates after that date.

Out of Band Update: Cobalt Strike 4.9.1

 

Cobalt Strike 4.9.1 is now available. This is an out of band update to fix an issue that was discovered in the 4.9 release that we felt would negatively impact customers as they start to roll out the release and for which there is no straightforward workaround. We also took the opportunity to address a couple of other issues that were slated to be addressed in the 4.10 release. This update does not affect the 4.10 release which is underway and due to ship in early 2024.  

Post-Ex Loader Obfuscate and Cleanup Settings

We have fixed an issue whereby the default post-ex reflective loader was unable to apply the postex.obfuscate and postex.cleanup Malleable C2 options correctly. We also fixed a related issue that impacted UDRL developers due to the post-ex DLL’s CrtStartup routines. As a result of the above, we are also making a minor update to the UDRL-VS library available in the Arsenal kit. 

Data Store

The data store was not able to identify .NET assemblies when the post-ex.obfuscate Malleable C2 profile option was set to “true.” This issue has now been fixed. We also took the opportunity to update the console help for the data store command. This now provides more information on how to run BOFs and .NET assemblies from the data store. 

We apologise for any problems that these issues may have caused and we hope that we have addressed these issues before the majority of our users have put the 4.9 release into play on active engagements. If you notice any other issues with Cobalt Strike, please refer to the online support page, or report them to our support email address. Licensed users can download version 4.9.1 from the website. To purchase Cobalt Strike or learn more, please contact us

Cobalt Strike 4.9: Take Me To Your Loader

 

Cobalt Strike 4.9 is now available. This release sees an overhaul to Cobalt Strike’s post exploitation capabilities to support user defined reflective loaders (UDRLs), the ability to export Beacon without a reflective loader which adds official support for prepend-style UDRLs, support for callbacks in a number of built-in functions, a new in-Beacon data store and more.  

We intend to publish a few follow-up blog posts over the next couple of weeks to provide more detail on some of the changes in this release, so please keep your eye on the blog for those updates. If you haven’t subscribed to the technical mailing list for blog updates, it is worth considering doing that as well so that you don’t miss anything!  

Post-Exploitation Overhaul

Cobalt Strike’s post-exploitation capabilities have been given an overhaul, with support for prepend-style User Defined Reflective Loaders being added to the following post-exploitation DLLs: 

  • browserpivot 
  • hashdump 
  • invokeassembly 
  • keylogger 
  • mimikatz 
  • netview 
  • portscan 
  • powershell 
  • screenshot 
  • sshagent 

A new Aggressor Script hook, POSTEX_RDLL_GENERATE, has been added in order to implement this change, and replace the default reflective loader with a UDRL. Full details on this new hook and how it is used can be found in the documentation.  

It is important to note that UDRLs for Beacon payloads and post-exploitation payloads are very similar but have some subtle differences. Information on those differences, that relate to the loader entry function, the DLL’s entry point, the RDATA_SECTION pointer argument and the obfuscation start offset can be found in the documentation and should be carefully reviewed prior to making your own changes in this area. 

You can find an example implementation of a post-exploitation loader in the UDRL-VS kit in the Cobalt Strike Arsenal Kit. 

A new Malleable C2 option, post-ex.cleanup, has been added to specify whether or not to clean up the post-exploitation reflective loader memory when the DLL is loaded. We have also added the post-ex.transform-x64 and post-ex.transform-x86 blocks to the post-ex Malleable C2 block. Both new blocks support the strrep option, which replaces a string in all post-exploitation DLLs, and strrepex which replaces a string within a specific post-exploitation DLL. Valid DLL names are BrowserPivot, ExecuteAssembly, Hashdump, Keylogger, Mimikatz, NetView, PortScanner, PowerPick, Screenshot, and SSHAgent. For example:  

post-ex { 
    # cleanup the post-ex UDRL memory when the post-ex DLL is loaded  
    set cleanup "true"; 
    
    transform-x64 { 
        # replace a string in the port scanner dll 
        strrepex "PortScanner" "Scanner module is complete" "Scan is complete"; 

        # replace a string in all post exploitation dlls 
        strrep "is alive." "is up."; 
    } 

    transform-x86 { 
        # replace a string in the port scanner dll 
        strrepex "PortScanner" "Scanner module is complete" "Scan is complete"; 

        # replace a string in all post exploitation dlls 
        strrep "is alive." "is up."; 
    }
} 

You can find more information on this change in the documentation. 

Export Beacon Without A Reflective Loader 

Beacon can now be used without the exported reflective loader function when using UDRLs. This change also improves support for prepend-style UDRLs.  

The BEACON_RDLL_SIZE Aggressor Script hook is called when Beacon is being prepared and can now be used to remove the entire reflective loader space from the Beacon DLL. By returning a value of “0”, a Beacon without the reflective loader is passed to the BEACON_RDLL_GENERATE and BEACON_RDLL_GENERATE_LOCAL hooks. For example: 

# ------------------------------------ 
# $1 = DLLfilename 
# $2 = arch 
# ------------------------------------ 

set BEACON_RDLL_SIZE { 
    warn("Running 'BEACON_RDLL_SIZE' for DLL " .$1. " with architecture " .$2);    
    return"0"; 
} 

As a result of this change, the default BEACON_RDLL_SIZE return value has been changed from 0 to 5.  

Callback Support

We have had a number of requests from our users to make it easier to process the results of certain function calls. This is challenging due to the asynchronous nature of Cobalt Strike’s communications, but this has been addressed in this release by the addition of callbacks for a number of built-in functions. Callbacks are triggered following a response to a command by Beacon, and also when dealing with custom dialogs via dialog input and action button clicks.  

Support for callbacks has been added to the following Aggressor Script functions: 

  • bnet 
  • beacon_inline_execute 
  • binline_execute 
  • bdllspawn 
  • bexecute_assembly 
  • bhashdump 
  • bmimikatz 
  • bmimikatz_small 
  • bportscan 
  • bpowerpick 
  • bpowershell 
  • bpsinject 

In general, there are three types of techniques that can be used to deal with callbacks – anonymous closure, named closure, and lambda closure. 

An anonymous closure is useful when you want to keep a small amount of code inline with the caller. For example, logging output from a BOF to the Beacon console would look like this: 

alias cs_example { 
    # User setup code removed for brevity      
    beacon_inline_execute($bid, $data, "go", $args, { blog($1, $2); }); 
} 

A named closure is useful when you have a lot of code that you may want to reuse. In this example, we create a closure named “bof_cb”, which is executed when data is returned by the BOF: 

 $1 - bid, $2 - result, $3 - info map 
sub bof_cb { 
    # User defined code removed for brevity 
} 

alias cs_example { 
    local('$bid $data $args'); 
    # User setup code removed for brevity 
    beacon_inline_execute($bid, $data, "go", $args, &bof_cb); 
} 

A lambda closure is useful when you want to pass variables that would not be in scope using the previous examples. This example demonstrates how you are able to access the $test_num variable, which is in the scope of the cs_example alias: 

# $1 - bid, $2 – result, $3 - infomap, $4 - test_num 
sub bof_cb{ 
    # User defined code removed for brevity 
} 

alias cs_example { 
    local('$bid $file $test_num'); 
    # User setup code removed for brevity  
    binline_execute($bid, $file, $test_num, lambda({ bof_cb($1, $2, $3, $test_num); }, \$test_num); 
} 

Examples can also be found in a public Cobalt Strike GitHub repository, found here

Beacon Data Store

Along similar lines to the token store in the 4.8 release, we have added a Beacon Data Store that allows you to store BOFs and .NET assemblies in Beacon’s memory, allowing the stored items to be executed multiple times without having to resend the item. The Cobalt Strike client will automatically detect whether an object to be executed is already in the data store so there is nothing additional that you need to do on your part once an object is stored. Stored entries are masked by default, only becoming unmasked when used. It is also possible to store generic files in the data store which will be available for BOFs to use.  

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.  

data-store load [bof|dotnet|file] <name> [path] stores an item in the store. 
data-store unload [index] removes a stored item.
data-store list lists all items available in the data store. 

A number of BOF API functions have also been added to allow you to access and protect items that are stored in the Beacon Data Store:  

BeaconDataStoreGetItem(size_t index) returns a pointer to the specified item. The function will return NULL if no entry exists at the specified index. 
BeaconDataStoreProtectItem(size_t index) obfuscates a specific item in the Beacon Data Store. 
BeaconDataStoreUnprotectItem(size_t index) deobfuscates a specific item in the  Beacon Data Store. 
BeaconDataStoreMaxEntries() returns the maximum size of the Beacon Data Store. 

Beacon User Data 

Beacon User Data is a C structure that allows Reflective Loaders to pass additional data to Beacons. It is passed as a pointer to Beacon by calling Beacon’s DllMain function with a custom reasoning known as DLL_BEACON_USER_DATA (0x0d). This must be passed to Beacon before the standard DLL_PROCESS_ATTACH reason is invoked. It is not required to keep the structure in memory after the DLL_BEACON_USER_DATA call because Beacon copies necessary values from it during the call.  

A version number is contained in the structure to ensure backward compatibility between different versions of Beacons and Reflective Loaders. Newer Beacons will therefore be able to handle and utilize older Beacon User Data structures without crashing.  

Beacon User Data also allows a Reflective Loader to resolve and pass system call information to Beacon, overriding Beacon’s default system call resolver. The SYSCALL_API_ENTRY structure is used for each supported system call. The SYSCALL_API structure holds these entries. Each entry contains information on the jump address (depending on system architecture), the system call number and the address of the corresponding Nt* function. The jump address and system call number are required for indirect system calls, whilst the function address is required for direct system calls. If values are not specified, Beacon will fall back to the corresponding WinAPI call. If the system calls fields in the USER_DATA structure points to NULL, then the system call information is skipped.  

Beacon User Data also allows a Reflective Loader to pass a small (32 bytes) data buffer to Beacon, allowing users to specify and pass their own custom data. BOFs can retrieve a pointer to this data with the BeaconGetCustomUserData function.  

You can download beacon_user_data.h here and you can find a usage example in the UDRL-VS, which can be found in the Arsenal Kit.  

WinHTTP Support

Up until now, Beacon’s HTTP(S) listener has used the WinInet library by default. Based on feedback from a number of users, support for the WinHTTP library has been added.  

A new Malleable C2 group, .http-beacon, has been created. Additionally, a .http-beacon.library option has been added to allow you to set the default library used when creating a new HTTP(S) listener. Valid values are wininet and winhttp. If the new Malleable C2 profile option is not specified, new HTTP(S) listeners will continue to default to WinInet.  

The new http-beacon Malleable C2 profile group also supports variants, which can then be assigned to listeners. For example:  

http-beacon { 
    set library "winhttp"; 
} 

http-beacon "httplib-wininet" { 
    set library "wininet"; 
} 

http-beacon "httplib-winhttp" { 
    set library "winhttp"; 
} 

The default value in the Malleable C2 profile can be overridden via the new HTTP library option in the stageless payload generator, generate all payloads, and windows executable dialogs. For example:  

Support has also been added in a number of Aggressor Script functions, which have been updated to add support for the new optional library parameter. When the parameter is not specified, the default library value is resolved from the listener definition. When specified, the value must be either an empty string, $null, wininet or winhttp. The following functions have been updated to support this additional parameter: 

  • payload 
  • payload_local 
  • artifact_payload 
  • all_payloads 

Host Profile Support for HTTP(S) Listeners 

Cobalt Strike’s HTTP(S) processing has limitations. Whilst we will be reviewing this and plan to make other, impactful changes in a future release, we have identified and addressed a couple of limitations in the scope of this release. Specifically, up to now, callback host names are assigned to a single URI when the Beacon payload is generated, and HTTP(S) parameters and headers are defined at a profile or variant level. This means that all HTTP(S) traffic to that host looks very similar.  

We have addressed these limitations by adding a new Malleable C2 profile group – http-host-profiles. This allows you to define HTTP characteristics (URI, headers and parameters) that will be used for HTTP(S) communications for a specific host name. Dynamic (randomly selected) values are supported. Variants are used to define host profiles for multiple host names.

Dynamic data is surrounded by square brackets and supports a list of values (up to 32) separated by a pipe character. A single value will be randomly selected from the list of dynamic data values, per request. It can also be embedded in static data, randomising part of the string.

The host-name field is a fixed string that links the host profile to the matching HTTP Hosts field on the HTTP(S) listener dialog. 

Up to 10 values are supported for the parameter and header values in a single host profile get/post definition. Both options support dynamic data syntax. Parameters and headers defined in a host profile are added in addition to any parameters and headers defined in the applicable default or variant profile.  

Beacons support up to 8 host profile definitions per listener. A generated Beacon has space for 1024 bytes of host profile data in total. If multiple hosts are defined then they must all fit within 1024 bytes. 

You can find a Malleable C2 profile with an example http-host-profiles block here.

Inter-Client Communications 

This release sees the addition of Aggressor Script support for sending and receiving data between Cobalt Strike clients. Up until this point, the only way to share data between clients was via Cobalt Strike’s Event Log – for example, @Octoberfest73’s MemFiles uses this approach to share data between clients and this is an excellent example use case for this new feature.  

Three new Aggressor Script functions have been added to facilitate the firing and consumption of custom events:  

custom_event is used to broadcast a custom event to all Cobalt Strike clients.
Arguments are:  
$1 – the topic name 
$2 – the event data 

custom_event_private is used to send a custom event to a single, specific Cobalt Strike client.
Arguments are:
$1 – who to send the custom event to 
$2 – the topic name 
$3 – the event data 

custom_event_<topic-name> is fired when a client receives a custom event from another client.
Arguments are:
$1 – who sent the custom event 
$2 – the event data 
$3 – the time the event was sent 

BOF Updates 

A feature that we’ve had on our backlog for quite some time is to add a key/value store to Beacon, which is intended to be used as a persistent store between BOF executions. As we have had recent customer requests along those lines, we figured that now would be a good time to address this.  

Three new APIs have been added to Beacon to support this key/value store:  
BeaconAddValue(const char * key, void * ptr) allows you to add a memory address to a key. 
BeaconGetValue(const char * key) allows you to retrieve the memory address associated with a key. 
BeaconRemoveValue(const char * key) allows you to remove the key. Note that this will not do any memory clean-up; in order to prevent memory leaks, this clean-up should be handled by the BOF. 

We have also added a new API that can be used by BOFs to get information on Beacon such as the Beacon address, sections to mask, heap records to mask, the mask, sleep mask address and sleep mask size information: 
BeaconInformation(BEACON_INFO * pBeaconInfo) 

This API is particularly useful for the Sleep Mask BOF as it uses it to populate the BEACON_INFO data structure, and this information can then be passed to the evasive sleep implementation to provide size information that is required to hide the sleep mask BOF. The sleep mask kit in the Arsenal kit has been updated with these changes.  

Examples of these changes have been added to the bof_template project in the public Cobalt Strike GitHub

Whilst not part of the main product release, another relevant update that we recently released is the ability to debug and test BOFs without having to spawn a Beacon. The BOF-VS template was created and a blog post authored during the current release cycle, and I’m including a reference here to highlight that work. Following user feedback and questions around how the BOF-VS is licensed and how they can publish their own work, we have decided to move the BOF-VS out of the Arsenal kit and publish it in the public Cobalt-Strike GitHub to address those issues. 

Sleep Mask Update 

The sleep mask processing has been updated to mask the sleep mask code that is patched into Beacon.  

System Call Updates 

An update has been made to the system call support that was added in the 4.8 release. Support for direct and indirect system calls has been added for the following functions:  

  • DuplicateHandle 
  • ReadProcessMemory 
  • WriteProcessMemory 

Product Security Updates

A change has been made to authorization files so that they are no longer backwards compatible with older versions of Cobalt Strike. This means that the authorization file generated when you update to or install the 4.9 release will not work with any 4.8 versions that you may also need to use. Whilst this change should not affect the majority of our users, we do know that some users test newer versions before using them in engagements and could be impacted by this change.  

Licensed users that need an old (pre-4.9) authorization file can generate one here: https://download.cobaltstrike.com/authgen.slp 

Backwards Compatibility

While we are on the subject of backwards compatibility of the authorization files, I feel that this is a good opportunity to reaffirm that Cobalt Strike itself is not backwards compatible with previous versions. This is a subject that comes up frequently after each new release.  

If you want to put Cobalt Strike into play in an existing engagement, you need to stand up a new team server and new Beacons need to be started. Ideally, users would wait until new engagements are about to be started before switching to the latest release rather than attempting this in the middle of an existing engagement. This is, of course, up to you – but please be aware of the issues that may arise when doing this.

Other Updates

We have made a few other, smaller changes in this release. 

The listeners listed in the Listener Chooser are now listed by name, instead of presented in a random order. 

The about box has been given an update so that it’s more responsive when it is expanded. 

We have added support for spawning processes under the impersonated user security context.  

A new Malleable C2 option, sleep, has been added to match the sleep command syntax added in the 4.8 release. The new setting accepts both seconds/jitter values or using the new d/h/m/s/j syntax. For example: 

sleep 20 25 
sleep 1d 3h 15m 30s 50j 

Note that if the sleep value is set, the existing sleeptime and jitter values cannot be used. The settings are mutually exclusive. 

Java Support

Whilst we haven’t made any changes in this release, we just wanted to give our users advanced notice that we are planning to update the minimum supported Java version from Java 8 to Java 11 in the next release. Hopefully, this won’t negatively impact any of our users but this should give you enough time to factor this in, if you need to make changes to your environment.  

To see a full list of what’s new in Cobalt Strike 4.9, please check out the release notes. Licensed users can run the update program to get the latest version, or download version 4.9 from the website. To purchase Cobalt Strike or learn more, please contact us

Cobalt Strike 2023 Roadmap and Strategy Update

 

I blogged about the Cobalt Strike roadmap in March last year and while the fundamental tenets of our approach to R&D remain unaltered, a lot has changed behind the scenes over the past year or so. I try to engage with our customers on various platforms and over the past few months, I’ve been asked a lot of questions about our roadmap. My hope is that this blog post will help to answer some of those questions. As we have some major changes planned for the next 12-18 months, I’d like to spend a little time providing some insights into the current state of Cobalt Strike R&D as well as offering some transparency about our plans for 2023 and beyond.  

Cobalt Strike R&D Team

I mentioned in the roadmap update last year that we were planning on expanding the size of the R&D team. Over the past 12 months we have more than doubled the size of the team. We have added experienced software engineers to the core development team and built a research team that is dedicated to driving the product forward.

One of our more recent hires, William Burgess, is leading our research team. He will be playing a key role in shaping the future direction of the product, bringing his extensive experience in developing security tools to bear. A key part of his role is to provide technical guidance and help to define priorities for both research activities and main product releases. In addition to this, he will also be conducting his own research activities. He recently released a blog post on spoofing call stacks dynamically with timers and already has others in the pipeline.

Henri Nurmi is another recent hire and he brings both extensive red teaming and software engineering experience to the team. Henri was behind the token store change in the 4.8 release (which was an update on the version that he submitted to the Community Kit a while ago!). In addition to his work on the core product, Henri has also been working on several other items that we’ll eventually be releasing into the Arsenal Kit and blogging about. Jean-François Maes has been a team member for quite some time and while he is currently focussing on updating and improving our training material (as a certified SANS instructor, this is definitely in his wheelhouse) he is also continuing to perform research activities.

Several other new (and older) team members prefer to keep a lower public profile but are nonetheless helping to drive development of the core product, contribute to research, update product security and more. A recent example of this was the first post in a series revisiting the User-Defined Reflective Loader (UDRL) that accompanied a new addition to the Arsenal Kit.

It has taken a while to hire the team that we were looking for and build up some momentum on associated R&D tasks, but I feel that we’re in a really good place now. We are cognisant of the fact that we have customers with a wide range of expertise and skill levels and I feel we are now better able to cater to the needs of our customers. Things were relatively quiet while that was playing out but you can now expect to see more output on the blog, more tools in the Arsenal Kit, and more cutting-edge features in the main product releases. Fortra continues to invest in Cobalt Strike and I’m grateful for the support from our leadership team.

Collaboration

The Cobalt Strike R&D team is part of a wider team that we are actively collaborating with on multiple fronts. Fortra acquired Outflank in September last year and the two teams are working closely together, collaborating on research topics and looking at ways in which we can improve the interoperability between Cobalt Strike and Outflank’s OST. Users can benefit from the new Cobalt Strike/OST bundle and leverage tools within OST to help with their engagements.

We also work closely on research topics with the Core Security team. Some members of the Core Impact research team also work on Cobalt Strike research items and both teams look at ways to improve the interoperability between the products. We are also lucky enough to work alongside and collaborate closely with other members of the wider Core Security team such as Santiago Pecin, as well as exploit writers and other red teams and penetration testing teams across Fortra.

There is a huge array of talent right across the Offensive Security department within Fortra and we are all pulling in the same direction. It has taken a while to get this all ramped up but you will now start to see the benefits of this work – especially customers that own other offensive security products from Fortra (OST/Core Impact) in addition to Cobalt Strike.

Flexibility And Stability

The recent customer survey (thank you to everyone that responded) affirmed our belief that stability and flexibility are key features of the product and are very much something that our users value. They are the core tenets of our development philosophy and play a key role in our releases.

Cobalt Strike’s strategy around evasion has always been “evasion through flexibility” meaning that we want to provide you with tools that you can use to modify default behaviours. This approach was something that Raphael Mudge pioneered with the Artifact and Resource kits and is something that we continue to support via the Arsenal Kit. It is important for us to address the concerns of our customers and we are aware that “evasion through flexibility” only works when there is enough documentation and example code to simplify modifications to the tools that we provide. This was one of the reasons behind the UDRL-VS that we recently released into the Arsenal Kit. In addition to this, we will also continue to update the tools available in the Arsenal Kit – for example, the evasive changes made to the Sleep Mask Kit in the 4.8 release.

We are also acutely aware that Cobalt Strike’s Beacon has been widely signatured in recent years. We have a blog post coming out in the next week or two which will help address some of these concerns and we will continue to review this in future. Ultimately, I have every confidence that our research team will continue to ease the burden on our users with these efforts.

The focus on flexibility is also a key reason for the infrequent releases. As I mentioned, our users have told us that they want fewer releases to give them more time to test the product before putting it into service – due at least in part to the fact that we give them the ability to bring their own tooling to bear. 

Roadmap

It’s fair to say that we have a very ambitious roadmap for the next 9-12 months. I’m not going to go into a huge amount of detail, partly because I don’t want to risk over-promising and under-delivering (I’m being pragmatic, as our priorities may change), and partly because we do still like to keep our cards close to our chest to some degree at least. I would like to offer some degree of transparency into both our roadmap and strategy though. 

There are essentially three strands to our R&D activities over the coming months, all of which are underpinned by the varied research activities carried out by our research team. Main product releases are of course the focus, with the 4.9 release already being scoped out and features for subsequent releases already being planned as well. Secondly, we will be tackling some technical debt which will allow the product to gracefully evolve (i.e. it will allow us to bring in some ground-breaking changes without fundamentally changing what the product has grown to be). Thirdly, we are aiming to overhaul our update infrastructure which will allow us to make improvements to product security, as well as add some really impactful features later on down the line.

We have a lot of key updates on our backlog that we will start to address once we have completed the infrastructure migration. The migration will open up a number of different possibilities to evolve the product and offer our users some amazing new features. There is a lot more to come from us towards the end of this year and into 2024.

Main Product Releases

The 4.9 release is shaping up to be quite significant and while we’re still working on fleshing out the scope, a late Summer release is what we’re working towards at the moment.  We’re also currently planning a further release towards the end of the year. This release should also start to provide greater interoperability between Cobalt Strike and Outflank’s OST, which will be an ongoing development focus. 

Features requested and pain points expressed by our users all feed into our roadmap. Your feedback is paramount when considering the scope of each release. 

Technical Debt

There is a need for us to address some technical debt. This will provide a platform to evolve the product while we stay true to the fundamentals of the incredible product created by Raphael Mudge. We want to do the product justice and improve upon it, not tear apart Raphael’s legacy. This is always at the forefront of any change that we make. Tackling technical debt is a necessary part of the development process for any professionally maintained product, but not something that we talk about in the release blogs.

Addressing technical debt will allow us to evolve our product security measures. The changes that we have made over the last few releases have had a very real, demonstrable impact on malicious use of the software, but we need to continue to make improvements in this area. It will also allow us to address some pain points and feature suggestions that can’t currently be addressed. An example that I know will be popular is to “do something about Sleep”. We’re limited in what we can do right now but adding support for other scripting languages is definitely something that we can consider once we have made the necessary changes under the covers.

Update Infrastructure Migration

The migration of the Cobalt Strike update infrastructure is a huge undertaking and we will be collaborating with other teams within Fortra to roll this change out. One of the main drivers for the change is that it will allow us to make several key product security changes, although it does also provide us with a platform that we can use to evolve the product and bring several significant benefits to users as well. I will follow up in a separate blog post to go into those additional benefits in more detail when we are a lot further along as the migration will be an iterative process – but there will be a number of useful features that we are looking to include right from the off.

The first change of note is that we ultimately intend to deprecate the current download site and migrate to a new platform that will pull everything that users need into one place. This should eventually include software downloads, documentation, training material, a feature suggestion portal, the ability to submit technical support tickets and more. Ultimately, we have a raft of features that we intend build into the platform, giving users unprecedented levels of flexibility. As I said, more to come on that topic further on down the line. We have a lot of work to do before we get to those really innovative items. 

Another part of the migration is the deprecation of the current update process. We will be aiming to tighten up product security in a number of different ways as well as make it easier for users to provision their red teaming infrastructure. One change that we are planning to make in this area is the addition of API support to make the process of provisioning red teaming infrastructure via scripting much more straightforward and more secure.

We are also looking to make changes to how the product is licensed and how license keys feed into the update process. We’ve actually had some timely customer requests in this area (again, thanks to the customer survey) and we’ll be taking that into account.

We are carefully considering how to roll these changes out so that we don’t negatively impact users that are used to working in specific ways. These changes, along with others that we will be making to the new platform, will be positively impactful for users that choose to take advantage of them but won’t negatively impact users that can’t or don’t want to.  

Community

Before wrapping up this post, I wanted to mention our user community. We continue to add flexibility to the product and our users continue to take advantage of that to mould it into something that works for them. The real power of Cobalt Strike, and something that Raphael Mudge was passionate about, is the flexibility that allows our users to customise, extend and use their own tools as well as share them with other community members. This is where our incredible user community really shines and has helped shape the product into what it is today. We do not take our users for granted and it is your feedback and feature suggestions that continue to shape the direction of the product. Thank you for your support.  

One of the ways that we try to recognise the contributions of our user community is the Cobalt Strike Community Kit. There are hundreds of tools written by our user community that are scattered all over GitHub and the Community Kit was created to cultivate a number of those projects into one easy-to-reference area. There are over 100 projects listed, with more being added regularly. If you have a tool that you would like to submit, there is a submission link on the site that can be used for that.  

Feature requests can be submitted to [email protected] and we are always happy to talk to users on social media, Slack and Discord. 

Thank you again for your continued support.

Cobalt Strike 4.8: (System) Call Me Maybe

 

Cobalt Strike 4.8 is now available. This release sees support for system calls, options to specify payload guardrails, a new token store, and more.  

We had originally planned to get this release out late in 2022 but progress was stymied due to the 4.7.1 and 4.7.2 patch releases that we had to put out to fix vulnerabilities that were reported in the 4.7 release. We spent a few development cycles performing a security review of the code and working on some technical debt, and then it was the holiday season. It’s here now though, and better late than never!  

Before getting into the details of this release, I just wanted to mention that you should now start to see much more content from us to supplement main product releases. William Burgess recently released his first blog post since joining the Cobalt Strike team and he will be playing a key role in providing technical guidance on the future direction of the product. We have more blog posts and tooling coming over the next few weeks and months, starting with a series on UDRL development (the first of which should drop next week). Coming later in the year are some huge changes to Cobalt Strike itself. More details on that will come in a follow-up blog post soon. We know that our users are struggling with evasion and have reported other pain points. As I mentioned in my roadmap update last year, we have been aggressively building out our R&D team and while it’s taken a while to do that and get all of our ducks in a row, you’ll now really start to see the benefits of those behind-the-scenes changes. Now, back to the 4.8 release. 

System Calls Support

This release sees the addition of support for direct and indirect system calls. We have added support for a number of system calls, specifically:  

  • CloseHandle
  • CreateFileMapping
  • CreateRemoteThread
  • CreateThread
  • GetThreadContext
  • MapViewOfFile
  • OpenProcess
  • OpenThread
  • ResumeThread
  • SetThreadContext
  • UnmapViewOfFile
  • VirtualAlloc
  • VirtualAllocEx
  • VirtualFree
  • VirtualProtect
  • VirtualProtectEx
  • VirtualQuery

The stageless Beacon payload generation dialog has been updated to allow you to specify the system call method to be used at execution time. The available options are:  

None: Use the standard Windows API function
Direct: Use the Nt* version of the function
Indirect: Jump to the appropriate instruction within the Nt* version of the function

It is important to note that there are some commands and workflows that inject or spawn a new Beacon that do not allow you to set the initial system call method. Those commands/workflows are:

  • elevate 
  • inject 
  • jump 
  • spawn 
  • spawnas 
  • spawnu 
  • teamserver responding to a stageless payload request 
  • teamserver responding to an External C2 payload request 

The stage.syscall_method in the MalleableC2 profile controls the method used at execution time, and you can use the syscall-method [method] command to modify the method that will be used for subsequent commands. Additionally, syscall-method without any arguments will query and return the current method.  

System call support is something that we intend to continue to update and enhance in future releases. Your feedback on this is welcomed.  

Generate Payloads With Built-In Guardrails 

Support has been added for payload guardrails, which can be set at the listener level and then, if required, overridden when generating a payload.  

Guardrails can be set based on the following criteria: 

  • IP address: This can be a single IP address or a range using a wildcard to replace the rightmost octet(s). For example, 123.123.123.123, 123.123.123.*, 123.123.*.* and 123.*.*.* are all valid inputs. 123.*.123.* is not. 
  • Username: This can be a specific user name, or you can prefix/suffix a wildcard (i.e. *user or user*). The username field is case insensitive.  
  • Server name: Again, this can be a specific server name, or you can prefix/suffix a wildcard (i.e. *server or server*). The server name field is case insensitive. 
  • Domain: As with username and server name, the domain field can either be a specific domain or you can prefix/suffix a wildcard (i.e. *domain or domain*). The domain name field is also case insensitive.

The listener dialog has a new “Guardrails” option at the bottom of the screen that allows you to set and update guardrails for that listener.  

When generating a payload, the guardrails value from the associated listener is used as a default value.  

You can use the default values or override them to set specific values for the payload being created. Setting specific values here does not change the default values set at the listener level.

Multi-Byte Support For Obfuscating Beacon’s Reflective DLL’s Import Table

We have made a change to the obfuscation routine used for the stage.obfuscate MalleableC2 option which relates to how Beacon’s Reflective DLL’s import table is obfuscated.

Part of this process involved moving from a fixed, single byte XOR key to a randomly generated multi-byte XOR key. The single byte XOR mask was easily signatured and caught by tools such as YARA. Moving to a randomly generated multi-byte XOR key should help address those issues. 

Sleep Mask Updates

A number of updates have been made to the Sleep Mask. The main change is that the Sleep Mask size limit has been increased from 8192 to 16384 bytes. Other changes include: 

  • Support for the use of system calls with the MASK_TEXT_SECTION capability
  • The addition of define tags for the Windows API functions to remove the need for LIBRARY$Function syntax
  • The implementation of evasive sleep via stack spoofing (x64 only). Related changes include the addition of a bypass for Control Flow Guard (CFG), as well as the addition of a helper utility (getFunctionOffset)

Token Store

One change that we’ve had on the backlog for a while was the addition of a token store, to facilitate the hot swapping of access tokens. Windows tokens are process specific; hence each Beacon has its own token store with its own tokens. Please be aware that those tokens are therefore only available to be used by that specific Beacon.

The token store is based around the new token-store command. The command supports a number of options that perform specific functions (all supported by tab completion). Available functions are as follows:

token-store steal [pid,…] <OpenProcessToken access mask>
This steals the token(s) from the specificed PID(s). Use commas to separate each PID. This command will steal the token and put it into the token store, but will not impersonate straight away. The steal-and-use command should be used for that purpose (although it should be noted that steal-and-use only supports a single PID). This command supports the optional OpenProcessToken access mask like the existing steal_token command. 

token-store use [id]
This tasks Beacon to use the token with the specified ID from the token store.  

token-store steal-and-use [pid] <OpenProcessToken access mask>
This allows you to steal the token from the specified PID, add it to the token store and immediately use it. This command supports the optional OpenProcessToken access mask like the existing steal_token command. 

token-store show 
This displays the tokens in the token store. 

token-store remove [id,…]
This allows you to remove the token(s) corresponding to the specific ID(s) from the token store. Use commas to specify multiple IDs.  

token-store remove-all 
This removes all tokens from the token store. 

One additional point is that tokens can also be stolen via the process list in the GUI. Steal a token in the usual way (i.e. Explore -> Process List, select one or more PIDs and click on Steal Token) and then make sure the “store token in the token store” checkbox is checked before stealing the token. You are also able to select multiple Beacons at once before opening the process list.  

Finally, we have also implemented corresponding aggressor functions to the options described above, i.e.:  

  • btoken_store_remove 
  • btoken_store_show 
  • btoken_store_steal_and_use 
  • btoken_store_steal 
  • btoken_store_remove_all 
  • btoken_store_use 

ETW Blinding 

This release also sees the addition of support for ETW blinding via patching for the execute-assembly and powerpick commands. While there is limited support in this release, this is something that we will look to build on in future releases.  

The execute-assembly and powerpick commands now have an optional PATCHES parameter, specified as follows: 

execute-assembly “[PATCHES: [patch-rule] [patch-rule] [patch-rule] [patch-rule]]” [/path/to/file.exe] [arguments] 

and  

powerpick “[PATCHES: [patch-rule] [patch-rule] [patch-rule] [patch-rule]]” [commandlet] [arguments] 

The optional PATCHES parameter can modify functions in memory for the process. Up to four patch-rule rules can be specified (delimited by spaces), with each patch-rule being made up of a library, function, offset and hex patch value, for example: [library],[function],[offset],[hex-patch-value], where:

  • library can be 1 – 260 characters  
  • function can be 1-256 characters 
  • offset is the offset from the start of the executable function and can be 0 – 65535 
  • hex-patch-value can be 2 – 200 hex characters (0 – 9, A – F) and the length must be and even number (hex pairs)

Further information on the patch-rule syntax can be found in the documentation.  

Sync Data At Teamserver Startup 

There has been a long-standing issue within Cobalt Strike whereby any data retrieved from a target (for example, screenshots, keylog data etc.) is unavailable in the client after the teamserver is restarted. This issue has been addressed, and data that was previously “lost” to the UI is now persisted between restarts.  

We have also added a new script, clearteamserverdata, that can be used to delete all data after an engagement has completed. 

Change How License Expiration Date Is Processed 

A key update related to product security is a change to how the license expiration date is processed. Previously, the expiration date was checked at teamserver startup and if it was valid, the teamserver was able to start. No further checks were performed and the teamserver was able to run until shut down by the operator.

We have tightened this processing up so that the license expiration date is checked on a daily basis. The reasoning behind the previous behaviour was that it wasn’t always convenient or logistically possible to run an update in the middle of an engagement (to grab a new authorization file with an updated expiration date). Nor was it convenient under those circumstances to restart the teamserver following an update. We have added mitigations for those scenarios in the new processing, meaning that there will be no impact on operations while refreshing your authorization file. If you need to update your license while an engagement is running, please consult the documentation for information on how you can do this. We do recommend, however, that you consider your license expiration date before starting a new engagement and avoid this situation occurring, if at all possible.

To make sure that you don’t get caught out by an expiring license, we have added a couple of new banners to the client UI.  

Starting 45 days before your license is due to expire, a warning banner will appear in the client, informing you that your license is expiring and when it is due to expire. This warning message can be dismissed but will reappear each day when the expiration date is checked. This should provide sufficient time to renew your license key if this has not already been taken care of:

If you fail to renew your license before it expires, you will have a 14-day grace period in which to do so. For the duration of that grace period, you will see an error banner that cannot be dismissed:

After the grace period has ended, if your license has not been renewed and the authorization file refreshed, the teamserver will shut down and you will be unable to restart it until you have renewed your license.  

Quality Of Life Changes 

In addition to the features already mentioned, we have also added a number of smaller changes, mainly requested by our users, as follows:

Added Flexibility To Specifying Sleep Time

A small change requested by a user was to make the sleep time easier to set. Rather than only being able to specify the sleep time in seconds, you can now also specify days, hours and minutes by suffixing those values with “d”, “h” and “m” respectively.  

A usage example is sleep 2d 13h 45m 8s 30j which translates to “sleep for 2 days, 13 hours, 45 minutes, 8 seconds with 30% jitter”. 

We have also added a new aggressor function, bsleepu that works in the same way.  

Display Current Token In The UI

Another user request was to display the current token in the client UI. This gelled nicely with the new token store and you are now able to see the current token the table view and status bar in brackets alongside the user name.  

Related to this change, we also addressed the issue whereby make_token would report the wrong user name (i.e. the user name of the current Beacon process) due to a Windows API limitation. This has been addressed and the correct username appears in brackets.   

Copy/Paste From The Beacon Output Pane 

We have added support for copying and pasting commands from the Beacon output pane.  

CTRL+C copies and CTRL+X cuts the selected text from either the output pane or the command line. Text can only be selected in the output pane or command line, not both. CTRL+V pastes text from the clipboard onto the command line. This works for any console window (for example, the Beacon console, SSH console, script console, event log and web log).  

Chain Multiple Commands In A Single Mimikatz Call 

The mimikatz command has been updated to support chaining multiple commands in a single operation. This also applies to the bmimikatz and bmimikazt_small aggressor functions (although bmimikatz_small is limited to lsadump::dcsync, sekurlsa::logonpasswords and sekurlsa::pth).  

Commands can be chained by adding a semicolon as a delimiter between commands, for example:
mimikatz standard::coffee;standard::coffee  

Note that the semicolon can still be escaped if it is required in a command (i.e. “\;”). Also, the command length is limited to 511 characters to ensure that the final character in the string is EOS (\0).  

Specify Exit Function On Stageless Windows Executable Dialog

A change was made in the 4.7 release to allow you to specify the exit option (either “thread” or “process”) on the Stageless Payload Generator dialog.  A similar change has now been made to the Stageless Windows Executable dialog that also allows you to specify the exit option (“thread” or “process”).  

Arsenal Kit Checksum

One final change to mention, again requested by a user, was to add a checksum for the Arsenal Kit. This has been done and it can be found at https://download.cobaltstrike.com/scripts .

To see a full list of what’s new in Cobalt Strike 4.8, please check out the release notes. While licensed users can run the update program to get the latest version, we recommend that you download version 4.8 from scratch from the website to get the new update application. This is because the TLS certificates on download.cobaltstrike.com and verify.cobaltstrike.com will be updated soon, and the existing updater will report errors if it isn’t updated. To purchase Cobalt Strike or learn more, please contact us

Read the latest release blog:

Out Of Band Update: Cobalt Strike 4.7.1

 

Cobalt Strike 4.7.1 is now available. This is an out of band update to fix an issue discovered in the 4.7 release that was reported to be impacting users, and for which there was no workaround. We also took the opportunity to address a vulnerability that was reported shortly after the 4.7 release, along with mitigations for potential denial-of-service attacks.

Sleep Mask Issue

An issue was reported whereby when stage.sleep_mask is not set (i.e. set to false), Beacon will still allocate space for the sleep mask BOF in memory. This issue has now been fixed.

CVE-2022-39197

An independent researcher identified as “Beichendream” reached out to inform us about an XSS vulnerability that they discovered in the teamserver. This would allow an attacker to set a malformed username in the Beacon configuration, allowing them to remotely execute code. We created a CVE for this issue which has been fixed.

As part of this fix, a new property has been added to the TeamServer.prop file (located in the home folder of the teamserver):

limits.beacons_xssvalidated specifies whether XSS validation is performed on selected Beacon metadata. By default, this is set to true.

Denial-of-Service Mitigations

We were also made aware of the potential to conduct a denial-of-service attack against the teamserver itself. While this can be mitigated by good OPSEC (using a redirector, turning staging off and so on), we have made updates to mitigate this type of attack.

A number of new properties have been added to the TeamServer.prop file as part of the mitigations:

limits.beacons_max sets a limit on the total number of Beacons that the teamserver will support. The default is 500. To turn this off (support an unlimited number of Beacons), use 0.

Three additional settings allow you to set a threshold rate for adding new Beacons (how many new Beacons can be added in a specific time period):

limits.beacon_rate_period specifies the time period (in milliseconds) during which the number of Beacons added is monitored and limited.

limits.beacon_rate_maxperperiod specifies how many new Beacons can be added in the specified time period.

limits.beacon_rate_disableduration specifies how long the teamserver will ignore additional new Beacons for if the number of new Beacons exceeds the limit in the given time period.

Example

limits.beacon_rate_period is set to 3000, limits.beacon_rate_maxperperiod is set to 50 and limits.beacon_rate_disableduration is set to 600000. If more than 50 new Beacons are added in a 3 second (3000ms) time period, any additional new Beacons added in the next 10 minutes (600000ms) will be ignored.

We apologise for any problems that these issues may have caused. If you notice any other issues with Cobalt Strike, please refer to the online support page, or report them to our support email address. Licensed users can run the update program to get this version, or download version 4.7.1 from scratch from the website. We recommend taking a copy of your existing Cobalt Strike folder before upgrading in case you need to revert to the previous version. To purchase Cobalt Strike or learn more, please contact us.

Cobalt Strike 4.7: The 10th Anniversary Edition

 

Cobalt Strike 4.7 is now available. This release sees support for SOCKS5, new options to provide flexibility around how BOFs live in memory, updates to how Beacon sleeps and a number of other changes that have been requested by our users. We’ve also given the user interface a bit of a refresh (including support for the much-requested dark mode!).

In recognition of Cobalt Strike’s 10th anniversary, I’d like to say a sincere thanks to all of our users for your continued support over the years – from the very first version created by Raphael Mudge, through the acquisition by Fortra (the new face of HelpSystems) and up to today and beyond. When I first met Raphael, he impressed upon me how unique and special Cobalt Strike’s user community is, and I’m reminded of that every day – from interactions on social media, to submissions to the Community Kit and all of the great (and to be honest, sometimes not so great!) feedback that we receive. Cobalt Strike wouldn’t be where it is today without your support and constant feedback, so thank you. Here’s to the next 10 years!

A Word About Evasion

Before getting into the details of the 4.7 release, I’d like to spend a little time talking about what isn’t in the release. We’ve had a lot of feedback over the last few months that Cobalt Strike is being aggressively fingerprinted, and this is making it difficult to bypass AV and EDR tools. This is making things particularly difficult for teams that don’t have the time to develop their own tools, and you may have been expecting changes in the 4.7 release to push back on this. However, as I mentioned in a blog post about our roadmap back in March, we aren’t going to be adding any out of the box evasive measures to the core Cobalt Strike product (and just to avoid repeating myself, please do read the blog post as it goes into depth about why that’s the case). That isn’t to say that we aren’t doing anything at all–of course we take this seriously, and of course we are focussing our efforts on making improvements. Our main product releases will continue to add flexibility, make changes to the product requested by our users, and keep things stable. Meanwhile, our growing research team will focus on adding new and updating existing evasive tools to the Arsenal Kit outside of the main release cycle, keeping things moving without affecting or making you wait for main product releases. This should work out much better for you, our users, in the long term. Rather than waiting for main product releases, you should start to see regular releases of, and updates to, the evasive tooling that you need in the Arsenal Kit.

Fortra continues to invest in both the development team and the research team. We recently released a Thread Stack Spoofing tool into the Cobalt Strike Arsenal Kit and we have a number of other tools currently in development that we are expecting to release over the next few weeks, filling in the gap between now and the 4.8 release at the end of the year. The reason for this aside is to reassure you all that we are acutely aware of the issues that you’re facing and while the 4.7 release itself doesn’t contain a raft of tools to address issues around evasion, we are taking this seriously and already working on this in the background. Thank you all for your patience as our research team finds their feet and research efforts ramp up.

Now, back to the details of the 4.7 release. That’s what you’re here for, after all.

SOCKS5 Proxy Server Support

This release sees the implementation of a popular feature request – support for SOCKS5. Rather than replacing SOCKS4a altogether, you can choose whether to use SOCKS4a or SOCKS5 when starting SOCKS. A number of changes have been made, including an update to the “Start SOCKS” dialog to enable you to choose between SOCKS4a and SOCKS5 (as well as enter required parameters if SOCKS5 is selected), an update to the Proxy Pivots table to display whether SOCKS4a or SOCKS5 is being used, updates to the commands to start and stop SOCKS in the Beacon console, and an update to the bsocks Aggressor Script command. For details on the new command line options, run help socks within a Beacon console. For general details of the changes, please refer to the documentation.

It is important to note that these changes currently only add support for DNS resolution and UDP. We have not added support for IPv6 or GSSAPI authentication in this release, because the feedback that we got from you is that those features aren’t critical. We will, of course, continue to monitor feedback and will add support for those features if and when you indicate that they are important to add. We also intend to make other changes in future releases, including decoupling SOCKS5 from Beacon which should improve both speed and reliability. That is a bigger change though, and our priority for this release was to add this initial support.

Adding Flexibility Around How BOFs Live In Memory

Beacon Object Files are a key feature for Cobalt Strike. We have added more malleability around how Beacon Object Files live in memory, which should make them more difficult to fingerprint. To facilitate this, two new Malleable C2 profile settings have been added:

bof_allocator controls how you allocate memory for your BOF. Supported settings are VirtualAlloc, MapViewOfFile and HeapAlloc.

bof_reuse_memory determines whether or not memory is released. If this setting is “true”, memory is cleared and then reused for the next BOF execution; if this setting is “false”, memory is released and the appropriate memory free function is used, based on the bof_allocator setting.

Memory permissions (RWX/RX or RW/RX) are set according to the values set in the new Malleable C2 profile settings above. The exception is HeapAlloc, which is always RWX.

Review Of BOF Usage Of VirtualAlloc RWX/RX Memory

Adding flexibility around how BOFs live in memory provided us with the means to address another item that we had on our backlog. We have added support for additional relocation types for BOFs, specifically the .xdata, .pdata, and .bss sections. This change firstly means that an issue has been resolved whereby BOFs sometimes wouldn’t run because the address offset was greater than 4GB. Secondly, the number of available dynamic functions has been increased from 32 to 64.

Sleep Updates

Changes have been made to the Sleep Mask Kit and around sleep in general.

The main change is that you are now able to override the method called when Beacon goes to sleep. From 4.4 through 4.6, Beacon would call the sleep mask function that was patched into the .text section. This had some drawbacks as you were limited on how the code could be written in the sleep_mask.c files used for writing BOFs, and there was also an issue related to size constraints. In this release, Beacon has been reworked to add support for all of the things that you can do in a BOF when it comes to sleeping. Not only do you now have the ability to use your own sleep function, but you are also now able to call dynamic functions (LIBRARY$function) and Beacon API functions (when the Beacon code isn’t masked).

There are two other benefits of this change worth highlighting:

Executable code is now no longer located within Beacon’s .text section and has instead been moved to a different memory region.

The sleep mask BOF size limit has been increased from 769 bytes to 8192 bytes.

Related to this, while the Arsenal Kit still supports the older versions of the sleep mask, this release adds support for implementing the sleep mask as a true BOF. You will need to pull the updated Arsenal Kit to be able to use this feature.

Steal Token Update

The steal_token function has been updated to enable it to steal tokens from processes that it previously couldn’t get to. A user reported that as Beacon used OpenProcessToken to request TOKEN_ALL_ACCESS, in some cases this returned an access denied error. Manually tweaking the permissions in Beacon when it called OpenProcessToken was enough for them to get steal_token to succeed.

We took this feedback on board and you are now able to customize the access mask when steal_token is invoked. A number of changes have been made to facilitate this:

A steal_token_access_mask option has been added to the Malleable C2 profile. This is optional and allows you to set a default access mask used for steal_token and bsteal_token.

Support has been added to allow you to set the access mask (and override the default value) when invoking steal_token and bsteal_token from the command line.

The Steal Token dialog has been updated to allow you to set the access mask (and override the default value). This applies when both a single process and multiple processes are selected before opening the dialog.

Note that if no default value for the access mask is provided (either via the new Malleable C2 profile option, dialog option, or command line options), steal_token will default to the current access mask of TOKEN_ALL_ACCESS.

Module Stomping Update

Based on user feedback, a small change has been made to module stomping. In some cases, although the module was loaded, the actual stomping failed because Beacon remained in virtual memory. This was because unless the exported function had an ordinal value between 1 and 15, Beacon would default to using VirtualAlloc. This limitation has now been addressed by adding optional syntax to the setting to specify the starting ordinal when searching for exported functions.

Clipboard Stealer

You are now able to steal the contents of the Windows clipboard on the target system via a command (clipboard) or an Aggressor Script command (bclipboard), with a caveat: this feature is only useful when the clipboard contains text (for example, credential material). This is a quick change and the intended use case is for those occasions where a target is observed using a password manager (or similar) to grab a password; you would then be able to copy that password (or other relevant material) from the clipboard for use. If there is text on the clipboard, this will be returned and displayed; if not, an error will be displayed informing you that the clipboard contents are not text based. The exception to this is that if the clipboard contents exceed 204800 bytes, an error will be returned instead.

While this is a quick change with limited scope, we will likely enhance this feature in a future release. There are a number of interesting directions that we could go with this and we’d be interested to hear your feedback.

User Interface/Default Aggressor Script Updates

This release brings a refresh to the look and feel of the client UI (although not the complete overhaul that we’re still considering for a future release), along with a number of changes to the default aggressor script that introduce some usability improvements. You may recognise some of the default Aggressor Script changes, as some of those changes were inspired by mgeeky’s “cobalt-arsenal” Aggressor Scripts (which incidentally can be found within the Cobalt Strike Community Kit). While we have also added our own changes and implemented some things in our own way, we would just like to say a huge thank you to mgeeky for permission to bring some of that functionality into Cobalt Strike itself.

We have made a number of changes in this area. Here are a few highlights:

Dark Mode

The most eye-catching change (and one of the most requested) is the addition of dark mode. This can be toggled via a new menu option.

Sleep Time Tracking

Sleep time tracking works by recording the sleep time for each Beacon and displaying it in a new column in the Beacon table view. This information is persisted between teamserver restarts so it should always be available.

Beacon Health Tracking

Linked to the sleep time tracking is a new Beacon Health tracking feature. This feature uses the sleep time and cross references this with the last check-in time to determine whether the Beacon is active, disconnected, or dead. This information is displayed in the Beacon table view and reflected in the Beacon’s icon. This feature can be enabled or disabled via a new option on the preferences dialog.

Icon Updates

Speaking of icons, we have updated the icons that are used on the pivot graph and in the Beacon table view to represent Beacon status and OS type.

Toolbar And Menu Updates

We have also updated the icons on the toolbar in the client and have removed toolbar buttons for some of the less popular functions. Related to this change, the main menu has been reorganised, flattening the menus and moving some of the options around into more useful and intuitive locations.

Bulk Payload Generation

Related to the menu reorganisation, we have added a new menu item to allow you to generate x86 and x64 stageless payloads for all available payload variants at once. A new Sleep function, all_payloads, has also been added to allow you to do this from the command line.

Stageless Payload Generator With Exit Option

We have added a stageless payload generator dialog that allows you to set either “thread” or “process” as the exit option.

Windows Error Code Resolution

Windows error codes are now automatically parsed and resolved, so you no longer need to memorise every single Windows error code or go and look it up when Beacon just returns the error code. The relevant error message is now displayed alongside the error code. We have also added a new Beacon console command (windows_error_code) and an Aggressor Script function (windows_error_code) that can be used to convert an error code to a message on demand.

Process List Display Updates

The output of the ps command has been enhanced to resolve parent/child relationships and display the process list as a treeview instead of the old, flat version. The Beacon process is displayed in yellow. We have plans to enhance this with more colour coding in a future release, too.

There are a number of other UI changes that have been implemented, including displaying more information in the Beacon and event status bars, displaying timestamps, making it easier to interact with Beacons, a new “import credentials” option, and much more.

To see a full list of what’s new in Cobalt Strike 4.7, please check out the release notes. Licensed users can run the update program to get the latest version, or download version 4.7 from scratch from the website. To purchase Cobalt Strike or learn more, please contact us.

Arsenal Kit Update: Thread Stack Spoofing

 

As I mentioned in the recent Roadmap Update blog post, we are in the process of expanding the Cobalt Strike development team and ramping up our research activities so that we can release more tools outside of the core product release schedule. We’re also acutely aware of Cobalt Strike’s limitations when it comes to EDR and AV evasion, and our research efforts at the moment aim to make improvements in that area. In that vein, a new tool is now available in the Cobalt Strike Arsenal that adds thread stack spoofing capabilities.

AV and EDR detection mechanisms have been improving over the years and one specific technique that is used is thread stack inspection. This technique determines the legitimacy of a process that is calling a function or an API.

Thread stack spoofing is not a new technique and there are several good examples of this technique that are already available. The research team would like to highlight mgeeky’s thread stack spoofer, which works well and was the catalyst for the team to look into their own implementation. To avoid confusion here, it’s worth pointing out that the research team used new concepts and techniques resulting from their own research activities to develop their own unique take on this technique, rather than using mgeeky’s implementation.

Full details on our implementation are included in the readme that accompanies the tool in the Cobalt Strike Arsenal. This information and the tool itself are only available to licensed customers. The Cobalt Strike Arsenal is accessed via a link in Cobalt Strike, or directly here.

Out Of Band Update: Cobalt Strike 4.6.1

 

Cobalt Strike 4.6.1 is now available. This is an out of band update to fix a few issues that were discovered in the 4.6 release that were reported to be impacting users and for which there was no workaround. This does not affect the 4.7 release, which is still on track to ship this summer.

Website Cloning

Two issues related to website cloning were addressed. An issue was introduced with the 4.6 release that caused all website cloning to fail, and we had a separate backlog issue that caused an error when cloning https websites. Both of these issues have been fixed.

Error When Using rportfwd_local

An issue was reported whereby when using rportfwd_local, any connection that entered the forwarded port caused the Cobalt Strike client to disconnect and reconnect with the teamserver. This issue has been fixed.

Workaround: glibc Dependency Issue

Some users have reported an issue when running on certain (mainly older) Linux distributions that causes the teamserver to fail to start due to a glibc dependency. We are currently looking into ways to update our build process to minimise the impact of this in the 4.7 release. While there is no fix available at the moment, we have documented a workaround. If you are affected by this issue, please refer to the steps in the Cobalt Strike documentation.

We apologise for any problems that these issues may have caused. If you notice any other issues with Cobalt Strike, please refer to the online support page, or report them to our support email address. Licensed users can download version 4.6.1 from the website. To purchase Cobalt Strike or learn more, please contact us.