级别:初学者.我目前正在使用原始套接字使用python进行嗅探器.我有一个关于struct module提供的unpack()中使用的格式说明符的一般性问题.因为我们使用此方法根据指定的格式说明符解压缩数据.我见过很多使用unpack()的嗅探器程序来解码十六进制形式的数据包信息.例如,为了提取以下代码的以太网头信息,可以使用:
ethHeader = struct.unpack("!6s6s2s", ethernetHeader)
这里的ethernetHeader是变量,它包含先前从原始套接字捕获的实际以太网头数据.现在我的问题是如何知道哪个格式说明符用于标题?我怎么能提前知道以太网地址是字符串格式还是其他格式?有没有这方面的文件.我读了与unpack()相关的python文档,但没有找到任何信息.类似地,在IP地址的情况下,代码是这样的:
ipAddresses = struct.unpack("!12s4s4s", IPAddresses)
这里的IPAddresses是变量,包含先前从原始套接字捕获的实际IP地址信息.我怎么知道我必须使用字符串作为格式说明符(!12s4s4s).谢谢.
感谢JF Sebastian的暗示.我终于明白了,并且需要一些时间在这里解释一下.通常,我们必须在每个标头的结构中查找C类型,以了解在数据包的不同标头中的每个字段使用哪些C类型.然后我们可以使用这个表来知道哪个格式说明符将代表哪个C类型.例如,在IP头的情况下,结构如下所示:
struct ipheader { unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */ unsigned char ip_tos; unsigned short int ip_len; unsigned short int ip_id; unsigned short int ip_off; unsigned char ip_ttl; unsigned char ip_p; unsigned short int ip_sum; unsigned int ip_src; unsigned int ip_dst; };
对于例如:unsigned char表示为'B',unsigned int表示为'I'.现在我们可以使用这个方法来了解struct.unpack()中应该使用哪些格式说明符来获取IP头的字段值.如果是IP标头,则如下所示:
struct.unpack('!BBHHHBBHII')
但是你应该注意到程序的大部分用途
struct.unpack('!BBHHHBBH4s4s')
.
所以问题出现了为什么在使用unsigned int ip_src;
&unsigned int ip_dst;
's'而不是'I'作为格式说明符的情况下struct.unpack()
.原因是如果'I'用作格式说明符,则该unpack()
方法以整数形式返回IP地址(例如:3232267778).然后,您必须将其转换为实际的IP地址格式(例如:10.0.0.1).通常在互联网上可用的嗅探器程序中,只需socket.inet_ntoa()
用于获取实际的IP地址.此方法接受字符串类型而不是整数类型.这就是为什么在unsigned int ip_src的情况下; &unsigned int ip_dst; 使用's'代替'I'作为struct.unpack()中的格式说明符,以便稍后可以将结果提供给socket.inet_ntoa()以获得实际IP地址格式的IP地址.同样在以太网头的情况下.我们在struct.unpack()中使用's'而不是'B',因为我们需要一个可以稍后输入的字符串,binascii.hexlify()
以便以实际MAC地址格式获取MAC.