windows 和linux单个包嗅探
#-*-coding:utf-8-*-
import socket
import os
#监听的主机
host = "192.168.2.249"
#创建原始套接字,并绑定
if os.name == "nt":#判断系统平台
socket_protocol = socket.IPPROTO_IP
else:
socket_protocol = socket.IPPROTO_ICMP
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
#捕获的时候包含IP头
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
#win下开启IOCTL启用混杂模式
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
print sniffer.recvfrom(65565)
#对应关闭
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF
IP头结构
后面使用CTYPES模块创建类C结构
然后使用PYTHON套接字对IP头解密。
先简单了解下IP头结构
IP头部,总长度20字节
typedef struct _ip_hdr
{
#if LITTLE_ENDIAN
unsigned char ihl:4; //首部长度
unsigned char version:4, //版本
unsigned char version:4, //版本
unsigned char ihl:4; //首部长度
unsigned char tos; //服务类型
unsigned short tot_len; //总长度
unsigned short id; //标志
unsigned short frag_off; //分片偏移
unsigned char ttl; //生存时间
unsigned char protocol; //协议
unsigned short chk_sum; //检验和
struct in_addr srcaddr; //源IP地址
struct in_addr dstaddr; //目的IP地址
}ip_hdr;
PYTHON代码
#-*-coding:utf-8-*-
import socket
import os
import struct
from ctypes import *
#监听主机
host = "192.168.2.249"
#ip头定义
class IP(Structure):
_fields_ = [
("ihl", c_ubyte,4),
("version", c_ubyte,4),
("tos", c_ubyte),
("len", c_ushort),
("id", c_ushort),
("offset", c_ushort),
("ttl", c_ubyte),
("protocol_num",c_ubyte),
("sum", c_ushort),
("src", c_ulong),
("dst", c_ulong)
]
def __new__(self,socket_buffer=None):
return self.from_buffer_copy(socket_buffer)
def __init__(self,socket_buffer=None):
#协议字段跟协议名对应,常见的有如:
#1 ICMP
#2 IGMP
#6 TCP
#17 UDP
#88 IGRP
#89 OSPF
self.protocol_map = {1:"ICMP",6:"TCP",17:"UDP"}
#转换下可读性更强的IP地址
self.src_address = socket.inet_ntoa(struct.pack("<L",self.src))
self.dst_address = socket.inet_ntoa(struct.pack("<L",self.dst))
#协议类型
try:
self.protocol = self.protocol_map[self.protocol_num]
except:
self.protocol = str(self.protocol_num)
#创建原始套接字,并绑定,跟之前的代码差不多
if os.name == "nt":
socket_protocol = socket.IPPROTO_IP
else:
socket_protocol = socket.IPPROTO_ICMP
sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)
sniffer.bind((host, 0))
#捕获的时候包含IP头
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
try:
while True:
#读取数据包
raw_buffer = sniffer.recvfrom(65565)[0]
#将缓冲数据的前20字节按IP头格式解析
ip_header = IP(raw_buffer[0:20])
#输出双方IP
print "Protocol:%s %s -> %s" % (ip_header.protocol,
ip_header.src_address,
ip_header.dst_address)
except KeyboardInterrupt:
if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
开启上面代码,另一个终端随便PING一个地址,
WINDOWS下可以捕获TCP跟UDP,linux下只能捕获ICMP
效果:
ping www.baidu.com PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data. 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=56 time=13.2 ms 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=2 ttl=56 time=14.0 ms 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=3 ttl=56 time=13.4 ms 64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=4 ttl=56 time=13.4 ms
root@myspuerkali:~/python# python '/root/python/sniffer_ip_haader_decode.py' Protocol:ICMP 14.215.177.38 -> 192.168.2.249 Protocol:ICMP 14.215.177.38 -> 192.168.2.249 Protocol:ICMP 14.215.177.38 -> 192.168.2.249 Protocol:ICMP 14.215.177.38 -> 192.168.2.249 Protocol:ICMP 14.215.177.38 -> 192.168.2.249
总结
具体IP头结构详细解析自行百度,
后面会根据这前提来解析ICMP,跟制作一个扫描主机存活的工具