2025羊城杯初赛re wp

羊城杯

re1 GD1

用GDRE工具解包之后找到main.gd文件

查看文本

extends Node

@export var mob_scene: PackedScene
var score
var a = "000001101000000001100101000010000011000001100111000010000100000001110000000100100011000100100000000001100111000100010111000001100110000100000101000001110000000010001001000100010100000001000101000100010111000001010011000010010111000010000000000001010000000001000101000010000001000100000110000100010101000100010010000001110101000100000111000001000101000100010100000100000100000001001000000001110110000001111001000001000101000100011001000001010111000010000111000010010000000001010110000001101000000100000001000010000011000100100101"

func _ready():

    pass



func _process(delta: float) -> void :
    pass


func game_over():
    $ScoreTimer.stop()
    $MobTimer.stop()
    $HUD.show_game_over()

func new_game():
    score = 0
    $Player.start($StartPosition.position)
    $StartTimer.start()
    $HUD.update_score(score)
    $HUD.show_message("Get Ready")
    get_tree().call_group("mobs", "queue_free")

func _on_mob_timer_timeout():

    var mob = mob_scene.instantiate()


    var mob_spawn_location = $MobPath / MobSpawnLocation
    mob_spawn_location.progress_ratio = randf()


    var direction = mob_spawn_location.rotation + PI / 2


    mob.position = mob_spawn_location.position


    direction += randf_range( - PI / 4, PI / 4)
    mob.rotation = direction


    var velocity = Vector2(randf_range(150.0, 250.0), 0.0)
    mob.linear_velocity = velocity.rotated(direction)


    add_child(mob)


func _on_score_timer_timeout():
    score += 1
    $HUD.update_score(score)
    if score == 7906:
        var result = ""
        for i in range(0, a.length(), 12):
            var bin_chunk = a.substr(i, 12)
            var hundreds = bin_chunk.substr(0, 4).bin_to_int()
            var tens = bin_chunk.substr(4, 4).bin_to_int()
            var units = bin_chunk.substr(8, 4).bin_to_int()
            var ascii_value = hundreds * 100 + tens * 10 + units
            result += String.chr(ascii_value)
        $HUD.show_message(result)

func _on_start_timer_timeout():
    $MobTimer.start()
    $ScoreTimer.start()

先将二进制字符串被按 12 位一组进行分割,再将每组 12 位二进制再分为 3 个 4 位部分,分别代表百位数、十位数和个位数,然后转换为十进制后计算总和,最后将得到的数值转换成字符

解密脚本:

a = "000001101000000001100101000010000011000001100111000010000100000001110000000100100011000100100000000001100111000100010111000001100110000100000101000001110000000010001001000100010100000001000101000100010111000001010011000010010111000010000000000001010000000001000101000010000001000100000110000100010101000100010010000001110101000100000111000001000101000100010100000100000100000001001000000001110110000001111001000001000101000100011001000001010111000010000111000010010000000001010110000001101000000100000001000010000011000100100101"

result = ""
for i in range(0, len(a), 12):
    bin_chunk = a[i:i + 12]
    if len(bin_chunk) < 12:
        continue
    hundreds_bin = bin_chunk[0:4]
    tens_bin = bin_chunk[4:8]
    units_bin = bin_chunk[8:12]

    hundreds = int(hundreds_bin, 2)
    tens = int(tens_bin, 2)
    units = int(units_bin, 2)

    ascii_value = hundreds * 100 + tens * 10 + units

    result += chr(ascii_value)

print(result)

re2 PLUS

打开文件,用die看下pyd文件,确定python版本为3.9

切换版本后就可以运行了,就是输入,然后验证

看到好多数相加,于是简化了一下

from init import *
m(exec(exit(int(307) + int(922) + int(928) + int(883) + int(0) + int(60) + int(32))),exit(int(167) + int(772) + int(16)),exit(int(209) + int(715) + int(2)))(e);
m(exec(exit(int(307) + int(922) + int(928) + int(883) + int(0) + int(60) + int(32))),exit(int(188) + int(743) + int(68)),exit(int(655) + int(36)))(e);
m(exec(exit(int(201) + int(800) + int(370) + int(677) + int(125) + int(856) + int(982) + int(9))),exit(int(167) + int(772) + int(16)),exec(exit(int(215) + int(430) + int(820) + int(910) + int(458) + int(736) + int(505) + int(0) + int(51) + int(870) + int(224) + int(350) + int(847) + int(782) + int(563) + int(842) + int(941) + int(767) + int(450) + int(663) + int(266) + int(900) + int(616) + int(936) + int(594) + int(409) + int(721) + int(828) + int(862) + int(0) + int(50) + int(250) + int(877) + int(0) + int(0) + int(7) + int(259) + int(502) + int(951) + int(573) + int(354) + int(763) + int(0) + int(39) + int(390) + int(911) + int(514) + int(251) + int(779) + int(543) + int(944) + int(934) + int(960) + int(684) + int(0) + int(0) + int(8) + int(209) + int(628) + int(473) + int(304) + int(218) + int(610) + int(967) + int(519) + int(892) + int(397) + int(440) + int(123) + int(955) + int(636) + int(948) + int(631) + int(0) + int(47) + int(774) + int(533) + int(721) + int(835) + int(838) + int(0) + int(86) + int(0) + int(12) + int(898) + int(766) + int(274) + int(946) + int(831) + int(732) + int(554) + int(223) + int(371) + int(869) + int(0) + int(0) + int(7) + int(493) + int(373) + int(0) + int(65) + int(194) + int(188) + int(0) + int(38) + int(0) + int(55) + int(945) + int(3))),)(e);
m(exec(exit(int(211) + int(0) + int(23) + int(573) + int(828) + int(994) + int(606) + int(397) + int(3))),exit(int(44)),exit(int(189) + int(399) + int(0) + int(3)))(e);
m(exec(exit(int(201) + int(800) + int(370) + int(677) + int(125) + int(856) + int(982) + int(9))),exit(int(188) + int(784) + int(64)), i(exec(exit(int(520) + int(485) + int(229) + int(507) + int(545) + int(392) + int(928) + int(716) + int(380) + int(743) + int(873) + int(332) + int(979) + int(750) + int(615) + int(584)))).encode())(e);
m(exec(exit(int(211) + int(0) + int(23) + int(573) + int(828) + int(994) + int(606) + int(397) + int(3))),exit(int(39)),exit(int(188) + int(784) + int(64)))(e);
m(exec(exit(int(211) + int(0) + int(23) + int(573) + int(828) + int(994) + int(606) + int(397) + int(3))),exit(int(43)),exit(int(44)))(e);
m(exec(exit(int(211) + int(0) + int(23) + int(573) + int(828) + int(994) + int(606) + int(397) + int(3))),exit(int(40)),7)(e);
m(exec(exit(int(187) + int(100) + int(846) + int(671) + int(655) + int(242) + int(610) + int(0) + int())), exit(int(167) + int(772) + int(16)), exit(int(167) + int(773) + int(32)))(e);
m(exec(exit(int(173) + int(535) + int(626) + int(0) + int()))) \
if (b(m(exec(exit(int(788) + int(282) + int(697) + int(949) + int(0) + int(48) + int(867) + int(6))), exit(int(188) + int(784) + int(64)), exit(int(44)))(e)).decode()== exec(exit(int(636) + int(496) + int(797) + int(464) + int(929) + int(889) + int(819) + int(0) + int(18) + int(589) + int(958) + int(474) + int(261) + int(894) + int(226) + int(380) + int(884) + int(858) + int(896) + int(837) + int(0) + int(50) + int(849) + int(823) + int(120) + int(0) + int(96) + int(559) + int(828) + int(809) + int(884) + int(712) + int(107) + int(801) + int(783) + int(610) + int(237) + int(788) + int(137) + int(0) + int(0) + int(2) + int(972) + int(622) + int(711) + int(849) + int(132) + int(377) + int(866) + int(432) + int(975) + int(817) + int(0) + int(21)))) \
else p(exec(exit(int(310) + int(844) + int(326) + int(706) + int(854) + int(73)))) #type:ignore

补上import init 通过help(init)打印出pyd文件的函数信息

Help on module init:

NAME
    init

FUNCTIONS
    a2b_hex(hexstr, /)
        Binary data of hexadecimal representation.
        
        hexstr must contain an even number of hex digits (upper or lower case).
        This function is also available as "unhexlify()".
    
    exec(x)
    
    exit = eval(source, globals=None, locals=None, /)
        Evaluate the given source in the context of globals and locals.
        
        The source may be a string representing a Python expression
        or a code object as returned by compile().
        The globals must be a dictionary and locals can be any mapping,
        defaulting to the current globals and locals.
        If only globals is given, locals defaults to it.
    
    i = input(prompt=None, /)
        Read a string from standard input.  The trailing newline is stripped.
        
        The prompt string, if given, is printed to standard output without a
        trailing newline before reading input.
        
        If the user hits EOF (*nix: Ctrl-D, Windows: Ctrl-Z+Return), raise EOFError.
        On *nix systems, readline is used if available.
    
    p = print(...)
        print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
        
        Prints the values to a stream, or to sys.stdout by default.
        Optional keyword arguments:
        file:  a file-like object (stream); defaults to the current sys.stdout.
        sep:   string inserted between values, default a space.
        end:   string appended after the last value, default a newline.
        flush: whether to forcibly flush the stream.

DATA
    __test__ = {}
    e = <unicorn.unicorn_py3.arch.intel.UcIntel object>

可知p,i等指令的信息

逐个把m换成p,打印出执行过程,写成伪代码:

mem_map 16777216 2097152
mem_map 18874368 65536
mem_write 16777216 b'\xf3\x0f\x1e\xfaUH\x89\xe5H\x89}\xe8\x89u\xe4\x89\xd0\x88E\xe0\xc7E\xfc\x00\x00\x00\x00\xebL\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x00\x8d\x0c\xc5\x00\x00\x00\x00\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x002E\xe0\x8d4\x01\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x00\xc1\xe0\x05\x89\xc1\x8bU\xfcH\x8bE\xe8H\x01\xd0\x8d\x14\x0e\x88\x10\x83E\xfc\x01\x8bE\xfc;E\xe4r\xac\x90\x90]'
reg_write 44 18939903
mem_write 18878464 b'your_input'
reg_write 39 18878464
reg_write 43 44
reg_write 40 7
emu_start 16777216 16777332

if  mem_read 18878464 44 =="425MvHMxtLqZ3ty3RZkw3mwwulNRjkswbpkDMK+3CDCOtbe6kzAqPyrcEAI=" ;print(good)
else print(no way!)

其中

\xf3\x0f\x1e\xfaUH\x89\xe5H\x89}\xe8\x89u\xe4\x89\xd0\x88E\xe0\xc7E\xfc\x00\x00\x00\x00\xebL\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x00\x8d\x0c\xc5\x00\x00\x00\x00\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x002E\xe0\x8d4\x01\x8bU\xfcH\x8bE\xe8H\x01\xd0\x0f\xb6\x00\xc1\xe0\x05\x89\xc1\x8bU\xfcH\x8bE\xe8H\x01\xd0\x8d\x14\x0e\x88\x10\x83E\xfc\x01\x8bE\xfc;E\xe4r\xac\x90\x90]应该是x86虚拟指令集

转换为汇编,再结合pyd文件反汇编的函数集,逻辑大概是每个字节乘(32+8)再异或key,最后base64

由于是线性加密,于是我拿DASCTF{的头推出了key为7

于是写出解密脚本

脚本:

#include <stdio.h>
#include <stdint.h>

char decrypt_char(uint8_t encrypted, uint8_t key) {
    for (int orig = 0; orig <= 0xFF; orig++) {
        uint32_t result = (orig * 40) + (orig ^ key);
        if ((result & 0xFF) == encrypted) {
            return (char)orig;
        }
    }
    return '?';
}

int main() {
    uint8_t encrypted[] = {
        0xe3, 0x6e, 0x4c, 0xbc, 0x73, 0x31, 0xb4, 0xba, 
        0x99, 0xde, 0xdc, 0xb7, 0x45, 0x99, 0x30, 0xde, 
        0x6c, 0x30, 0xba, 0x53, 0x51, 0x8e, 0x4b, 0x30, 
        0x6e, 0x99, 0x03, 0x30, 0xaf, 0xb7, 0x08, 0x30, 
        0x8e, 0xb5, 0xb7, 0xba, 0x93, 0x30, 0x2a, 0x3f, 
        0x2a, 0xdc, 0x10, 0x02
    };
    int length = sizeof(encrypted) / sizeof(encrypted[0]);
    uint8_t key = 7; 
    char original[length + 1];  

    for (int i = 0; i < length; i++) {
        original[i] = decrypt_char(encrypted[i], key);
    }
    original[length] = '\0'; 
    
    printf("%s\n", original);
    
    return 0;
}

re3 ez_py

pyinstxtractor 提取 pyc

https://pylingual.io/ 网站反编译

反编译结果:

# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: key.py
# Bytecode version: 3.13.0rc3 (3571)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)

import ast
import types
import sys
o0o0o0 = [105084753, 3212558540, 351342182, 844102737, 2002504052, 356536456, 2463183122, 615034880, 1156203296]

def changli(o0o0o1, o0o0o2, o0o0o3):
    o0o0o4 = 2269471011
    o0o0o5 = o0o0o3 & 4294967295
    o0o0o6 = (o0o0o3 >> 8 ^ 305419896) & 4294967295
    o0o0o7 = (o0o0o3 << 4 ^ 2271560481) & 4294967295
    o0o0o8 = (o0o0o3 >> 12 ^ 2882400000) & 4294967295
    o0o0o9 = o0o0o1 & 4294967295
    o0o0o10 = o0o0o2 & 4294967295
    o0o0o11 = 0
    for _ in range(32):
        o0o0o11 = o0o0o11 + o0o0o4 & 4294967295
        o0o0o9 = o0o0o9 + ((o0o0o10 << 4) + o0o0o5 ^ o0o0o10 + o0o0o11 ^ (o0o0o10 >> 4) + o0o0o6) & 4294967295
        o0o0o10 = o0o0o10 + ((o0o0o9 << 4) + o0o0o7 ^ o0o0o9 + o0o0o11 ^ (o0o0o9 >> 4) + o0o0o8) & 4294967295
    return (o0o0o9, o0o0o10)

def Shorekeeper(o0o0o12):
    o0o0o13 = o0o0o12 >> 16
    o0o0o14 = o0o0o12 & 65535
    return (o0o0o13, o0o0o14)

def Kathysia(o0o0o15, o0o0o16):
    return o0o0o15 << 16 | o0o0o16 + 0

def Phrolova(o0o0o17):
    o0oA = 'Carlotta'
    o0oB = ['o0oC', 'o0oD', 'o0oE', 'o0oF']
    o0oG = []
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oH', ctx=ast.Store())], value=ast.Constant(305419896)))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oI', ctx=ast.Store())], value=ast.BinOp(ast.Name(id='o0oE', ctx=ast.Load()), ast.BitAnd(), ast.Constant(65535))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oJ', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.Name(id='o0oE', ctx=ast.Load()), ast.RShift(), ast.Constant(16)), ast.BitAnd(), ast.Constant(65535))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oK', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.Name(id='o0oE', ctx=ast.Load()), ast.BitXor(), ast.Name(id='o0oF', ctx=ast.Load())), ast.BitAnd(), ast.Constant(65535))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oL', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.BinOp(ast.Name(id='o0oE', ctx=ast.Load()), ast.RShift(), ast.Constant(8)), ast.BitXor(), ast.Name(id='o0oF', ctx=ast.Load())), ast.BitAnd(), ast.Constant(65535))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oM', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.Name(id='o0oH', ctx=ast.Load()), ast.Mult(), ast.BinOp(ast.Name(id='o0oF', ctx=ast.Load()), ast.Add(), ast.Constant(1))), ast.BitAnd(), ast.Constant(4294967295))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oN', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.BinOp(ast.BinOp(ast.Name(id='o0oD', ctx=ast.Load()), ast.LShift(), ast.Constant(5)), ast.Add(), ast.Name(id='o0oI', ctx=ast.Load())), ast.BitXor(), ast.BinOp(ast.Name(id='o0oD', ctx=ast.Load()), ast.Add(), ast.Name(id='o0oM', ctx=ast.Load()))), ast.Add(), ast.Name(id='o0oJ', ctx=ast.Load()))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oP', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.Name(id='o0oC', ctx=ast.Load()), ast.Add(), ast.Name(id='o0oN', ctx=ast.Load())), ast.BitAnd(), ast.Constant(65535))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oN', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.BinOp(ast.Name(id='o0oP', ctx=ast.Load()), ast.LShift(), ast.Constant(5)), ast.Add(), ast.Add(), ast.Constant(5)), ast.Add(), ast.Name(id='o0oL', ctx=ast.Load()))))
    o0oG.append(ast.Assign(targets=[ast.Name(id='o0oQ', ctx=ast.Store())], value=ast.BinOp(ast.BinOp(ast.Name(id='o0oD', ctx=ast.Load()), ast.Add(), ast.Name(id='o0oN', ctx=ast.Load())), ast.BitAnd(), ast.Constant(65535))))
    o0oG.append(ast.Return(ast.Tuple(elts=[ast.Name(id='o0oP', ctx=ast.Load()), ast.Name(id='o0oQ', ctx=ast.Load())], ctx=ast.Load())))
    o0oU = ast.FunctionDef(name=o0oA, args=ast.arguments(posonlyargs=[], args=[ast.arg(arg=a) for a in o0oB], kwonlyargs=[], kw_defaults=[], defaults=[]), body=o0oG, decorator_list=[])
    o0oV = ast.parse('\ndef _tea_helper_func(a, b, c):\n    magic1 = (a ^ b) & 0xDEADBEEF\n    magic2 = (c << 3) | (a >> 5)\n    return (magic1 + magic2 - (b & 0xCAFEBABE)) & 0xFFFFFFFF\n\ndef _fake_tea_round(x, y):\n    return ((x * 0x9E3779B9) ^ (y + 0x12345678)) & 0xFFFFFFFF\n\n_tea_magic_delta = 0x9E3779B9 ^ 0x12345678\n_tea_dummy_keys = [0x1111, 0x2222, 0x3333, 0x4444]\n').body
    o0oW = ast.Module(body=[o0oU] + o0oV, type_ignores=[])
    ast.fix_missing_locations(o0oW)
    o0oX = compile(o0oW, filename='<tea_obf_ast>', mode='exec')
    o0oY = {}
    exec(o0oX, o0oY)
    if o0oA in o0oY:
        o0o0o17[o0oA] = o0oY[o0oA]
    return None
Phrolova(globals())

def shouan(o0o0o32):
    raise ValueError('需要输入9个key') if len(o0o0o32)!= 9 else None

def jinhsi():
    print('请输入9个数字:')
    try:
        o0o0o46 = input().strip()
        if ',' in o0o0o46:
            o0o0o42 = o0o0o46.split(',')
        if len(o0o0o42)!= 9:
            print('错误: 需要输入9个数')
        return None
    except Exception as o0o0o47:
        print(f'发生错误: {o0o0o47}')
if __name__ == '__main__':
    jinhsi()

运行有错,ai修复一下主逻辑

import ast
import types
import sys


def changli(o0o0o1, o0o0o2, o0o0o3):
    o0o0o4 = 0x87456123
    o0o0o5 = o0o0o3 & 0xFFFFFFFF
    o0o0o6 = ((o0o0o3 >> 8) ^ 305419896) & 0xFFFFFFFF
    o0o0o7 = ((o0o0o3 << 4) ^ 0x87654321) & 0xFFFFFFFF
    o0o0o8 = ((o0o0o3 >> 12) ^ 0xABCDEF00) & 0xFFFFFFFF
    o0o0o9 = o0o0o1 & 0xFFFFFFFF
    o0o0o10 = o0o0o2 & 0xFFFFFFFF
    o0o0o11 = 0

    for _ in range(32):
        o0o0o11 = (o0o0o11 + o0o0o4) & 0xFFFFFFFF
        o0o0o9 = (o0o0o9 + (((o0o0o10 << 4) + o0o0o5) ^ (o0o0o10 + o0o0o11) ^ ((o0o0o10 >> 4) + o0o0o6))) & 0xFFFFFFFF
        o0o0o10 = (o0o0o10 + (((o0o0o9 << 4) + o0o0o7) ^ (o0o0o9 + o0o0o11) ^ ((o0o0o9 >> 4) + o0o0o8))) & 0xFFFFFFFF

    return (o0o0o9, o0o0o10)


def Shorekeeper(o0o0o12):
    o0o0o13 = o0o0o12 >> 16
    o0o0o14 = o0o0o12 & 65535
    return (o0o0o13, o0o0o14)


def Kathysia(o0o0o15, o0o0o16):
    return (o0o0o15 << 16) | o0o0o16


def Phrolova(o0o0o17):
    o0oA = 'Carlotta'
    o0oB = ['o0oC', 'o0oD', 'o0oE', 'o0oF']
    o0oG = []

    # Assignment: o0oH = 305419896
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oH', ctx=ast.Store())],
        value=ast.Constant(value=305419896)
    ))

    # Assignment: o0oI = o0oE & 65535
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oI', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.Name(id='o0oE', ctx=ast.Load()),
            op=ast.BitAnd(),
            right=ast.Constant(value=65535)
        )
    ))

    # Assignment: o0oJ = (o0oE >> 16) & 65535
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oJ', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.Name(id='o0oE', ctx=ast.Load()),
                op=ast.RShift(),
                right=ast.Constant(value=16)
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=65535)
        )
    ))

    # Assignment: o0oK = (o0oE ^ o0oF) & 65535
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oK', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.Name(id='o0oE', ctx=ast.Load()),
                op=ast.BitXor(),
                right=ast.Name(id='o0oF', ctx=ast.Load())
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=65535)
        )
    ))

    # Assignment: o0oL = ((o0oE >> 8) ^ o0oF) & 65535
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oL', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.BinOp(
                    left=ast.Name(id='o0oE', ctx=ast.Load()),
                    op=ast.RShift(),
                    right=ast.Constant(value=8)
                ),
                op=ast.BitXor(),
                right=ast.Name(id='o0oF', ctx=ast.Load())
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=65535)
        )
    ))

    # Assignment: o0oM = (o0oH * (o0oF + 1)) & 0xFFFFFFFF
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oM', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.Name(id='o0oH', ctx=ast.Load()),
                op=ast.Mult(),
                right=ast.BinOp(
                    left=ast.Name(id='o0oF', ctx=ast.Load()),
                    op=ast.Add(),
                    right=ast.Constant(value=1)
                )
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=0xFFFFFFFF)
        )
    ))

    # Assignment: o0oN = (((o0oD << 5) + o0oI) ^ (o0oD + o0oM) ^ ((o0oD >> 5) + o0oJ)) & 0xFFFFFFFF
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oN', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.BinOp(
                    left=ast.BinOp(
                        left=ast.Name(id='o0oD', ctx=ast.Load()),
                        op=ast.LShift(),
                        right=ast.Constant(value=5)
                    ),
                    op=ast.Add(),
                    right=ast.Name(id='o0oI', ctx=ast.Load())
                ),
                op=ast.BitXor(),
                right=ast.BinOp(
                    left=ast.BinOp(
                        left=ast.Name(id='o0oD', ctx=ast.Load()),
                        op=ast.Add(),
                        right=ast.Name(id='o0oM', ctx=ast.Load())
                    ),
                    op=ast.BitXor(),
                    right=ast.BinOp(
                        left=ast.BinOp(
                            left=ast.Name(id='o0oD', ctx=ast.Load()),
                            op=ast.RShift(),
                            right=ast.Constant(value=5)
                        ),
                        op=ast.Add(),
                        right=ast.Name(id='o0oJ', ctx=ast.Load())
                    )
                )
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=0xFFFFFFFF)
        )
    ))

    # Assignment: o0oP = (o0oC + o0oN) & 65535
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oP', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.Name(id='o0oC', ctx=ast.Load()),
                op=ast.Add(),
                right=ast.Name(id='o0oN', ctx=ast.Load())
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=65535)
        )
    ))

    # Assignment: o0oN = (((o0oP << 5) + o0oK) ^ (o0oP + o0oM) ^ ((o0oP >> 5) + o0oL)) & 0xFFFFFFFF
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oN', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.BinOp(
                    left=ast.BinOp(
                        left=ast.Name(id='o0oP', ctx=ast.Load()),
                        op=ast.LShift(),
                        right=ast.Constant(value=5)
                    ),
                    op=ast.Add(),
                    right=ast.Name(id='o0oK', ctx=ast.Load())
                ),
                op=ast.BitXor(),
                right=ast.BinOp(
                    left=ast.BinOp(
                        left=ast.Name(id='o0oP', ctx=ast.Load()),
                        op=ast.Add(),
                        right=ast.Name(id='o0oM', ctx=ast.Load())
                    ),
                    op=ast.BitXor(),
                    right=ast.BinOp(
                        left=ast.BinOp(
                            left=ast.Name(id='o0oP', ctx=ast.Load()),
                            op=ast.RShift(),
                            right=ast.Constant(value=5)
                        ),
                        op=ast.Add(),
                        right=ast.Name(id='o0oL', ctx=ast.Load())
                    )
                )
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=0xFFFFFFFF)
        )
    ))

    # Assignment: o0oQ = (o0oD + o0oN) & 65535
    o0oG.append(ast.Assign(
        targets=[ast.Name(id='o0oQ', ctx=ast.Store())],
        value=ast.BinOp(
            left=ast.BinOp(
                left=ast.Name(id='o0oD', ctx=ast.Load()),
                op=ast.Add(),
                right=ast.Name(id='o0oN', ctx=ast.Load())
            ),
            op=ast.BitAnd(),
            right=ast.Constant(value=65535)
        )
    ))

    # Return (o0oP, o0oQ)
    o0oG.append(ast.Return(
        value=ast.Tuple(
            elts=[
                ast.Name(id='o0oP', ctx=ast.Load()),
                ast.Name(id='o0oQ', ctx=ast.Load())
            ],
            ctx=ast.Load()
        )
    ))

    # Create FunctionDef for Carlotta
    o0oU = ast.FunctionDef(
        name=o0oA,
        args=ast.arguments(
            posonlyargs=[],
            args=[ast.arg(arg=a) for a in o0oB],
            kwonlyargs=[],
            kw_defaults=[],
            defaults=[]
        ),
        body=o0oG,
        decorator_list=[]
    )

    # Parse additional code
    o0oV = ast.parse("""
def _tea_helper_func(a, b, c):
    magic1 = (a ^ b) & 0xDEADBEEF
    magic2 = (c << 3) | (a >> 5)
    return (magic1 + magic2 - (b & 0xCAFEBABE)) & 0xFFFFFFFF

def _fake_tea_round(x, y):
    return ((x * 0x9E3779B9) ^ (y + 0x12345678)) & 0xFFFFFFFF

_tea_magic_delta = 0x9E3779B9 ^ 0x12345678
_tea_dummy_keys = [0x1111, 0x2222, 0x3333, 0x4444]
""").body

    # Create Module
    o0oW = ast.Module(
        body=[o0oU] + o0oV,
        type_ignores=[]
    )

    # Fix locations and compile
    ast.fix_missing_locations(o0oW)
    o0oX = compile(o0oW, '<tea_obf_ast>', 'exec')
    o0oY = {}
    exec(o0oX, o0oY)

    # Assign o0o0o17 to Carlotta if it exists
    if o0oA in o0oY:
        o0oY[o0oA] = o0o0o17

    return None


def shouan(o0o0o32):
    if len(o0o0o32) != 9:
        raise ValueError('闇€瑕佽緭鍏?')

    o0o0o35 = [
        105084753,
        0xBF7BC0CC,
        351342182,
        844102737,
        2002504052,
        356536456,
        0x92D13112,
        615034880,
        1156203296
    ]
    o0o0o49 = []

    for i, o0o0o34 in enumerate(o0o0o32):
        o0o0o33 = ord(o0o0o34)
        o0o0o36, o0o0o37 = Shorekeeper(o0o0o33)
        o0o0o38, o0o0o39 = changli(o0o0o36, o0o0o37, o0o0o35[i])
        o0o0o40 = Kathysia(o0o0o38, o0o0o39)
        o0o0o49.append(o0o0o40)

    return o0o0o49


jinhsi = globals()['shouan']

类似tea加密的过程,写脚本逆向

import asyncio

TARGETS = [105084753, 3212558540, 351342182, 844102737, 2002504052, 356536456, 2463183122, 615034880, 1156203296]


def split_int32(val):
    high = val >> 16
    low = val & 0xFFFF
    return (high, low)


def merge_int16(high, low):
    return (high << 16) | (low & 0xFFFF)


def decrypt_tea(v1, v2, key):
    delta = 2269471011
    k0 = key & 0xFFFFFFFF
    k1 = ((key >> 8) ^ 305419896) & 0xFFFFFFFF
    k2 = ((key << 4) ^ 2271560481) & 0xFFFFFFFF
    k3 = ((key >> 12) ^ 2882400000) & 0xFFFFFFFF
    x, y = v1 & 0xFFFFFFFF, v2 & 0xFFFFFFFF
    sum_val = (delta * 32) & 0xFFFFFFFF
    for _ in range(32):
        y = (y - (((x << 4) + k2) ^ (x + sum_val) ^ ((x >> 4) + k3))) & 0xFFFFFFFF
        x = (x - (((y << 4) + k0) ^ (y + sum_val) ^ ((y >> 4) + k1))) & 0xFFFFFFFF
        sum_val = (sum_val - delta) & 0xFFFFFFFF
    return (x, y)


def decrypt_transform(p, q, e, f):
    const = 305419896
    e_low = e & 0xFFFF
    e_high = (e >> 16) & 0xFFFF
    e_xor_f = (e ^ f) & 0xFFFF
    e_shift = ((e >> 8) ^ f) & 0xFFFF
    m = (const * (f + 1)) & 0xFFFFFFFF
    n2 = ((((p << 5) + e_xor_f) ^ (p + m)) ^ ((p >> 5) + e_shift)) & 0xFFFF
    d = (q - n2) & 0xFFFF
    n1 = ((((d << 5) + e_low) ^ (d + m)) ^ ((d >> 5) + e_high)) & 0xFFFF
    c = (p - n1) & 0xFFFF
    return (c, d)


async def compute_key():
    values = list(TARGETS)
    for i in range(7, -1, -1):
        x, y = values[i], values[i + 1]
        values[i], values[i + 1] = decrypt_tea(x, y, 2025)

    key = []
    for i, v in enumerate(values):
        e = i + 2025
        f = i * i
        p, q = split_int32(v)
        c, d = decrypt_transform(p, q, e, f)
        key.append(merge_int16(c, d))
    return key


async def main():
    result = await compute_key()
    print(', '.join(map(str, result)))


if __name__ == "__main__":
    asyncio.run(main())

解出key

1234, 5678, 9123, 4567, 8912, 3456, 7891, 2345, 6789

另外一个src文件需要 Pyarmor-Static-Unpack-1shot 解包

补上PY000000头

src放入pyarmor_runtime_000000文件夹,用工具解包

(cheardism_env) PS C:\Users\ASUS\Desktop\附件> python C:\Users\ASUS\Desktop\附件\src\pyarmor\oneshot\shot.py C:\Users\ASUS\Desktop\附件\src\c      

 ____                                                                     ____
( __ )                                                                   ( __ )
 |  |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|  |
 |  |   ____                                      _ ___  _          _     |  |
 |  |  |  _ \ _  _  __ _ _ __ _ _ __   ___  _ _  / / __|| |_   ___ | |_   |  |
 |  |  | |_) | || |/ _` | '__| ' `  \ / _ \| '_| | \__ \| ' \ / _ \| __|  |  |
 |  |  |  __/| || | (_| | |  | || || | (_) | |   | |__) | || | (_) | |_   |  |
 |  |  |_|    \_, |\__,_|_|  |_||_||_|\___/|_|   |_|___/|_||_|\___/ \__|  |  |
 |  |         |__/                                                        |  |
 |__|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|__|
(____)                                                                   (____)

              For technology exchange only. Use at your own risk.
        GitHub: https://github.com/Lil-House/Pyarmor-Static-Unpack-1shot

INFO     2025-10-12 11:00:11,145      Found new runtime: 000000 (C:\Users\ASUS\Desktop\附件\src\pyarmor_runtime_000000\pyarmor_runtime.pyd)
        ========================
        Pyarmor Runtime (Trial) Information:
        Product: non-profits
        AES key: ab738f35ffce23b13ae73d5a2c17a896
        Mix string AES nonce: 692e6e6f6e2d70726f666974
        ========================
INFO     2025-10-12 11:00:11,151      Found data in source: src.py
INFO     2025-10-12 11:00:11,173      Using executable: pyarmor-1shot.exe
INFO     2025-10-12 11:00:11,174      Decrypting: 000000 (src.py)

# Source Generated with Decompyle++
# File: src.py.1shot.seq (Python 3.13)

'__pyarmor_enter_54743__(...)'
cipher = [
    1473,
    3419,
    9156,
    1267,
    9185,
    2823,
    7945,
    618,
    7036,
    2479,
    5791,
    1945,
    4639,
    1548,
    3634,
    3502,
    2433,
    1407,
    1263,
    3354,
    9274,
    1085,
    8851,
    3022,
    8031,
    734,
    6869,
    2644,
    5798,
    1862,
    4745,
    1554,
    3523,
    3631,
    2512,
    1499,
    1221,
    3226,
    9237]

def init(key, key_len):
    '__pyarmor_enter_54746__(...)'
    _var_var_0 = 0
    _var_var_1 = None(list, None(range, 256))
    for _var_var_2 in None(range, 256):
        _var_var_0 = (_var_var_0 + _var_var_1[_var_var_2] + key[_var_var_2 % key_len]) % 256
        _var_var_1[_var_var_2], _var_var_1[_var_var_0] = _var_var_1[_var_var_0], _var_var_1[_var_var_2]
    '__pyarmor_exit_54747__(...)'
    return _var_var_1


def make(box):
    '__pyarmor_enter_54749__(...)'
    _var_var_2 = 0
    _var_var_0 = 0
    _var_var_3 = []
    for _var_var_4 in None(range, 256):
        _var_var_2 = (_var_var_2 + 1) % 256
        _var_var_0 = (_var_var_0 + box[_var_var_2]) % 256
        box[_var_var_2], box[_var_var_0] = box[_var_var_0], box[_var_var_2]
        _var_var_5 = (box[_var_var_2] + box[_var_var_0] + _var_var_4 % 23) % 256
        None(_var_var_3.append, box[_var_var_5])
    '__pyarmor_exit_54750__(...)'
    return _var_var_3

if __name__ == '__main__':
    init.__doc__ = '欢迎来到羊城!\nThe key len is:9'
    make.__doc__ = '    flag = list(b"flag{???}")\n    fuck_key = [1,2,3,4,5,6,7,8,9]\n    __ = [i % 0xff for i in fuck_key]\n    key = make(init(bytes(__), len(__)))\n    for i in range(len(cipher)):\n        _ = fuck_key[i % 9] if i % 2 == 0 else (fuck_key[i % 9] * 2) % 0xFFF\n        flag[i] ^= key[i] + _\n    '
    print(init.__doc__)
exit(0)
exit(0)
'__pyarmor_exit_54744__(...)'

一个rc4

写出脚本

data = [1473,3419,9156,1267,9185,2823,7945,618,7036,2479,5791,1945,4639,1548,3634,3502,2433,1407,1263,3354,9274,1085,8851,3022,8031,734,6869,2644,5798,1862,4745,1554,3523,3631,2512,1499,1221,3226,9237]

def setup(k, l):
    s = list(range(256))
    m = 0
    for n in range(256):
        m = (m + s[n] + k[n % l]) % 256
        s[n], s[m] = s[m], s[n]
    return s

def generate(b):
    x, y, o = 0, 0, []
    for _ in range(256):
        x = (x + 1) % 256
        y = (y + b[x]) % 256
        b[x], b[y] = b[y], b[x]
        z = (b[x] + b[y] + _ % 23) % 256
        o.append(b[z])
    return o

async def process():
    k = [1234, 5678, 9123, 4567, 8912, 3456, 7891, 2345, 6789]
    b = bytes([v % 0xff for v in k])
    s = generate(setup(b, len(b)))
    r = []
    for i in range(len(data)):
        m = k[i % 9] if i % 2 == 0 else (k[i % 9] * 2) % 0xFFF
        c = data[i] ^ (s[i] + m)
        r.append(c)
    return ''.join(chr(c) for c in r)

async def main():
    result = await process()
    print(result)

if __name__ == '__main__':
    import asyncio
    asyncio.run(main())

运行得到flag

re4 easyTauri

ida打开,搜索字符串main.js dump下 unk_14063B211

写入res文件

IDA_14063b211 = [
    0x1B, 0xBB, 0xA, 0x0, 0x64, 0x5C, 0x6A, 0xFE, 0xFD, 0x79, 0x71, 0xAE, 0x4E, 0x86, 0x86, 0xA4,
    0x8C, 0xE5, 0x72, 0xDC, 0xED, 0xEE, 0x15, 0xB9, 0x11, 0x18, 0x32, 0x3A, 0xE2, 0xC8, 0x71, 0xB6,
    0xFC, 0xD7, 0x7E, 0xAD, 0xFE, 0xFF, 0x2F, 0x52, 0x1A, 0xF5, 0x4A, 0xBD, 0x10, 0x9, 0x85, 0x46,
    0xA8, 0x6B, 0xB7, 0x37, 0xBB, 0x30, 0xF, 0x53, 0x79, 0x7F, 0x11, 0xD1, 0xE6, 0x49, 0xD4, 0x1A,
    0x43, 0x4A, 0x4C, 0x37, 0x35, 0x73, 0x5E, 0x3A, 0xE0, 0x57, 0xC8, 0x76, 0xE5, 0x80, 0x6, 0xE4,
    0xFA, 0x47, 0x1, 0x3F, 0x1, 0x27, 0xB0, 0x58, 0x6E, 0x9B, 0xBF, 0x9, 0xF4, 0x95, 0x6F, 0x99,
    0x4C, 0xBE, 0xDC, 0x7C, 0xFD, 0xF4, 0x72, 0x32, 0x19, 0xE1, 0x58, 0xD3, 0x66, 0xD9, 0xBF, 0xD4,
    0x81, 0xB7, 0x1C, 0x1C, 0xD7, 0xBD, 0x5C, 0xAE, 0x36, 0xDD, 0xC3, 0x3F, 0x9B, 0x9A, 0xFC, 0x76,
    0x3D, 0xDB, 0x1B, 0x5E, 0x76, 0xFE, 0xB9, 0x9, 0xD9, 0x97, 0xDA, 0xA7, 0xC4, 0xF0, 0x84, 0xEC,
    0xA9, 0x88, 0x3C, 0x96, 0xE8, 0xA4, 0x90, 0x5E, 0x6E, 0x97, 0x94, 0x50, 0xED, 0x26, 0x64, 0xCF,
    0x15, 0xF, 0xC5, 0x1A, 0xB2, 0x40, 0x78, 0x49, 0x5C, 0xD5, 0x54, 0x88, 0xEC, 0xB7, 0x5C, 0xFC,
    0x0, 0x9E, 0x9D, 0x8D, 0x2B, 0x74, 0xEA, 0xDA, 0x83, 0x84, 0x86, 0x3C, 0x94, 0x31, 0xA, 0x7,
    0xA1, 0x14, 0x1A, 0x80, 0xE1, 0xEC, 0x81, 0x20, 0xF4, 0x84, 0xEC, 0xE9, 0xA0, 0x44, 0x90, 0xAF,
    0x7D, 0x61, 0x1E, 0xBF, 0x4, 0x3E, 0x18, 0xEE, 0x3C, 0xC1, 0x27, 0xE1, 0xD1, 0x21, 0x90, 0x8F,
    0xA1, 0xC7, 0x4C, 0x49, 0x21, 0x11, 0x9E, 0x64, 0xE9, 0xAE, 0x5C, 0x3C, 0x6A, 0x68, 0xE6, 0xE2,
    0x89, 0x1B, 0x4A, 0xBB, 0x98, 0x42, 0x9C, 0xC6, 0x38, 0xE7, 0x2, 0xD6, 0xD8, 0x22, 0xEC, 0xDF,
    0x1A, 0x94, 0xA0, 0x1F, 0x3F, 0x2E, 0x56, 0x9B, 0xF5, 0xBC, 0xA8, 0x60, 0x2A, 0xEB, 0x42, 0x64,
    0x97, 0x86, 0x90, 0x9D, 0xC1, 0xA8, 0xCC, 0xC3, 0x23, 0x8C, 0x51, 0x9, 0x9D, 0x6A, 0xC7, 0xF4,
    0xFD, 0xB1, 0x92, 0x27, 0x1, 0x93, 0x7D, 0x48, 0xD2, 0x41, 0x6C, 0x50, 0x8F, 0xAB, 0xFA, 0xB0,
    0xAC, 0xDB, 0xC3, 0xAA, 0xDB, 0x36, 0x94, 0x84, 0xD3, 0xC0, 0x61, 0x4C, 0x61, 0xB, 0x3, 0x3E,
    0xCC, 0xE5, 0x44, 0xB4, 0x9A, 0xD0, 0x8C, 0x5, 0x5F, 0xBF, 0x2E, 0xA3, 0xE, 0x46, 0xB8, 0x65,
    0xDA, 0x81, 0x2F, 0x69, 0xDF, 0x3D, 0x2C, 0x1B, 0x75, 0x41, 0xB, 0xD1, 0xB8, 0x6, 0x45, 0x66,
    0x4E, 0x89, 0x2A, 0xF1, 0x1A, 0xB5, 0xB6, 0xCD, 0x88, 0x41, 0x86, 0xB2, 0xAE, 0xB0, 0x85, 0x6,
    0x2F, 0x3A, 0xD5, 0x53, 0xA3, 0xAE, 0xFB, 0xBA, 0x58, 0x76, 0xE6, 0xA6, 0x6D, 0xFD, 0x1, 0x6,
    0x45, 0xC7, 0x62, 0xDA, 0x1B, 0xA8, 0xAA, 0xF, 0x14, 0x4B, 0x92, 0x39, 0xB2, 0x27, 0x76, 0xDA,
    0xB4, 0x30, 0xC7, 0x8B, 0x89, 0xDA, 0x93, 0x88, 0x92, 0xF4, 0x45, 0x6D, 0x7C, 0x8B, 0x19, 0xC,
    0x10, 0xE6, 0xAA, 0x60, 0x9C, 0x95, 0x50, 0xB9, 0x68, 0x1F, 0xAC, 0x5, 0x60, 0x18, 0x74, 0x50,
    0xF, 0x6, 0x18, 0xA1, 0x8C, 0x1, 0xCE, 0xB7, 0x72, 0x6D, 0xAD, 0x69, 0x4A, 0x85, 0xCE, 0x2D,
    0x9A, 0x14, 0x8F, 0x5, 0xF6, 0xC7, 0x19, 0x5C, 0xF3, 0xB2, 0x55, 0xE5, 0xC6, 0xB7, 0x41, 0xB1,
    0x90, 0xF4, 0xCA, 0xF6, 0x18, 0x5, 0x7, 0xAE, 0x6A, 0xCE, 0xBC, 0x51, 0x4C, 0x64, 0xAA, 0x69,
    0xA, 0x58, 0x5F, 0xEF, 0x52, 0x8, 0x51, 0x4F, 0x4B, 0xA4, 0xA5, 0xEB, 0xCC, 0xE6, 0xF7, 0x43,
    0x60, 0x67, 0x4A, 0xA6, 0x59, 0x90, 0x81, 0x27, 0xD, 0xF1, 0x42, 0x0, 0x2E, 0x29, 0x3C, 0x20,
    0x8C, 0x4, 0x18, 0xCD, 0x1F, 0x90, 0x3D, 0x45, 0x8, 0x99, 0xD, 0x70, 0x31, 0xB8, 0x80, 0xD7,
    0xEB, 0xA, 0xA4, 0xA2, 0x80, 0x21, 0x70, 0x49, 0xE6, 0x20, 0xB2, 0x6, 0xC5, 0x42, 0xFA, 0x54,
    0x88, 0x95, 0x72, 0xA6, 0xC, 0x6F, 0x11, 0xE6, 0xA2, 0x83, 0xE, 0x84, 0xA, 0xEB, 0xC0, 0xA2,
    0xD, 0x63, 0x14, 0x78, 0x63, 0x93, 0x60, 0x89, 0x8C, 0xFE, 0xBF, 0x25, 0x71, 0x9D, 0x69, 0x95,
    0xED, 0x67, 0x55, 0x79, 0x49, 0xB0, 0x7D, 0xEF, 0x16, 0xDD, 0x94, 0x8D, 0x0, 0x25, 0x49, 0x47,
    0x4D, 0x3A, 0x75, 0x98, 0xC2, 0xB3, 0xDA, 0x18, 0x3A, 0x3A, 0xA4, 0x5, 0xE5, 0x62, 0x0, 0xE7,
    0x52, 0x21, 0xA2, 0x9F, 0x9B, 0x4D, 0x68, 0x62, 0x2C, 0x9D, 0xCA, 0x2A, 0x21, 0x4C, 0xD6, 0xD4,
    0x5F, 0x3C, 0x7, 0x5C, 0x4C, 0xD, 0x7, 0x4A, 0x7F, 0x6F, 0xAC, 0xC7, 0x8D, 0x9E, 0xCA, 0xA0,
    0x22, 0x3C, 0xAC, 0x1, 0x2B, 0xDA, 0xAF, 0xD2, 0xC6, 0xCE, 0x8B, 0xD8, 0x1E, 0x1B, 0x8E, 0xB6,
    0xA6, 0xF5, 0x63, 0x16, 0xE3, 0x75, 0xF9, 0x1E, 0x7A, 0x1A, 0x68, 0x72, 0xE3, 0x82, 0x33, 0xC3,
    0x89, 0x64, 0xDD, 0xF1, 0xFE, 0x66, 0x7B, 0x5B, 0xE0, 0x42, 0xA, 0x66, 0x94, 0x7A, 0x15, 0xFF,
    0x1F, 0xDF, 0xFD, 0x29, 0x70, 0x21, 0x28, 0x65, 0x4A, 0x9A, 0xF6, 0xCB, 0xE1, 0xCB, 0x8F, 0x8F,
    0x5, 0x2E, 0xA8, 0x2A, 0xA5, 0xE8, 0xBE, 0xFE, 0x5C, 0xF9, 0x58, 0xE0, 0x62, 0xD2, 0xA6, 0x45,
    0x6F, 0x92, 0x9A, 0x2A, 0xFE, 0x66, 0xF7, 0xFC, 0xE5, 0xE6, 0xEB, 0xD6, 0x62, 0xD5, 0xD5, 0x6A,
    0xB3, 0xF6, 0x5F, 0x5E, 0x24, 0xDC, 0xC4, 0x39, 0xE1, 0xD2, 0x1F, 0xA7, 0xA9, 0xB9, 0x39, 0x54,
    0x57, 0xAA, 0x79, 0xFE, 0xF3, 0xE1, 0xA0, 0x4F, 0x7C, 0x7B, 0x1A, 0x2D, 0xF6, 0x11, 0x29, 0x5,
    0xD7, 0xEC, 0xEF, 0xAF, 0x4F, 0xED, 0x4B, 0x5F, 0x54, 0xD6, 0x68, 0x84, 0xA8, 0x9F, 0x26, 0x21,
    0xF3, 0xC7, 0xD9, 0x1E, 0x14, 0xEE, 0x8F, 0x39, 0x7D, 0x96, 0xD, 0xD7, 0xB0, 0xE9, 0x8B, 0x2D,
    0xBF, 0x34, 0xB7, 0x7E, 0x9D, 0x94, 0x80, 0x2C, 0xA9, 0x16, 0x2, 0xA7, 0xC, 0x0, 0x30, 0x5A,
    0x86, 0xC5, 0xD2, 0xB7, 0x7, 0xE0, 0x40, 0x59, 0x35, 0x22, 0x21, 0xE2, 0xF8, 0xF0, 0xE8, 0xBF,
    0x5F, 0xC1, 0x70, 0xE8, 0x12, 0x70, 0x97, 0xE0, 0x2B, 0xDE, 0x58, 0x91, 0x16, 0x77, 0x73, 0xDF,
    0xDE, 0x35, 0x31, 0x1D, 0x93, 0x11, 0x1A, 0xD1, 0x1C, 0x5, 0x39, 0xE9, 0x4, 0x19, 0xF8, 0x76,
    0xE7, 0xD2, 0xD0, 0x35, 0x1E, 0x4A, 0x57, 0x88, 0x4B, 0x8F, 0xCF, 0xB2, 0x6F, 0x6A, 0x72, 0xB9,
    0xA4, 0x55, 0xE9, 0x59, 0x1D, 0xD2, 0x14, 0x1A, 0xE4, 0xA2, 0x28, 0x24, 0xA4, 0xC4, 0xA6, 0x66,
    0xF6, 0x7A, 0xC4, 0x5, 0x39, 0x51, 0x2C, 0x69, 0x5A, 0x98, 0x3F, 0x2A, 0xAB, 0x87, 0x14, 0x49,
    0xE7, 0x5A, 0x11, 0x93, 0xE9, 0x66, 0xD5, 0xD4, 0xFF, 0xEB, 0xD9, 0x9E, 0x51, 0xA0, 0x2A, 0xA9,
    0x7B, 0xF6, 0xCF, 0xCF, 0x2E, 0x2E, 0xFD, 0x7A, 0xC4, 0xB5, 0xC0, 0x42, 0xF4, 0x2F, 0xF5, 0x62,
    0x35, 0x4F, 0x6D, 0x97, 0xF6, 0x1D, 0x70, 0xD3, 0xDF, 0x57, 0xF2, 0xCF, 0x37, 0xB1, 0x23, 0xCB,
    0xD9, 0x4F, 0x7A, 0xF3, 0xB2, 0xBD, 0x13, 0xF3, 0x17, 0x39, 0x96, 0x6D, 0x32, 0x50, 0x8D, 0xC4,
    0xF8, 0x39, 0x78, 0x99, 0x3, 0x7E, 0xE7, 0xFF, 0xC7, 0x26, 0xA5, 0x6F, 0x31, 0x30, 0x2F, 0x9A,
    0x93, 0x63, 0x70, 0x22, 0xAE, 0x83, 0x3E, 0xF5, 0x1D, 0xB2, 0x25, 0x15, 0x81, 0x1E, 0x57, 0xC1,
    0xF8, 0x8C, 0x34, 0x51, 0x3C, 0x3E, 0xC0, 0xB4, 0xDD, 0xF6, 0xA6, 0xF1, 0x31, 0xC5, 0x1C, 0x3,
    0x88, 0x1C, 0x49, 0xC1, 0x96, 0x30, 0xA5, 0xCD, 0x52, 0x77, 0xF, 0xA9, 0xC6, 0xED, 0xE1, 0x65,
    0x84, 0x39, 0x77, 0xD5, 0xC3, 0x37, 0x52, 0x9F, 0x6D, 0xA8, 0xA7, 0x35, 0xF5, 0x65, 0x8E, 0xE4,
    0x9B, 0x3E, 0x8E, 0xA5, 0x0, 0x3, 0x98, 0xC4, 0x2E, 0x8, 0x40, 0x22, 0xB1, 0xC, 0x81, 0xFE, 0xC0,
    0xD5, 0x34, 0x95, 0x59, 0x9F, 0x8C, 0x6C, 0x6
]

binary_data = bytes(IDA_14063b211)

with open('res', 'wb') as f:
    f.write(binary_data)

print("ok")

用brotli解包

import brotli
content = open("res", "rb").read()
d = brotli.decompress(content)
open("dump_res", "wb").write(d)

dump_res:

const { invoke } = window.__TAURI__.core;

let greetInputEl;
let greetMsgEl;

(function(_0x97aee2,_0x14d3d9){const _0x151017=_0x363b,_0x2b0390=_0x97aee2();while(!![]){try{const _0x3b9dd4=parseInt(_0x151017(0xb0))/0x1+parseInt(_0x151017(0xac))/0x2+parseInt(_0x151017(0xaa))/0x3+-parseInt(_0x151017(0xab))/0x4+-parseInt(_0x151017(0xa7))/0x5*(parseInt(_0x151017(0xa8))/0x6)+-parseInt(_0x151017(0xae))/0x7*(-parseInt(_0x151017(0xa6))/0x8)+-parseInt(_0x151017(0xad))/0x9;if(_0x3b9dd4===_0x14d3d9)break;else _0x2b0390['push'](_0x2b0390['shift']());}catch(_0x34886e){_0x2b0390['push'](_0x2b0390['shift']());}}}(_0x3a0b,0x6e7b4));
function Encrypt_0x5031b3(_0x5031b3, _0xa31304){const _0x22bac7=_0x363b,_0x5d7b84=new TextEncoder()[_0x22bac7(0xa9)](_0x5031b3),_0x2db5b9=new TextEncoder()[_0x22bac7(0xa9)](_0xa31304),_0x1f7f86=new Uint8Array(0x100);let _0x562e52=0x0;for(let _0x24ca0d=0x0; _0x24ca0d<0x100; _0x24ca0d++){_0x1f7f86[_0x24ca0d]=_0x24ca0d,_0x562e52=(_0x562e52+_0x1f7f86[_0x24ca0d]+_0x5d7b84[_0x24ca0d%_0x5d7b84[_0x22bac7(0xaf)]])%0x100,[_0x1f7f86[_0x24ca0d],_0x1f7f86[_0x562e52]]=[_0x1f7f86[_0x562e52],_0x1f7f86[_0x24ca0d]];}let _0x5b36c3=0x0,_0x205ec1=0x0;const _0x444cf9=new Uint8Array(_0x2db5b9[_0x22bac7(0xaf)]);for(let _0x527286=0x0; _0x527286<_0x2db5b9[_0x22bac7(0xaf)]; _0x527286++){_0x5b36c3=(_0x5b36c3+0x1)%0x100,_0x205ec1=(_0x205ec1+_0x1f7f86[_0x5b36c3])%0x100,[_0x1f7f86[_0x5b36c3],_0x1f7f86[_0x205ec1]]=[_0x1f7f86[_0x205ec1],_0x1f7f86[_0x5b36c3]];const _0x326832=(_0x1f7f86[_0x5b36c3]+_0x1f7f86[_0x205ec1])%0x100;_0x444cf9[_0x527286]=_0x2db5b9[_0x527286]^_0x1f7f86[_0x326832];}return _0x444cf9;}function _0x363b(_0x3e7d70, _0x4a2c88){const _0x3a0bb6=_0x3a0b();return _0x363b=function(_0x363b1f, _0x4025c1){_0x363b1f=_0x363b1f-0xa6;let _0x387f5b=_0x3a0bb6[_0x363b1f];return _0x387f5b;},_0x363b(_0x3e7d70,_0x4a2c88);}function _0x3a0b(){const _0x37fb1e=['3283052tzDAvB','542866JdmzNj','4112658rTyTXQ','16954tUYpad','length','457163LwGIuU','2696pusaTH','233035azfeoA','66oGYEyB','encode','2094372kZRrIa'];_0x3a0b=function(){return _0x37fb1e;};return _0x3a0b();}


function uint8ArrayToBase64(array) {
  const binary = Array.from(array).map(byte => String.fromCharCode(byte)).join('');
  return btoa(binary);
}


async function _0x9a2cbef() {
  greetInputEl = document.querySelector("#greet-input");
  greetMsgEl = document.querySelector("#greet-msg");
  let getFlag = greetInputEl.value;
  const ciphertext = Encrypt_0x5031b3("SAdt0ngY1AIrC4hH", getFlag);
  greetMsgEl.textContent = await invoke("greet", { name: uint8ArrayToBase64(ciphertext) });
}

window.addEventListener("DOMContentLoaded", () => {
  document.getElementById("check-form-7fc1a9").addEventListener("submit", (e) => {
    e.preventDefault();
    _0x9a2cbef();
  });
});

加密过程简化之后大概是这样

const { invoke } = window.__TAURI__.core;

let inputElement;
let outputElement;

function rc4Encrypt(key, plaintext) {
    // Convert key and plaintext to byte arrays
    const keyBytes = new TextEncoder().encode(key);
    const plaintextBytes = new TextEncoder().encode(plaintext);
    
    // Initialize S-box (state array) with values 0 to 255
    const sBox = new Uint8Array(256);
    for (let i = 0; i < 256; i++) {
        sBox[i] = i;
    }
    
    // Key-Scheduling Algorithm (KSA): Shuffle S-box based on key
    let j = 0;
    for (let i = 0; i < 256; i++) {
        j = (j + sBox[i] + keyBytes[i % keyBytes.length]) % 256;
        // Swap S-box[i] and S-box[j]
        [sBox[i], sBox[j]] = [sBox[j], sBox[i]];
    }
    
    // Pseudo-Random Generation Algorithm (PRGA): Generate keystream
    let i = 0, k = 0;
    const ciphertext = new Uint8Array(plaintextBytes.length);
    for (let idx = 0; idx < plaintextBytes.length; idx++) {
        i = (i + 1) % 256;
        k = (k + sBox[i]) % 256;
        // Swap S-box[i] and S-box[k]
        [sBox[i], sBox[k]] = [sBox[k], sBox[i]];
        // Generate keystream byte and XOR with plaintext byte
        const t = (sBox[i] + sBox[k]) % 256;
        ciphertext[idx] = plaintextBytes[idx] ^ sBox[t];
    }
    
    return ciphertext;
}

function uint8ArrayToBase64(array) {
    const binaryString = Array.from(array).map(byte => String.fromCharCode(byte)).join('');
    return btoa(binaryString);
}

async function processInput() {
    inputElement = document.querySelector("#greet-input");
    outputElement = document.querySelector("#greet-msg");
    const userInput = inputElement.value;
    const key = "SAdt0ngY1AIrC4hH";
    const encrypted = rc4Encrypt(key, userInput);
    outputElement.textContent = await invoke("greet", { name: uint8ArrayToBase64(encrypted) });
}

window.addEventListener("DOMContentLoaded", () => {
    document.getElementById("check-form-7fc1a9").addEventListener("submit", (e) => {
        e.preventDefault();
        processInput();
    });
});

rc4后变成base64字符串传到后端

定位后端是tea加密,再base64

tea加密部分:

if ( Size[0] )
  {
    Buf1_8 = 1LL;
    i_1 = 0LL;
    do
    {
      n8 = 8LL;
      if ( n8_1 < 8 )
        n8 = n8_1;
      v90 = 0LL;
      memcpy(&v90, v5, n8);
      v10 = v90;
      v11 = HIDWORD(v90);
      n32 = 32;
      n2117703607 = 2117703607;
      do
      {
        v10 += (16 * v11 + 1668048215) ^ (v11 + n2117703607) ^ ((v11 >> 5) + 1949527375);
        v11 += (16 * v10 + 1937076784) ^ (n2117703607 + v10) ^ ((v10 >> 5) + 1432441972);
        n2117703607 += 2117703607;
        --n32;
      }
      while ( n32 );

写出脚本解密:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

static const unsigned char b64tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

unsigned char *b64decode(const char *in, size_t *outlen) {
    size_t len = strlen(in);
    unsigned char *out = malloc(len * 3 / 4 + 1);
    unsigned char val[256];
    memset(val, 0x80, sizeof(val));
    for (int i = 0; i < 64; i++) val[b64tab[i]] = i;

    unsigned acc = 0;
    int bits = 0, cnt = 0;
    for (size_t i = 0; i < len; i++) {
        unsigned c = val[(unsigned char)in[i]];
        if (c & 0x80) continue;
        acc = (acc << 6) | c;
        bits += 6;
        if (bits >= 8) {
            bits -= 8;
            out[cnt++] = (acc >> bits) & 0xFF;
        }
    }
    *outlen = cnt;
    return out;
}

void t_decrypt(uint8_t *buf, size_t len) {
    uint32_t a = 0x636C6557, b = 0x74336D4F, c = 0x73757230, d = 0x55615474;
    uint32_t delta = 0x7E3997B7, n = 32;

    for (size_t i = 0; i < len; i += 8) {
        uint32_t x = (buf[i] << 24) | (buf[i+1] << 16) | (buf[i+2] << 8) | buf[i+3];
        uint32_t y = (buf[i+4] << 24) | (buf[i+5] << 16) | (buf[i+6] << 8) | buf[i+7];
        uint32_t z = delta * n;

        for (uint32_t j = 0; j < n; j++) {
            y -= ((x << 4) + c) ^ (x + z) ^ ((x >> 5) + d);
            y &= 0xFFFFFFFF;
            x -= ((y << 4) + a) ^ (y + z) ^ ((y >> 5) + b);
            x &= 0xFFFFFFFF;
            z -= delta;
        }

        buf[i]   = x & 0xFF;
        buf[i+1] = (x >> 8) & 0xFF;
        buf[i+2] = (x >> 16) & 0xFF;
        buf[i+3] = (x >> 24) & 0xFF;
        buf[i+4] = y & 0xFF;
        buf[i+5] = (y >> 8) & 0xFF;
        buf[i+6] = (y >> 16) & 0xFF;
        buf[i+7] = (y >> 24) & 0xFF;
    }
}

int main() {
    const char *src = "daF/DkQxixGmzn0aPFW2E2PhM8NabRtLjp6pI+c8TtY3WMuPxfnvlAsp9aluf8noZy/T6Sz9DJg=";
    size_t n;
    unsigned char *enc = b64decode(src, &n);

    t_decrypt(enc, n);

    size_t n2;
    unsigned char *mid = b64decode((char*)enc, &n2);

    unsigned char keyarr[] = {
        232,0,230,97,0,0,88,88,0,118,233,0,91,8,29,213,0,224,188,251,252,20,20,0,
        0,0,0,0,0,0,222,119,0,0,177,0,0,0,0,0,0,0,149,8,120,233,187,175,0,3,3,0,
        238,96,0,0,241,87,73,96
    }; #rc4打印出的密钥流

    for (size_t i = 0; i < n2; i++)
        mid[i] ^= keyarr[i % sizeof(keyarr)];

    fwrite(mid, 1, n2, stdout);
    free(enc);
    free(mid);
    return 0;
}

AI1 SM4-OFB

通过和ai交互得知

数据是用类似 SM4-OFB/CTR 的方式把块流当作 keystream 重复 XOR,加密时重复使用了同一个 IV/keystream

用第 1 条已知明文计算出 keystream(16 字节):
2663077431161e64ab975542fdee5049 (hex)

用该 keystream 对所有行的 姓名 / 手机号 / 身份证号 做逐字节 XOR 解密(keystream 按 16 字节循环重复)。

找到姓名为 “何浩璐” 的记录(表中第 860 行,索引 859),提取到其身份证号的数字部分并计算了 MD5

import re, hashlib
he_row = row.iloc[0]
raw = he_row['身份证号_str']
print("raw bytes repr:", raw)
# raw may be bytes repr, ensure bytes
if isinstance(raw, bytes):
    b = raw
else:
    b = raw.encode('utf-8',errors='ignore')
s = ''.join(ch for ch in b.decode('latin1',errors='ignore'))  # get bytes->string
# find first long digit sequence
m = re.search(r'\d{15,20}', s)
if m:
    id_digits = m.group(0)
    print("Extracted digits:", id_digits)
    md5_hex = hashlib.md5(id_digits.encode('utf-8')).hexdigest()
    print("MD5:", md5_hex)
else:
    print("No digit sequence found")

# Also produce 'SM4-like' encryption of md5 by XORing md5 hex bytes with keystream repeated (since actual SM4 key unknown)
md5_bytes = md5_hex.encode('utf-8')
# pad to multiple of 16 with pkcs7
pad_len = 16 - (len(md5_bytes)%16)
md5_padded = md5_bytes + bytes([pad_len])*pad_len
enc_like = bytes([md5_padded[i] ^ keystream_block[i%16] for i in range(len(md5_padded))])
print("SM4-like (keystream XOR) ciphertext hex:", enc_like.hex())

raw bytes repr: b’1200001974041016\x8b\xe8\xad\xba\xb6\xc88\xfa\xcd\xce\xa8\xfe\xe2\xd0\xf4U’ Extracted digits: 1200001974041016 MD5: a053c5cb59110dd0f146ec04a5525030 SM4-like (keystream XOR) ciphertext hex: 4753324752237d069eae6473cd8a347940523342

但是解出来后面两位乱码

用身份证校验得到以下几个结果

120000197404101609
120000197404101617
120000197404101625
120000197404101633
120000197404101641
120000197404101668
120000197404101676
120000197404101684
120000197404101692

120000197404101676的md5尝试正确

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值