破解 [CrackMe] 自己平时用py写了个一体化打包,来检验一下好破解吗 思路

查看 57|回复 9
作者:神奇的人鱼   
原帖地址:自己平时用py写了个一体化打包,来检验一下好破解吗 - 吾爱破解 - 52pojie.cn1. 首先观察楼主给出的图片,根据打码的长度和下面汉字的长度(一个汉字两个字符长度),判断出密码是10位


image.png (19.15 KB, 下载次数: 0)
下载附件
2025-9-22 10:27 上传

2. 下载exe拖入die判断,其实从图标也能看出是pyinstaller封装的


image.png (20.29 KB, 下载次数: 0)
下载附件
2025-9-22 10:29 上传

3. 使用在线工具解包
PyInstaller Extractor WEB
这个可以把exe解包成压缩包,直接选择文件上传exe即可,解包后自动下载压缩包


image.png (98.28 KB, 下载次数: 0)
下载附件
2025-9-22 10:31 上传

可以观察到主要的入口pyc文件


image.png (27.94 KB, 下载次数: 0)
下载附件
2025-9-22 10:33 上传

同时也观察到作者使用了pyarmor 进行混淆加密,参考资料:Pyarmor 9.0 用户文档 — Pyarmor 9.0.8 文档


image.png (24.07 KB, 下载次数: 0)
下载附件
2025-9-22 10:34 上传

4. 使用在线工具反编译PYC文件 PyLingual


image.png (68.28 KB, 下载次数: 0)
下载附件
2025-9-22 10:37 上传

这里截图时显示排队了,使用原帖下面的截图充当一下


image.png (45.79 KB, 下载次数: 0)
下载附件
2025-9-22 10:40 上传

5. 使用github上的工具直接破解 Lil-House/Pyarmor-Static-Unpack-1shot: ✅ No execution ✅ Pyarmor 8.0 - latest 9.1.x ✅ Universal ✅ Statically convert obfuscated scripts to disassembly and (experimentally) source code.
该工具会自动识别pyc中的pyarmor 混淆加密自动解密


image.png (79.32 KB, 下载次数: 0)
下载附件
2025-9-22 10:43 上传

6. 得到第一层解密后的python代码
[Python] 纯文本查看 复制代码# Source Generated with Decompyle++
# File: obfuscated_jiami.pyc.1shot.seq (Python 3.13)
'__pyarmor_enter_860__(...)'
__assert_armored__ = '__pyarmor_assert_859__'
import sys
import os
import threading
import time
def _anti_debug_check():
    '''反调试检查'''
    '__pyarmor_enter_863__(...)'
    __assert_armored__ = '__pyarmor_assert_862__'
# WARNING: Decompyle incomplete
None(threading.Thread(target = _anti_debug_check, daemon = True).start)
import base64
def xor_decrypt(data, key):
    '''XOR 解密函数'''
    '__pyarmor_enter_866__(...)'
    __assert_armored__ = '__pyarmor_assert_865__'
    _var_var_3 = None(len, key)
    _var_var_4 = None(bytearray)
# WARNING: Decompyle incomplete
SECRET_KEY = b'my_secret_key_123'
ENCRYPTED_B64 = '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'
encrypted_data = base64.b64decode(ENCRYPTED_B64)
decrypted_script = xor_decrypt(encrypted_data, SECRET_KEY)
exec(decrypted_script, {
    '__name__': '__main__' })
'__pyarmor_exit_861__(...)'
很显然这个base64解码并异或解密后就是原始保护文件
解密后的python文件
[Python] 纯文本查看 复制代码#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import base64
import hashlib
import sys
# ============= 配置区(加密时生成,逆向者需破解) =============
PASSWORD_HASH = "c9f4b8200faf4114995bd09fdc3def271bdd206b2c223b3967da74e818ecdd0e"  # 实际应为 64 位十六进制
ENCRYPTED_B64 = "ZwkCKR0HXxKQ+OhZlsHeluGsndjsnc3glNPD2NXHicP2qMzqk4jYje3/ldDilfuhlOz1lszBUVp9QAANAw1YYoPs46NSgePmlef4l8yTlcTsnMfylfvn1fj7i/DXqNL/lLDwRkRzADIaHQMYFEad5uTRU5fKkJra/pz15ZTp89bfx4rY3qXc9ZCQ84L11kpgCAMWQwETAgsUPVFafUAADQMNWGKD7OS1UoHQ6pXJ/pXghpvz2UNSbFMsKFkfFAILBB8sW1BUExAIDRktFlReHhYFGRwEKR4WWV4dE0VQWUo="
# ============================================================
def verify_password(input_password: str) -> bool:
    """验证用户输入的密码是否正确(比对哈希)"""
    input_hash = hashlib.sha256(input_password.encode()).hexdigest()
    return input_hash == PASSWORD_HASH
def xor_decrypt(data: bytes, key: bytes) -> bytes:
    """使用重复密钥 XOR 解密"""
    decrypted = bytearray()
    key_len = len(key)
    for i in range(len(data)):
        decrypted.append(data ^ key[i % key_len])
    return bytes(decrypted)
def main():
    print("🔐 这是一个受保护的脚本,请输入密码以继续:")
    password = input(">>> ").strip()
    if not verify_password(password):
        print("❌ 密码错误!程序退出。")
        sys.exit(1)
    print("✅ 密码验证通过,正在解密...")
    # 使用密码作为 XOR 密钥
    key = password.encode('utf-8')
    try:
        encrypted_data = base64.b64decode(ENCRYPTED_B64)
        decrypted_code = xor_decrypt(encrypted_data, key)
        # 尝试解码为字符串(防止乱码执行)
        source_code = decrypted_code.decode('utf-8')
    except Exception as e:
        print(f"⚠️  解密失败(密码可能错误或数据损坏): {e}")
        sys.exit(2)
    # 执行解密后的代码
    print("🚀 正在执行解密后的脚本...")
    exec(source_code, {"__name__": "__main__", "password": password})
    input(">>>您已成功解密 ").strip()
if __name__ == "__main__":
    main()
7. 我们现在得到了这个代码但是不知道密码是多少,通过第一步知道了密码是10位,但是现在只有一个sha256,我们现在又不想使用彩虹表,那怎么办呢?
观察作者给出的截图,我们可以发现有部分打印字符是第三层解密后才会出现的
”你破解了这个逆向挑战!“
”原始代码已成功执行。“
”你输入的正确密码是:“
那我们就有了一个思路:密码是循环异或,长度只有10位,解密后需要通过.decode('utf-8') 还原成汉字,那我们的思路有了,先把这三行文字encode,但是不知道相对于密文的偏移值是多少,但是我们知道key已经是可打印字符,我们可以遍历所有可打印字符暴力破解encode后的第一个字符然后和密文对比,限制条件encode后的第一个字符通过key的第一位加密后是必须在密文中,并且encode的密文向后10位也需要使用同样的key第一位进行异或加密后的密文也必须存在并且顺序上一个密文的后十位,我们可以循环10此得到一个key的密钥顺序,可能包含多个结果
然后再通过相同的办法暴力破解第二条已经存在的语句,key已经包含相同的字符 但是由于两个已知密文的偏移值不同 key的顺序也不同,但是足以筛选出真正的key包含的字符
一旦我们找了真正的key序列,我们就可以循环10次对比sha256 找到真正的key 解密最后一段密文了
给出代码:
[Python] 纯文本查看 复制代码import string
# 密文
cipher_hex = """67 09 02 29 1D 07 5F 12 90 F8 E8 59 96 C1 DE 96
E1 AC 9D D8 EC 9D CD E0 94 D3 C3 D8 D5 C7 89 C3
F6 A8 CC EA 93 88 D8 8D ED FF 95 D0 E2 95 FB A1
94 EC F5 96 CC C1 51 5A 7D 40 00 0D 03 0D 58 62
83 EC E3 A3 52 81 E3 E6 95 E7 F8 97 CC 93 95 C4
EC 9C C7 F2 95 FB E7 D5 F8 FB 8B F0 D7 A8 D2 FF
94 B0 F0 46 44 73 00 32 1A 1D 03 18 14 46 9D E6
E4 D1 53 97 CA 90 9A DA FE 9C F5 E5 94 E9 F3 D6
DF C7 8A D8 DE A5 DC F5 90 90 F3 82 F5 D6 4A 60
08 03 16 43 01 13 02 0B 14 3D 51 5A 7D 40 00 0D
03 0D 58 62 83 EC E4 B5 52 81 D0 EA 95 C9 FE 95
E0 86 9B F3 D9 43 52 6C 53 2C 28 59 1F 14 02 0B
04 1F 2C 5B 50 54 13 10 08 0D 19 2D 16 54 5E 1E
16 05 19 1C 04 29 1E 16 59 5E 1D 13 45 50 59 4A""".replace('\n', '').replace(' ', '')
ciphertext = bytes.fromhex(cipher_hex)
# 三段已知明文
p1 = b'\xe5\x8e\x9f\xe5\xa7\x8b\xe4\xbb\xa3\xe7\xa0\x81\xe5\xb7\xb2\xe6\x88\x90\xe5\x8a\x9f\xe6\x89\xa7\xe8\xa1\x8c\xe3\x80\x82'  # len=24
p2 = b'\xe4\xbd\xa0\xe7\xa0\xb4\xe8\xa7\xa3\xe4\xba\x86\xe8\xbf\x99\xe4\xb8\xaa\xe9\x80\x86\xe5\x90\x91\xe6\x8c\x91\xe6\x88\x98'  # len=24
p3 = b'\xe4\xbd\xa0\xe8\xbe\x93\xe5\x85\xa5\xe7\x9a\x84\xe6\xad\xa3\xe7\xa1\xae\xe5\xaf\x86\xe7\xa0\x81\xe6\x98\xaf'              # len=21
# 可打印字符:ASCII 32 ~ 126
VISIBLE_PRINTABLE = set(range(32, 127))
def is_printable(b):
    return b in VISIBLE_PRINTABLE
def check_index(target_byte):
    positions = [i for i, byte in enumerate(ciphertext) if byte == target_byte]
    return positions
def has_plus_10(list1, list2):
    set2 = set(list2)  # 转成集合,提高查找效率
    for x in list1:
        if (x + 10) in set2:
            return True
    return False
for index, item in enumerate(p1[:10]):
    print(f"p1 {index}")
    for key in VISIBLE_PRINTABLE:
        if item ^ key in ciphertext:
            p1_first_offset = check_index(item ^ key)
            if p1[index + 10] ^ key in ciphertext:
                p1_second_offset = check_index(p1[index + 10] ^ key)
                if has_plus_10(p1_first_offset,p1_second_offset):
                    print(f"第{index}位 测试key{key} 解密后在密文中的位置{p1_first_offset}")
                    print(f"第{index}位 测试key{key} 解密后在密文中的位置{p1_second_offset}")
for index, item in enumerate(p2[:10]):
    print(f"p2 {index}")
    for key in VISIBLE_PRINTABLE:
        if item ^ key in ciphertext:
            p2_first_offset = check_index(item ^ key)
            if p2[index + 10] ^ key in ciphertext:
                p2_second_offset = check_index(p2[index + 10] ^ key)
                if has_plus_10(p2_first_offset, p2_second_offset):
                    print(f"第{index}位 测试key{key} 解密后在密文中的位置{p2_first_offset}")
                    print(f"第{index}位 测试key{key} 解密后在密文中的位置{p2_second_offset}")
for index, item in enumerate(p3[:10]):
    print(f"p3 {index}")
    for key in VISIBLE_PRINTABLE:
        if item ^ key in ciphertext:
            p3_first_offset = check_index(item ^ key)
            if p3[index + 10] ^ key in ciphertext:
                p3_second_offset = check_index(p3[index + 10] ^ key)
                if has_plus_10(p3_first_offset, p3_second_offset):
                    print(f"第{index}位 测试key{key} 解密后在密文中的位置{p3_first_offset}")
                    print(f"第{index}位 测试key{key} 解密后在密文中的位置{p3_second_offset}")
运行后打印结果如下:
[Python] 纯文本查看 复制代码p1 0
第0位 测试key34 解密后在密文中的位置[29, 82, 129]
第0位 测试key34 解密后在密文中的位置[139]
第0位 测试key100 解密后在密文中的位置[69, 169]
第0位 测试key100 解密后在密文中的位置[79]
第0位 测试key115 解密后在密文中的位置[12, 15, 51]
第0位 测试key115 解密后在密文中的位置[25]
p1 1
第1位 测试key109 解密后在密文中的位置[66, 70]
第1位 测试key109 解密后在密文中的位置[20, 49, 65, 80, 165]
p1 2
第2位 测试key121 解密后在密文中的位置[71, 111]
第2位 测试key121 解密后在密文中的位置[81, 121]
p1 3
第3位 测试key112 解密后在密文中的位置[42, 45, 72, 78, 84, 172, 175]
第3位 测试key112 解密后在密文中的位置[29, 82, 129]
p1 4
第4位 测试key64 解密后在密文中的位置[73, 86]
第4位 测试key64 解密后在密文中的位置[83]
p1 5
第5位 测试key115 解密后在密文中的位置[9, 74, 88]
第5位 测试key115 解密后在密文中的位置[42, 45, 72, 78, 84, 172, 175]
p1 6
第6位 测试key115 解密后在密文中的位置[75, 115]
第6位 测试key115 解密后在密文中的位置[46, 85, 89]
第6位 测试key120 解密后在密文中的位置[81, 121]
第6位 测试key120 解密后在密文中的位置[91, 98]
p1 7
第7位 测试key78 解密后在密文中的位置[50, 122, 135, 140]
第7位 测试key78 解密后在密文中的位置[14, 132]
第7位 测试key119 解密后在密文中的位置[34, 52, 76]
第7位 测试key119 解密后在密文中的位置[73, 86]
p1 8
第8位 测试key48 解密后在密文中的位置[36, 77]
第8位 测试key48 解密后在密文中的位置[28, 87]
第8位 测试key51 解密后在密文中的位置[8, 117, 136, 137]
第8位 测试key51 解密后在密文中的位置[127, 141]
第8位 测试key117 解密后在密文中的位置[127, 141]
第8位 测试key117 解密后在密文中的位置[8, 117, 136, 137]
p1 9
第9位 测试key114 解密后在密文中的位置[42, 45, 72, 78, 84, 172, 175]
第9位 测试key114 解密后在密文中的位置[9, 74, 88]
p2 0
第0位 测试key121 解密后在密文中的位置[18, 21, 110]
第0位 测试key121 解密后在密文中的位置[26, 31]
p2 1
第1位 测试key112 解密后在密文中的位置[22]
第1位 测试key112 解密后在密文中的位置[32]
p2 2
第2位 测试key52 解密后在密文中的位置[24, 48, 96, 124]
第2位 测试key52 解密后在密文中的位置[134]
第2位 测试key61 解密后在密文中的位置[18, 21, 110]
第2位 测试key61 解密后在密文中的位置[28, 87]
第2位 测试key64 解密后在密文中的位置[23, 176]
第2位 测试key64 解密后在密文中的位置[33, 93]
p2 3
第3位 测试key115 解密后在密文中的位置[24, 48, 96, 124]
第3位 测试key115 解密后在密文中的位置[34, 52, 76]
p2 4
第4位 测试key106 解密后在密文中的位置[116]
第4位 测试key106 解密后在密文中的位置[126, 138, 179]
第4位 测试key115 解密后在密文中的位置[25]
第4位 测试key115 解密后在密文中的位置[35, 171]
p2 5
第5位 测试key108 解密后在密文中的位置[19, 27, 38, 131]
第5位 测试key108 解密后在密文中的位置[37]
第5位 测试key119 解密后在密文中的位置[26, 31]
第5位 测试key119 解密后在密文中的位置[36, 77]
p2 6
第6位 测试key43 解密后在密文中的位置[26, 31]
第6位 测试key43 解密后在密文中的位置[36, 77]
第6位 测试key48 解密后在密文中的位置[19, 27, 38, 131]
第6位 测试key48 解密后在密文中的位置[37]
p2 7
第7位 测试key55 解密后在密文中的位置[8, 117, 136, 137]
第7位 测试key55 解密后在密文中的位置[18, 21, 110]
第7位 测试key114 解密后在密文中的位置[28, 87]
第7位 测试key114 解密后在密文中的位置[19, 27, 38, 131]
p2 8
第8位 测试key100 解密后在密文中的位置[29, 82, 129]
第8位 测试key100 解密后在密文中的位置[39]
第8位 测试key125 解密后在密文中的位置[14, 132]
第8位 测试key125 解密后在密文中的位置[24, 48, 96, 124]
p2 9
第9位 测试key109 解密后在密文中的位置[30]
第9位 测试key109 解密后在密文中的位置[40]
p3 0
第0位 测试key115 解密后在密文中的位置[75, 115]
第0位 测试key115 解密后在密文中的位置[125]
p3 1
第1位 测试key110 解密后在密文中的位置[25]
第1位 测试key110 解密后在密文中的位置[35, 171]
第1位 测试key119 解密后在密文中的位置[116]
第1位 测试key119 解密后在密文中的位置[126, 138, 179]
p3 2
第2位 测试key48 解密后在密文中的位置[8, 117, 136, 137]
第2位 测试key48 解密后在密文中的位置[127, 141]
第2位 测试key51 解密后在密文中的位置[36, 77]
第2位 测试key51 解密后在密文中的位置[28, 87]
第2位 测试key118 解密后在密文中的位置[127, 141]
第2位 测试key118 解密后在密文中的位置[8, 117, 136, 137]
p3 3
第3位 测试key47 解密后在密文中的位置[29, 82, 129]
第3位 测试key47 解密后在密文中的位置[139]
第3位 测试key105 解密后在密文中的位置[69, 169]
第3位 测试key105 解密后在密文中的位置[79]
第3位 测试key114 解密后在密文中的位置[118]
第3位 测试key114 解密后在密文中的位置[128]
第3位 测试key126 解密后在密文中的位置[12, 15, 51]
第3位 测试key126 解密后在密文中的位置[25]
p3 4
第4位 测试key100 解密后在密文中的位置[119]
第4位 测试key100 解密后在密文中的位置[29, 82, 129]
p3 5
第5位 测试key63 解密后在密文中的位置[17]
第5位 测试key63 解密后在密文中的位置[19, 27, 38, 131]
第5位 测试key109 解密后在密文中的位置[120, 174]
第5位 测试key109 解密后在密文中的位置[130]
p3 6
第6位 测试key121 解密后在密文中的位置[81, 121]
第6位 测试key121 解密后在密文中的位置[19, 27, 38, 131]
p3 7
第7位 测试key73 解密后在密文中的位置[34, 52, 76]
第7位 测试key73 解密后在密文中的位置[73, 86]
第7位 测试key112 解密后在密文中的位置[50, 122, 135, 140]
第7位 测试key112 解密后在密文中的位置[14, 132]
p3 8
第8位 测试key64 解密后在密文中的位置[123]
第8位 测试key64 解密后在密文中的位置[133]
p3 9
第9位 测试key115 解密后在密文中的位置[24, 48, 96, 124]
第9位 测试key115 解密后在密文中的位置[134]
第9位 测试key122 解密后在密文中的位置[18, 21, 110]
第9位 测试key122 解密后在密文中的位置[28, 87]
我们可以得到几组key的序列,我们的key序列一定是这三者的交集
第一个已知明文得到的序列 [[34,100,115],109,121,112,64,115,[115,120],[78,119],[48,51,117],114]
第二个已知明文得到的序列 [121,112,[52,61,64],115,[106,115],[108,119],[43,48],[55,114],[100,125],109]
第三个已知明文得到的序列 [115,[110,119],[48,51,118],[47,105,114,126],100,[63,109],121,[73,112],64,115,122]
可以看到唯一满足三者的序列为 [121,112,64,115,115,119,48,114,100,109]
下面编写代码找到hash为 c9f4b8200faf4114995bd09fdc3def271bdd206b2c223b3967da74e818ecdd0e 的正确顺序
[Python] 纯文本查看 复制代码# 找到真正的顺序
import hashlib
key_bytes = [121, 112, 64, 115, 115, 119, 48, 114, 100, 109]
s = ''.join(chr(b) for b in key_bytes)
target_sha256 = "c9f4b8200faf4114995bd09fdc3def271bdd206b2c223b3967da74e818ecdd0e"
print(f"原始序列: {s}")
print(f"目标SHA256: {target_sha256}\n")
print("="*60)
for i in range(len(s)):
    rotated = s[i:] + s[:i]
    sha256_hash = hashlib.sha256(rotated.encode('utf-8')).hexdigest()
    match = "✅ MATCH!" if sha256_hash == target_sha256 else ""
    print(f"偏移 {i:2d}: {rotated:
最终正确的key是 myp@ssw0rd
解密最终的代码:
[Python] 纯文本查看 复制代码rint("✅ 恭喜!你破解了这个逆向挑战!")
print("🔓 原始代码已成功执行。")
print(f"🔑 你输入的正确密码是: {password}")
print("📅 当前时间:", __import__('datetime').datetime.now())

文中, 位置

Teemo   


神奇的人鱼 发表于 2025-9-22 14:36
我之前也尝试看这个pyarmor,太复杂了直接放弃了

https://cyber.wtf/2025/02/12/unpacking-pyarmor-v8-scripts/
这个文章分析pyarmor很详细了,就是不知道能撑多久,等pyarmor更新版本又要重新找方法解了
Teemo   

终于等来大佬的解密过程啦,我在解的时候拿Lil-House/Pyarmor-Static-Unpack-1shot试了一把,没能成功,应该是没用对应的Python版本的问题,于是就放弃了。
pyarmor_runtime.pyd还自带了一层UPX壳的?直接丢IDA里面解不出来,还要先脱壳才行。应该是pyarmor自带的壳吧
最后这个绕过sha256,直接根据已有信息暴力尝试解码的思路很不错啊,学习了
博爵   

感谢分享,很厉害呀
神奇的人鱼
OP
  


Teemo 发表于 2025-9-22 14:35
终于等来大佬的解密过程啦,我在解的时候拿Lil-House/Pyarmor-Static-Unpack-1shot试了一把,没能成功,应 ...

我之前也尝试看这个pyarmor,太复杂了直接放弃了
1346   

非常厉害步骤很详细。终于明白如何逆向py文件啦
神奇的人鱼
OP
  


Teemo 发表于 2025-9-22 14:39
https://cyber.wtf/2025/02/12/unpacking-pyarmor-v8-scripts/
这个文章分析pyarmor很详细了,就是不知 ...

有点意思啊
神奇的人鱼
OP
  


Teemo 发表于 2025-9-22 14:35
终于等来大佬的解密过程啦,我在解的时候拿Lil-House/Pyarmor-Static-Unpack-1shot试了一把,没能成功,应 ...

要不是作者留了一些线索,不管是有意还是无意,才能这样不然只能通过彩虹表了
JJarvis   

看不懂,但是感觉好厉害的样子
xlwllm   

感觉很牛的样子 赞一个!
您需要登录后才可以回帖 登录 | 立即注册

返回顶部