A Morning with Cobalt Strike & Symantec
Joff Thyer //
If you have been penetration testing a while, you likely have ended up in a Red Team situation or will be engaged in it soon enough. From a command channel perspective, the work that Raphael Mudge has put into Cobalt Strike makes it an attractive platform for teamwork. Unlike traditional methods of using things like Linux “screen” with PowerShell Empire, and/or Metasploit, Cobalt Strike allows for the setup of an operational attack infrastructure that further promotes real threat emulation possibilities.
One of the Black Hills friends in the community (Lee Kagan) contributed an excellent blog post which you can find at https://www.blackhillsinfosec.com/build-c2-infrastructure-digital-ocean-part-1/ detailing how to go about setting up Cobalt Strike with a threat emulation profile. (Part 2 is forthcoming, he promises.)
As a part of that post, it includes a link to a shell script that automates a portion of the setup such that the proper Cobalt Strike profile is created. This can be found from @KillSwitch’s GitHub repository https://github.com/killswitch-GUI/CobaltStrike-ToolKit/blob/master/HTTPsC2DoneRight.sh.
On some recent Red Team activities, I leveraged all of the above information with some nice custom domains, and my own unique DNS name server infrastructure all running within virtual machines at Digital Ocean. This allowed me to create an operational infrastructure that could properly provide either DNS, HTTP, or HTTPS command channels via an appropriately “matured” domain name with full threat emulation of Amazon-like web traffic. All of this using virtual systems with IP addresses not easily attributed back to myself.
I was feeling pretty good about this, and I set out on my adventure to deliver C2 payloads into the customer network. Now, in this case, the customer was actually happy to run some things for me thus removing the social engineering aspect of the test. My natural inclination was to jump towards PowerShell and/or executable content though I did need to be cognizant of endpoint protection solutions.
Some initial attempts at using executable content revealed that Symantec endpoint protection was at play and that certain things would fire a signature on the endpoint. Symantec (and others) have evolved some interesting changes in feature sets over time, some of which are effective, and some not so much. I do maintain a subscription to the non-enterprise consumer version of Symantec so I moved into research mode a while.
In terms of Symantec endpoint protection features, I mostly encounter the following obstacles during pentesting:
- Endpoint/host-based intrusion prevention (HIPS)
- Signature-based protection for executable content on disk
- Signature-based protection that appears to leverage the application compatibility toolkit (ACT) shim during the process creation pipeline.
- Memory-based detection of shellcode.
Given this knowledge, and the goal of proper threat emulation, I decided to set up three different scenarios with Cobalt Strike for some advance testing of Symantec endpoint protection responses. In these scenarios, I deliberately avoided both DLL/EXE content and any TLS channels. I wanted to focus on the HIPS and memory-based detection functionality of the defenses.
- Cobalt Strike team server with no custom HTTP/HTTPS profile and a listener on port 80 using HTTP.
- Cobalt Strike team server with an Amazon web server profile generated by the HTTPSC2DoneRight.sh script and using an HTTP listener.
- Cobalt Strike team server with a customized version of the Amazon HTTP listener profile.
The version of the Symantec software I was using for this test is shown in the following screenshots. Yes, it was fully up to date as of today.
All payloads for the above scenarios were generated as PowerShell commands from Cobalt Strike and pasted into a command shell on a test system. Cobalt Strike has either a 32-bit based shellcode or 64-bit based shellcode which can be generated.
The first discovery was that regardless of the server-side listener configuration, the 32-bit payloads would always generate an IPS alert and be blocked before any traffic reached the server. An example alert is shown above.
In the case of 64-bit payloads, a successful command channel session is established to the Cobalt Strike team server in two of the above use cases:
- No specific/custom profile at all with HTTP listener
- Highly customized profile with HTTP listener
The strangest case was the second scenario in which the HTTPSC2DoneRight.sh script was used to generate the Amazon-like profile. In this case with a 64-bit payload, I observed that the second binary stage of payload was delivered just fine. After that delivery comes to the initial HTTP GET request. The Amazon-like script above generates a GET REQUEST as follows.
What is completely bizarre is that the C2 Channel back to Cobalt Strike is NOT ESTABLISHED, but furthermore there is absolutely no output or feedback of malicious activity on the client workstation.
I decided to break out the packet sniffer and noted the payload delivery observation of the second stage, and then saw that connection requests were being immediately torn down with a TCP RESET when the client-side attempted the GET request above.
So then I decided to break out the sniffer for the same profile on the team server but on a client system with no Symantec endpoint protection installed.
Sure enough, as the below screenshot from Wireshark shows, the traffic went right on through as expected.
It becomes abundantly clear to me that the Symantec HIPS was blocking and resetting the TCP connection whenever the TCP stack attempted to transmit the above GET request, and that this must be a specific signature written to match the scripted Amazon profile.
Naturally, I decided to make a small change on the team server profile which replaced the original sequence of digits in the GET request with all 8’s instead. Note that this is a really minor change that would not even circumvent a well constructed regular expression and/or IPS signature with multiple matching criteria. I changed not a single other parameter for this test. Other parameters that could be dead giveaways included the host header, and certainly some fixed cookie values.
The result? Yes, you guessed right, one happy C2 session established.
In conclusion, while I think that endpoint protection suites are getting better in general, there is still a lot of work to be done for custom malware activity. In performing this testing work, I surmised that in a Symantec endpoint protection context:
- 64-bit shellcode delivered into memory with typical injection techniques still has a good chance of success.
- The HIPS functionality does not seem to inspect second stage shellcode delivery at all.
- Writing a specific HIPS signature in response to a widely published penetration tester threat modeling technique seems quite arbitrary but moreover is not an effective defense.
- Not informing the end-user of potential malicious activity is a “false negative”. Frankly, there is nothing worse than not knowing.
The lesson learned for penetration testers here is to not fall into the trap of trying to press the “Easy Button”. I know we are often in a hurry to get things done, but using canned scripts on the internet will end up getting you blocked in some form or another. This is clearly the case even if the canned script is well-intended threat modeling. Always review, and validate what you are about to do! Happy hunting folks.
You can learn more straight from Joff himself with his classes:
Regular Expressions, Your New Lifestyle
Enterprise Attacker Emulation and C2 Implant Development
Available live/virtual and on-demand!