一个合格的僵尸机是实现僵尸扫描的关键因素,僵尸至少要保证在进行扫描阶段不会产生其它的 IP 包,即是不会与我们主机之外的任何机器进行第三层的 IP 通讯,至少在我们控制其进行扫描的阶段不可以,否则将直接导致 IPID 的数值增大
何为合适的僵尸机:1)足够闲置;2)它的 IPID 必须是递增的,0 和随机都不可以。然而现在大部分主流的 OS 的 IPID 都是随机产生的,但是早期的 xp,比如 xp2000,xp2003 都是递增的 IPID。
僵尸扫描的过程
三次握手:
僵尸扫描过程:
扫描者主机对 Zombie(僵尸机)发送 SYN/ACK 包,然后 Zombie(假设此时系统产生的 IPID 为 x)会回给主机一个 RST,主机将会得到 Zombie 的 IPID,然后扫描主机向目标机器发送一个 SYN 包,有所不同的是,此时扫描主机会伪造一个伪装成 Zombie 的 IP(即是 x)向目标主机发送 SYN 包。如果目标的端口开放,便会向 Zombie 返回一个 SYN/ACK 包,但是 Zombie 并没有发送任何包,zombie 会向目标主机发送 RST,此时 Zombie 的 IPID 将会增加 1:x+1,最后,扫描者主机对 Zombie(僵尸机)发送 SYN/ACK 包,然后 Zombie 会回给主机一个 RST,此时 IPID=x+2
若果目标主机的端口并未开放,那么目标主机也会向 Zombie 发送一个 RST,但是 Zombie 收到 RST 包不会有任何反应,所以 IPID 不会改变(依旧是 x)。最后扫描者主机再向 Zombie 发送一个 SYN/ACK,同样的 Zombie 会向扫描者主机发送一个 RST 包,此时 Zombie 的 IPID 将变成(x+1). 通过 IPID 的数值来判断目标机器的端口是否开放
测试
扫描主机 kali: ip:192.168.0.5
zombie kali: ip:192.168.0.6
目标主机 Windows: ip:192.168.0.7
scapy 实现僵尸扫描
构造 request zombie 包:
>>> i=IP() #构造 ip 包头
>>> t=TCP() #构造 tcp 包头
>>> rz=(i/t) #request_zombie,构造发送给僵尸机的数据包,将发送给 zombie Kali
>>> rt=(i/t) #request_target, 构造发送给目标主机的数据包,将发送给 windows
>>> rz[IP].dst="192.168.0.6"// 定义 zombie 的 ip 地址
>>> rz[TCP].dport=445 // 定义发送到 zombie 的端口,务必确保这个端口是开启的端口,445 端口是 win 中默认开启的
>>> rz[TCP].flags="SA"// 定义向 zombie 发送的数据包是 SYN/ACK 包
构造 request target 包:
>>> rt[IP].src="192.168.0.6"// 定义 rt 包的源 ip 地址,直接伪造为 zombie Kali 的 IP
>>> rt[IP].dst="192.168.0.7"// 定义 rt 包的目的 ip,就是目标 windows 的 IP
>>> rt[TCP].dport=25// 定义 rt 包扫描的端口
>>> rt[TCP].flags="S"// 定义发送的 rt 包为 SYN 包
然后将会发送两次 rz 包,一次 rt 包,最后在对结果进行分析。
>>>az1=sr1(rz) #向 zombie 发第一个包
Begin emission:
Finished to send 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
>>>at=sr1(rt,timeout=1) #向目标机发包,由于我们不会收到回包,因为给 zombie 了,所以需要设置超时时间
Begin emission:
Finished to send 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
>>>az2=sr1(rz) #向 zombie 发送第二个包
Begin emission:
Finished to send 1 packets.
*
Received 1 packets, got 1 answers, remaining 0 packets
分析 az1 与 az2 的 IPID:
>>> az1
<IP version=4L ihl=5L tos=0x0 len=40 id=436 flags= frag=0L ttl=128 src=192.168.0.6 dst=192.168.0.5 options=[]
>>> az2
<IP version=4L ihl=5L tos=0x0 len=40 id=438 f proto=tcp chksum=0xac5 src=192.168.0.6 dst=192.168.0.5
通过分析发现目标的 25 是开放的。
Python 脚本实现僵尸扫描
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
from scapy.all import *
def ipid(zombie):# 定义一个 ipid 函数,同时定义一个 zombie 变量。该函数的作用是探测一主机是否可以作为僵尸机
reply1 = sr1(IP(dst=zombie)/TCP(flags="SA"), timeout=2,verbose=0)# 向 zombie 发送一个 syn/ack 包
send(IP(dst=zombie)/TCP(flags="SA"),verbose=0)#send()与 sr1()方法的区别是:sr1 发送出去一个包以后会在接收对方的一个回包,而 send 方法不会接收包
reply2 = sr1(IP(dst=zombie)/TCP(flags="SA"),timeout=2,verbose=0)# 紧接着在向僵尸机发送一个 syn/ack 包
if reply2[IP].id == (reply1[IP].id+2):# 根据发送的三个来判断僵尸机是否足够空闲, 并且 ipid 序号是否为递增的。print("IPID secquence is incremental and target appears to be idle,ZOMBIE LOCATED")
response = raw_input("Do you want to use this zombie to perform a scan?(Y or N):")
if response == "Y": #是否使用该僵尸机执行扫描
target = raw_input("Enter the IP address of the target system:") #输入要扫描的目标主机 ip
zombiescan(target, zombie)
else:
print("Either the IPID secquence is not incremental or the target if not idle. NOT A Good zombie")
def zombiescan(target, zombie):
print("\nScanning target"+target+"with zombie"+zombie)
print"\n-------Open Ports On Target-----\n"
for port in range(1,100):# 扫描目标 1 -100 的端口
try:
start_val = sr1(IP(dst=zombie)/TCP(flags="SA",dport=port),timeout=2,verbose=0)
send(IP(src=zombie,dst=target)/TCP(flags="S",dport=port),verbose=0)
end_val = sr1(IP(dst=zombie)/TCP(flags="SA"),timeout=2,verbose=0)
if end_val[IP].id == (start_val[IP].id+2):
print(port)
except:
pass
#主函数内容
print"------Zombie Scan Suite------\n" #这是僵尸扫描套件程序
print"1.----Identity Zombie Host\n" #识别僵尸机
print"2.----Preform Zombie Scan\n" #执行扫描过程
aws = raw_input("Select an Option (1 or 2):")
if aws == "1":
zombie = raw_input("Enter IP address to test IPID sequence:")
ipid(zombie)
else:
if aws == "2":
zombie = raw_input("Enter IP address for zombie System:\n")
target = raw_input("Enter IP address for Scan Target:\n")
zombiescan(target,zombie)
NMAP 实现僵尸扫描
同样的,如果使用 NMAP 进行僵尸扫描,首先找到合适的僵尸机是最关键的。
除此以为,NMAP 本身提供了大量用于僵尸扫描的脚本程序(大概 400 多种),可以在 NMAP 中调用这些脚本程序来判断一个主机是否是一个合适的僵尸机。同样这些脚本所遵循也是根据对方 IPIID 是否递增来判断的。
NMAP 扫描指定端口判断主机是否是合适的 zombie
root@kali:~# nmap -p445 192.168.86.132 --script=ipidseq.nse
Starting Nmap 7.01 (https://nmap.org) at 2016-05-28 05:12 EDT
Nmap scan report for bogon (192.168.86.132)
Host is up (0.00033s latency).
PORT STATE SERVICE
445/tcp open microsoft-ds
MAC Address: 00:0C:29:10:88:B3 (VMware)
Host script results:
|_ipidseq: Incremental!
Nmap done: 1 IP address (1 host up) scanned in 0.49 seconds
可以看到该主机的 ipid 是递增的, 僵尸找到了,开始进行扫描
NMAP 僵尸扫描
root@kali:~# nmap 192.168.0.7 -sI 192.168.0.6 -Pn -P 0-100
Starting Nmap 7.01 (https://nmap.org) at 2016-05-28 05:16 EDT
Idle scan using zombie 192.168.0.6 (192.168.0.6:80); Class: Incremental
Nmap scan report for bogon (192.168.0.7)
Host is up (0.051s latency).
Not shown: 977 closed|filtered ports
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
25/tcp open smtp
53/tcp open domain
80/tcp open http
111/tcp open rpcbind
139/tcp open netbios-ssn
445/tcp open microsoft-ds
512/tcp open exec
513/tcp open login
514/tcp open shell
1099/tcp open rmiregistry
1524/tcp open ingreslock
2049/tcp open nfs
2121/tcp open ccproxy-ftp