[英]Confused by Pythons ctypes LittleEndianStructure
I'm experimenting with using the ctypes module to parse packets captured using the socket module and I'm confused by what I see when using the LittleEndianStructure
.我正在尝试使用 ctypes 模块来解析使用 socket 模块捕获的数据包,我对使用
LittleEndianStructure
时看到的内容感到困惑。
Using Python 3.6.8 on a CentOS 7 64bit VM, I'm capturing a UDP packet with the payload 0x8401
在 CentOS 7 64 位 VM 上使用 Python 3.6.8,我正在捕获带有有效负载
0x8401
的 UDP 数据包
I then want to parse the payload into the following structure, and print out the field values.然后我想将有效负载解析为以下结构,并打印出字段值。
class MSG(BigEndianStructure):
_fields_ = [
("A", c_ubyte, 4),
("B", c_ubyte, 3),
("C", c_ubyte, 1),
("D", c_ubyte, 4),
("E", c_ubyte, 4)
]
when I use BigEndianStructure
, I get the results I expect当我使用
BigEndianStructure
时,我得到了我期望的结果
MSG
A: 8
B: 2
C: 0
D: 0
E: 1
I then try using LittleEndianStructure
where I expected the payload to be swapped to 0x0184
and produce the following然后我尝试使用
LittleEndianStructure
我希望有效载荷被交换到0x0184
并产生以下
MSG
A: 0
B: 0
C: 1
D: 8
E: 4
However I instead get the following, and I don't understand why.但是,我却得到以下信息,但我不明白为什么。
MSG
A: 4
B: 0
C: 1
D: 1
E: 0
here's the full code.这是完整的代码。 I appreciate any help.
我很感激任何帮助。
import socket
import sys
import struct
from ctypes import *
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_uint32),
("dst", c_uint32)
]
def __new__(self, socket_buffer=None):
return self.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer=None):
pass
class UDP(BigEndianStructure):
_fields_ = [
("sport", c_ushort),
("dport", c_ushort),
("length", c_ushort),
("checksum", c_ushort)
]
def __new__(self, socket_buffer):
return self.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer):
pass
class MSG(LittleEndianStructure):
_fields_ = [
("A", c_ubyte, 4),
("B", c_ubyte, 3),
("C", c_ubyte, 1),
("D", c_ubyte, 4),
("E", c_ubyte, 4)
]
def __new__(self, socket_buffer):
return self.from_buffer_copy(socket_buffer)
def __init__(self, socket_buffer):
pass
def sniff():
eth_length = 14
ip_length = 20
udp_length = 8
msg_length = 2
try:
# Capture all packets
protocol = socket.ntohs(0x0003) # captures all packets
sniffer = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, protocol)
except KeyboardInterrupt:
sys.exit()
while True:
# read a packet
raw_buffer = sniffer.recvfrom(65535)[0]
eth_header = raw_buffer[:eth_length]
eth_payload = raw_buffer[eth_length:]
eth = struct.unpack('!6s6sH', eth_header)
eth_protocol = socket.ntohs(eth[2])
# IP packet
if eth_protocol == 8:
# create an IP header from the first 20 bytes
ip_header = IP(eth_payload[:ip_length])
ip_data = eth_payload[ip_length:]
# UDP packet
if ip_header.protocol_num == 17:
udp_header = UDP(ip_data[:udp_length])
udp_data = ip_data[udp_length:]
if udp_header.dport == 8001:
msg_header = MSG(udp_data[:msg_length])
print("MSG")
print(" A: %s" % msg_header.A)
print(" B: %s" % msg_header.B)
print(" C: %s" % msg_header.C)
print(" D: %s" % msg_header.D)
print(" E: %s" % msg_header.E)
if __name__ == '__main__':
sniff()
The actual little-endian result is fetching bits from the lowest first.实际的 little-endian 结果是从最低的第一个获取位。
Bytes: 84 01字节:84 01
Big endian word 8401 16 (1000010000000001 2 ) and divide the bits starting with high bit:大端字 8401 16 (1000010000000001 2 ) 并除以高位开始的位:
A B C D E
1000 010 0 0000 0001 so ABCDE = 82001
Little endian word 0184 16 (0000000110000100 2 ) and divide the bits starting with the low bit:小端字 0184 16 (0000000110000100 2 ) 并除以低位开始的位:
E D C B A
0000 0001 1 000 0100 so ABCDE = 40110
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.