主机发现和端口扫描的原理及实现

0x00 Introduction

作为一个合格的渗透测试人员,是不能过度依赖工具的,因为很多环境下是不能使用这些红队工具的。比如拿到的是一台内网机器,没有 nmap 怎么办?被防火墙拦截了怎么办?使用工具被蓝队发现了怎么办?

所以我们要有能自己写脚本的能力,前提就是要了解该工具的原理。原理摸透之后,不仅能自己实现,使用相应工具也会更加游刃有余。

这篇博客主要介绍的是主机发现和端口扫描的原理及实现,应对无法使用 nmap 的情况。

0x01 主机发现- ping 命令

首先来看看 ping 命令的参数:

重点关注 -c-W 两个参数,如果不指定参数,主机会一直发送 ICMP 报文,直到手动停止。

接下来就是写一个 bash 脚本,对该网段中的 ip 进行遍历,依次 ping 每个ip,查看回显,从而进行主机探测。

for i in {1..254}; do ping -c 1 -W 1 192.168.86.$i ; done

但是要从 1 遍历到 254,数据量比较大。想停止的话,按 Ctrl + C 不好用。这就涉及到对控制台信号的理解。Ctrl + C 是发送 SIGINT 信号给运行中的程序以尝试中断它,但以上语句是一个循环嵌套多个命令的脚本,而不是单个进程。即使当前的 ping 命令被中断,for 循环会继续执行并启动下一个 ping 子进程。正确做法是按下 Ctrl + Z 暂停脚本运行(发送 SIGTSTP 信号),然后使用 kill 终止:

kill -9 %1
// %1:最近的一条命令

我们可以先 ping 自己主机 ip 附近的几个 ip,查看开放和未开放的主机数据特征,然后根据相应的特征筛选。

for i in {126..130}; do ping -c 1 -W 1 192.168.86.$i ; done

根据开放主机的回显,可以将ttl作为过滤的关键词,bash 脚本如下:

for i in {1..254}; do ping -c 1 -W 1 192.168.86.$i | grep ttl; done

可以看到该网段存活的一些主机:

0x02 端口扫描- netcat

实现端口扫描需要旧版的 nc,而 kali 中默认安装的是新版 nc,因此要使用 nc.traditional,需要指定以下两个参数:

nc.traditional -vv -z 192.168.86.130 1-65535

同样也需要对输出信息进过滤。首先指定一个区间看看有没有开放的端口:

nc.traditional -vv -z 192.168.86.130 20-120

发现 111 是开放的:

那么就可以用关键词 open 过滤,也可以筛选没有 refused 字眼的:

nc.traditional -vv -z 192.168.86.130 1-65535 | grep -v refused
// -v:反向匹配

但是这样过滤是无效的:

需要添加2>&1将标准错误输出(stderr)重定向到标准输出(stdout),才可以对整个输出进行过滤:

nc.traditional -vv -z 192.168.86.130 1-65535 2>&1 | grep -v refused

这样就可以看到开放端口了:

0x03 端口扫描-伪设备

很多经典的语句和方法都是基于 bash 的,使用 bash 会更加稳定。而 Kali Linux中默认的shell环境是zsh:

我们需要输入 bash 字符调整为 bash 的 shell 环境。

bash 脚本如下:

for i in {1..65535}; do (echo < /dev/tcp/192.168.86.130/$i) &>/dev/null && printf "\n[+] The open port is : %d\n" "$i" || printf ".";done

[!NOTE] 脚本解读

  • /dev/tcp 是一种虚拟设备文件,通过访问 /dev/tcp/host/port,可以直接与目标主机和端口建立 TCP 连接。
  • < 是输入重定向符号,实际上只是触发连接尝试。
  • &>/dev/null 将标准输出和标准错误输出都丢弃,不会显示在屏幕上。
  • 如果端口连接成功,打印出开放的端口号。
  • 如果端口连接失败,执行 printf “.”。

0x04 Conclusion

要想真正掌握一门技术,一定要多思考背后的原理。不仅如此,也要慢慢提升自己代码能力,不能单纯依赖工具,还是要会自己编写脚本。