0

0

Python中十六进制地址到字节序列转换的正确姿势与常见误区

DDD

DDD

发布时间:2025-09-25 09:43:01

|

313人浏览过

|

来源于php中文网

原创

Python中十六进制地址到字节序列转换的正确姿势与常见误区

本文深入探讨了在Python中将十六进制地址(如内存地址)转换为特定字节序列的方法,尤其关注在处理大小端序和Python字节字符串表示时可能遇到的常见困惑。文章详细介绍了struct模块的pack函数作为实现此转换的推荐方案,并澄清了pwnlib等库函数的正确用法,强调了Python字节字符串显示方式的细节,旨在帮助开发者准确、高效地实现十六进制地址到字节序列的转换。

在逆向工程、网络编程或系统级开发中,我们经常需要将一个十六进制的地址(例如 0x7ffd6fa90940)转换为其对应的字节序列表示,通常是小端序(little-endian),就像在gdb等调试器中看到的那样,例如 b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00'。然而,初次尝试时,开发者可能会发现python内置函数或常用库的输出与预期不符,这往往是由于对字节表示、大小端序以及字符串处理方式的误解所致。

Python字节字符串表示的陷阱

一个常见的困惑点在于Python bytes 对象在打印时的显示方式。例如,b'\x40' 和 b'@' 在Python中表示的是同一个字节值,即十六进制的 0x40。同样,b'\x6f' 和 b'o' 都代表 0x6F,而 b'\t' 和 b'\x09' 都代表 0x09。Python在打印 bytes 对象时,会尝试将其中的可打印ASCII字符直接显示,而将不可打印或非ASCII字符显示为十六进制转义序列(如 \xNN)。这种显示上的差异,导致许多开发者误以为两种形式的字节序列是不同的,但实际上它们在底层是完全等价的。

# 验证字节表示的等价性
print(b'\x40' == b'@')  # True
print(b'\x6f' == b'o')  # True
print(b'\x09' == b'\t')  # True

理解这一点是解决后续转换问题的关键。

常见转换方法的分析与纠正

让我们分析一些常见的尝试以及它们为何可能导致误解:

1. 使用 binascii.unhexlify

binascii.unhexlify 函数用于将十六进制字符串转换为字节序列。它按照大端序(big-endian)的方式,将每两个十六进制字符解释为一个字节。

立即学习Python免费学习笔记(深入)”;

import binascii

addr_hex_str = '0x7ffd6fa90940'[2:] # 移除'0x'前缀
# 为了得到8字节,这里假设用户可能尝试补齐,但实际上这会改变原始地址的含义
# 如果原始地址是6字节,直接unhexlify会得到6字节
# 如果想得到8字节,需要先将整数转换为定长十六进制字符串
# 假设我们想处理 '7ffd6fa90940' 这个序列
addr_bytes_big_endian = binascii.unhexlify(addr_hex_str)
print(f"[DEBUG] binascii.unhexlify: {addr_bytes_big_endian}")
# 输出: b'\x7f\xfd\x6f\xa9\x09@' (注意:这里是6字节,因为原始十六进制字符串是12位,即6字节)
# 如果想要8字节,需要先将数字补齐到16位十六进制字符串
# 例如,0x7ffd6fa90940 作为一个64位整数,其十六进制表示是 '00007ffd6fa90940'
addr_padded_hex_str = '0000' + addr_hex_str # 补齐到16位十六进制字符串
addr_bytes_padded_big_endian = binascii.unhexlify(addr_padded_hex_str)
print(f"[DEBUG] binascii.unhexlify (padded): {addr_bytes_padded_big_endian}")
# 输出: b'\x00\x00\x7f\xfd\x6f\xa9\x09@'

binascii.unhexlify 仅仅是机械地将十六进制字符对转换为字节,它不关心数字的“值”或“大小端序”,只处理字符串的字面顺序。因此,它不能直接将一个整数按小端序转换为字节序列。如果需要小端序,还需要手动反转字节序列。

2. 使用 pwnlib.util.packing 模块

pwnlib 库是CTF(Capture The Flag)比赛中常用的工具,其 util.packing 模块提供了方便的打包(pack)和解包(unpack)函数。

ImgGood
ImgGood

免费在线AI照片编辑器

下载
import pwnlib.util.packing

addr_int = 0x7ffd6fa90940

# 使用 p64 打包为64位小端序字节
addr_p64 = pwnlib.util.packing.p64(addr_int, endian='little')
print(f"[DEBUG] pwnlib.util.packing.p64 (little-endian): {addr_p64}")
# 输出: b'@\t\xa9o\xfd\x7f\x00\x00'

# 使用 pack 函数,指定字长和端序
addr_pack = pwnlib.util.packing.pack(addr_int, word_size=64, endianness='little')
print(f"[DEBUG] pwnlib.util.packing.pack (little-endian): {addr_pack}")
# 输出: b'@\t\xa9o\xfd\x7f\x00\x00'

这里,pwnlib 的 p64 和 pack 函数实际上已经正确地将 0x7ffd6fa90940 这个整数转换成了小端序的8字节序列 b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00'。之所以看起来与预期 b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00' 不同,仅仅是因为Python在打印时将 0x40 显示为 @,将 0x6f 显示为 o,将 0x09 显示为 \t。实际上,这两个字节序列是完全相同的。

推荐的解决方案:struct 模块

Python的 struct 模块是处理二进制数据打包和解包的标准库。它提供了强大的功能来将Python值转换为C结构体表示的字节序列,反之亦然,并能灵活控制字节顺序和数据类型。

要将一个十六进制地址(作为整数)转换为小端序的字节序列,特别是对于指针或地址这类平台相关的类型,struct.pack 是一个非常合适的选择。

import struct

addr_int = 0x7ffd6fa90940

# 使用 struct.pack
# 格式字符串 '@P' 的含义:
# '@' 表示使用本地字节序和对齐方式。在大多数x86/x64系统上,这意味着小端序。
# 'P' 表示一个 'void *' 类型,它会根据平台自动调整为合适的指针大小(例如,在64位系统上是8字节)。
packed_addr = struct.pack("@P", addr_int)
print(f"[DEBUG] struct.pack('@P'): {packed_addr}")
# 输出: b'@\t\xa9o\xfd\x7f\x00\x00'

# 或者直接使用 'P',通常也会是本地字节序
packed_addr_P = struct.pack("P", addr_int)
print(f"[DEBUG] struct.pack('P'): {packed_addr_P}")
# 输出: b'@\t\xa9o\xfd\x7f\x00\x00'

# 如果需要明确指定小端序,可以使用 '<Q' (小端序,unsigned long long,8字节)
packed_addr_little_endian = struct.pack("<Q", addr_int)
print(f"[DEBUG] struct.pack('<Q'): {packed_addr_little_endian}")
# 输出: b'@\t\xa9o\xfd\x7f\x00\x00'

# 验证其与期望的字节序列是否一致
expected_bytes = b'\x40\x09\xa9\x6f\xfd\x7f\x00\x00'
print(f"[DEBUG] struct.pack结果与预期一致: {packed_addr == expected_bytes}")
# 输出: True

struct.pack 结合 P 格式符,能够以最符合平台惯例的方式处理地址转换。如果需要更精细的控制,例如强制大端序,可以使用 > 字符,或者强制小端序使用 < 字符,配合 Q(无符号长长整型,8字节)等类型符。

总结与注意事项

  1. 理解字节表示: Python bytes 对象在打印时,会将可打印的ASCII字符直接显示,而将其他字节显示为 \xNN 形式。b'@' 和 b'\x40' 表示的是同一个字节值。这是导致许多误解的根本原因。
  2. struct 模块是首选: 对于将整数(如内存地址)转换为特定大小和端序的字节序列,struct.pack 是Python标准库中功能最强大且推荐的工具。使用 @P 或 <Q 等格式字符串可以灵活控制转换行为。
  3. pwnlib 库同样有效: pwnlib.util.packing.p64 和 pack 函数在指定 endian='little' 时,也能够正确地生成小端序的字节序列。如果您的项目已经使用了 pwnlib,可以继续使用这些函数。
  4. binascii.unhexlify 的局限性: unhexlify 仅将十六进制字符串转换为字节序列,不涉及整数到字节的端序转换逻辑。如果需要处理整数,应先将整数转换为定长十六进制字符串,然后可能需要手动进行字节反转以适应不同端序。
  5. 验证结果: 始终通过直接比较字节序列(例如 packed_addr == b'\x40\x09...')来验证转换结果,而不是仅仅依赖于打印输出的视觉形式。

通过理解Python字节字符串的表示方式,并选择合适的工具(如 struct 或 pwnlib),您可以准确无误地完成十六进制地址到字节序列的转换。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

338

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

225

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

138

2026.02.12

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1229

2024.03.22

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号