Python字节编码函数异常:栈地址十六进制转字节表示问题
栈地址十六进制转字节表示问题
我想把栈地址类十六进制数(比如0x7ffd6fa90940)转换成对应字节表示b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00',要和GDB中的显示格式一致,比如pwndbg的hexdump输出:
pwndbg> hexdump $rsp \32 +#### 0x7fffffffdc## 0 1 2 3 4 5 6 7 8 9 A B C D E F │ │ +0000 0x7fffffffdc30 e0 af 4b 00 15 00 00 00 [40 dc ff ff ff 7f 00 00] │..K.....│........│ +0010 0x7fffffffdc40 25 39 24 73 00 00 00 00 [50 dc ff ff ff 7f 00 00] │%9$s....│P.......│
但我用以下方法都没得到预期结果:
import pwnlib.util.packing import binascii addr = '0000' + '0x7ffd6fa90940'[2:] addr = binascii.unhexlify(addr) print("[DEBUG] addr: {}".format(addr)) # 输出大端:b'\x00\x00\x7f\xfdo\xa9\t@' # 与预期 b'\x7f\xfd\x6f\xa9\x09\x40' 不符 addr = 0x7ffd6fa90940 addr = pwnlib.util.packing.p64(addr, endian='little') print("[DEBUG] addr: {}".format(addr)) # 输出小端:b'@\t\xa9o\xfd\x7f\x00\x00' # 与预期 b'\x7f\xfd\x6f\xa9\x09\x40' 不符 addr = 0x7ffd6fa90940 addr = pwnlib.util.packing.pack(addr, word_size=64, endianness='little') print("[DEBUG] addr: {}".format(addr)) # 输出小端:b'@\t\xa9o\xfd\x7f\x00\x00' # 与预期 b'\x7f\xfd\x6f\xa9\x09\x40' 不符 # 自定义实现: addr = '0000' + '0x7ffd6fa90940'[2:] addr = ''.join(reversed(['\\x'+addr[i:i+2] for i in range(0, len(addr), 2)])) print("[DEBUG] addr: {}".format(addr)) # 输出小端表示的字符串:\x40\x09\xa9\x6f\xfd\x7f\x00\x00 # 但不知道怎么转成实际字节:b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00' # addr = addr.encode('utf-8').replace(b'\\\\',b'\\') print("[DEBUG] addr: {}".format(addr)) # 结果:b'\\x40\\x09\\xa9\\x6f\\xfd\\x7f\\x00\\x00'
问题原因
- 字节序混淆:你混淆了内存实际存储的小端字节序和字符串显示的大端顺序。x86架构是小端存储,栈地址在内存中就是
p64输出的b'@\t\xa9o\xfd\x7f\x00\x00',这和GDB的hexdump显示完全一致——比如GDB里[40 dc ff ff ff 7f 00 00]对应地址0x7fffffffdc40,内存中第一个字节40正是地址的最后两位,符合小端存储规则。 - 字符串转字节错误:自定义实现里直接拼接
\x字符串再encode,无法让Python识别为字节转义符,因为字符串中的\\x只是普通字符,替换后也不会被解析为字节转义。
正确实现方法
方法1:基于pwnlib(推荐,符合内存实际存储)
如果需要得到内存中实际存储的字节(和GDB显示一致的小端),p64的输出已经正确:
import pwnlib.util.packing addr = 0x7ffd6fa90940 mem_bytes = pwnlib.util.packing.p64(addr, endian='little') print(mem_bytes) # 输出 b'@\t\xa9o\xfd\x7f\x00\x00',和GDB内存显示一致
如果非要得到你预期的大端字节对象,只需反转小端字节:
import pwnlib.util.packing addr = 0x7ffd6fa90940 little_endian_bytes = pwnlib.util.packing.p64(addr, endian='little') big_endian_bytes = little_endian_bytes[::-1] print(big_endian_bytes) # 输出 b'\x7f\xfd\x6f\xa9\x09@\x00\x00',与你预期一致
方法2:手动处理十六进制字符串
import binascii addr_hex = '0x7ffd6fa90940'[2:] # 补全到16个字符(对应8字节64位地址) addr_hex_padded = addr_hex.zfill(16) # 直接转成大端字节 big_endian_bytes = binascii.unhexlify(addr_hex_padded) print(big_endian_bytes) # 输出 b'\x7f\xfd\x6f\xa9\x09@\x00\x00'
内容的提问来源于stack exchange,提问作者PatrickSteiner
相关产品推荐
相关产品推荐

