嗅探
程序接收数据包的过程:
1.数据包在传播介质中流动时,网络中的每个网卡都能收到所有的数据帧,这些数据帧会被复制到网卡的内存中,然后检查目的MAC地址,是否为自己的MAC地址,是,则会通过直接存储器(DMA)的方式被复制到操作系统内核的缓存中,否则拒绝接收。然后网卡会以中断的方式告诉CPU,接收到了新数据,CPU会将这些数据从缓存复制到一个队列中(链路层驱动),为新数据的到来腾出空间。
2.然后通过协议栈,检查网络层头部,目的IP地址,目的IP地址不是自己的IP,会进行丢弃,在检查传输层的目的端口,交给相应的程序。会依次去掉各层的头部,交给程序的是数据部分。
如下图:
Q: Sniffer程序位于用户空间部分,想观察到完整的(包含首部信息)、未经处理的、没有进行丢弃的数据包,怎么办?
A: OS内核 为嗅探程序 提供了 一个Raw Socket API ,当数据包到达链路层驱动位置,会进行复制,通过raw socket 交给嗅探程序,如果有多个嗅探程序,会复制多份,分别交付。如下图:
Sniffer程序并不需要获得所有的报文,可能只需要获得其中的一小部分报文,比如UDP报文,这里就需要进行过滤,UNIX系统添加了一个BSD 数据包过滤器(BSD packet filter,BPF),如下图:
Q:为什么不在Sniffer程序处过滤,而在OS内核里面进行过滤?
A: 可以节省资源,在数据包复制之前进行过滤,之后进行复制的数据包相应大大减少。
注意:Sniffer程序,嗅探的是收包的过程。(站在攻击者的角度)
伪造
正常的应用程序 仅仅向OS 内核提供数据,目的IP地址,目的端口等信息,其他构造数据包的过程都交给OS内核去完成,而不能随意的去构造各个包头。与嗅探一样,这列也可用raw socket API,进行数据包的构造,然后交给下层,发送出去。如下图:
注意:该图是简化的图,大体理解一下过程,没有具体提及OS内核中的链路层操作。
另外,进行伪造,一般是发包的过程。(站在攻击者的角度)
SEED Sniff and Spoof lab:
from scapy.all import *
def spoof_pkt(pkt):
if ICMP in pkt and pkt[ICMP].type==8:
print("Original Packet...")
print("Source IP:",pkt[IP].src)
print("Destination IP:",pkt[IP].dst)
ip = IP(src=pkt[IP].dst,dst=pkt[IP].src,ihl=pkt[IP].ihl)
ip.ttl = 99
icmp = ICMP(type=0,id=pkt[ICMP].id,seq=pkt[ICMP].seq)
if pkt.haslayer(Raw):
data = pkt[Raw].load
newpkt = ip/icmp/data
else:
newpkt = ip/icmp
print("Spoof Packet...")
print("Source IP: ",newpkt[IP].src)
print("Destination IP:",newpkt[IP].dst)
send(newpkt,verbose=0)
pkt=sniff(filter='icmp and src host 10.0.2.4',prn = spoof_pkt)
具体实验指导书,可见:https://seedsecuritylabs.org/