#!/usr/bin/python
#coding=utf-8
from scapy.all import *
import time
import optparse
# 为避免IPy库中的IP类与Scapy库中的IP类冲突,重命名为IPTEST类
from IPy import IP as IPTEST
ttlValues = {}
THRESH = 5
# 检查数据包的IP层,提取出源IP和TTL字段的值
def testTTL(pkt):
try:
if pkt.haslayer(IP):
ipsrc = pkt.getlayer(IP).src
ttl = str(pkt.ttl)
#print "[+] Pkt Received From: " + ipsrc + " with TTL: " + ttl
checkTTL(ipsrc, ttl)
except:
pass
def checkTTL(ipsrc, ttl):
# 判断是否是内网私有地址
if IPTEST(ipsrc).iptype() == 'PRIVATE':
return
# 判断是否出现过该源地址,若没有则构建一个发往源地址的ICMP包,并记录回应数据包中的TTL值
if not ttlValues.has_key(ipsrc):
#ICMP发现扫描
#pkt = sr1(IP(dst=ipsrc) / ICMP(), retry=0, timeout=1, verbose=0)
pkt = sr1(IP(dst=ipsrc) / ICMP() / "zhou")
print pkt
ttlValues[ipsrc] = pkt.ttl
# 若两个TTL值之差大于阈值,则认为是伪造的源地址
if abs(int(ttl) - int(ttlValues[ipsrc])) > THRESH:
print '\n[!] Detected Possible Spoofed Packet From: ' + ipsrc
print '[!] TTL: ' + ttl + ', Actual TTL: ' + str(ttlValues[ipsrc])
def main():
parser = optparse.OptionParser("[*]Usage python spoofCheckTTL.py -i <interface> -t <thresh>")
parser.add_option('-i', dest='iface', type='string', help='specify network interface')
parser.add_option('-t', dest='thresh', type='int', help='specify threshold count ')
(options, args) = parser.parse_args()
if options.iface == None:
conf.iface = 'eth0'
else:
conf.iface = options.iface
if options.thresh != None:
THRESH = options.thresh
else:
THRESH = 5
sniff(prn=testTTL, store=0)
if __name__ == '__main__':
main()
重点说明一下,避免大家走一些弯路,这段代码中最重要部分就是:
# 判断是否出现过该源地址,若没有则构建一个发往源地址的ICMP包,并记录回应数据包中的TTL值
if not ttlValues.has_key(ipsrc):
#ICMP发现扫描
#pkt = sr1(IP(dst=ipsrc) / ICMP(), retry=0, timeout=1, verbose=0)
pkt = sr1(IP(dst=ipsrc) / ICMP() / "zhou")
ttlValues[ipsrc] = pkt.ttl
其中原文中的
#pkt = sr1(IP(dst=ipsrc) / ICMP(), retry=0, timeout=1, verbose=0)
我已注释掉了,因为在调试过过程,PKT结果一直是None,所我翻查了关于
scapy学习icmp报文资料,将代码改为
pkt = sr1(IP(dst=ipsrc) / ICMP() / "zhou") 后,结果正常输出。有兴趣有朋友可以深入研究。