目录
一、信息搜集基础
1、信息收集获得信息的方法可以分成两种:被动扫描和主动扫描。
✦被动扫描主要指的是在目标 无法察觉的情况下 进行的信息收集,例如,如果想了解一个远在天边的人,你会怎么做呢?显然可以选择在搜索引擎中去搜索这个名字。其实这就是一次对目标的被动扫描。
✦主动扫描一般都是针对目标发送特制的数据包,然后根据目标的反应来获得一些信息。 扫描之后将会获得的信息包括:目标网络的结构,目标网络所使用设备的类型,目标主机上运行的操作系统,目标主机上所开放的端口,目标主机上所提供的服务,目标主机上所运行的应用程序。
2、选择扫描目标的nmap语法如下所示。
(1)扫描指定IP主机:nmap 192.168.169.133
(2)扫描指定域名主机:nmap www.nmap.com。
(3)扫描指定范围主机:nmap 192.168.169.1-20。
(4)扫描一个子网主机:nmap 192.168.169.0/24。
3、对目标的端口进行扫描的nmap语法如下所示。
(1)扫描一个主机的特定端口:nmap -p 22 192.168. 169.1。
(2)扫描指定范围端口:nmap -p 1-80 192.168. 169.1。
(3)扫描100个最为常用的端口:nmap -F 192.168. 169.1。
4、对目标端口状态进行扫描的nmap语法如下所示。
(1)使用TCP全开扫描:nmap -sT 192.168. 169.1。
(2)使用TCP半开扫描:nmap -sS 192.168. 169.1。
(3)使用UDP扫描:nmap -sU -p 123,161,162 192.168. 169.1。
5、对目标的操作系统和运行服务进行扫描的nmap语法如下所示。
(1)扫描目标主机上运行的操作系统:nmap -O 192.168.169.1。
(2)扫描目标主机上运行的服务类型:nmap -sV 192.168.169.1。
二、主机状态扫描
1、下面构造一个扫描192.168.26.100的ARP请求数据包并将其发送出去
>>>ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.26.100"),timeout=2)
对这个请求的回应进行监听,如果得到回应,那么证明目标在线,并打印输出这个主机的硬件地址:
>>> ans.summary(lambda (s,r): r.sprintf("%Ether.src% %ARP.psrc%") )
如果发出这个数据包,但是没有收到这个数据包回应,则说明目标主机不在线
2、基于ICMP的活跃主机发现技术
✦ICMP位于TCP/IP协议族中的网络层,它的目的是用于在IP主机、路由器之间传递控制消息。ICMP中提供了多种报文,这些报文又可以分成两大类:差错报文和查询报文。其中,查询报文都是由一个请求和一个应答构成的。
✦ ICMP查询报文有4种,分别是响应请求或应答、时间戳请求或应答、地址掩码请求或应答、路由器询问或应答。
案例:编写一个利用ICMP实现的活跃主机扫描程序
✦src会自动设置为本机地址。所以只需要将dst设置为“192.168.26.100”即可将数据包发到目标主机上。 接下来构造一个扫描192.168.26.100的ICMP请求数据包并将其发送出去。
>>> ans,unans=sr(IP(dst="192.168.26.100")/ICMP())
✦对这个请求的回应进行监听,如果得到了回应,那么证明目标在线,并打印输出这个主机的IP地址。
>>> ans.summary(lambda (s,r): r.sprintf("%IP.src% is alive") )
3、基于TCP的活跃主机发现技术
如果检测到一台主机的某个端口有回应,也一样可以判断这台主机是活跃主机。 如果一台主机处于活跃状态,那么它的端口即使是关闭的,在收到请求时,也会给出一个回应,只不过并不是一个“SYN+ACK”数据包,而是一个拒绝连接的“RST”数据包。
案例:编写一个利用TCP实现的活跃主机扫描程序
✦构造一个发往192.168.1.2的80端口的SYN请求数据包并将其发送出去。
>>>ans,unans=sr( IP(dst="192.168.26.*")/TCP(dport=80,flags="S") )
✦对这个请求的回应进行监听,如果得到了回应,就证明目标在线,并打印输出这个主机的IP地址。
>>> ans.summary(lambda (s,r): r.sprintf("%IP.src% is alive") )
4、基于UDP的活跃主机发现技术
但基于UDP的活跃主机发现技术和TCP不同,UDP没有三次握手。 当向目标发送一个UDP数据包之后,目标是不会发回任何UDP数据包的。 不过,如果目标主机是处于活跃状态的,但是目标端口是关闭的时候,可以返回一个ICMP数据包,这个数据包的含义为“unreachable” 如果目标主机不处于活跃状态,这时是收不到任何回应的
案例:
✦接下来构造一个发往192.168.26.100的6777端口的UDP数据包并将其发送出去。
>>> ans,unans=sr( IP(dst="192.168.26.100")/UDP(dport=6777) )
✦对这个请求的回应进行监听,如果得到了回应,当然这个回应是ICMP类型的,就证明目标在线,并打印输出这个主机的IP地址。
>>> ans.summary(lambda (s,r): r.sprintf("%IP.src% is alive"))
三、端口扫描
1、基于TCP全开的端口扫描技术
✦TCP全开扫描:如果目标端口是开放的,那么在接到主机端口发出的SYN请求之后,就会返回一个SYN+ACK回应,表示愿意接受这次连接的请求,然后主机端口再回应一个ACK,这样就成功地和目标端口建立了一个TCP连接
如果目标端口是关闭的,那么在接到主机端口发出的SYN请求之后,就会返回一个RST回应,表示不接受这次连接的请求,这样就中断了这次TCP连接
✦构造一个SYN的请求数据包
packet = IP(dst=dst_ip)/TCP(sport=src_port,dport=dst_port,flags="S")
✦然后使用sr1函数将这个数据包发送出去
resp = sr1(packet,timeout=10)
要根据收到对应的应答包来判断目标端口的状态,这时会有以下三种情况。
✦第一种:如果此时resp的值为空,就表示 没有收到来自目标的回应。
使用str(type(resp))来判断这个resp是不是为空,当type(resp)的值转换为字符串之后为"<type'NoneType'>"时就表明resp是空,也就是没有收到任何数据包,判断该端口为closed。 如果不为这个值,则说明resp不为空,也就是收到了回应的数据包,那么就转到后面的第二种或者第三种。
✦第二种:当收到了回应的数据包之后,需要判断一下这个数据包是“SYN+ACK”类型还是“RST”类型的。
在Scapy中数据包的构造是分层的,可以使用haslayer()函数来判断这个函数是否具有某一个协议, 例如,判断一个数据包是否使用了TCP,就可以使用haslayer(TCP)来判断 也可以使用getlayer(TCP)来读取其中某个字段的内容。 可以使用如下语句来判断回应数据包是否为“SYN+ACK”类型。 resp.getlayer(TCP).flags == 0x12
#0x12就是"SYN+ACK" 如果结果为真,表示目标接受TCP请求,需要继续发送一个ACK数据包过去,完成三次握手。
✦第三种:如果resp.getlayer(TCP).flags的结果不是0x12,而是0x14(表示RST),那么表明目标端口是关闭的。
resp.getlayer(TCP).flags == 0x14
案例:编写一个基于TCP全开的完整端口扫描程序
2、基于TCP半开的端口扫描技术
定义: 如果目标端口是开放的,那么在接到主机端口发出的SYN请求之后,就会返回一个SYN+ACK回应,表示愿意接受这次连接的请求,然后主机端口不再回应一个ACK,而是发送一个 RST 表示中断这个连接。这样实际上并没有建立好完整的TCP连接,所以称为半开。
✦如果目标端口是关闭的,半开扫描和全开扫描没有区别
✦当TCP连接的数据包被屏蔽时(filtered状态),一般会返回如下所示的几种ICMP错误消息
案例:
3、服务扫描
①利用抓取软件banner的方式
✦首先引入需要的Socket库: import socket
✦然后初始化一个TCP类型的Socket: s=socket.socket()
✦使用这个Socket去连接目标127.0.0.1的21号端口(测试使用的本机地址): s.connect(("127.0.0.1", 21))
✦连接成功之后,向目标发送任意的一段数据: s.send('111111')
✦目标会将自己的banner作为应答信息返回: banner = s.recv(1024)
✦关闭这个连接: s.close()
✦打印输出得到的banner: print('Banner: {}'.format(banner))
案例:
②使用更为强大的Nmap库
✦扫描的过程很简单,核心语句变成了nm.scan(target, port,"-sV"),关键是对扫描结果的处理