羊城杯
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尝试正确



2207

被折叠的 条评论
为什么被折叠?



