等级:初学者。我目前正在使用原始套接字使用python进行嗅探器。 我有一个关于struct module提供的unpack()中使用的格式说明符的一般性问题。因为我们使用此方法根据指定的格式说明符解压缩数据。我见过很多使用unpack()的嗅探器程序来解码十六进制形式的数据包信息。 例如,为了提取以下代码的以太网头信息,可以使用:
ethHeader = struct.unpack("!6s6s2s", ethernetHeader)
这里ethernetHeader是变量,它包含先前从原始套接字捕获的实际以太网头数据。现在我的问题是如何知道哪个格式说明符用于标题?我怎么能提前知道以太网地址是字符串格式还是其他格式?有没有这方面的文件。我读了与unpack()相关的python文档,但没有找到任何信息。类似地,在IP地址的情况下,代码是这样的:
ipAddresses = struct.unpack("!12s4s4s", IPAddresses)
此处IPAddresses是变量,包含先前从原始套接字捕获的实际IP地址信息。我怎么知道我必须使用字符串作为格式说明符(!12s4s4s)。 感谢。
答案 0 :(得分:5)
感谢J.F. Sebastian的暗示。我终于明白了,并且需要一些时间在这里解释一下。通常我们必须在每个标头的结构中查找C类型,以了解在数据包的不同标头中的每个字段使用哪些C类型。然后我们可以使用这个table来知道哪个格式说明符将代表哪个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'用来代替'我'作为struct.unpack()
中的格式说明符。原因是if' I'用作格式说明符,然后unpack()
方法以整数形式返回IP地址(例如:3232267778)。然后,您必须将其转换为实际的IP地址格式(例如:10.0.0.1)。通常在互联网上可用的嗅探器程序中,只需使用socket.inet_ntoa()
来获取实际的IP地址。此方法接受字符串类型而不是整数类型。这就是为什么在unsigned int ip_src的情况下; &安培; unsigned int ip_dst; ' S'用来代替'我'作为struct.unpack()中的格式说明符,以便稍后可以将结果提供给socket.inet_ntoa()以获取实际IP地址格式的IP地址。同样在以太网头的情况下。我们使用'而不是' B'在struct.unpack()中,因为我们需要一个字符串,以后可以将其提供给binascii.hexlify()
,以便以实际的MAC地址格式获取MAC。
答案 1 :(得分:1)
struct.unpack
允许您将包含格式(第一个参数)中指定的C类型的字节序列转换为相应的Python对象(整数,浮点数,字符串)。
它是通用的。
如何知道哪个格式说明符用于标题?我怎么能提前知道以太网地址是字符串格式还是其他格式?有没有这方面的文件。我读了与unpack()相关的python文档,但没有找到任何信息。
struct
模块对您的应用程序可能需要的格式一无所知。它特定于您的应用程序,即在这种情况下,它涉及TCP / IP套件,协议,嗅探器和网络。阅读它以了解ethernetHeader
,IPAddresses
等期望的C类型,然后使用this table创建适当的格式字符串。