You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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'

问题原因

  1. 字节序混淆:你混淆了内存实际存储的小端字节序和字符串显示的大端顺序。x86架构是小端存储,栈地址在内存中就是p64输出的b'@\t\xa9o\xfd\x7f\x00\x00',这和GDB的hexdump显示完全一致——比如GDB里[40 dc ff ff ff 7f 00 00]对应地址0x7fffffffdc40,内存中第一个字节40正是地址的最后两位,符合小端存储规则。
  2. 字符串转字节错误:自定义实现里直接拼接\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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:22:15