2026 新春快乐破解活动五之windows中级题

查壳分析

按例查壳,Python Nuitka打包的,所以可以提取Python字节码。

nuitka-extractor.exe 提取工具可以提取Python Bytecode

可以看到crack_me dll

基本都是Python处理,没什么头绪处理,然后看到run code,推测是相关的处理逻辑。

Python Bytecode解析

然后双击进去该代码区域,看到了对Bytecode的解析函数,

提取资源id为3的数据,然后进行解析

然后对id为3的资源进行解析,解析流程如下:

c 复制代码
if ( (_WORD)v77 )
  {
    do
    {
      v80 = a2;
      a2 += 8i64;
      result = sub_31340ECE0(a1, v80, v78);
      v78 = (char *)result;
    }
    while ( a2 != v79 );
  }

然后可以sub_31340ECE0 该函数对Bytecode进行了解析,通过大量的switch case处理了各种情况,这里可以使用AI生成相应的Python脚本。提取id为3的资源数据,可以使用Resource Hacker进行提取,保存为bin,然后利用Python进行解析。

python 复制代码
import struct
import sys
from typing import Any, Dict, List, Optional, Tuple, Union
import io
​
​
class NuitkaBinaryParser:
    """解析Nuitka编译的二进制bin文件"""
​
    def __init__(self, data: bytes):
        self.data = data
        self.pos = 0
        self.result_stack = []  # 用于p类型引用
        self.global_objects: Dict[int, Any] = {}  # 全局对象缓存
​
        # 预定义对象(模拟C代码中的Py_NoneStruct等)
        self.Py_None = None
        self.Py_True = True
        self.Py_False = False
        self.Py_Ellipsis = Ellipsis
        self.Py_NotImplemented = NotImplemented
​
        # 模拟C代码中的全局字典(qword_31344Axxx)
        self.global_dicts = {
            'integers': {},  # qword_31344A108
            'bytes': {},  # qword_31344A0F8
            'floats': {},  # qword_31344A100
            'frozenset': None,  # qword_31344A120
            'set': None,  # qword_31344A118
            'list': None,  # qword_31344A130
            'tuple': None,  # qword_31344A138
            'module_cache': {},  # qword_31344A128?
        }
​
        # 预定义浮点数常量(Z类型)
        self.predefined_floats: List[Optional[float]] = [None] * 256
​
        # 运行时状态(模拟PyRuntime)
        self.PyRuntime = {
            'refcounts': {},  # 引用计数
            'thread_state': None,  # 线程状态
        }
​
    def read_uint8(self) -> int:
        """读取1字节无符号整数"""
        if self.pos >= len(self.data):
            raise EOFError("Unexpected end of data")
        val = self.data[self.pos]
        self.pos += 1
        return val
​
    def read_uint16(self) -> int:
        """读取2字节无符号整数"""
        if self.pos + 2 > len(self.data):
            raise EOFError("Unexpected end of data")
        val = struct.unpack('<H', self.data[self.pos:self.pos + 2])[0]
        self.pos += 2
        return val
​
    def read_uint32(self) -> int:
        """读取4字节无符号整数"""
        if self.pos + 4 > len(self.data):
            raise EOFError("Unexpected end of data")
        val = struct.unpack('<I', self.data[self.pos:self.pos + 4])[0]
        self.pos += 4
        return val
​
    def read_uint64(self) -> int:
        """读取8字节无符号整数"""
        if self.pos + 8 > len(self.data):
            raise EOFError("Unexpected end of data")
        val = struct.unpack('<Q', self.data[self.pos:self.pos + 8])[0]
        self.pos += 8
        return val
​
    def read_leb128(self) -> int:
        """读取LEB128编码的无符号整数"""
        result = 0
        shift = 0
        while True:
            byte_val = self.read_uint8()
            result |= (byte_val & 0x7F) << shift
            if not (byte_val & 0x80):
                break
            shift += 7
        return result
​
    def read_c_string(self) -> bytes:
        """读取以空字节结尾的C风格字符串"""
        start = self.pos
        while self.pos < len(self.data) and self.data[self.pos] != 0:
            self.pos += 1
        if self.pos >= len(self.data):
            raise EOFError("Unexpected end of data while reading C string")
        result = self.data[start:self.pos]
        self.pos += 1  # 跳过null
        return result
​
    def read_bytes(self, length: int) -> bytes:
        """读取指定长度的字节"""
        if self.pos + length > len(self.data):
            raise EOFError(f"Unexpected end of data, need {length} bytes")
        result = self.data[self.pos:self.pos + length]
        self.pos += length
        return result
​
    def read_double(self) -> float:
        """读取8字节双精度浮点数"""
        return struct.unpack('<d', self.read_bytes(8))[0]
​
    def parse_blob(self) -> Any:
        """解析一个blob对象 - 对应 sub_31340ECE0 函数"""
        if self.pos >= len(self.data):
            return None
​
        # 保存当前位置用于调试
        start_pos = self.pos
​
        # 读取类型字节
        type_byte = self.read_uint8()
        type_char = chr(type_byte)
​
        # 根据类型进行解析
        if type_char == '.':
            # 错误情况
            # raise ValueError("Missing blob values")
            obj = ""
            pass
​
        elif type_char == ':':
            # 切片对象 - 读取3个对象
            items = []
            for _ in range(3):
                items.append(self.parse_blob())
            # 模拟 PySlice_Type 创建
            obj = slice(items[0], items[1], items[2])
            # TO DO: 处理引用计数和线程状态
            # v160 = *(_QWORD *)(a1 + 16); // 当前线程状态
            # 复杂的引用计数处理...
​
        elif type_char == ';':
            # range对象 - 读取3个对象
            items = []
            for _ in range(3):
                items.append(self.parse_blob())
            # 模拟 PyRange_Type 创建
            if all(item is not None for item in items):
                obj = range(items[0], items[1], items[2])
            else:
                obj = None
​
        elif type_char == 'A':
            # 泛型别名 - 读取2个对象
            obj1 = self.parse_blob()
            obj2 = self.parse_blob()
            # TO DO: Py_GenericAlias
            obj = f"<GENERIC_ALIAS {obj1}[{obj2}]>"
​
        elif type_char == 'B':
            # 字节数组
            length = self.read_leb128()
            data = self.read_bytes(length)
            obj = bytearray(data)
​
        elif type_char == 'C':
            # 代码对象 - 复杂结构
            flags = self.read_leb128()
            # 读取基本字段
            pos = self.pos
​
            # 根据C代码解析
            if flags & 0x80:  # 检查是否有额外标志
                # TO DO: 解析复杂代码对象
                pass
​
            obj1 = self.parse_blob()  # 第一个对象
            # 读取更多字段...
            obj2 = self.parse_blob()
​
            # TO DO: 完整解析PyCodeObject
            obj = f"<CODE_OBJECT flags={flags}>"
​
        elif type_char == 'D':
            # 字典
            count = self.read_leb128()
            d = {}
            if count > 0:
                # 先读取所有key
                keys = []
                for _ in range(count):
                    keys.append(self.parse_blob())
                # 再读取所有value
                values = []
                for _ in range(count):
                    values.append(self.parse_blob())
                # 组合成字典
                for k, v in zip(keys, values):
                    d[k] = v
            obj = d
​
        elif type_char == 'E':
            # 跳过字符串
            while self.pos < len(self.data) and self.data[self.pos] != 0:
                self.pos += 1
            obj = None
​
        elif type_char == 'F':
            # False
            obj = False
​
        elif type_char in ('G', 'g'):
            # 特殊处理 - 读取计数
            count = self.read_leb128()
            # TO DO: 处理G/g类型
            if type_char == 'G':
                obj = f"<G_TYPE:{count}>"
            else:
                obj = f"<g_TYPE:{count}>"
​
        elif type_char == 'H':
            # 位运算操作
            obj1 = self.parse_blob()
            obj2 = self.parse_blob()
            if isinstance(obj1, int) and isinstance(obj2, int):
                obj = obj1 | obj2
            else:
                obj = f"<OR:{obj1}|{obj2}>"
​
        elif type_char == 'J':
            # 复数 - 读取两个双精度浮点数
            real = self.read_double()
            imag = self.read_double()
            obj = complex(real, imag)
​
        elif type_char == 'L':
            # 列表
            count = self.read_leb128()
            items = []
            for _ in range(count):
                items.append(self.parse_blob())
            obj = items
​
        elif type_char == 'M':
            # 匿名对象
            anon_type = self.read_uint8()
            if anon_type == 0:
                obj = None
            elif anon_type == 1:
                obj = Ellipsis
            elif anon_type == 2:
                obj = NotImplemented
            elif anon_type == 3:
                obj = "<PyFunction_Type>"
            elif anon_type == 4:
                obj = "<PyGen_Type>"
            elif anon_type == 5:
                obj = "<PyCFunction_Type>"
            elif anon_type == 6:
                obj = "<PyCode_Type>"
            elif anon_type == 7:
                obj = "<PyModule_Type>"
            elif anon_type == 10:
                obj = "<qword_3134488C8>"
            else:
                obj = f"<ANON_TYPE_{anon_type}>"
​
        elif type_char == 'O':
            # 动态属性获取
            attr_name = self.read_c_string().decode('utf-8', errors='replace')
            # TO DO: PyObject_GetAttrString
            obj = f"<DYNAMIC_ATTR_GET:{attr_name}>"
​
        elif type_char in ('P', 'S'):
            # 集合/冻结集合
            count = self.read_leb128()
            items = []
            for _ in range(count):
                items.append(self.parse_blob())
            if type_char == 'S':
                obj = set(items)
            else:  # 'P'
                obj = frozenset(items)
​
        elif type_char == 'Q':
            # 特殊值
            special_type = self.read_uint8()
            if special_type == 0:
                obj = Ellipsis
            elif special_type == 1:
                obj = NotImplemented
            elif special_type == 2:
                obj = "<SELF_REFERENCE>"
            else:
                obj = f"<SPECIAL_VALUE_{special_type}>"
​
        elif type_char == 'T':
            # 元组
            count = self.read_leb128()
            items = []
            for _ in range(count):
                items.append(self.parse_blob())
            obj = tuple(items)
​
        elif type_char == 'X':
            # 跳过指定长度
            skip_length = self.read_leb128()
            self.pos += skip_length
            return None
​
        elif type_char == 'Z':
            # 预定义浮点数
            index = self.read_uint8()
            # TO DO: 从预定义浮点数表中获取
            if index < len(self.predefined_floats):
                if self.predefined_floats[index] is None:
                    # 根据C代码中的case创建不同浮点数
                    if index == 0:
                        self.predefined_floats[index] = 0.0
                    elif index == 1:
                        self.predefined_floats[index] = 1.0
                    elif index == 2:
                        self.predefined_floats[index] = -1.0
                    elif index == 3:
                        self.predefined_floats[index] = 2.0
                    elif index == 4:
                        self.predefined_floats[index] = -2.0
                    elif index == 5:
                        self.predefined_floats[index] = 0.5
                    else:
                        self.predefined_floats[index] = float(index)
                obj = self.predefined_floats[index]
            else:
                obj = f"<PREDEFINED_FLOAT_INDEX_{index}>"
​
        elif type_char in ('a', 'u'):
            # UTF-8字符串
            s_bytes = self.read_c_string()
            obj = s_bytes.decode('utf-8', errors='replace')
            if type_char == 'a':  # interned
                obj = sys.intern(obj)
​
        elif type_char == 'b':
            # 字节串
            length = self.read_leb128()
            data = self.read_bytes(length)
            # 缓存到全局字典
            if data not in self.global_dicts['bytes']:
                self.global_dicts['bytes'][data] = data
            obj = self.global_dicts['bytes'][data]
​
        elif type_char == 'c':
            # 字节串 (interned)
            s_bytes = self.read_c_string()
            if len(s_bytes) > 1:
                if s_bytes not in self.global_dicts['bytes']:
                    self.global_dicts['bytes'][s_bytes] = s_bytes
                obj = self.global_dicts['bytes'][s_bytes]
            else:
                obj = s_bytes
​
        elif type_char == 'd':
            # 预定义浮点数索引
            index = self.read_uint8()
            # TO DO: 从浮点数常量表中获取
            obj = f"<PREDEFINED_FLOAT_INDEX_{index}>"
​
        elif type_char == 'f':
            # 双精度浮点数
            value = self.read_double()
            # 缓存浮点数
            if value not in self.global_dicts['floats']:
                self.global_dicts['floats'][value] = value
            obj = self.global_dicts['floats'][value]
​
        elif type_char == 'j':
            # 复数 - 读取16字节
            real = self.read_double()
            imag = self.read_double()
            obj = complex(real, imag)
​
        elif type_char in ('l', 'q'):
            # 有符号整数
            value = self.read_leb128()
            if type_char == 'q':
                value = -value
            # 缓存整数
            if value not in self.global_dicts['integers']:
                self.global_dicts['integers'][value] = value
            obj = self.global_dicts['integers'][value]
​
        elif type_char == 'n':
            # None
            obj = None
​
        elif type_char == 'p':
            # 引用前面的对象
            if self.result_stack:
                obj = self.result_stack[-1]
            else:
                obj = "<STACK_REFERENCE>"
​
        elif type_char == 's':
            # interned字符串
            length = self.read_leb128()
            s_bytes = self.read_bytes(length)
            obj = sys.intern(s_bytes.decode('utf-8', errors='replace'))
​
        elif type_char == 't':
            # True
            obj = True
​
        elif type_char == 'v':
            # 长度可变的UTF-8字符串
            length = self.read_leb128()
            s_bytes = self.read_bytes(length)
            obj = s_bytes.decode('utf-8', errors='replace')
​
        elif type_char == 'w':
            # 单字符字符串
            char_bytes = self.read_bytes(1)
            obj = char_bytes.decode('utf-8', errors='replace')
​
        else:
            # 未知类型
            obj = f"<UNKNOWN_TYPE_{type_char}>"
            print(f"Warning: Unknown type '{type_char}' (0x{type_byte:02X}) at {start_pos}")
​
        # 保存到结果栈
        if obj is not None:
            self.result_stack.append(obj)
​
        return obj
​
    def parse_blob_with_count(self, count: int) -> List[Any]:
        """解析指定数量的blob对象"""
        results = []
        for _ in range(count):
            obj = self.parse_blob()
            if obj is not None:
                results.append(obj)
        return results
​
​
def parse_nuitka_bin_file(filepath: str) -> Optional[List[Any]]:
    """解析Nuitka编译的bin文件"""
    try:
        with open(filepath, 'rb') as f:
            data = f.read()
    except Exception as e:
        print(f"Error reading file: {e}")
        return None
​
    print(f"File size: {len(data)} bytes")
    print("-" * 60)
​
    # 读取文件头
    if len(data) < 8:
        print("Error: File too small")
        return None
​
    pos = 0
    hash_val = struct.unpack('<I', data[0:4])[0]
    total_size = struct.unpack('<I', data[4:8])[0]
    pos = 8
​
    print(f"Header: hash=0x{hash_val:08X}, total_size={total_size} bytes")
​
    # 遍历所有blob
    while pos < len(data) and pos < total_size:
        # 读取blob名称
        name_start = pos
        while pos < len(data) and data[pos] != 0:
            pos += 1
        if pos >= len(data):
            break
​
        blob_name = data[name_start:pos].decode('utf-8', errors='replace')
        pos += 1
​
        # 读取blob大小和数量
        if pos + 6 > len(data):
            break
​
        blob_size = struct.unpack('<I', data[pos:pos + 4])[0]
        blob_count = struct.unpack('<H', data[pos + 4:pos + 6])[0]
        pos += 6
​
        print(f"\nFound blob: '{blob_name}' at {name_start}")
        print(f"  Size: {blob_size}, Count: {blob_count}")
​
        if blob_name == "__main__":
            print(f"\n{'=' * 60}")
            print(f"Decoding '__main__' blob...")
            print(f"{'=' * 60}")
​
            # 解析blob数据
            blob_data = data[pos:pos + blob_size - 2]
            parser = NuitkaBinaryParser(blob_data)
            results = parser.parse_blob_with_count(blob_count)
​
            # 输出结果
            print(f"\nDecoded {len(results)} objects:")
            print(f"{'-' * 60}")
            for i, obj in enumerate(results):
                if isinstance(obj, bytes):
                    ascii_str = ''.join(chr(b) if 32 <= b < 127 else '.' for b in obj[:50])
                    if len(obj) > 50:
                        ascii_str += "..."
                    print(f"{i:3d}: {obj!r} (ASCII: {ascii_str})")
                else:
                    print(f"{i:3d}: {obj!r}")
​
            print(f"{'-' * 60}")
            return results
​
        else:
            # 跳过其他blob
            print(f"  Skipping blob '{blob_name}'")
            pos += blob_size - 2
​
    return None
​
​
def main():
    """主函数"""
    if len(sys.argv) < 2:
        print("Usage: python nuitka_parser.py <main.bin>")
        return
​
    filepath = sys.argv[1]
    results = parse_nuitka_bin_file(filepath)
​
    if results:
        print(f"\nSuccessfully decoded {len(results)} objects from __main__ blob")
​
        # 特别处理:查找加密数据
        if results and isinstance(results[0], list):
            print(f"\n{'=' * 60}")
            print("Encrypted data parts:")
            encrypted_parts = []
            for i, item in enumerate(results[0]):
                if isinstance(item, bytes):
                    print(f"  Part {i}: {item!r} (len={len(item)})")
                    encrypted_parts.append(item)
                else:
                    print(f"  Part {i}: {item}")
​
            # 尝试解密
            if encrypted_parts:
                encrypted_data = b''.join(encrypted_parts)
                print(f"\nTotal encrypted data length: {len(encrypted_data)} bytes")
​
                # TO DO: 查找密钥(可能在results中)
                key = 81  # 根据之前分析
                decrypted = bytes([b ^ key for b in encrypted_data])
                try:
                    flag = decrypted.decode('ascii')
                    print(f"\nPotential flag (key={key}): {flag}")
                except:
                    print(f"\nDecrypted bytes (hex): {decrypted.hex()}")
    else:
        print("Failed to decode __main__ blob")
​
​
if __name__ == "__main__":
    main()[/mw_shl_code]

运行的结果分析

复制代码
C:\Users\WNN\PyCharmMiscProject\.venv\Scripts\python.exe C:\Users\WNN\PyCharmMiscProject\555.py "D:\Software\OD\Project\cEVm8pds\【2026春节】解题领红包之五 {Windows 中级题} 出题老师:云在天.exe_extracted\main.bin"File size: 5635506 bytes
------------------------------------------------------------
Header: hash=0xDCAA9D4E, total_size=5635498 bytes
​
Found blob: '.bytecode' at 8
  Size: 5633009, Count: 323
  Skipping blob '.bytecode'
​
Found blob: '' at 5633031
  Size: 878, Count: 107
  Skipping blob ''
​
Found blob: '__main__' at 5633914
  Size: 1579, Count: 83
​
============================================================
Decoding '__main__' blob...
============================================================
Warning: Unknown type '¬' (0xAC) at 323
Warning: Unknown type 'Ñ' (0xD1) at 324
Warning: Unknown type '•' (0x91) at 325
Warning: Unknown type '•' (0x01) at 326
Warning: Unknown type '•' (0x01) at 329
Warning: Unknown type '•' (0x81) at 330
Warning: Unknown type 'Þ' (0xDE) at 331
Warning: Unknown type '·' (0xB7) at 332
Warning: Unknown type 'Þ' (0xDE) at 333
Warning: Unknown type '•' (0x02) at 334
​
Decoded 83 objects:
------------------------------------------------------------
  0: [b'dc!a;`b', '<PREDEFINED_FLOAT_INDEX_17>', b'cacg', '<PREDEFINED_FLOAT_INDEX_47>', b'\x19e!!(', '<PREDEFINED_FLOAT_INDEX_14>', b'\x1fb&', '<PREDEFINED_FLOAT_INDEX_14>', b'\x08be#', b'ppp']
  1: '_parts'
  2: 81
  3: '_key'
  4: 30
  5: '_total_len'
  6: '解密单个字符'
  7: 'current'
  8: '_decrypt_char'
  9: '获取指定位置的字符'
10: 'self'
11: '_get_char_at_position'
12: '验证用户输入'
13: 'total'
14: '计算校验和'
15: 'flag\x00achecksum\x00u获取目标校验和\x00ahashlib\x00asha256\x00aencode\x00ahexdigest\x00:nl\x08nl\x10u哈希函数\x00l�'
16: '<UNKNOWN_TYPE_¬>'
17: '<UNKNOWN_TYPE_Ñ>'
18: '<UNKNOWN_TYPE_\x91>'
19: '<UNKNOWN_TYPE_\x01>'
20: '<g_TYPE:2>'
21: '<UNKNOWN_TYPE_\x01>'
22: '<UNKNOWN_TYPE_\x81>'
23: '<UNKNOWN_TYPE_Þ>'
24: '<UNKNOWN_TYPE_·>'
25: '<UNKNOWN_TYPE_Þ>'
26: '<UNKNOWN_TYPE_\x02>'
27: 1380994890
28: 'hash_input'
29: '假检查'
30: 'print'
31: ('==================================================',)
32: ('   CrackMe Challenge - Binary Edition',)
33: ('Keywords: 52pojie, 2026, Happy New Year',)
34: ('Hint: 1337 5p34k & 5ymb0l5!',)
35: ('      Try to decompile this in IDA!',)
36: ('--------------------------------------------------',)
37: 'CrackMeCore'
38: '\n[?] Enter the password: '
39: 'fake_check'
40: ('\n[!] Close, but not quite there...',)
41: '\nPress Enter to exit...'
42: 'verify'
43: 'get_target_checksum'
44: ('\n==================================================',)
45: ('        *** SUCCESS! ***',)
46: ('[+] L33T H4X0R!',)
47: '[+] Your answer: '
48: '\n[!] Checksum mismatch: '
49: ' != '
50: ('\n[X] Access Denied!',)
51: ('[X] Wrong password!',)
52: '主函数'
53: '__doc__'
54: '__file__'
55: '__cached__'
56: '__annotations__'
57: 'sys'
58: '__main__'
59: '__module__'
60: '核心验证类 - 将被编译成二进制'
61: '__qualname__'
62: '__init__'
63: 'CrackMeCore.__init__'
64: 'CrackMeCore._decrypt_char'
65: 'CrackMeCore._get_char_at_position'
66: 'CrackMeCore.verify'
67: 'CrackMeCore.checksum'
68: 'CrackMeCore.get_target_checksum'
69: 'main'
70: ('\n\n[!] Interrupted',)
71: 'crackme_hard.py'
72: '<module>'
73: ('self',)
74: ('self', 'part_idx', 'char_idx', 'encrypted_byte')
75: ('self', 'pos', 'current', 'part_idx', 'part')
76: ('self', 's', 'total', 'i', 'c')
77: ('user_input', 'fake_hashes', 'user_hash')
78: ('self', 'flag', 'i')
79: ('s',)
80: ('core', 'user_input', 'cs', 'target')
81: ('self', 'user_input', 'i', 'expected')
82: ''
------------------------------------------------------------
​
Successfully decoded 83 objects from __main__ blob
​
============================================================
Encrypted data parts:
  Part 0: b'dc!a;`b' (len=7)
  Part 1: <PREDEFINED_FLOAT_INDEX_17>
  Part 2: b'cacg' (len=4)
  Part 3: <PREDEFINED_FLOAT_INDEX_47>
  Part 4: b'\x19e!!(' (len=5)
  Part 5: <PREDEFINED_FLOAT_INDEX_14>
  Part 6: b'\x1fb&' (len=3)
  Part 7: <PREDEFINED_FLOAT_INDEX_14>
  Part 8: b'\x08be#' (len=4)
  Part 9: b'ppp' (len=3)
​
Total encrypted data length: 26 bytes
​
Potential flag (key=81): 52p0j132026H4ppyN3wY34r!!!
​
进程已结束,退出代码为 0[/mw_shl_code]

关键信息如下:字符串如下,key :81,长度为30

复制代码
b'dc!a;`b', '<PREDEFINED_FLOAT_INDEX_17>', b'cacg', '<PREDEFINED_FLOAT_INDEX_47>', b'\x19e!!(', '<PREDEFINED_FLOAT_INDEX_14>', b'\x1fb&', '<PREDEFINED_FLOAT_INDEX_14>', b'\x08be#', b'ppp']
  1: '_parts'
  2: 81
  3: '_key'
  4: 30

让AI解析Python的这段部分字符串,可以生成完整的Python代码,

python 复制代码
import hashlib
import sys
​
​
class CrackMeCore:
    """核心验证类 - 将被编译成二进制"""
​
    def __init__(self):
        # 加密的数据部分
        self._parts = [
            b'dc!a;`b',  # 第0部分
            b'\x11',  # 浮点数占位符
            b'cacg',  # 第2部分
            b'\x2F',  # 浮点数占位符
            b'\x19e!!(',  # 第4部分
            b'\x0E',  # 浮点数占位符
            b'\x1fb&',  # 第6部分
            b'\x0E',  # 浮点数占位符
            b'\x08be#',  # 第8部分
            b'ppp'  # 第9部分
        ]
        self._key = 81  # 解密密钥
        self._total_len = 30  # 总长度
​
    def _get_char_at_position(self, pos):
        """获取指定位置的字符(加密数据)"""
        current = 0
        for part in self._parts:
            # 跳过浮点数占位符
            # if not isinstance(part, bytes):
            #     continue
​
            part_len = len(part)
            if current + part_len > pos:
                # 找到目标位置
                char_idx = pos - current
                encrypted_byte = part[char_idx]
                return encrypted_byte
            current += part_len
        return None
​
    def _decrypt_char(self, encrypted_byte):
        """解密单个字符"""
        # 使用密钥进行异或解密
        return encrypted_byte ^ self._key
​
    def checksum(self, s):
        """计算校验和"""
        total = 0
        for i, c in enumerate(s):
            # 使用位置和字符值计算校验和
            total += (i + 1) * ord(c)
        return total
​
    def get_target_checksum(self):
        """获取目标校验和"""
        flag = ""
        for i in range(self._total_len):
            encrypted_byte = self._get_char_at_position(i)
            if encrypted_byte is not None:
                decrypted_char = self._decrypt_char(encrypted_byte)
                flag += chr(decrypted_char)
​
        # 计算目标校验和
        target = self.checksum(flag)
        return target, flag
​
    def leet_to_text(leet_str):
        """将Leet语转换为正常文本"""
        leet_map = {
            '1': 'L', '3': 'E', '4': 'A', '5': 'S', '0': 'O',
            '7': 'T', '8': 'B', '9': 'G', '2': 'Z', '6': 'G',
            # 小写版本
            'l': 'l', 'e': 'e', 'a': 'a', 's': 's', 'o': 'o',
            't': 't', 'b': 'b', 'g': 'g', 'z': 'z',
        }
​
        result = ""
        for c in leet_str:
            if c in leet_map:
                result += leet_map[c]
            else:
                result += c
        return result
​
    def verify(self, user_input):
        """验证用户输入"""
        # 假的验证(混淆用)
        fake_hashes = [
            hashlib.sha256("fake".encode()).hexdigest(),
            hashlib.sha256("check".encode()).hexdigest()
        ]
        user_hash = hashlib.sha256(user_input.encode()).hexdigest()
​
        # 实际验证:计算用户输入的校验和
        cs = self.checksum(user_input)
​
        # 获取目标校验和和标志
        target, flag = self.get_target_checksum()
        # flag = self.leet_to_text(flag)
        print(flag)
​
        # 比较校验和
        if cs == target:
            return True, flag
        else:
            return False, None
​
    def fake_check(self, user_input):
        """假检查函数(混淆用)"""
        expected = "fake_flag_123"
        if len(user_input) == len(expected):
            return True
        return False
​
​
​
def main():
    """主函数"""
    try:
        # 显示欢迎信息
        print("==================================================")
        print("   CrackMe Challenge - Binary Edition")
        print("Keywords: 52pojie, 2026, Happy New Year")
        print("Hint: 1337 5p34k & 5ymb0l5!")
        print("      Try to decompile this in IDA!")
        print("--------------------------------------------------")
​
        # 创建核心验证对象
        core = CrackMeCore()
​
        # 获取用户输入
        user_input = input("\n[?] Enter the password: ")
​
        # 验证输入
        success, flag = core.verify(user_input)
​
        if success:
            print("\n==================================================")
            print("        *** SUCCESS! ***")
            print("[+] L33T H4X0R!")
            print(f"[+] Your answer: {flag}")
        else:
            print("\n[X] Access Denied!")
            print("[X] Wrong password!")
​
            # 获取目标校验和用于调试
            target, flag = core.get_target_checksum()
            user_cs = core.checksum(user_input)
            print(f"\n[!] Checksum mismatch: {user_cs} != {target}")
​
    except KeyboardInterrupt:
        print("\n\n[!] Interrupted")
​
    input("\nPress Enter to exit...")
​
​
if __name__ == "__main__":
    # 模块级变量
    __doc__ = None
    __file__ = "crackme_hard.py"
    __cached__ = None
    __annotations__ = {}
​
    # 主函数执行
    main()

然后运行,可以生成flag,

这里注意一个点,就是部分字符串没有解析出来,而是<PREDEFINED_FLOAT_INDEX_17>,<PREDEFINED_FLOAT_INDEX_47>,<PREDEFINED_FLOAT_INDEX_14>,<PREDEFINED_FLOAT_INDEX_14>

  • 什么float index,17,14,14,没有理解,
  • 所以刚开始就跳过了这些字符串,然后得到了如下字符串,
  • 然后看起来是对的,实际不对, 少了那几个字符,
  • 最后才知道,直接替换成对应的数字就可以

测试成功,

  • 注意到,1337,5p34k,这是一种古老的加密方式,让数字代替字母,提示flag里面也是这样的情形,
  • 如果加密flag为,flag{52pojie_2026_Happy_New_Year!_>w<},
  • 那么替换后的flag可能为:fl4g{52p0j13_2026_H4ppy_N3w_Y34r!_>w<}做一个小小的改变,
    +那么就和本题目的flag对应起来了。
相关推荐
星河漫步Lu1 小时前
Anaconda搭建深度学习虚拟环境
开发语言·python·深度学习
GEO_youxuan1 小时前
财务报表分析软件哪个好?2026年主流产品实测对比
python
为爱停留1 小时前
我的第一个智能问答:给智能体接上网页 + 流式输出
python
专注VB编程开发20年1 小时前
Python爬虫、提取网页内容,免费调用谷歌翻译接口
爬虫·python·信息可视化
gCode Teacher 格码致知1 小时前
Python教学:十六进制编码的显示方法-由Deepseek产生
开发语言·python·算法
biter down1 小时前
8:YAML 语法
运维·python
知识分享小能手1 小时前
数据预处理入门学习教程,从入门到精通,数据获取 — 知识点详解与案例代码(4)
python·学习·pandas
weixin_468466851 小时前
深度学习损失函数新手实战指南
人工智能·python·深度学习·算法·机器学习·ai
biter down1 小时前
3.Python 接口自动化之 Pytest 测试框架
开发语言·python