从十六进制字符串到整数再到十六进制字符串
我在用Scapy这个工具在Python里伪造数据包,但我需要手动修改一个特定数据包里的某些位(Scapy不支持这个),所以我这样做:
首先,我把数据包p转换成十六进制字符串,然后再转换成十进制,最后变成二进制数字。我修改我感兴趣的位,接着再转换回数据包。不过,我在把它转换回原来的十六进制字符串格式时遇到了麻烦……
# I create a packet with Scapy
In [3]: p = IP(dst="www.google.com") / TCP(sport=10000, dport=10001) / "asdasdasd"
In [6]: p
Out[6]: <IP frag=0 proto=tcp dst=Net('www.google.com') |<TCP sport=webmin dport=10001 |<Raw load='asdasdasd' |>>>
# I convert it to a hex string
In [7]: p_str = str(p)
In [8]: p_str
Out[8]: "E\x00\x001\x00\x01\x00\x00@\x06Q\x1c\x86;\x81\x99\xad\xc2t\x13'\x10'\x11\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x19a\x00\x00asdasdasd"
# I convert it to an integer
In [9]: p_int = int(p_str.encode('hex'), 16)
In [10]: p_int
Out[10]: 2718738542629841457617712654487115358609175161220115024628433766520503527612013312415911474170471993202533513363026788L
# Finally, I convert it to a binary number
In [11]: p_bin = bin(p_int)
In [11]: p_bin
Out[11]: '0b1000101000000000000000000110001000000000000000100000000000000000100000000000110010100010001110010000110001110111000000110011001101011011100001001110100000100110010011100010000001001110001000100000000000000000000000000000000000000000000000000000000000000000101000000000010001000000000000000011001011000010000000000000000011000010111001101100100011000010111001101100100011000010111001101100100'
# ... (I modify some bits in p_bin, for instance the last three)...
In [12]: p_bin_modified = p_bin[:-3] + '000'
# I convert it back to a packet!
# First to int
In [13]: p_int_modified = int(p_bin_modified, 2)
In [14]: p_int_modified
Out[14]: 2718738542629841457617712654487115358609175161220115024628433766520503527612013312415911474170471993202533513363026784L
# Then to a hex string
In [38]: hex(p_int_modified)
Out[38]: '0x45000031000100004006511c863b8199adc274132710271100000000000000005002200019610000617364617364617360L'
哎呀!看起来跟原来的十六进制字符串格式不太一样。有没有什么好主意可以解决这个问题?
编辑: 好的,我找到了decode('hex'),这个方法可以处理十六进制数字,但它破坏了整个转换的可逆性……
In [73]: hex(int(bin(int(str(p).encode('hex'), 16)), 2)).decode('hex')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-73-f5b9d74d557f> in <module>()
----> 1 hex(int(bin(int(str(p).encode('hex'), 16)), 2)).decode('hex')
/usr/lib/python2.7/encodings/hex_codec.pyc in hex_decode(input, errors)
40 """
41 assert errors == 'strict'
---> 42 output = binascii.a2b_hex(input)
43 return (output, len(input))
44
TypeError: Odd-length string
编辑2:如果我去掉转换成二进制数字的步骤,我也会遇到同样的错误……
In [13]: hex(int(str(p).encode('hex'), 16)).decode('hex')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/home/ricky/<ipython-input-13-47ae9c87a5d2> in <module>()
----> 1 hex(int(str(p).encode('hex'), 16)).decode('hex')
/usr/lib/python2.7/encodings/hex_codec.pyc in hex_decode(input, errors)
40 """
41 assert errors == 'strict'
---> 42 output = binascii.a2b_hex(input)
43 return (output, len(input))
44
TypeError: Odd-length string
1 个回答
1
好的,我解决了这个问题。
我需要去掉长整型数字后面的 L
和十六进制表示前面的 0x
。
In [76]: binascii.unhexlify(hex(int(binascii.hexlify(str(p)), 16)).lstrip('0x').rstrip('L')) == str(p)
Out[76]: True