Python Byte-encoding functions do not work as expected

66 Views Asked by At

I'm trying to convert a hexadecimal number, like the stack address 0x7ffd6fa90940,
into its corresponding Byte representation b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00'.
Just like how it is represented in gdb:

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.......│

I found three functions, but they do not convert the hex number as expected:

import pwnlib.util.packing
import binascii

addr = '0000' + '0x7ffd6fa90940'[2:]
addr = binascii.unhexlify(addr)
print("[DEBUG] addr: {}".format(addr))
# Prints big endian: 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))
# Prints lit endian: 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))
# Prints lit endian: b'@\t\xa9o\xfd\x7f\x00\x00'
#                !=  b'\x7f\xfd\x6f\xa9\x09\x40'

# Custom implementation:
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))
# Prints lit endian notation as a string: \x40\x09\xa9\x6f\xfd\x7f\x00\x00
# But how to convert to actual Bytes?:  b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00'
#
addr = addr.encode('utf-8').replace(b'\\\\',b'\\')
print("[DEBUG] addr: {}".format(addr))
# Results in:   b'\\x40\\x09\\xa9\\x6f\\xfd\\x7f\\x00\\x00'

Why is that and how can it be converted as expected?
Thanks in advance for any hints, links, and answers!

1

There are 1 best solutions below

0
On BEST ANSWER

I'd use the following:

import struct
struct.pack( "@P", 0x7ffd6fa90940 )   # Or just `"P"`

That said, your second and third solutions give what you want.

>>> b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00' == b'@\t\xa9o\xfd\x7f\x00\x00'
True

They are equivalent because

  • b'\x40' and b'@' both produce byte 0x40.
  • b'\x6f' and b'o' both produce byte 0x6F.
  • b'\x09' and b'\t' both produce byte 0x09.