扫盲 netcat(网猫)的 N 种用法——从网络诊断”到“系统入侵

★招数1:(网络诊断)测试某个远程主机的【监听】端口是否可达

◇使用场景

经常有这种需求,要判断某个主机的监听端口是否能连上。
  导致监听端口【无法】,通常有两种原因:
其一,这个监听端口根本就【没开启】;
其二,监听端口虽然开启,但是被防火墙阻拦了。
  对第1个原因,(如果你能在该主机上运行命令)可以直接用 netstat 这个命令查看监听端口是否开启(不懂 netstat 命令的同学,可以看这篇博文)
  但对于第2个原因,netstat 就用不上了。这时候就可以用 nc 来帮你搞定。

◇方法

用如下命令可以测试某个 IP 地址(x.x.x.x)上的某个监听端口(xx)是否开启。

1
nc -nv x.x.x.x xx

上述命令用到了如下几个选项:

选项 -v
  如果你是 nc 的新手,俺建议总是带上这个选项——通过更详细的输出,能帮你搞明白状况。
  在本文后续的举例中,俺会尽量都加上这个选项(但这段话就不再重复唠叨啦)

选项 -n
  由于测试的是【IP 地址】,用该选项告诉 nc,【无须】进行域名(DNS)解析;
  反之,如果你要测试的主机是基于【域名】,就【不能】用“选项 -n”。

◇补充说明:超时设置

在测试链接的时候,如果你【没】使用 -w 这个超时选项,默认情况下 nc 会等待很久,然后才告诉你连接失败。
  如果你所处的网络环境稳定且高速(比如:局域网内),那么,你可以追加“-w 选项”,设置一个比较小的超时值。在下面的例子中,超时值设为3秒。
nc -nv -w 3 x.x.x.x xx

★招数2:(网络诊断)判断防火墙是否“允许 or 禁止”某个端口

◇使用场景

前一个章节(招数1)的场景是——已经有某个网络软件开启了监听端口,然后用 nc 测试端口是否可达。
  现在换另一个场景:
  假设你正在配置防火墙规则,禁止 TCP 的 8080 端口对外监听。那么,你如何【验证】自己的配置是 OK 滴?
  更进一步说:如果当前【没有】任何软件开启 8080 这个监听端口,你如何判断:该端口号是否会被防火墙阻拦?
  为了叙述方便,设想如下场景:
有两台主机——“主机C”充当客户端,“主机S”充当服务端。
然后要判断“主机S”上的防火墙是否会拦截其它主机对 8080 TCP 端口的连接。

◇方法

在“主机S”上运行 nc,让它在 8080 端口,命令如下:

1
nc -lv -p 8080

选项 -l
  这个选项会让 nc 进入监听模式。

选项 -p
  这个选项有“选项值”,也就是具体端口号。

然后在“主机C”上运行 nc,测试“主机S”上的 8080 端口是否可达(具体的命令行参见前一章节“招数1”)

◇补充说明:如何让 nc 的监听端口【持续开启】

在默认情况下,nc 开启 listen 模式充当服务端,在接受【第一次】客户端连接之后,就会把监听端口关闭。
  为啥会这样捏?因为当年设计 nc 更多的是作为某种网络诊断/配置工具,并【不是】真拿它当服务端软件来用的。
  如果你想要让 nc 始终监听模式,使之能【重复】接受客户端发起的连接,可以追加 -k 选项。

◇补充说明:UDP

上述举例是基于 TCP 协议。如果你要测试 UDP 协议,要记得【两边】的 nc 都要追加 -u 选项。

★招数3:(渗透测试)用 nc 玩“端口扫描”

◇使用场景

在“招数1”里面介绍了:如何测试【单个】端口是否可达。
  扩展一下:如果你要测试的不止一个端口,而是某个【范围】的端口。这种行为有个专门的术语叫【端口扫描】。
  “端口扫描”是一把双刃剑——“黑帽子”用这招进行信息收集,为后续的入侵做铺垫;“白帽子”用这招来进行“渗透测试”,以排查自己系统中【尚未屏蔽】的对外监听端口。
  作为一款牛逼的网络瑞士军刀,nc 当然可以用来干这事儿啦。
  顺便说一下:
不论是 TCP 还是 UDP,协议规定的【有效】端口号范围都是:1 ~ 65535

◇方法

下面这个命令,用来扫描 IP 地址为 x.x.x.x 的主机,扫描的端口范围从 1 到 1024

1
nc -znv x.x.x.x 1-1024

选项 -z
  意思是:开启“zero-I/O 模式”。该模式指的是:nc 只判断某个监听端口是否能连上,连上后【不】与对端进行数据通讯。
  选项 -n
  (前面已聊过,参见“招数1”)
  选项 -v
  -v 选项前面也聊过,这里要特地强调一下。
  对 nc 的其它用法,-v 选项是可加可不加滴;但对于“端口扫描”而言,一定要有这个选项——否则你【看不到】扫描结果。

◇补充说明:优化输出

玩“端口扫描”的时候,“-v 选项”会把“成功/失败”的结果统统打印出来。
  通常大伙儿关注的都是“扫描成功”的那些端口。因此,可以用如下命令过滤一下,只打印扫出来的端口。
nc -znv x.x.x.x 1-1024 2>&1 | grep succeeded
  由于“-v 选项”产生的输出位于【stderr】,上述命令中的 2>&1 用来把【stderr】合并到【stdout】(注:这种写法只适用于 POSIX 系统上的 shell)
  grep 命令用来进行【过滤】。对于 Windows 系统,默认【没有】grep 命令,需改用 find 命令过滤。

◇补充说明:超时设置

如果你要扫描的端口范围,跨度比较大,超时值要【恰到好处】——
超时值太大,会浪费时间;超时值太小,可能会遗漏某些端口(端口本身开放,但 nc 还没来得及连上就超时了)
  具体如何设置,参见“招数1”的“补充说明”。

◇补充说明:【并发】扫描

如果你设置了较小的超时值,依然嫌慢,还可以用【并发】扫描的方式,进一步提升效率。
  简而言之就是:同时运行多个 nc,分别扫描不同的端口范围。

★招数4:(隐匿性)如何让 nc 走暗网(以 Tor 为例)

◇方法

为了支持代理,nc 的“OpenBSD 变种”增加了两个选项:-X 与 -x

选项 -x
  该选项表示【代理的位置】,以 x.x.x.x:xxx 的形式表示(中间是【半角冒号】)。

选项 -X
  该选项表示【代理的类型】,含义如下:
选项值 含义
5 SOCKS5 代理
4 SOCKS4 代理
connect CONNECT 型的 HTTP 代理
  上述这几种类型的代理,功能上有啥差异,参见下面这篇博文开头部分的★预备知识章节。
《如何让【不支持】代理的网络软件,通过代理进行联网(不同平台的 N 种方法)》

首先,确保你本机已经运行了 Tor;
  然后,拿俺的域名测试一下。如果 nc 的输出中包含 succeeded(参见下面的第2行),说明 OK 啦——nc 已经能通过 Tor 联网。
nc -X 5 -x 127.0.0.1:9050 -q 3 -v program-think.blogspot.com 443

Connection to program-think.blogspot.com 443 port [tcp/https] succeeded!
◇补充说明:Tor 暗网的好处

关于 Tor 的用处/好处,俺在博客上重复唠叨的次数,已经数不清了。
  (简而言之)由于 Tor 暗网的线路会经历“三级跳”&“三重套”,而且其线路每隔10分钟就会【随机】变换一次。这种变态的玩法,可以让【网络层面】的逆向追溯变得非常非常困难。
  对这方面的更多介绍,参见:《关于 Tor 的常见问题解答》

◇补充说明:域名解析

当你用刚才的招数做到【nc over Tor】之后,一旦 nc 的网络行为需要解析域名,会自动通过 Tor 的 SOCKS 代理进行【远程域名解析】。
  也就是说,“DNS 协议”相关数据流也经过 Tor 暗网——这样既可以【防止】“域名解析”暴露你的网络行为,还可以避免 GFW 的“域名污染”。
  关于“DNS 协议”的引申阅读,可以看如下几篇:
《扫盲 DNS 原理,兼谈“域名劫持”和“域名欺骗/域名污染”》
《对比4种强化域名安全的协议——DNSSEC,DNSCrypt,DNS over TLS,DNS over HTTPS》

◇补充说明:设置别名(alias)

如果你比较懒,觉得每次都输入上述两个代理选项太麻烦,可以为 nc 设置一个【别名】(命令如下)
alias nc-tor=‘nc -X 5 -x 127.0.0.1:9050’
  设置好之后,你只要用 nc-tor 就可以自动追加代理选项。
  如果想让别名【永久】生效,要把上述命令加入到:你当前使用的 shell 的启动文件中。
  再次唠叨:“裸 Tor”与“Tor Browser”的监听端口有差异。俺上述命令的 9050 是用于“裸 Tor”。

★招数5(信息收集)用 nc 探测“服务器类型”和“软件版本”(以 SSH 为例)

如今要【远程管理】服务器,最常用的大概就是 SSH 这种方式了。
  如果某个服务器运行了 SSH 服务端(默认监听端口是 22),那么用如下命令可以看出:该服务器的操作系统类型,以及 SSH server 的版本。

1
2
Connection to 192.168.1.25 port 22 [tcp/*] succeeded!
SSH-2.0-OpenSSH_for_Windows_7.7

◇补充说明:批处理 & 自动化

某些“有心人”甚至可以搞一个脚本,批量探测某个 IP 地址段的 22 端口,然后把找到的服务器信息保存在某个文件中。
  另外,
  有的系统管理员会把 sshd 的监听端口从 22 改为其它数值,想要迷惑攻击者。但这么干,【效果不大】。
  攻击者可以先进行端口扫描,拿到所有已开启的 TCP 监听端口;然后利用上述方法,对这些 TCP 端口进行【自动化】探测,从而判断出哪个端口是 SSH Server。

◇补充说明:防范措施

本章节以“SSH Server”举例来说明入侵者如何探测服务端的软件版本。
  除了“SSH Server”,很多其它的服务端软件,也存在类似的【信息暴露】。
  一个谨慎的系统管理员,应该通过定制,【消除 or 伪造】这些信息,从而增加入侵者的攻击成本。

★招数7:(网络配置)基于 nc 的端口转发(Port Forward)

◇原理

用 nc 进行端口转发,需要运行【两个】nc 进程,一个充当“服务端”,另一个是“客户端”,然后用【管道】让把两个进程的“标准输入输出”交叉配对。所谓的“交叉配对”就是——每一个 nc 进程的“标准输出”都【对接】到另一个 nc 进程的“标准输入”。如此一来,就可以完美地建立【双向通讯】。
  玩过命令行的同学,应该都知道:大部分 shell 都支持【管道符】(就是那个竖线符号 |),可以把某个进程的标准输出,重定向给另一个进程的标准输入。但是 shell 的“管道符”只能做到“单向配对”,【无法】做到“交叉配对”。所以还需要再借助另一个管道——也就是“命名管道”。
  “命名管道”洋文叫做“named pipe”,是一种进程间通讯(IPC)的机制。顾名思义,“命名管道”就是有名号滴,而 shell 中使用的那个【管道符】,其本质上是“匿名管道”(无名管道)。
  主流的操作系统(Windows、Linux、UNIX)都支持“命名管道”这种机制。由于俺本人的环境是 Linux,下面只以 Linux 举例。

◇方法

步骤1:创建命名管道
  用下面这个简单的命令创建一个“命名管道”,其名称叫做 nc_pipe。(俺用这个名称只是为了举例,你也可以用别的名称)
mkfifo nc_pipe

步骤2:同时启动两个 nc
nc -l -p 1234 < nc_pipe | nc 127.0.0.1 5678 > nc_pipe
  运行上述命令之后,就可以把本机的 1235 端口重定向到本机的 5678 端口。

这个命令有点复杂。技术菜鸟如果看不懂,就算了(没关系滴,不影响你看后续的章节)。
  如果你比较喜欢刨根问底,俺稍微解释一下:
  上述命令行中,前一个 nc 充当【服务端】,后一个 nc 充当【客户端】。命令行中的“管道符”使得“服务端 nc”的输出绑定到“客户端 nc”的输入。然后再用 nc_pipe 这个命名管道做中转,使得“客户端 nc”的输出绑定到“服务端 nc”的输入。从而完成了【交叉配对】。

◇补充说明:如何让 nc 的监听端口【持续开启】

参见“招数2”章节中的“补充说明”。

1
netstat -an | grep "LISTEN"

招数9:(系统管理)用 nc 传输文件

◇使用场景

有时候,你需要在两台电脑之间传输文件。也可以用 nc 搞定。
  俺猜到某些技术小白会问:为啥不用 Windows 的共享目录?
  反驳的理由很多——
反驳1:这个玩意儿只能在 Windows 上用。
反驳2:为了使用“共享目录”,需要启用(Enable)系统中的好几个 service,这会增加你系统的【攻击面】。
反驳3:启用的 service 越多,占用的内容也越多,影响性能。

  还有些同学会问:为啥不用 FTP、SSH(或诸如此类的东东)?
  俺觉得:
1、如果只是临时传一个文件,还要额外再去装某某软件的客户端/服务端,岂不是很蛋疼?
2、任何服务端软件,(从某种意义上说)都是在【增加攻击面】。

◇方法

为了叙述方便,假设你有两台主机 A 与 B,你要把 A 主机上的文件 file1 传输到 B 主机上,保存为 file2

你先在【接收端】(B 主机)运行如下命令(其中的 xxx 是端口号)
nc -l -p xxx > file2

然后在【发送端】(A 主机)运行如下命令。
nc x.x.x.x xxx < file1
  第二条命令中的 xxx 是端口号,要与第一条命令中的端口号相同;第二条命令中的 x.x.x.x 是【主机 B】的 IP 地址。

◇补充说明:nc 的性能优势

用 nc 传输文件,相当于是:直接在【裸 TCP】层面传输。你可以通俗理解为:【没有】应用层。
  (不熟悉网络分层的同学,再去复习一下本文开头的 OSI 模型)
  如果你传输的文件【超级大】或者文件数量【超级多】,用 nc 传输文件的性能优势会很明显(相比“FTP、SSH、共享目录…”而言)

招数10:(系统管理)用 nc 远程备份整个磁盘

◇使用场景

当你学会“用 nc 传输文件”,还可以用 nc【复制整个硬盘】。
  无论是对“系统管理员”,还是对“入侵者”甚至是“数据取证人员”,这招都是蛮有用滴。

考虑到某些读者是“技术菜鸟”,俺稍微说明一下。
  “磁盘复制”【不同于】“在两块磁盘之间复制文件”。两者之间有很多差别,至少包括:
  性能差异——如果“源盘”上有非常多的小文件,“在两块磁盘之间复制文件”就会【非常慢】。
  完整性差异——“磁盘复制”可以确保两块盘的内容是完全一致滴。而如果你仅仅在两块磁盘之间复制文件,很多信息都损失掉了。
  一般来说,“系统管理员”和“入侵者”更看重第1个差异(性能);而“数据取证人员”更看重第2个差异(完整性)。

◇原理

为了传输整个磁盘,你需要用到 dd 命令。这玩意儿源自 UNIX,后来也移植到 Linux 和 Windows。
  俺曾经在如下博文中稍微介绍过 dd 命令的使用。
《如何用 ISO 镜像制作 U 盘安装盘(通用方法、无需 WinPE)》
  关于 dd 命令的更详细介绍,可以参见“维基百科”(这里)或“Gnu 官网”(这里)。

通过 dd 命令,你可以把“整个硬盘”(或者硬盘上的某个“物理分区”、“逻辑分区”)dump 成一个文件。
  在本章节,由于最终目的是要【跨主机备份磁盘】,所以并【不】需要真的把 dd 命令的输出保存成文件,而是把 dd 的输出通过管道符(|)重定向给【本机】的 nc,然后让【本机】的 nc 发送到另一台主机的 nc(参见前一个招数)。

◇方法

由于操作物理磁盘会涉及到操作系统的差异,下面俺以 Linux 举例。
  假设你要把 A 主机 /dev/sda 磁盘的【原始数据】整个复制到 B 主机的 /dev/sdb 磁盘。

你先在【接收端】(B 主机)运行如下命令(其中的 xxx 是端口号)
nc -l -p xxx | dd of=/dev/sdb

然后在【发送端】(A 主机)运行如下命令。
dd if=/dev/sda | nc x.x.x.x xxx
  第二条命令中的 xxx 是端口号,要与第一条命令中的端口号相同;第二条命令中的 x.x.x.x 是【主机 B】的 IP 地址。

◇补充说明:nc 的性能优势

如今的存储设备越来越大了。“磁盘”或者“分区”,动不动都是几百个 GB,这时候 nc 的【性能优势】就体现出来啦。
  (具体的原因,前一个章节已经分析过了)

招数11:(入侵手法)用 nc 开启【被动】连接型后门

既然聊 netcat,很自然地会聊到“黑客/骇客”的入侵招数。
  做这方面的介绍,并【不是】为了传授入侵技巧;而是为了——让那些注重安全性的同学,能做到“知己知彼”。

◇使用场景

假设1:你使用的浏览器存在某个安全漏洞,并且该漏洞会让攻击者获得【执行代码】的机会。
  假设2:你在某个公共场合使用某个 wifi 热点上网。遗憾的是,这个热点是攻击者设置的陷阱。
  假设3:设置该陷阱的攻击者,正好也知道:如何利用上述漏洞。
  当这三个假设都成立,攻击者就可以获得在你【本机】执行代码的机会。这时候,攻击者可以下载一个 nc 到你本机,然后用 nc 开启一个【被动】连接型后门。所谓的“【被动】连接型”就是指——nc 开启对外监听端口。
  在该场景中,因为攻击者与你处于【同一个局域网】,攻击者自然能从自己的机器访问到你本机的 nc 后门。

◇原理

为了让后门能工作,通常会使用 nc 的 -e 选项,该选项的“选项值”是一个可执行文件的路径。
  设置了该选项之后,当处于监听状态的 nc 接受到某个连接,会启动“选项值”对应的可执行文件(并得到某个进程),nc 会把该进程的“标准输入输出”与网络通讯【对接】。
  为了让这个后门用起来足够爽,攻击者通常会让 nc 去启动一个【shell 进程】。对 Windows 系统而言,就是 cmd.exe;对 POSIX 系统(Linux or UNIX)而言,就是 /bin/sh
  在这种情况下(nc 挂载 shell),攻击者远程连入 nc 的端口,就可以直接在这个 shell 上进行各种操作,其效果类似于 SSH 或(老式的)telnet。

◇入侵方法

步骤1
  如果受害者是 Windows 系统,只须如下命令就可以开启一个后门(其中的 xxx 是端口号)
nc.exe -l -p xxx -e cmd.exe
  如果受害者是 POSIX 系统(Linux or UNIX),则用如下命令:
nc -l -p xxx -e /bin/sh

步骤2
  后门创建好之后,攻击者在自己机器上也运行 nc(客户端 nc),然后连接到作为后门的 nc(服务端 nc)。一旦连上之后,攻击者就可以在自己的 nc 上看到对方(受害者机器)的 shell 提示符。

◇补充说明:-e 选项

据说是考虑到 -e 选项太过危险,nc 的 OpenBSD 变种(在多年前)已经【移除】了该选项。但其实捏,还是可以用间接的方式达到同样的效果(具体如何做,俺就不透露啦)。
  另,“原版 nc”依然有这个选项;nc 的很多其它变种,也依然有这个选项。

◇【不够】靠谱的防范措施

在这个场景中,大伙儿可能会想到三个值得改进之处:
1、浏览器的漏洞
2、使用公共 wifi 热点的习惯
3、防火墙的设置

对第1点
  其实是【无解】滴!因为任何人都无法确保浏览器是【零漏洞】;

对第2点
  要看每个人的具体情况而定。对有些人而言,“用公共热点上网”属于【刚需】。那就没办法了。

对第3点
  “防火墙”这招,似乎是比较通用的解决之道。对大部分人而言,桌面 PC 根本就【不必】开启对外监听端口。因此,你可以配置操作系统自带防火墙,禁止【所有的】对外监听端口。
  但是!(俺要开始说【但是】了)
  操作系统自带的防火墙,本身也运行在操作系统【之内】。如果你是以【管理员身份】遭遇入侵,入侵者在进行【代码执行】的时候,就已经具有了【管理员权限】。在这个权限下,入侵者完全有可能“搞定”防火墙。方法有很多种——
比如说:把用作后门的端口号,悄悄加入到防火墙的白名单中;
再比如说:直接把防火墙的过滤模块干掉;
更牛逼的入侵者,甚至可以在【网卡驱动】上做文章——因为网卡驱动位于防火墙的过滤模块【之下】(比防火墙更底层)

◇【靠谱】的防范措施——NAT 模式的虚拟机(Guest OS)

首先,这里所说的“NAT 模式”指的是【虚拟机的网卡模式】。如果你不熟悉虚拟机的网卡模式,建议先看俺写的《扫盲操作系统虚拟机》系列教程。

要想用这招,步骤如下:
1、当然先要安装【虚拟化软件】(VBox、VMware …),
2、安装一个虚拟的操作系统(洋文叫“Guest OS”)
3、虚拟系统的网卡设置为【NAT】模式

完成上述步骤后,你就可以在这个虚拟系统中上网。
  NAT 的好处在于【单向可见】。也就是说,Guest OS 可以访问到物理系统(Host OS)【外部】的网络环境;但外部网络环境只能看到 Host OS,看不到 Guest OS。
  在这种配置下,就算某个入侵者完全控制了你的 Guest OS,他/她也【没】办法在 Guest OS 中搭建“被动连接型后门”。换句话说,即使入侵者运行了这种后门,(但由于 NAT 的缘故)后门【无法】接受外部网络的连接,这个后门就【失去意义】啦。

◇补充说明:“NAT 模式”如何搭配“系统防火墙”?

上述“NAT 招数”与“系统防火墙”并【不】矛盾。
  也就是说,即使你用了这招,你的物理系统(Host OS)还是要配置系统防火墙,并禁止【所有的】对外监听端口。

https://program-think.blogspot.com/2019/09/Netcat-Tricks.html
https://program-think.blogspot.com/2016/03/GitHub-Security-Tips.html
https://program-think.blogspot.com/2019/09/Netcat-Tricks.html
https://program-think.blogspot.com/2013/11/tor-faq.html
https://program-think.blogspot.com/2009/09/break-through-gfw-with-tor.html
https://program-think.blogspot.com/2019/04/Proxy-Tricks.html