NMAP速查表

带上你的千军万马,即使最后难免孤军奋战。

阅读提要

全文约2.8W字,大致阅读完约20分钟,包含主要知识点:Nmap命令详解Masscan命令详解python调用Nmap,Masscan端口运行服务识别

功能

端口扫描:扫描开放的端口并且识别运行服务

主机探测:Nmap可査找目标网络中的在线主机。默认情况下,Nmap通过4种方式—— ICMP echo请求(ping)、向443端口发送TCP SYN 包、向80端口发送TCP ACK包和ICMP 时间戳请求——发现目标主机。

服务/版本检测:在发现开放端口后,Nmap可进一步检查目标主机的检测服务协议、应用 程序名称、版本号等信息。

操作系统检测:Nmap 向远程主机发送一系列数据包,并能够将远程主机的响应与操作系统 指纹数据库进行比较。如果发现了匹配结果,它就会显示匹配的操作系统。它确实可能无法 识别目标主机的操作系统;在这种情况下,如果您知道目标系统上使用的何种操作系统,可 在它提供的 URL 里提交有关信息,更新它的操作系统指纹数据库。

网络路由跟踪:它通过多种协议访问目标主机的不同端口,以尽可能访问目标主机。Nmap 路由跟踪功能从TTL的高值开始测试,逐步递减TTL,直到它到零为止。

Nmap脚本引擎:这个功能扩充了Nmap的用途。如果您要使用Nmap实现它(在默认情况 下)没有的检测功能,可利用它的脚本引擎手写一个检测脚本。目前,Nmap可检査网络服务 的漏洞,还可以枚举目标系统的资源。

常用功能

直接扫描

nmap 192.168.31.13

获取开放端口与运行服务

检测指定端口

nmap -p 8080 192.168.31.13

检测8080端口是否开放

-p端口范围:只扫描指定的端口。扫描1〜1024号端口,可设定该选项为–p 1-1024。扫描1 〜65535端口时,可使用-p-选项。

扫描网段

nmap  -p 22,21,80 192.168.31.1-253

识别运行服务

服务版本识别(-sV),Nmap可以在进行端口扫描的时候检测服务端软件的版本信息。版本信息将使后续的漏 洞识别工作更有针对性。

nmap -sV 192.168.31.13 -p 8080

识别操作系统

操作系统检测(-O),Nmap还能识别目标主机的操作系统。

nmap -O 192.168.31.13

强力优化检测

强力检测选项(-A),启用-A选项之后,Nmap将检测目标主机的下述信息
服务版本识别(-sV);
操作系统识别(-O);
脚本扫描(-sC);
Traceroute(–traceroute)

nmap -A 192.168.31.13

禁用主机检测

禁用主机检测(-Pn),如果主机屏蔽了ping请求,Nmap可能会认为该主机没有开机。这将使得Nmap无法进行进一 步检测,比如端口扫描、服务版本识别和操作系统识别等探测工作。为了克服这一问题,就 需要禁用Nmap的主机检测功能。在指定这个选项之后,Nmap会认为目标主机已经开机并会 进行全套的检测工作

nmap -Pn -A 192.168.31.13

常用片段

nmap -sP 192.168.0.0/24   判断哪些主机存活
nmap -sT 192.168.0.3   开放了哪些端口
nmap -sS 192.168.0.127 开放了哪些端口(隐蔽扫描)
nmap -sU 192.168.0.127 开放了哪些端口(UDP)
nmap -sS -O  192.168.0.127 操作系统识别

输出选项

Nmap可以把扫描结果保存为外部文件。在需要使用其他工具处理Nmap的扫描结果时,这一 功能十分有用。即使您设定程序把扫描结果保存为文件,Nmap还是会在屏幕上显示扫描结果。

Nmap支持以下几种输出形式。

正常输出(-oN):不显示runtime信息和警告信息。

XML    文件(-oX):生成的    XML    格式文件可以转换成    HTML    格式文件,还可被Nmap    的图 形用户界面解析,也便于导入数据库。本文建议您尽量将扫描结果输出为XML文件。

生成便于Grep使用的文件(-oG):虽然这种文件格式已经过时,但仍然很受欢迎。这种格 式的文件,其内容由注释(由#开始)和信息行组成。信息行包含6个字段,每个字段的字段 名称和字段值以冒号分割,字段之间使用制表符隔开。这些字段的名称分别为Host、Ports、Protocols、Ignored State、OS、Seq Index、IP ID    Seq    和Status。这种格式的文件便于 grep或awk之类的UNIX指令整理扫描结果。

输出至所有格式(-oA)利用-oA<basename>选项 可将扫描结果以标准格式、XML格式和Grep格式一次性输出。分别存放在 <basename>.nmap,<basename>.xml和 <basename>.gnmap文件中。也可以在文件名前 指定目录名,如在UNIX中,使用~/nmaplogs/foocorp/, 在Window中,使用c:\hacking\sco on Windows。

为使用方便,利用-oA选项 可将扫描结果以标准格式、XML格式和Grep格式一次性输出。分别存放在.nmap,.xml和.gnmap文件中。

时间排程控制选项

Nmap可通过-T选项指定时间排程控制的模式。它有6种扫描模式。

paranoid(0):每5分钟发送一次数据包,且不会以并行方式同时发送多组数据。这种模式 的扫描不会被IDS检测到。

sneaky(1):每隔15秒发送一个数据包,且不会以并行方式同时发送多组数据。

polite(2):每0.4    秒发送一个数据包,且不会以并行方式同时发送多组数据。

normal(3):此模式同时向多个目标发送多个数据包,为    Nmap    默认的模式,该模式能自 动在扫描时间和网络负载之间进行平衡。

aggressive(4):在这种模式下,Nmap    对每个既定的主机只扫描5    分钟,然后扫描下一 台主机。它等待响应的时间不超过1.25秒。

insane(5):在这种模式下,Nmap    对每个既定的主机仅扫描75    秒,然后扫描下一台主 机。它等待响应的时间不超过0.3秒。

默认的扫描模式通常都没有问题。除非您想要进行更隐匿或更快速的扫 描,否则没有必要调整这一选项。

脚本引擎功能(Nmap Scripting Engine,NSE)

Nmap本身已经很强大了,但是加上它的脚本引擎更加开挂了,NSE 可使用户的各种网络检査工作更为自动化,有助于识别应 用程序中新发现的漏洞、检测程序版本等Nmap原本不具有的功能。虽然Nmap软件包具有各 种功能的脚本,但是为了满足用户的特定需求,它还支持用户撰写自定义脚本。

auth:此类脚本使用暴力破解等技术找出目标系统上的认证信息。

default:启用--sC    或者-A    选项时运行此类脚本。这类脚本同时具有下述特点:执行速度快;输出的信息有指导下一步操作的价值;输出信息内容丰富、形式简洁;必须可靠;不会侵入目标系统;能泄露信息给第三方。

discovery:该类脚本用于探索网络。

dos:该类脚本可能使目标系统拒绝服务,请谨慎使用。

exploit:该类脚本利用目标系统的安全漏洞。在运行这类脚本之前,渗透测试人员需要获取 被测单位的行动许可。

external:该类脚本可能泄露信息给第三方。

fuzzer:该类脚本用于对目标系统进行模糊测试。

instrusive:该类脚本可能导致目标系统崩溃,或耗尽目标系统的所有资源。

malware:该类脚本检査目标系统上是否存在恶意软件或后门。

safe:该类脚本不会导致目标服务崩溃、拒绝服务且不利用漏洞。

version:配合版本检测选项(-sV),这类脚本对目标系统的服务程序进行深入的版本检 测。

vuln:该类脚本可检测检査目标系统上的安全漏洞。
在Kali    Linux系统中,Nmap脚本位于目录/usr/share/nmap/scripts。

-sC    或--script=default:启动默认类NSE    脚本。

--script    <filename>|<category>|<directories>:根据指定的文件名、类别名、目录名,执行 相应的脚本。

--script-args    <args>:这个选项用于给脚本指定参数。例如,在使用认证类脚本时,可通过 这个选项指定用户名和密码

使用方法:

nmap --script http-enum,http-headers,http-methods,http-php-version    -p    80 192.168.56.103

增强版漏洞扫描

上提供的脚本虽然强啊,但是数量相对较少,于是乎我们来隆重推荐一下Vulscan,它是Nmap的一个漏洞扫描增强模块,通过它可以把Nmap打造成一款实用高效免费的漏洞扫描器。Vulscan目前包含了CVE、OSVDB、Exploit-db、openvas等多个漏洞平台指纹数据,具备离线扫描功能,对主机系统漏洞有很好的探测识别效果。

安装

通过其程序Github官网压缩包下载,解压后把其中的文件释放到以下Nmap文件夹内:

Nmap\scripts\vulscan\*

使用1

如下命令对目标主机开始扫描:

nmap -sV –script=vulscan/vulscan.nse www.example.com

该-sV是绝对必要的。使用-sV,我们告诉Nmap探测版本信息的目标地址。如果Nmap不生成版本信息,nmap-vulners将不会有任何数据来查询Vulners数据库。使用这些NSE脚本时始终使用-sV

我们可以像nmap-vulners一样使用vulscan NSE脚本:

nmap --script vulscan -sV <目标IP>

默认情况下,vulscan会一次查询所有前面提到的数据库!正如我们在上面的图片中看到的那样,消化的信息量非常大。这比我们需要的信息要多得多。我强烈建议一次只查询一个数据库。我们可以通过将vulscandb参数添加到我们的Nmap命令并指定数据库来实现此目的,如下面的示例所示。

nmap --script vulscan --script-args vulscandb = database_name -sV <目标IP>
nmap --script vulscan --script-args vulscandb = scipvuldb.csv -sV <目标IP>
nmap --script vulscan --script-args vulscandb = exploitdb.csv -sV <目标IP>
nmap --script vulscan --script-args vulscandb = securitytracker.csv -sV <目标IP>

使用2

合并为一个命令,NSE脚本作为安全扫描器显着提高了Nmap的多功能性,范围。为了充分利用Nmap的版本扫描,我们可以在一个命令中使用nmap-vulners和vulscan。要执行此操作,请在终端中输入以下命令。

nmap --script nmap-vulners,vulscan --script-args vulscandb = scipvuldb.csv -sV <目标IP>

漏洞库数据

scipvuldb.csv – https://vuldb.com

cve.csv – http://cve.mitre.org

osvdb.csv – http://www.osvdb.org

securityfocus.csv – http://www.securityfocus.com/bid/

securitytracker.csv – http://www.securitytracker.com

xforce.csv – http://xforce.iss.net

expliotdb.csv – http://www.exploit-db.com

openvas.csv – http://www.openvas.org

单个漏洞库使用命令

--script-args vulscandb=your_own_database

漏洞库升级

需要在官网下载或通过以下链接手动下载数据库文件到/vulscan/目录中保持数据更新:

http://www.computec.ch/projekte/vulscan/download/cve.csv

http://www.computec.ch/projekte/vulscan/download/exploitdb.csv

http://www.computec.ch/projekte/vulscan/download/openvas.csv

http://www.computec.ch/projekte/vulscan/download/osvdb.csv

http://www.computec.ch/projekte/vulscan/download/scipvuldb.csv

http://www.computec.ch/projekte/vulscan/download/securityfocus.csv

http://www.computec.ch/projekte/vulscan/download/securitytracker.csv

http://www.computec.ch/projekte/vulscan/download/xforce.csv

##版本检测功能

版本检测功能在于对软件版本和漏洞数据库的具体信息进行探测,关闭该功能可能会导致误报,减少漏报提高运行效率,你可以使用以下命令把该功能关闭:

--script-args vulscanversiondetection=0

优先匹配功能

该功能在于对漏洞检测进行最优匹配扫描,可能会引起误报,但有利于对漏洞进行全面识别,使用以下命令开启该功能:

--script-args vulscanshowall=1

交互模式

该功能可以涵盖所有端口的检测结果,使用以下命令开启该功能:

--script-args vulscaninteractive=1

规避检测的选项

在渗透测试的工作中,目标主机通常处于防火墙或 IDS 系统的保护之中。在这种环境中使用 Nmap 的默认选项进行扫描,不仅会被发现,而且往往一无所获。此时,我们就要使用Nmap 规避检测的有关选项。

-f(使用小数据包):这个选项可避免对方识别出我们探测的数据包。指定这个选项之后, Nmap将使用8字节甚至更小数据体的数据包。

--mtu:这个选项用来调整数据包的包大小。MTU(Maximum    Transmission    Unit,最大传输 单元)必须是8的整数倍,否则Nmap将报错。

-D(诱饵):这个选项应指定假    IP,即诱饵的    IP。启用这个选项之后,Nmap    在发送侦测 数据包的时候会掺杂一些源地址是假IP(诱饵)的数据包。这种功能意在以藏木于林的方法 掩盖本机的真实    IP。也就是说,对方的log还会记录下本机的真实IP。您可使用RND生成随机 的假IP地址,或者用RND:number的参数生成<number>个假IP地址。您所指定的诱饵主机 应当在线,否则很容易击溃目标主机。另外,使用了过多的诱饵可能造成网络拥堵。尤其是 在扫描客户的网络的时候,您应当极力避免上述情况。

--source-port    <portnumber>或-g(模拟源端口):如果防火墙只允许某些源端口的入站流 量,这个选项就非常有用。

--data-length:这个选项用于改变Nmap    发送数据包的默认数据长度,以避免被识别出来是 Nmap的扫描数据。

--max-parallelism:这个选项可限制Nmap    并发扫描的最大连接数。

--scan-delay    <time>:这个选项用于控制发送探测数据的时间间隔,以避免达到IDS/IPS端 口扫描规则的阈值。

TCP/UDP扫描

TCP扫描选项

​ 1.TCP连接扫描(-sT):指定这个选项后,程序将和目标主机的每个端口都进行完整的三次 握手。如果成功建立连接,则判定该端口是开放端口。由于在检测每个端口时都需要进行三 次握手,所以这种扫描方式比较慢,而且扫描行为很可能被目标主机记录下来。如果启动 Nmap的用户的权限不足,那么默认情况下Nmap程序将以这种模式进行扫描。

​ 2.SYN扫描(-sS):该选项也称为半开连接或者SYN stealth。采用该选项后,Nmap将使用 含有SYN标志位的数据包进行端口探测。如果目标主机回复了SYN/ACK包,则说明该端口处 于开放状态:如果回复的是RST/ACK包,则说明这个端口处于关闭状态;如果没有任何响应 或者发送了ICMP unreachable信息,则可认为这个端口被屏蔽了。SYN模式的扫描速度非常 好。而且由于这种模式不会进行三次握手,所以是一种十分隐蔽的扫描方式。如果启动Nmap 的用户有高级别权限,那么在默认情况下Nmap程序将以这种模式进行扫描。

​ 3.TCP NULL(-sN)、FIN(-sF)及XMAS(-sX)扫描:NULL 扫描不设置任何控制位; FIN扫描仅设置FIN标志位:XMAS扫描设置FIN、PSH和URG的标识位。如果目标主机返回 了含有RST标识位的响应数据,则说明该端口处于关闭状态;如果目标主机没有任何回应, 则该端口处于打开|过滤状态。

​ 4.TCP Maimon扫描(-sM):Uriel Maimon 首先发现了TCP Maimom扫描方式。这种模式的 探测数据包含有FIN/ACK标识。对于BSD衍生出来的各种操作系统来说,如果被测端口处于 开放状态,主机将会丢弃这种探测数据包;如果被测端口处于关闭状态,那么主机将会回复 RST。

​ 5.TCPACK扫描(-sA):这种扫描模式可以检测目标系统是否采用了数据包状态监测技术 (stateful)防火墙,并能确定哪些端口被防火墙屏蔽。这种类型的数据包只有一个ACK标识 位。如果目标主机的回复中含有RST标识,则说明目标主机没有被过滤。

​ 6.TCP窗口扫描(-sW):这种扫描方式检测目标返回的RST数据包的TCP窗口字段。如果目 标端口处于开放状态,这个字段的值将是正值;否则它的值应当是0。

​ 7.TCP Idle扫描(-sI):采用这种技术后,您将通过指定的僵尸主机发送扫描数据包。本机 并不与目标主机直接通信。如果对方网络里有IDS,IDS将认为发起扫描的主机是僵尸主机。

UDP扫描选项

Nmap有多种TCP扫描方式,而UDP扫描仅有一种扫描方式(-sU)。虽然UDP扫描结果没有 TCP扫描结果的可靠度高,但渗透测试人员不能因此而轻视UDP扫描,毕竟UDP端口代表着 可能会有价值的服务端程序。但是UDP扫描的最大问题是性能问题。由干Linux内核限制1秒内最多发送一次ICMP Port Unreachable信息。按照这个速度,对一台主机的65536个UDP端口进行完整扫描,总耗时必 定会超过18个小时。

优化方法主要是:

1.进行并发的UDP扫描;
2.优先扫描常用端口;
3.在防火墙后面扫描;
4.启用--host-timeout选项以跳过响应过慢的主机。

假如我们需要找到目标主机开放了哪些 UDP端口。为提高扫描速度,我们仅扫描 53端口 (DNS)和161端口(SNMP)。

可以使用命令nmap -sU 192.168.56.103 -p 53,161

Python-Nmap

Nmap提供给Python调用的API,方便自定义快速扫描,获取数据结果更加方便。

安装:

pip3 install python-nmap

然后安装nmap并添加到环境变量

扫描单个开放端口获取服务

代码:

import nmap
nm = nmap.PortScanner()
ip = '118.24.11.235'
res = nm.scan(ip,ports='1-500')
# 扫面主机的1~500号端口
r = res['scan'][ip]['tcp']
# 获取扫描结果详细数据
for k,v in r.items():
    print('端口:'+str(k))
    print('服务:'+v['name'])
    print('产品:'+v['product'])
    print('版本:'+v['version'])
    print('信息:'+v['extrainfo'])
    print('扫描地址:'+res['scan'][ip]['addresses']['ipv4'])
    print('扫描命令:'+res['nmap']['command_line'])
    print('扫描方式:'+res['nmap']['scaninfo']['tcp']['method'])
    print('主机存活:'+res['nmap']['scanstats']['uphosts'])
    print('扫描时间:'+res['nmap']['scanstats']['timestr'])
    print('*'*10)

ports = list(res['scan'][ip]['tcp'].keys())
print('开放端口:'+str(ports))

扫描结果:

端口:80
服务:http
产品:nginx
版本:1.15.11
信息:
扫描地址:118.24.11.235
扫描命令:nmap -oX - -p 1-500 -sV 118.24.11.235
扫描方式:syn
主机存活:1
扫描时间:Fri Feb 26 18:16:14 2021
**********
端口:445
服务:microsoft-ds
产品:
版本:
信息:
扫描地址:118.24.11.235
扫描命令:nmap -oX - -p 1-500 -sV 118.24.11.235
扫描方式:syn
主机存活:1
扫描时间:Fri Feb 26 18:16:14 2021
**********
开放端口:[42, 80, 135, 136, 137, 138, 139, 445]

扫描网段信息

代码:

import nmap
nma = nmap.PortScanner()
result = nma.scan(hosts='192.168.1.0/24', arguments='-n -sP -PE')
AliveHost = list(result['scan'].keys())
print('存活主机:{}'.format(AliveHost))
# ['192.168.1.1', '192.168.1.103']
# 获取到网段存活的主机
for k,v in (result['scan']).items():
    print('当前ip:{}'.format(k))
    print('地址:'+str(v['addresses']))
    print('版本:'+str(v['vendor']))
    print('存活状态:'+v['status']['state'])
    print('*'*10)

扫描结果:

存活主机:['192.168.1.1', '192.168.1.102', '192.168.1.103', '192.168.1.106']
当前ip:192.168.1.1
地址:{'ipv4': '192.168.1.1', 'mac': '48:8A:D2:C2:94:98'}
版本:{'48:8A:D2:C2:94:98': 'Mercury Communication Technologies'}
存活状态:up
**********
当前ip:192.168.1.102
地址:{'ipv4': '192.168.1.102', 'mac': '38:D2:CA:B5:A9:4E'}
版本:{'38:D2:CA:B5:A9:4E': 'Zhejiang Tmall Technology'}
存活状态:up
**********
当前ip:192.168.1.103
地址:{'ipv4': '192.168.1.103', 'mac': '4A:41:85:3B:5D:27'}
版本:{}
存活状态:up
**********
当前ip:192.168.1.106
地址:{'ipv4': '192.168.1.106'}
版本:{}
存活状态:up
**********

扫描网段并且获取详细信息【较慢】

代码:

import nmap
nm = nmap.PortScanner()
result = nm.scan(hosts='192.168.1.0/24', arguments='-sV -A')
# 耗时比较久
AliveHostCount = result['nmap']['scanstats']['uphosts']
# 获取C段内存活主机数量
print('存活主机数量:{}'.format(AliveHostCount))
scaninfo = result['scan']
# 获取详细扫描结果
for k,v in scaninfo.items():
    print(k,v)

扫描结果:

存活主机数量:2
192.168.1.1 {'hostnames': [{'name': 'localhost', 'type': 'PTR'}], 'addresses': {'ipv4': '192.168.1.1', 'mac': '48:8A:D2:C2:94:98'}, 'vendor': {'48:8A:D2:C2:........

异步多进程实现及时获取

# coding:utf-8
import nmap,multiprocessing
nm = nmap.PortScannerAsync()
def callback_result(host, scan_result):
    print(host, scan_result)
if __name__ == '__main__':
    multiprocessing.freeze_support()
    nm.scan(hosts='192.168.1.0/24', arguments='-sP', callback=callback_result)
    while nm.still_scanning():
        nm.wait(2)

使用生成器及时获取

# coding:utf-8
import nmap
nm = nmap.PortScannerYield()
for progressive_result in nm.scan('192.168.1.0/24', '0-100'):
    print(progressive_result)

使用内置多线程

# coding:utf-8
import nmap
def scan(ip):
    nm = nmap.PortScanner()
    print(nm.scan(ip))
import time
t1 = time.time()
n = nmap.Process(target=scan,args=('192.168.1.0/24',))
n.run()
print('耗时:{}'.format(time.time()-t1))

使用漏扫模块

# coding:utf-8
import nmap
common = '--script vulscan --script-args vulscandb=cve.csv -sV'
nm = nmap.PortScanner()
result = nm.scan(hosts='192.168.200.130',arguments=common)
print(result)
res = result['scan']
for k,v in res.items():
    print(k)
    print(v)

IPy

负责对IP处理的一个库

获取网段的IP地址

获取C段

import IPy
ip = IPy.IP('192.168.0.0/24')
print( ip.len())
print(ip[0:10])

返回结果

256
[IP('192.168.0.0'), IP('192.168.0.1'), IP('192.168.0.2'), IP('192.168.0.3'), IP('192.168.0.4'), IP('192.168.0.5'), IP('192.168.0.6'), IP('192.168.0.7'), IP('192.168.0.8'), IP('192.168.0.9')]

获取B段

import IPy
ip = IPy.IP('192.168.0.0/16')
print( ip.len())
print(ip[0:10])

返回结果

65536
[IP('192.168.0.0'), IP('192.168.0.1'), IP('192.168.0.2'), IP('192.168.0.3'), IP('192.168.0.4'), IP('192.168.0.5'), IP('192.168.0.6'), IP('192.168.0.7'), IP('192.168.0.8'), IP('192.168.0.9')]

获取A段

ip_address = '192.0.0.0/8'
ip = IPy.IP(ip_address)
print(len(ip))

返回

16777216

还可以通过这种方式生成

ip = IPy.IP('10.2.32.0-10.2.32.3')

判断包含关系

'10.0.0.1' in IP('10.0.0.0/24')

返回结果

true

判断内网or外网

import IPy
ip_address = '192.168.1.102'
ip = IPy.IP(ip_address)
print(ip.iptype())

内网返回:PRIVATE 外网返回: PUBLIC

Masscan

简单使用

masscan相比nmap之所以快很多,masscan采用了异步传输方式,无状态的扫描方式。nmap需要记录tcp/ip的状态,os能够处理的TCP/IP连接最多为1500左右。

masscan -p0-65535 192.168.1.0/16 –banners –rate 100000000

masscan –ping 192.168.1.0/16 –rate 1000000 #主机存活

默认情况下,Masscan扫描速度为每秒100个数据包

masscan -p443 192.168.1.0/16 –banners –heartbleed #–banners 进行漏洞扫描任务,–heartbleed masscan仅支持该漏洞扫描选项,首先监测端口,软后发送漏洞探测数据包

masscan -p80,8000-8100 192.168.1.0/16 –echo > test.conf #导出配置文件 masscan -c test.conf –rate 100000000

masscan -p80 192.168.1.0/16 -oX xx.xml (-oJ xx.json -oL xx.list)

使用参数

IP地址范围,有三种有效格式:

1、单独的IPv4地址
2、类似"10.0.0.1-10.0.0.233"的范围地址
3、CIDR地址 类似于"0.0.0.0/0",多个目标可以用都好隔开

-p  指定端口进行扫描
--banners 获取banner信息,支持少量的协议
--rate 指定发包的速率
-c,--conf 读取配置文件进行扫描
--echo 将当前的配置重定向到一个配置文件中
-e,--adapter 指定用来发包的网卡接口名称
--adapter-ip 指定发包的IP地址
--adapter-port 指定发包的源端口
--adapter-mac 指定发包的源MAC地址
--router-mac 指定网关的MAC地址
--exclude IP地址范围黑名单,防止masscan扫描
--excludefile 指定IP地址范围黑名单文件
--includefile,-iL 读取一个范围列表进行扫描
--ping 扫描应该包含ICMP回应请求
--append-output 以附加的形式输出到文件
--iflist 列出可用的网络接口,然后退出
--retries 发送重试的次数,以1秒为间隔
--nmap 打印与nmap兼容的相关信息
--http-user-agent 设置user-agent字段的值
--show [open,close] 告诉要显示的端口状态,默认是显示开放端口
--noshow [open,close] 禁用端口状态显示
--pcap 将接收到的数据包以libpcap格式存储
--regress 运行回归测试,测试扫描器是否正常运行
--ttl 指定传出数据包的TTL值,默认为255
--wait 指定发送完包之后的等待时间,默认为10秒
--offline 没有实际的发包,主要用来测试开销
-sL 不执行扫描,主要是生成一个随机地址列表
--readscan 读取从-oB生成的二进制文件,可以转化为XML或者JSON格式
--connection-timeout 抓取banners时指定保持TCP连接的最大秒数,默认是30秒

获取banner

masscan 10.0.0.0/8 -p80 --banners

排除指定文本内的IP

masscan 0.0.0.0/0 -p0-65535 --excludefile exclude.txt

提高运行速度

masscan 0.0.0.0/0 -p0-65535 --max-rate 100000

异常处理

nmap以及masscan都依赖winpcap,扫描的时候,如果安装了多个网卡或者虚拟网卡,则会报错:

'FAIL: failed to detect IP of interface "\\Device\\xxxxxxxxxxxx"\r\n [hint] did you spell the name correctly?\r\n [hint] if it has no IP address, manually set with "--adapter-ip 192.168.100.5"\r\n'

这个时候把所有的虚拟网卡,无线网卡全部禁用,只留下一个网卡就好了。

常用命令搭配

扫描指定IP文件中的地址

./masscan -iL ip.txt -oX result.txt -p1-65535 --banners --rate=10000

其中ip.txt内容为:

1.1.0.0/16
192.168.1.1/24

Masscan-python

Masscan提供给Python调用的API,方便自定义快速扫描,获取数据结果更加方便。

安装命令:

pip3 install python-masscan

如果安装失败,则直接下载安装包即可,下载地址:http://www.langzi.fun/upload/python-masscan-master.rar

下载解压后,使用命令:

python3 setup.py install 

即可安装

这个安装的只是masscan的python整理api。你其实还要安装masscan,在巡风扫描器的masscan中下载了win10的编译好的masscan.exe,然后把masscan.exe所在的文件夹加入系统环境变量。cmd下运行masscan.exe提示确实wpacp.dll,网络流量嗅探劫持扫描都依赖这个dll文件,安装nmap,wireshark也都需要这个的,安装就ok了。

常用方法

使用方法如下:

import masscan
mas = masscan.PortScanner()
mas.scan('110.0.0.0',ports='3389,80')
print mas.scan_result

ports是可选参数,如果不填的话,默认全端口。返回对象是字典格式,解析这个字典看看结果。

import masscan
mas = masscan.PortScanner()
mas.scan('110.0.0.0')
result = mas.scan_result()
d = result['masscan']
for x in d:
    print x + ':' + str(d[x])
print d.keys()
print '-'*50

d1 = result['scan']
for x in d1:
    print x + ':' + str(d1[x])

print d1.keys()

result字典有两个键,分别是masscan和scan。结构分支如下:

masscan:
    1. scanstats(一些结果参数)
        1. timestr(时间)
        2. uphosts(存活主机数量)
        3. downhosts(关闭的主机数量)
        4. totalhosts(总数)
        5. elapsed(不明白意思)
    2. command_line(在masscan的参数指令,不重要)

scan:
    1. 110.0.0.0 键就是传入的ip,他下面有多个键
        1. tcp(tcp方式扫描)
            1. 3389(开放端口)
                1. services(服务信息) 
                2. state(开放情况)
                3. reason(请求方式)
                4. reson_ttl(返回长度)
            2. 80(开放端口)
                1. services(服务信息) 
                2. state(开放情况)
                3. reason(请求方式)
                4. reson_ttl(返回长度)

这就是传入一个ip,扫描全端口返回的结果,扫描一个ip段返回的数据估计也差不多….

传入一个ip,然后获取所有的开放情况代码如下:

re = result['scan'][ip]['tcp'].keys()

返回对象是一个列表

[5985, 3389, 80]

就是开放的端口,总结一下用法:

import masscan
mas = masscan.PortScanner()
ip = '118.24.11.235'
mas.scan(ip, ports='80,1000-8888',arguments='--max-rate 2000')
# 扫描ip为:118.24.11.235
# 除了单个IP,还能直接扫描C/B段,直接修改传入的参数即可
# 扫描端口为:80,1000-8888
# 额外命令为:--max-rate 2000 设置最大发包量为2000
Results = mas.scan_result['scan']
# 获取扫描结果
for k,v in Results.items():
    print('当前IP:{}'.format(k))
    print('开放端口:{}'.format(list(v['tcp'].keys())))

扫描结果:

当前IP:118.24.11.235
开放端口:[5985, 3389, 80]

拓展之端口对应服务识别

对一个IP的开放端口扫描完成后,除去开放的端口数据,还需要识别端口对应的服务,常规的识别方法如下:

  1. 默认的端口对应服务数据库
  2. 对端口进行发起连接,对返回的banner进行指纹识别
  3. Nmap识别开放端口与运行服务

Nmap同样能识别出开放的端口和服务,原理也就是上面说的,许多思路就是利用Masscan高速性快速扫描出开放的端口,然后使用Nmap扫描这些端口,对结果中提取出运行的服务,然后整理结果。

但是按照经验,对端口发起连接识别指纹准确率较高,其次是Nmap识别端口服务,最后再是使用默认的数据库。

端口服务数据库

方法一

整理了一下常见端口对应的服务保存为字典格式:

PortLib={'21': 'ftp', '22': 'ssh', '23': 'telnet', '25': 'smtp', '53': 'dns', '68': 'dhcp', '8080': 'http', '69': 'tftp', '995': 'pop3', '135': 'rpc', '139': 'netbios', '143': 'imap', '443': 'https', '161': 'snmp', '489': 'ldap', '445': 'smb', '465': 'smtps', '512': 'linuxrrpe', '513': 'linuxrrlt', '514': 'linuxrcmd', '873': 'rsync', '993': 'imaps', '1080': 'proxy', '1099': 'javarmi', '1352': 'lotus', '1433': 'mssql', '1521': 'oracle', '1723': 'pptp', '2082': 'cpanel', '2083': 'cpanel', '2181': 'zookeeper', '2222': 'dircetadmin', '2375': 'docker', '2604': 'zebra', '3306': 'mysql', '3312': 'kangle', '3389': 'rdp', '3690': 'svn', '4440': 'rundeck', '4848': 'glassfish', '5432': 'postgresql', '5632': 'pcanywhere', '5900': 'vnc', '5984': 'couchdb', '6082': 'varnish', '6379': 'redis', '9001': 'weblogic', '7778': 'kloxo', '10050': 'zabbix', '8291': 'routeros', '9200': 'elasticsearch', '11211': 'memcached', '27017': 'mongodb', '27018': 'mongodb', '50070': 'hadoop'}

调用方法十分简单,如果开放的端口是 22 ,那么运行的服务就是

print(PortLib.get('22'))

返回结果:

ssh

方法二

对存活的ip解析其功能,如果自定义数据指纹的话,工程量大,并且不易维护。网上刚好有个whatportis的库,可以提供端口对应的常见服务。安装方法如下:

pip3 install whatportis

然后会直接加入环境变量,比如cmd输入 whatportis 3389,会输出:

+---------------+------+----------+---------------+
| Name          | Port | Protocol | Description   |
+---------------+------+----------+---------------+
| ms-wbt-server | 3389 |   tcp    | MS WBT Server |
| ms-wbt-server | 3389 |   udp    | MS WBT Server |
+---------------+------+----------+---------------+

格式化输出依赖pretty库。然而我只想要description的信息啊,详细的api懒得看,直接输入:

>>> import whatportis
>>> print help(whatportis)

whatportis - # -*- coding: utf-8 -*-

FILE
    f:\python27\lib\site-packages\whatportis\__init__.py

PACKAGE CONTENTS
    __main__
    core
    server

FUNCTIONS
    get_ports(port, like=False)
        This function creates the SQL query depending on the specified port and
        the --like option.

        :param port: the specified port
        :param like: the --like option
        :return: all ports matching the given ``port``
        :rtype: list

DATA
    __all__ = ['get_ports']


None

原来类下面有个get_ports()方法,接受一个参数端口,返回对象是列表,如果没有匹配到端口的服务,就返回一个空的列表。所以使用方法如下:

import whatportis
d = whatportis.get_ports('23')
print(d)
if d != []:
    print(d[0][3])

查看源码后发现可以完全移植一下代码,将whatportis目录下的指纹库文件port.json保存到自己的代码目录下,调用方法代码:

from tinydb import TinyDB, where
from tinydb.storages import JSONStorage
from tinydb.middlewares import CachingMiddleware
from collections import namedtuple
import os
Port = namedtuple("Port", ["name", "port", "protocol", "description"])

__BASE_PATH__ = os.path.dirname(os.path.abspath(__file__))
__DATABASE_PATH__ = os.path.join(__BASE_PATH__, 'ports.json')
__DB__ = TinyDB(__DATABASE_PATH__, storage=CachingMiddleware(JSONStorage))


def GetPortInfo(port, like=False):
    """
    判断端口服务,传入参数为 字符串类型的数字
    返回服务名称  'http',没有则返回  '检测失效'
    """
    where_field = "port" if port.isdigit() else "name"
    if like:
        ports = __DB__.search(where(where_field).search(port))
    else:
        ports = __DB__.search(where(where_field) == port)
    try:
        return ports[0]['name']  # flake8: noqa (F812)
    except:
        return '识别端口异常'

调用方法十分简单,如果开放的端口是 22 ,那么运行的服务就是

print(GetPortInfo('22'))

返回结果:

ssh

指纹库文件下载地址:http://www.langzi.fun/upload/ports.json

Banner指纹识别

Banner指纹识别:banner 信息来表示欢迎语,其中会包含一些敏感信息,比如不同的端口你请求连接后,返回的Banner是不一样的,所以可以根据这个Banner指纹来断定该端口运行的服务。

在Python使用socket库可以简单的对主机加端口进行访问请求,然后对返回的信息匹配指纹即可

Banner =  {b'http': [b'^HTTP/.*\nServer: Apach', b'^HTTP/.*\nServer: nginx', b'HTTP.*?text/html', b'http.*?</html>'], b'ssh': [b'^SSH-.*openssh', b'^ssh-', b'connection refused by remote host.'], b'netbios': [b'\xc2\x83\x00\x00\x01\xc2\x8f', b'^y\x08.*browse', b'^y\x08.\x00\x00\x00\x00', b'^\x05\x00\r\x03', b'^\x82\x00\x00\x00', b'\x83\x00\x00\x01\x8f'], b'backdoor-fxsvc': [b'^500 Not Loged in'], b'backdoor-shell': [b'^sh[$#]'], b'bachdoor-shell': [b'[a-z]*sh: .* command not found'], b'backdoor-cmdshell': [b'^Microsoft Windows .* Copyright .*>'], b'db2': [b'.*SQLDB2RA', b'.*sqldb2ra'], b'db2jds': [b'^N\x00', b'^n\x00'], b'dell-openmanage': [b'^N\x00\r'], b'finger': [b'finger: GET: ', b'^\r\n\tline\t  user', b'line\t user', b'login name: ', b'login.*name.*tty.*idle', b'^no one logged on', b'^\r\nwelcome', b'^finger:', b'^must provide username', b'finger: get: '], b'ftp': [b'^220 .* UserGate', b'^220.*\n331', b'^220.*\n530', b'^220.*ftp', b'^220 .* microsoft .* ftp', b'^220 inactivity timer', b'^220 .* usergate', b'^220.*filezilla server', b'^220-', b'^220.*?ftp', b'^220.*?filezilla'], b'http-iis': [b'^<h1>Bad Request .Invalid URL.</h1>'], b'http-jserv': [b'^HTTP/.*Cookie.*JServSessionId'], b'http-tomcat': [b'.*Servlet-Engine'], b'http-weblogic': [b'^HTTP/.*Cookie.*WebLogicSession'], b'http-vnc': [b'^HTTP/.*RealVNC/'], b'ldap': [b'^0E', b'^0\x0c\x02\x01\x01a', b'^02\x02\x01', b'^03\x02\x01', b'^08\x02\x01', b'^0\x84', b'^0e'], b'smb': [b'^\x00\x00\x00.\xc3\xbfSMBr\x00\x00\x00\x00.*', b'^\x00\x00\x00.\xffsmbr\x00\x00\x00\x00.*', b'^\x83\x00\x00\x01\x8f'], b'msrdp': [b'^\x03\x00\x00\x0b\x06\xc3\x90\x00\x004\x12\x00'], b'msrdp-proxy': [b'^nmproxy: Procotol byte is not 8\n$'], b'msrpc': [b'\x05\x00\r\x03\x10\x00\x00\x00\x18\x00\x00\x00....\x04\x00\x01\x05\x00\x00\x00\x00$', b'^\x05\x00\r\x03\x10\x00\x00\x00\x18\x00\x00\x00\x00\x00', b'\x05\x00\r\x03\x10\x00\x00\x00\x18\x00\x00\x00....\x04\x00\x01\x05\x00\x00\x00\x00$'], b'mssql': [b';MSSQLSERVER;', b'^\x05n\x00', b'^\x04\x01', b';mssqlserver;', b'mssqlserver'], b'telnet': [b'^\xc3\xbf\xc3\xbe', b'telnet', b'^\xff[\xfa-\xff]', b'^\r\n%connection closed by remote host!\x00$'], b'mysql': [b"whost '", b'mysql_native_password', b'^\x19\x00\x00\x00\n', b'^,\x00\x00\x00\n', b"hhost '", b"khost '", b'mysqladmin', b"whost '", b'^[.*]\x00\x00\x00\n.*?\x00', b'this mysql server', b'mariadb server', b'\x00\x00\x00\xffj\x04host'], b'mysql-blocked': [b'^\\(\x00\x00'], b'mysql-secured': [b'this MySQL'], b'mongodb': [b'^.*version.....([\\.\\d]+)', b'mongodb'], b'nagiosd': [b'Sorry, you \\(.*are not among the allowed hosts...', b'sorry, you \\(.*are not among the allowed hosts...'], b'nessus': [b'< NTP 1.2 >\nUser:', b'< ntp 1.2 >\nuser:'], b'oracle-tns-listener': [b'\\(ADDRESS=\\(PROTOCOL=', b'\\(error_stack=\\(error=\\(code=', b'\\(address=\\(protocol='], b'oracle-dbsnmp': [b'^\x00\x0c\x00\x00\x04\x00\x00\x00\x00', b'^\x00\x0c\x00\x00\x04\x00\x00\x00\x00'], b'oracle-https': [b'^220- ora', b'^220- ora'], b'oracle-rmi': [b'^N\x00\t'], b'postgres': [b'^EFATAL'], b'rlogin': [b'^\x01Permission denied.\n', b'login: ', b'rlogind: ', b'^\x01permission denied.\n'], b'rpc-nfs': [b'^\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00', b'^\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00'], b'rpc': [b'^\xc2\x80\x00\x00', b'\x01\x86\xa0', b'\x03\x9beb\x00\x00\x00\x01', b'^\x80\x00\x00'], b'rsync': [b'^@RSYNCD:.*', b'^@rsyncd:', b'@rsyncd:'], b'smux': [b'^A\x01\x02\x00', b'^a\x01\x02\x00'], b'snmp-public': [b'public\xc2\xa2', b'public\xa2'], b'snmp': [b'A\x01\x02', b'a\x01\x02'], b'socks': [b'^\x05[\x00-\x08]\x00', b'^\x05[\x00-\x08]\x00'], b'ssl': [b'^\x16\x03\x00..\x02...\x03\x00', b'^..\x04\x00.\x00\x02', b'^\x16\x03\x01..\x02...\x03\x01', b'^\x16\x03\x00..\x02...\x03\x00', b'ssl.*get_client_hello', b'^-err .*tls_start_servertls', b'^\x16\x03\x00\x00j\x02\x00\x00f\x03\x00', b'^\x16\x03\x00..\x02\x00\x00f\x03\x00', b'^\x15\x03\x00\x00\x02\x02\\.*', b'^\x16\x03\x01..\x02...\x03\x01', b'^\x16\x03\x00..\x02...\x03\x00'], b'sybase': [b'^\x04\x01\x00', b'^\x04\x01\x00'], b'tftp': [b'^\x00[\x03\x05]\x00', b'^\x00[\x03\x05]\x00'], b'uucp': [b'^login: password: ', b'^login: password: '], b'vnc': [b'^RFB.*', b'^rfb'], b'webmin': [b'^0\\.0\\.0\\.0:.*:[0-9]', b'.*miniserv', b'^0\\.0\\.0\\.0:.*:[0-9]'], b'websphere-javaw': [b'^\x15\x00\x00\x00\x02\x02\n', b'^\x15\x00\x00\x00\x02\x02\n'], b'xmpp': [b"^\\<\\?xml version='1.0'\\?\\>"], b'backdoor': [b'^500 not loged in', b'get: command', b'sh: get:', b'^bash[$#]', b'^sh[$#]', b'^microsoft windows'], b'bachdoor': [b'*sh: .* command not found'], b'rdp': [b'^\x00\x01\x00.*?\r\n\r\n$', b'^\x03\x00\x00\x0b', b'^\x03\x00\x00\x11', b'^\x03\x00\x00\x0b\x06\xd0\x00\x00\x12.\x00$', b'^\x03\x00\x00\x17\x08\x02\x00\x00z~\x00\x0b\x05\x05@\x06\x00\x08\x91j\x00\x02x$', b'^\x03\x00\x00\x11\x08\x02..}\x08\x03\x00\x00\xdf\x14\x01\x01$', b'^\x03\x00\x00\x0b\x06\xd0\x00\x00\x03.\x00$', b'^\x03\x00\x00\x0b\x06\xd0\x00\x00\x00\x00\x00', b'^\x03\x00\x00\x0e\t\xd0\x00\x00\x00[\x02\xa1]\x00\xc0\x01\n$', b'^\x03\x00\x00\x0b\x06\xd0\x00\x004\x12\x00'], b'rdp-proxy': [b'^nmproxy: procotol byte is not 8\n$'], b'rmi': [b'\x00\x00\x00vinva', b'^n\x00\t'], b'postgresql': [b'invalid packet length', b'^efatal'], b'imap': [b'^\\* ok.*?imap'], b'pop': [b'^\\+ok.*?'], b'smtp': [b'^220.*?smtp', b'^554 smtp'], b'rtsp': [b'^rtsp/'], b'sip': [b'^sip/'], b'nntp': [b'^200 nntp'], b'sccp': [b'^\x01\x00\x00\x00$'], b'squid': [b'x-squid-error'], b'vmware': [b'vmware'], b'iscsi': [b'\x00\x02\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'], b'redis': [b'^-err unknown command', b'^-err wrong number of arguments', b'^-denied redis is running'], b'memcache': [b'^error\r\n'], b'websocket': [b'server: websocket'], b'https': [b'instead use the https scheme to accesshttps', b'http request to an https server', b'location: https'], b'svn': [b'^\\( success \\( 2 2 \\( \\) \\( edit-pipeline svndiff1'], b'dubbo': [b'^unsupported command'], b'elasticsearch': [b'cluster_name.*elasticsearch'], b'rabbitmq': [b'^amqp\x00\x00\t\x01'], b'zookeeper': [b'^zookeeper version: ']}


def GetBannerServer(ip, port):
    try:
        s = socket.socket()
        s.settimeout(5)
        s.connect((ip, int(port)))
        s.send(b'langzi\r\n')
        SocketRecv = (s.recv(1024))
        s.close()
        for k, v in Banner.items():
            for b in v:
                banner = re.search(b, SocketRecv, re.I | re.S)
                if banner:
                    return k.decode()
        return '获取失败'
    except Exception as e:
        return '获取失败'
    finally:
        s.close()
print(GetBannerServer(ip='118.24.11.235',port='80'))

返回结果:

http

拓展

LangNetworkTopologys是一款调用MASSCAN对内网主机进行如下任务,完成内网主机资产快速获取的工具,具有如下功能:

  1. 开放端口扫描
  2. 运行服务检测,指纹识别
  3. 开放端口二次复检
  4. 主机部署网站探测
  5. 自动生成扫描结果报表

可以参考具体代码,了解端口扫描与运行服务获取的大致思路

具体代码地址:https://github.com/LangziFun/LangNetworkTopologys/blob/master/Project/LangNetworkTopology3/Lib/source/LangNetworkTopology3.py

拓展资料

NMAP

nmap2

NMAP3

官方文档

文档2

Masscan 资料1

Masscan 资料2

-------------本文结束感谢您的阅读-------------

腾讯云主机优惠打折:最新活动地址


版权声明

LangZi_Blog's by Jy Xie is licensed under a Creative Commons BY-NC-ND 4.0 International License
由浪子LangZi创作并维护的Langzi_Blog's博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证
本文首发于Langzi_Blog's 博客( http://langzi.fun ),版权所有,侵权必究。

0%