Python脚本解密工具:探索PyArmor逆向方案的技术路径
在Python开发领域,PyArmor作为常用的代码保护工具,通过加密和混淆技术为脚本提供安全防护。然而,当需要对加密脚本进行调试、维护或兼容性分析时,专业的解密工具就成为技术探索者的重要装备。本文将深入剖析PyArmor-Unpacker这款Python脚本解密工具的核心功能,对比三种创新解密方案的技术特性,并通过场景化应用指南与问题解决方案,帮助技术探索者构建完整的PyArmor逆向技术体系。
核心功能解析:PyArmor解密技术原理拆解
PyArmor-Unpacker的核心价值在于其实现了对PyArmor加密机制的深度逆向,通过三种差异化技术路径实现加密代码的还原。这些方案分别针对不同的运行环境和加密场景,构建了完整的解密技术矩阵。
动态内存拦截技术
方法一通过内存动态注入实现解密,其核心机制在于拦截PyArmor的加解密函数调用。代码中通过重写handle_armor_enter函数,在__armor_enter__和__armor_exit__关键节点捕获解密后的代码对象。以下是核心实现片段:
def handle_armor_enter(obj: types.CodeType):
raw_code = obj.co_code
try_start = find_first_opcode(obj.co_code, SETUP_FINALLY)
size = calculate_arg(obj.co_code, try_start)
raw_code = raw_code[:try_start + size]
raw_code = raw_code[try_start + 2:]
raw_code += RETURN_OPCODE # 添加返回指令
# 修复绝对跳转指令偏移量
raw_code = bytearray(raw_code)
i = 0
while i < len(raw_code):
op = raw_code[i]
if op in absolute_jumps:
argument = calculate_arg(raw_code, i)
# 调整跳转偏移量
new_arg = argument - (try_start + 2)
extended_args, new_arg = calculate_extended_args(new_arg)
# 更新操作码参数
raw_code[i + 1] = new_arg if not double_jump else new_arg // 2
i += 2
return copy_code_obj(obj, co_code=bytes(raw_code))
这段代码展示了如何通过分析字节码结构,移除PyArmor添加的保护壳代码,修复跳转指令偏移量,最终还原原始代码逻辑。动态注入技术的优势在于可以直接获取运行时解密的代码对象,适用于无法静态分析的复杂加密场景。
审计日志静态捕获方案
方法三则利用Python 3.9+引入的审计日志功能,通过sys.addaudithook注册钩子函数,在marshal.loads调用时捕获加密数据。其核心实现如下:
def log(event, arg):
if event == "marshal.loads" and not triggered and b"frozen" in arg[0]:
try:
triggered = True
code = marshal.loads(arg[0])
code = output_code(code) # 处理代码对象
marshal_to_pyc(DUMP_DIR/filename, code) # 保存解密结果
except Exception as e:
print(traceback.format_exc())
os.kill(os.getpid(), 9)
sys.addaudithook(log)
这种静态分析方法无需运行目标程序,通过拦截序列化数据直接获取解密后的代码对象,具有更高的执行效率和安全性,特别适合处理不需要动态执行的独立模块。
内存补丁限制绕过
针对PyArmor的限制模式保护,项目提供了专门的restrict_bypass.py工具,通过内存补丁技术绕过保护机制:
h_pytransform = ctypes.cdll.LoadLibrary("pytransform\\_pytransform.dll")
pytransform_base = h_pytransform._handle
patch_offset = 0x70A18F80 - pytransform_base
num_nops = 0x70A18FD5 - 0x70A18F80
VirtualProtect(pytransform_base+patch_offset, num_nops, PAGE_EXECUTE_READWRITE, ctypes.byref(oldprotect))
ctypes.memset(pytransform_base+patch_offset, 0x90, num_nops) # 0x90是NOP指令
这段代码通过修改_pytransform.dll的内存页权限,将保护检查代码替换为NOP指令,从而解除PyArmor的运行限制,为解密操作创造有利环境。
创新方案对比:解密技术路径的场景适配分析
三种解密方案各具技术特性,适用于不同的应用场景。通过对比分析其技术原理、实施难度和适用范围,可以为技术探索者提供清晰的方案选择指南。
动态注入方案(方法一)
技术特性:通过注入工具将解密代码注入目标进程,在运行时拦截解密后的代码对象。需要Process Hacker 2等注入工具配合,操作流程相对复杂。
适用场景:
- 需要完整执行流程的复杂加密脚本
- 包含动态生成代码的场景
- Python 3.8及以下版本环境
实施步骤:
- 复制method 1目录下所有文件至目标脚本目录
- 启动加密脚本,使用注入工具注入PyInjector
- 执行
python method_1.py捕获解密代码 - 通过
run.py验证解密结果
该方案的优势在于兼容性强,可处理大多数加密场景,但需要目标程序正常运行,可能触发程序中的反调试机制。
完整转储方案(方法二)
技术特性:在方法一基础上优化了解密代码的完整性,通过改进的代码对象修复技术,生成更完整的.pyc文件。
适用场景:
- 需要保留完整代码结构的场景
- 后续需进行反编译的情况
- 中等复杂度的加密项目
实施差异:
相比方法一,该方案在dumps目录中生成完整的模块转储,包含更多的上下文信息,适合需要进行深度代码分析的场景。但同样依赖目标程序的正常执行,对运行环境有较高要求。
静态审计方案(方法三)
技术特性:利用Python审计钩子机制,在不执行目标代码逻辑的情况下捕获加密数据。不需要注入工具,通过命令行直接执行解密。
适用场景:
- Python 3.9.7及以上版本
- 无需执行目标程序的场景
- 批量处理多个加密文件
- 对执行环境有严格限制的情况
实施步骤:
- 复制method 3目录下文件至目标目录
- 执行
python3 bypass.py filename.pyc - 在
dump目录获取解密后的.pyc文件
该方案具有操作简单、执行高效的特点,是Python 3.9+环境下的首选方案,但不支持早期Python版本,且无法处理依赖动态执行的加密逻辑。
场景化应用:PyArmor解密实施方案
针对不同的技术需求和环境约束,PyArmor-Unpacker提供了灵活的场景化解决方案。以下从环境准备、方案选择到结果验证,构建完整的实施指南。
环境准备与工具配置
基础环境要求:
- 与目标程序相同版本的Python环境
- Git版本控制工具
- 反编译工具(如uncompyle6、decompyle3)
- 注入工具(方法一/二需要,如Process Hacker 2)
项目获取:
git clone https://gitcode.com/gh_mirrors/py/PyArmor-Unpacker
依赖安装: 根据目标程序的依赖情况,安装相应的Python库,确保解密环境与目标程序环境一致,这是解密成功的关键因素。
单文件快速解密方案
适用场景:独立的PyArmor加密脚本,Python 3.9+环境。
实施流程:
- 选择方法三作为技术路径
- 复制
methods/method 3/bypass.py至目标文件目录 - 执行解密命令:
python3 bypass.py target_encrypted.pyc - 在生成的
dump目录中获取解密后的.pyc文件 - 使用反编译工具还原源代码:
uncompyle6 dump/target_encrypted.pyc > target_decrypted.py
这种方案适用于快速解密单个文件,整个过程无需执行目标程序,安全性高且操作简便。
复杂项目批量解密方案
适用场景:包含多个加密模块的复杂项目,需要完整保留模块结构。
实施流程:
- 选择方法二作为基础方案
- 复制
methods/method 2目录下所有文件至项目根目录 - 启动项目主程序,使用注入工具注入解密代码
- 监控
dumps目录生成的解密文件 - 编写批量反编译脚本处理所有
.pyc文件:import os from uncompyle6.main import decompile_file for root, dirs, files in os.walk("dumps"): for file in files: if file.endswith(".pyc"): pyc_path = os.path.join(root, file) py_path = pyc_path[:-1] with open(py_path, "w") as f: decompile_file(pyc_path, f)
该方案能够自动发现项目中的所有加密模块,适合处理大型项目的批量解密需求。
限制模式绕过方案
适用场景:目标程序启用了PyArmor的限制模式,常规解密方法失败。
实施流程:
- 复制
methods/method 1/restrict_bypass.py至目标目录 - 确保
pytransform目录存在且包含_pytransform.dll - 执行限制绕过脚本:
python restrict_bypass.py - 脚本将输出:
[+] _pytransform.dll loaded at 0x70a00000 [+] Setting memory permissions [+] Patching bootstrap restrict mode [+] Restoring memory permission [+] All done! Pyarmor bootstrap restrict mode disabled - 此时可使用方法一或方法二进行常规解密
该方案通过内存补丁技术解除PyArmor的限制模式,为后续解密操作扫清障碍。
问题解决方案:技术探索常见误区
在PyArmor解密实践中,技术探索者常遇到各种挑战。以下通过问答形式解答常见问题,帮助规避技术陷阱。
Python版本不一致会导致什么问题?
问题表现:解密过程无报错,但生成的.pyc文件无法反编译或运行时报错。
技术解析:PyArmor加密与Python版本密切相关,不同版本的字节码格式存在差异。解密工具通过MAGIC_NUMBER识别Python版本:
def get_magic():
if sys.version_info >= (3,4):
from importlib.util import MAGIC_NUMBER
return MAGIC_NUMBER
else:
import imp
return imp.get_magic()
解决方案:严格使用与目标程序相同的Python版本进行解密,可通过pyenv等工具管理多版本环境。
反编译后的代码存在大量LOAD_GLOBAL等指令如何处理?
问题表现:解密成功但反编译代码可读性差,包含大量PyArmor残留指令。
技术解析:这是由于代码对象修复不彻底导致的。方法一的handle_armor_enter函数专门处理此类问题:
names = tuple(n for n in obj.co_names if not n.startswith("__armor"))
return copy_code_obj(obj, co_names=names, co_code=raw_code)
解决方案:确保使用最新版本的解密工具,对于复杂情况可结合多种方法,先使用方法三静态解密,再用方法一修复代码对象。
注入过程中目标程序崩溃如何排查?
问题表现:使用方法一/二时,注入后程序立即崩溃或无响应。
技术解析:可能原因包括注入时机不当、Python环境冲突或目标程序存在反注入机制。
解决方案:
- 尝试不同的注入时机,在程序初始化后再注入
- 使用纯净的Python环境,避免第三方库冲突
- 检查目标程序是否存在反调试代码,可使用
restrict_bypass.py预处理 - 尝试以管理员权限运行注入工具
解密后的代码执行时报NameError如何解决?
问题表现:解密反编译后的代码运行时提示某些变量或函数未定义。
技术解析:这通常是由于解密过程中代码对象的常量池或变量名处理不完整导致的。
解决方案:
- 使用方法二获取更完整的代码转储
- 检查反编译代码中的
co_consts和co_names是否完整 - 对于复杂情况,可手动修复缺失的引用或导入语句
技术探索路径图
基于上述分析,我们可以构建一个PyArmor解密技术的决策路径图,帮助技术探索者根据具体场景选择最优方案:
-
环境检测
- Python版本 >= 3.9.7:优先选择方法三(静态审计方案)
- Python版本 < 3.9.7:选择方法一或方法二(动态注入方案)
-
加密场景判断
- 独立文件解密:方法三(简单高效)
- 复杂项目解密:方法二(完整转储)
- 限制模式加密:先使用
restrict_bypass.py,再选择动态注入方案
-
结果验证
- 反编译完整性检查:使用多种反编译工具交叉验证
- 代码可执行性测试:在隔离环境中运行解密代码
- 依赖关系修复:补全缺失的导入和依赖项
通过这套技术路径,技术探索者可以系统地应对各种PyArmor加密场景,实现高效、安全的脚本解密。PyArmor-Unpacker作为一款专业的Python脚本解密工具,其三种创新方案为PyArmor逆向工程提供了完整的技术支持,无论是简单的单文件解密还是复杂的项目级逆向,都能找到合适的解决方案。
在技术探索过程中,建议始终遵守软件许可协议和相关法律法规,仅在授权范围内使用解密技术。通过深入理解PyArmor的加密机制和本文介绍的解密方案,技术探索者不仅能够解决实际问题,还能提升对Python字节码和运行时机制的理解,为更深入的逆向工程和代码分析打下基础。
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5.1GLM-5.1是智谱迄今最智能的旗舰模型,也是目前全球最强的开源模型。GLM-5.1大大提高了代码能力,在完成长程任务方面提升尤为显著。和此前分钟级交互的模型不同,它能够在一次任务中独立、持续工作超过8小时,期间自主规划、执行、自我进化,最终交付完整的工程级成果。Jinja00
LongCat-AudioDiT-1BLongCat-AudioDiT 是一款基于扩散模型的文本转语音(TTS)模型,代表了当前该领域的最高水平(SOTA),它直接在波形潜空间中进行操作。00- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
HY-Embodied-0.5这是一套专为现实世界具身智能打造的基础模型。该系列模型采用创新的混合Transformer(Mixture-of-Transformers, MoT) 架构,通过潜在令牌实现模态特异性计算,显著提升了细粒度感知能力。Jinja00
FreeSql功能强大的对象关系映射(O/RM)组件,支持 .NET Core 2.1+、.NET Framework 4.0+、Xamarin 以及 AOT。C#00