题目列表
第一周
- 1.plzdebugme
- 2.Puzzle
- 3.Xor
- 4.Strange Base
- 5.EzMyDroid
第二周
- 1.ohNativeEnc
- 2.尤皮·埃克斯历险记(1)
- 3.Look at me carefully
- 4.采一朵花,送给艾达(1)
- 5.forgotten_code
第三周
- 1.采一朵花送给艾达(2)
- 2.尤皮·埃克斯历险记(2)
- 3.pyz3
- 4.Dancing Function
- 5.changemykey
- 6.changemykey-rev
第四周
- 1.hookme
- 2.尤皮.艾克斯历险记(3)
- 3.ezrust
- 4.Dancingkeys
- 5.NOT_TUI
第五周
- 1.天才的认证
- 2.AnEasySystem
- 3.河图洛书
- 4.魔法少女的秘密
- 5.Jvav Master
第一周
1.plzdebugme
题目给的信息是

用die查看文件信息,是elf文件

这里我用的是WSL2中安装Ubuntu去远程链接IDA调试
IDA中Debugger选择Remote GDB debugger,设置如下

打开WSL2
输入命令(前提是你要先把文件复制到WSL家目录,并赋予执行权限)
gdbserver :1234 ./plzdebugme会有以下输出

接下来在按提示在xor除下断点,调试
![]()

F9执行到断点,接下来F7单步执行

知道右边寄存器窗口中的flag变为flag+1F,查看

接下来就是putchar(),把这些十六进制转化为ASCII
flag{It3_D3bugG_T11me!_le3_play}
2.Puzzle
IDA中打开main函数,flag拼接

第一处在Puzzle_Challenge函数里(Do_Y0u_)

第二处在字符串中看到是一个函数名,点进出查看(Like_7his_Jig)
![]()

第三处函数名列表中找到Its_about_part3函数(s@w_puzz)
![]()
对数组进行异或


encrypted_array = [0xDE, 0xED, 0xDA, 0xF2, 0xDD, 0xD8, 0xD7, 0xD7] + [0x00] * 8print(''.join(chr(b ^ 0xAD) for b in encrypted_array if 32 <= (b ^ 0xAD) <= 126))第四处(1e_Gam3)
![]()
flag{Do_Y0u_Like_7his_Jigs@w_puzz1e_Gam3}
3.Xor
IDA中打开main函数,加密逻辑就在里面

对输入进行两次异或,并根据除3所得余数来决定与谁异或,并所得结果与 anu`ym7wKLl$P]v3q%D]lHpi 进行对照
脚本
s2="anu`ym7wKLl$P]v3q%D]lHpi"keys1={0:0x14,1:0x11,2:0x45}keys2 = {0:0x13,1:0x13,2:0x51}flag = "".join(chr(ord(c) ^ keys1[i%3] ^ keys2[i%3]) for i,c in enumerate(s2))print(flag)flag{y0u_Kn0W_b4s1C_xOr}
4.Strange Base
当看到题目内容时,我就想到会不会是自定义的Base表
![]()
IDA打开一看还真是
这是main函数,密文T>6uTqOatL39aP!YIqruyv(YBA!8y7ouCa9=

去看base64_encode函数

点开aHelloACrqzyB4s,果然是自定义Base表

随波逐流工具解密

脚本解密
import base64
custom_alphabet = "HElLo!A=CrQzy-B4S3|is'waITt1ng&Y0u^{/(>v<)*}GO~256789pPqWXVKJNMF"cipher = "T>6uTqOatL39aP!YIqruyv(YBA!8y7ouCa9="
std_b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"table = str.maketrans(custom_alphabet, std_b64)
decoded = base64.b64decode(cipher.translate(table))print(decoded.decode())flag{Wh4t_a_cra2y_8as3!!!}
5.EzMyDroid
用JADX打开,在AndroidManifest.xml中找到包名

去原代码中打开

进行ui初始化,并进行 Navigation 导航 指向Fragment
查看第一个Fragment,里面果然有加密逻辑,是AES-ECB 模式

密钥:1145141919810000
密文:cTz2pDhl8fRMfkkJXfqs2t8JBsqLkvQZDLYpWjEtkLE=
脚本
from Crypto.Cipher import AESimport base64
key = b"1145141919810000"ciphertext_b64 = "cTz2pDhl8fRMfkkJXfqs2t8JBsqLkvQZDLYpWjEtkLE="ciphertext = base64.b64decode(ciphertext_b64)
cipher = AES.new(key, AES.MODE_ECB)plaintext = cipher.decrypt(ciphertext)
pad_len = plaintext[-1]plaintext = plaintext[:-pad_len]
print("FLAG:", plaintext.decode())flag{@_g00d_st@r7_f0r_ANDROID}
第二周
1.ohNativeEnc
JADX中打开,mainactivity函数里

用apktool反编译

在lib目录里找到符合自己机型架构的so文件,用IDA打开

是个xxtea加密,轮数是12,delta值是114514,密钥在Thisisaxxteake

最后与mm里的数据对比

import struct
mm = bytes.fromhex( "B6536E4D775D08D2FB2C631EBB7B019BF5046AF40E84274764A1E4D9EF124437")
key = b"ThisIsAXXteaKey" + b"\x00"
def xxtea_decrypt_8x32_le(cipher32: bytes, key16: bytes) -> bytes: v = list(struct.unpack('<8I', cipher32)) k = list(struct.unpack('<4I', key16)) delta = 114514 & 0xFFFFFFFF rounds = 12 sum_ = (delta * rounds) & 0xFFFFFFFF for _ in range(rounds): e = (sum_ >> 2) & 3 v[7] = (v[7] - (((v[6] >> 5) ^ ( (v[0] << 2) & 0xFFFFFFFF)) + ((v[0] >> 3) ^ ((v[6] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[0]) + (v[6] ^ k[(e ^ 3) & 3])))) & 0xFFFFFFFF v[6] = (v[6] - (((v[5] >> 5) ^ ((v[7] << 2) & 0xFFFFFFFF)) + ((v[7] >> 3) ^ ((v[5] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[7]) + (v[5] ^ k[(e ^ 2) & 3])))) & 0xFFFFFFFF v[5] = (v[5] - (((v[4] >> 5) ^ ((v[6] << 2) & 0xFFFFFFFF)) + ((v[6] >> 3) ^ ((v[4] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[6]) + (v[4] ^ k[(e ^ 1) & 3])))) & 0xFFFFFFFF v[4] = (v[4] - (((v[3] >> 5) ^ ((v[5] << 2) & 0xFFFFFFFF)) + ((v[5] >> 3) ^ ((v[3] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[5]) + (v[3] ^ k[e])))) & 0xFFFFFFFF v[3] = (v[3] - (((v[2] >> 5) ^ ((v[4] << 2) & 0xFFFFFFFF)) + ((v[4] >> 3) ^ ((v[2] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[4]) + (v[2] ^ k[(e ^ 3) & 3])))) & 0xFFFFFFFF v[2] = (v[2] - (((v[1] >> 5) ^ ((v[3] << 2) & 0xFFFFFFFF)) + ((v[3] >> 3) ^ ((v[1] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[3]) + (v[1] ^ k[(e ^ 2) & 3])))) & 0xFFFFFFFF v[1] = (v[1] - (((v[0] >> 5) ^ ((v[2] << 2) & 0xFFFFFFFF)) + ((v[2] >> 3) ^ ((v[0] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[2]) + (v[0] ^ k[(e ^ 1) & 3])))) & 0xFFFFFFFF v[0] = (v[0] - (((v[7] >> 5) ^ ((v[1] << 2) & 0xFFFFFFFF)) + ((v[1] >> 3) ^ ((v[7] << 4) & 0xFFFFFFFF)) ^ ((sum_ ^ v[1]) + (k[e] ^ v[7])))) & 0xFFFFFFFF sum_ = (sum_ - delta) & 0xFFFFFFFF return struct.pack('<8I', *v)
plain = xxtea_decrypt_8x32_le(mm, key)print(plain.rstrip(b'\x00').decode())flag{Ur_G00d_@_n@tive_Func}
2.尤皮·埃克斯历险记(1)
die看到是upx加壳

upx脱壳

IDA打开main函数

对34字节长度的明文,做异或,并映射


将一下代码保存在同文件夹,运行
first=b"isfhGJ\tt~cU\ny\nuTjcj\tT~cj"target=first+int("0x5047B777E756451",16).to_bytes(8,"little")+(16753).to_bytes(2,"little")e=bytes([b^0x3C for b in target])flag=bytes([105-b if 48<=b<=57 else 187-b if (65<=b<=90 or 97<=b<=122) else b for b in e]).decode("ascii")print(flag)
flag{E4sy_R3v3rSe_e4Sy_eNcrypt10n}
3.Look at me carefully
IDA打开,发现是个重排

就是对cH4_1elo{ookte?0dv_}alafle___5yygume字符串按以下顺序重排
27,5,6,9,28,18,32,29,4,11,15,17,22,8,34,16,19,7,26,35,2,14,21,0,1,25,13,23,20,37,30,33,10,3,12,36,24,31重排后结果
flag{H4ve_you_lo0ked_at_me_c1o5ely?}
4.采一朵花,送给艾达(1)
有五处花指令
第一处改前

改后

第二处改前

改后

第三处改前

改后

第四处和第五出改前

改后
第四处

第五处

之后正常F5编译

但缺少两段数据,我们动调去dump另外两段,位置在这,下断点


脚本
target_hex = """C7 7F C1 43 03 64 75 11 88 B8 8C 55 F6 C0 23 DF4D 0F 2E 9E F6 82 F0 F2 BC 51 6B 08 29 83 27 E1CB BD C6 88 B1 80 4F 4E"""
def rc4_add_decrypt(target: bytes, key: bytes) -> bytes: # KSA with reversed initial S S = [(-i) & 0xFF for i in range(256)] j = 0 for i in range(256): j = (S[i] + key[i % len(key)] + j) & 0xFF S[i], S[j] = S[j], S[i]
i = 0 j = 0 out = bytearray() for t in target: i = (i + 1) & 0xFF j = (j + S[i]) & 0xFF S[i], S[j] = S[j], S[i] k = S[(S[i] + S[j]) & 0xFF]
out.append((t - k) & 0xFF) return bytes(out)
def main(): target = bytes(int(x, 16) for x in target_hex.split()) key = b"EasyJunkCodes" plain = rc4_add_decrypt(target, key) try: print(plain.decode("utf-8")) except UnicodeDecodeError: print(plain)
if __name__ == "__main__": main()flag{Junk_C0d3s_4Re_345y_t0_rEc0gn1Ze!!}
5.forgotten_code
010打开 这段是 GAS(GNU assembler)生成的 x86-64 汇编
.file "chal.cpp" .intel_syntax noprefix .text .section .text$_Z5scanfPKcz,"x" .linkonce discard .globl _Z5scanfPKcz .def _Z5scanfPKcz; .scl 2; .type 32; .endef .seh_proc _Z5scanfPKcz_Z5scanfPKcz:.LFB39: push rbp .seh_pushreg rbp push rbx .seh_pushreg rbx sub rsp, 56 .seh_stackalloc 56 lea rbp, 48[rsp] .seh_setframe rbp, 48 .seh_endprologue mov QWORD PTR 32[rbp], rcx mov QWORD PTR 40[rbp], rdx mov QWORD PTR 48[rbp], r8 mov QWORD PTR 56[rbp], r9 lea rax, 40[rbp] mov QWORD PTR -16[rbp], rax mov rbx, QWORD PTR -16[rbp] mov ecx, 0 mov rax, QWORD PTR __imp___acrt_iob_func[rip] call rax mov rcx, rax mov rax, QWORD PTR 32[rbp] mov r8, rbx mov rdx, rax call __mingw_vfscanf mov DWORD PTR -4[rbp], eax mov eax, DWORD PTR -4[rbp] add rsp, 56 pop rbx pop rbp ret .seh_endproc .section .text$_Z6printfPKcz,"x" .linkonce discard .globl _Z6printfPKcz .def _Z6printfPKcz; .scl 2; .type 32; .endef .seh_proc _Z6printfPKcz_Z6printfPKcz:.LFB45: push rbp .seh_pushreg rbp push rbx .seh_pushreg rbx sub rsp, 56 .seh_stackalloc 56 lea rbp, 48[rsp] .seh_setframe rbp, 48 .seh_endprologue mov QWORD PTR 32[rbp], rcx mov QWORD PTR 40[rbp], rdx mov QWORD PTR 48[rbp], r8 mov QWORD PTR 56[rbp], r9 lea rax, 40[rbp] mov QWORD PTR -16[rbp], rax mov rbx, QWORD PTR -16[rbp] mov ecx, 1 mov rax, QWORD PTR __imp___acrt_iob_func[rip] call rax mov rcx, rax mov rax, QWORD PTR 32[rbp] mov r8, rbx mov rdx, rax call __mingw_vfprintf mov DWORD PTR -4[rbp], eax mov eax, DWORD PTR -4[rbp] add rsp, 56 pop rbx pop rbp ret .seh_endproc .globl ng .data .align 16ng: .ascii "sp\177vuctp|xeb|hv~" .globl ezgm .align 32ezgm: .long 1210405119 .long 710975774 .long -90350153 .long -1958008304 .long -745722482 .long 67707510 .long -86515270 .long -1728462407 .text .globl _Z2fnPj .def _Z2fnPj; .scl 2; .type 32; .endef .seh_proc _Z2fnPj_Z2fnPj:.LFB188: push rbp .seh_pushreg rbp mov rbp, rsp .seh_setframe rbp, 0 sub rsp, 48 .seh_stackalloc 48 .seh_endprologue mov QWORD PTR 16[rbp], rcx mov DWORD PTR -4[rbp], 0 jmp .L6.L7: mov eax, DWORD PTR -4[rbp] cdqe lea rdx, ng[rip] movzx eax, BYTE PTR [rax+rdx] xor eax, 17 mov edx, DWORD PTR -4[rbp] movsx rdx, edx lea rcx, ng[rip] mov BYTE PTR [rdx+rcx], al add DWORD PTR -4[rbp], 1.L6: cmp DWORD PTR -4[rbp], 15 jle .L7 mov rax, QWORD PTR 16[rbp] mov eax, DWORD PTR [rax] mov DWORD PTR -8[rbp], eax mov rax, QWORD PTR 16[rbp] mov eax, DWORD PTR 4[rax] mov DWORD PTR -12[rbp], eax mov DWORD PTR -16[rbp], 0 mov DWORD PTR -24[rbp], -1640531527 mov DWORD PTR -20[rbp], 0 jmp .L8.L9: lea rax, ng[rip] mov eax, DWORD PTR [rax] mov DWORD PTR -28[rbp], eax mov eax, DWORD PTR ng[rip+4] mov DWORD PTR -32[rbp], eax mov eax, DWORD PTR ng[rip+8] mov DWORD PTR -36[rbp], eax mov eax, DWORD PTR ng[rip+12] mov DWORD PTR -40[rbp], eax mov eax, DWORD PTR -24[rbp] add DWORD PTR -16[rbp], eax mov eax, DWORD PTR -12[rbp] sal eax, 4 mov edx, eax mov eax, DWORD PTR -28[rbp] add edx, eax mov ecx, DWORD PTR -12[rbp] mov eax, DWORD PTR -16[rbp] add eax, ecx xor edx, eax mov eax, DWORD PTR -12[rbp] shr eax, 5 mov ecx, eax mov eax, DWORD PTR -32[rbp] add eax, ecx xor eax, edx add DWORD PTR -8[rbp], eax mov eax, DWORD PTR -8[rbp] sal eax, 4 mov edx, eax mov eax, DWORD PTR -36[rbp] add edx, eax mov ecx, DWORD PTR -8[rbp] mov eax, DWORD PTR -16[rbp] add eax, ecx xor edx, eax mov eax, DWORD PTR -8[rbp] shr eax, 5 mov ecx, eax mov eax, DWORD PTR -40[rbp] add eax, ecx xor eax, edx add DWORD PTR -12[rbp], eax add DWORD PTR -20[rbp], 1.L8: cmp DWORD PTR -20[rbp], 31 jbe .L9 mov rax, QWORD PTR 16[rbp] mov edx, DWORD PTR -8[rbp] mov DWORD PTR [rax], edx mov rax, QWORD PTR 16[rbp] add rax, 4 mov edx, DWORD PTR -12[rbp] mov DWORD PTR [rax], edx nop add rsp, 48 pop rbp ret .seh_endproc .section .rdata,"dr".LC0: .ascii "Input your flag: \0".LC1: .ascii "%s\0".LC2: .ascii "flag{\0".LC3: .ascii "Wrong length!\12\0".LC4: .ascii "Wrong flag!\12\0".LC5: .ascii "Right!\12\0".LC6: .ascii "Invalid flag format!\12\0" .text .globl main .def main; .scl 2; .type 32; .endef .seh_proc mainmain:.LFB189: push rbp .seh_pushreg rbp mov rbp, rsp .seh_setframe rbp, 0 sub rsp, 144 .seh_stackalloc 144 .seh_endprologue call __main lea rax, .LC0[rip] mov rcx, rax call _Z6printfPKcz lea rax, -112[rbp] lea rcx, .LC1[rip] mov rdx, rax call _Z5scanfPKcz lea rdx, .LC2[rip] lea rax, -112[rbp] mov r8d, 5 mov rcx, rax call strncmp test eax, eax jne .L11 lea rax, -112[rbp] mov rcx, rax call strlen sub rax, 1 movzx eax, BYTE PTR -112[rbp+rax] cmp al, 125 jne .L11 lea rax, -112[rbp] mov rcx, rax call strlen sub eax, 6 mov DWORD PTR -12[rbp], eax cmp DWORD PTR -12[rbp], 32 je .L12 lea rax, .LC3[rip] mov rcx, rax call _Z6printfPKcz mov eax, 0 jmp .L20.L12: mov DWORD PTR -4[rbp], 0 jmp .L14.L15: mov eax, DWORD PTR -4[rbp] sal eax, 3 cdqe lea rdx, 5[rax] lea rax, -112[rbp] add rax, rdx mov rcx, rax call _Z2fnPj add DWORD PTR -4[rbp], 1.L14: mov eax, DWORD PTR -12[rbp] lea edx, 7[rax] test eax, eax cmovs eax, edx sar eax, 3 cmp DWORD PTR -4[rbp], eax jl .L15 mov DWORD PTR -8[rbp], 0 jmp .L16.L18: mov eax, DWORD PTR -8[rbp] cdqe sal rax, 2 lea rdx, 5[rax] lea rax, -112[rbp] add rax, rdx mov ecx, DWORD PTR [rax] mov eax, DWORD PTR -8[rbp] cdqe lea rdx, 0[0+rax*4] lea rax, ezgm[rip] mov eax, DWORD PTR [rdx+rax] cmp ecx, eax je .L17 lea rax, .LC4[rip] mov rcx, rax call _Z6printfPKcz mov eax, 0 jmp .L20.L17: add DWORD PTR -8[rbp], 1.L16: mov eax, DWORD PTR -12[rbp] lea edx, 3[rax] test eax, eax cmovs eax, edx sar eax, 2 cmp DWORD PTR -8[rbp], eax jl .L18 lea rax, .LC5[rip] mov rcx, rax call _Z6printfPKcz jmp .L19.L11: lea rax, .LC6[rip] mov rcx, rax call _Z6printfPKcz.L19: mov eax, 0.L20: add rsp, 144 pop rbp ret .seh_endproc .def __main; .scl 2; .type 32; .endef .ident "GCC: (x86_64-posix-seh-rev0, Built by MinGW-Builds project) 15.1.0" .def __mingw_vfscanf; .scl 2; .type 32; .endef .def __mingw_vfprintf; .scl 2; .type 32; .endef .def strncmp; .scl 2; .type 32; .endef .def strlen; .scl 2; .type 32; .endef原始字节,偶数块用异或0x11,奇数块用原始

这是期望密文

主函数汇编,算法是标准TEA

import structng_raw=b"sp\x7fvuctp|xeb|hv~"ng_xor=bytes(b^0x11 for b in ng_raw)ezgm=[1210405119,710975774,-90350153,-1958008304,-745722482,67707510,-86515270,-1728462407]ct=b''.join(struct.pack('<I',x&0xffffffff)for x in ezgm)def tea_dec(b,k): v0,v1=struct.unpack('<2I',b);k=struct.unpack('<4I',k) s=(0x9E3779B9*32)&0xffffffff for _ in range(32): v1=(v1-(((v0<<4)+k[2])^(v0+s)^((v0>>5)+k[3])))&0xffffffff v0=(v0-(((v1<<4)+k[0])^(v1+s)^((v1>>5)+k[1])))&0xffffffff s=(s-0x9E3779B9)&0xffffffff return struct.pack('<2I',v0,v1)pt=b''for i in range(0,len(ct),8): k=ng_xor if(i//8)%2==0 else ng_raw pt+=tea_dec(ct[i:i+8],k)print("flag{"+pt.decode()+"}")flag{4553m81y_5_s0o0o0_345y_jD5yQ5mD9}
第三周
1.采一朵花送给艾达(2)
rc4_init的花指令

改完后

rc4_crypt的花指令

改完后

KeyGen的花指令

改完后

main的花指令

改完后

是一个RC4变种,S[i] = i ^ 0xCC,RC4加密后每个字节加上其索引位置
import struct
data = [0x673AF04AEFE18A5C, 0x0DCBAFF24A65D456, 0xCFD8B1539076E546, 0xFD469B79EF8A33B7, 0x5985D24E20980BEC]encrypted = b''.join([struct.pack('<Q', x) for x in data])key = b"PickingUpFlowers"
step1 = [(byte - i) % 256 for i, byte in enumerate(encrypted)]
S = [i ^ 0xCC for i in range(256)]j = 0for i in range(256): j = (S[i] + j + key[i % len(key)]) % 256 S[i], S[j] = S[j], S[i]
i = j = 0flag = []for byte in step1: i = (i + 1) % 256 j = (S[i] + j) % 256 S[i], S[j] = S[j], S[i] flag.append(byte ^ S[(S[i] + S[j]) % 256])
print(bytes(flag).decode())flag{WO0o0O0w_So0Oo0o_m4Ny_F1oO0o0oW3R5}
2.尤皮·埃克斯历险记(2)
打开010editor

改回去

正常脱壳

IDA打开

去看加密函数encrypt,明文为 48 字节,按小端打包成 12 个,对对每个三元组 [a,b,c] ,使用 72 个子密钥 KEYS[0..71] 迭代,再逐字异或

RoundFunc函数,每轮混合里用到的 32 位可逆“搅拌函数”

keys,iv,target数据

脚本
import struct
MASK32 = 0xFFFFFFFF
KEYS = [ 0x0D344FC67, 0x2210BDB7, 0x76BB9C00, 0x53F1B5DE, 0x821A977F, 0x0F5B01673, 0x2A406627, 0x935F493C, 0x0B98347C1, 0x0E1AD274A, 0x0F68B39CE, 0x0BCB77109, 0x0AE8207AF, 0x54F52F5A, 0x2487ACB7, 0x2BAA52BD, 0x0D7A45B9F, 0x0B93D82C7, 0x77FBF041, 0x1747530C, 0x7EA63DEE, 0x8BAD0343, 0x38822BD3, 0x806B9E9D, 0x242525CF, 0x1F5D96BE, 0x1ADB4554, 0x47B628D0, 0x77C9A358, 0x3C43D913, 0x711165D3, 0x1AFDEA6E, 0x57EF6F26, 0x75CDB37E, 0x0F08680DE, 0x7EAAD562, 0x7ABA9243, 0x45AF3320, 0x0F7F816B2, 0x3DD5C8D1, 0x6D8251F6, 0x7606E5D0, 0x38DCED31, 0x7FA1260B, 0x0BAEFF202, 0x0D9D85E1D, 0x5E583700, 0x35DFCC5F, 0x1B689ABB, 0x1B2BBB67, 0x0CF506375, 0x3A3D4268, 0x46A5141B, 0x7FE3136C, 0x3E86F672, 0x8A0B8EEE, 0x33D87CD7, 0x0D4A50EA9, 0x0C77AFCDD, 0x0CDC0D74D, 0x0E0B6F0BC, 0x66C0E9C7, 0x0D494B811, 0x9D1D8A81, 0x147C00B6, 0x0DF60C3E4, 0x5FA112F8, 0x7186229A, 0x7FDCDC37, 0x1435FE6B, 0x0F97112A5, 0x0EA79306C]
IV = [0xBE87E8B2, 0x88E9F392, 0x16FB40C3]
TARGET_BYTES = bytes([ 0xC7,0xC9,0x4C,0x95,0x6F,0xBF,0xC9,0xF4,0xC4,0x86, 0xA4,0x20,0x57,0x55,0x6B,0xE2,0xEA,0xDC,0xB7,0x3F, 0x9C,0x42,0x1E,0xE1,0x72,0x82,0x0D,0x93,0xB3,0xF9, 0xD0,0x35,0x93,0x70,0xFF,0x44,0x72,0x61,0x55,0xF8, 0xEC,0xDA,0xFB,0x6E,0xA8,0xA6,0xCB,0x9E])
def roundfunc(x): x &= MASK32 v2 = 603658669 while v2 != -1835366127: if v2 == -187717688: x = (x - 1886114759) & MASK32 v2 = -1469481454 elif v2 == -759506153: v2 = -1835366127 elif v2 == -815798305: x = (x - 1020965622) & MASK32 v2 = -1415620839 elif v2 == -849861613: x = (x + 759745135) & MASK32 v2 = -815798305 elif v2 == -1075847271: x = (x - 487836449) & MASK32 v2 = 459874289 elif v2 == -1415620839: x = (x + 1171837779) & MASK32 v2 = -1075847271 elif v2 == -1469481454: x = (x - 1008740535) & MASK32 v2 = 2115108864 elif v2 == -1756392047: x = (x - 1645591540) & MASK32 v2 = -849861613 elif v2 == -1888773086: x = x ^ 0x1756F5FD v2 = -187717688 elif v2 == 2115108864: x = (x + 977397887) & MASK32 v2 = -759506153 elif v2 == 1601918207: x = (x - 451012892) & MASK32 v2 = 177990911 elif v2 == 1182471351: x = (x - 927205391) & MASK32 v2 = 1601918207 elif v2 == 1073315825: x = (x - 1030555907) & MASK32 v2 = -1888773086 elif v2 == 603658669: x = (x + 1071031968) & MASK32 v2 = 86236952 elif v2 == 459874289: x = (x + 717238452) & MASK32 v2 = 1073315825 elif v2 == 177990911: x = (x - 1460128592) & MASK32 v2 = 347638 elif v2 == 86236952: x = x ^ 0xFD714A3E v2 = 1182471351 elif v2 == 67638: x = (x + 1979752636) & MASK32 v2 = -1756392047 else: x = (x + 45479597) & MASK32 v2 = 67638 return x & MASK32
def get_round_ops(): ops = [] v2 = 603658669 while v2 != -1835366127: if v2 == -187717688: ops.append(('-', 1886114759)) v2 = -1469481454 elif v2 == -759506153: v2 = -1835366127 elif v2 == -815798305: ops.append(('-', 1020965622)) v2 = -1415620839 elif v2 == -849861613: ops.append(('+', 759745135)) v2 = -815798305 elif v2 == -1075847271: ops.append(('-', 487836449)) v2 = 459874289 elif v2 == -1415620839: ops.append(('+', 1171837779)) v2 = -1075847271 elif v2 == -1469481454: ops.append(('-', 1008740535)) v2 = 2115108864 elif v2 == -1756392047: ops.append(('-', 1645591540)) v2 = -849861613 elif v2 == -1888773086: ops.append(('^', 0x1756F5FD)) v2 = -187717688 elif v2 == 2115108864: ops.append(('+', 977397887)) v2 = -759506153 elif v2 == 1601918207: ops.append(('-', 451012892)) v2 = 177990911 elif v2 == 1182471351: ops.append(('-', 927205391)) v2 = 1601918207 elif v2 == 1073315825: ops.append(('-', 1030555907)) v2 = -1888773086 elif v2 == 603658669: ops.append(('+', 1071031968)) v2 = 86236952 elif v2 == 459874289: ops.append(('+', 717238452)) v2 = 1073315825 elif v2 == 177990911: ops.append(('-', 1460128592)) v2 = 347638 elif v2 == 86236952: ops.append(('^', 0xFD714A3E)) v2 = 1182471351 elif v2 == 67638: ops.append(('+', 1979752636)) v2 = -1756392047 else: ops.append(('+', 45479597)) v2 = 67638 return ops
ROUND_OPS = get_round_ops()
def roundfunc_inv(y): x = y & MASK32 for op, c in reversed(ROUND_OPS): if op == '+': x = (x - c) & MASK32 elif op == '-': x = (x + c) & MASK32 elif op == '^': x = x ^ c else: raise RuntimeError("unknown op") return x & MASK32
def E_triple_inverse(out_triple, keys): v8 = [0]*76 v8[72], v8[73], v8[74] = out_triple[0] & MASK32, out_triple[1] & MASK32, out_triple[2] & MASK32 for n in range(71, -1, -1): inner = roundfunc((v8[n+2] ^ v8[n+1] ^ keys[n]) & MASK32) v8[n] = (roundfunc_inv(v8[n+3]) ^ inner) & MASK32 return [v8[0], v8[1], v8[2]]
def decrypt_target(target_bytes, keys, iv): if len(target_bytes) % 4 != 0: raise ValueError("target length must be multiple of 4") Count = len(target_bytes) // 4 cipher_words = list(struct.unpack('<' + 'I'*Count, target_bytes)) pre_xor = [0]*Count v14 = (Count + 2)//3 for jj in range(v14): for kk in range(3): idx = 3*jj + kk if idx >= Count: break if jj == 0: pre_xor[idx] = (cipher_words[idx] ^ iv[kk]) & MASK32 else: pre_xor[idx] = (cipher_words[idx] ^ cipher_words[idx-3]) & MASK32 recovered_words = [0]*Count for t in range(v14): base = 3*t if base >= Count: break out_triple = [] for kk in range(3): out_triple.append(pre_xor[base+kk] if base+kk < Count else 0) in_triple = E_triple_inverse(out_triple, keys) for kk in range(3): if base+kk < Count: recovered_words[base+kk] = in_triple[kk] & MASK32 recovered = b''.join(struct.pack('<I', w) for w in recovered_words) return recovered[:48]
if __name__ == "__main__": pt = decrypt_target(TARGET_BYTES, KEYS, IV) print(pt.decode('ascii', errors='replace'))flag{CoN7r0l_F10w_F14t73n1nG_C4N_b3_c0NfU5iNg!!}
3.pyz3
题目给了一个exe文件,我们先用pyinstxtractor提取里面的资源文件

我们接着用pycdc去反编译task.pyc文件

打开txt文件
# Source Generated with Decompyle++# File: task.pyc (Python 3.12)
def check(flag): if 47 * flag[0] + 41 * flag[1] + 32 * flag[2] + 56 * flag[3] + 52 * flag[4] + 67 * flag[5] + 13 * flag[6] + 25 * flag[7] + 20 * flag[8] + 98 * flag[9] + 88 * flag[10] + 65 * flag[11] + 82 * flag[12] + 92 * flag[13] + 3 * flag[14] + 29 * flag[15] + 93 * flag[16] + 88 * flag[17] + 45 * flag[18] + 58 * flag[19] + 40 * flag[20] + 72 * flag[21] + 99 * flag[22] + 10 * flag[23] + 94 * flag[24] + 62 * flag[25] + 82 * flag[26] + 92 * flag[27] + 23 * flag[28] + 46 * flag[29] + 55 * flag[30] + 72 * flag[31] + 44 * flag[32] + 9 * flag[33] + 65 * flag[34] + 42 * flag[35] == 176386 and 10 * flag[0] + 98 * flag[1] + 5 * flag[2] + 28 * flag[3] + 68 * flag[4] + 20 * flag[5] + 2 * flag[6] + 22 * flag[7] + 65 * flag[8] + 44 * flag[9] + 85 * flag[10] + 97 * flag[11] + 33 * flag[12] + 74 * flag[13] + 93 * flag[14] + 74 * flag[15] + 41 * flag[16] + 65 * flag[17] + 32 * flag[18] + 93 * flag[19] + 22 * flag[20] + 69 * flag[21] + 68 * flag[22] + 57 * flag[23] + 47 * flag[24] + 29 * flag[25] + 74 * flag[26] + 54 * flag[27] + 91 * flag[28] + 90 * flag[29] + 26 * flag[30] + 11 * flag[31] + 89 * flag[32] + 57 * flag[33] + 100 * flag[34] + 95 * flag[35] == 186050 and 25 * flag[0] + 22 * flag[1] + 54 * flag[2] + 5 * flag[3] + 8 * flag[4] + 3 * flag[5] + 12 * flag[6] + 70 * flag[7] + 25 * flag[8] + 61 * flag[9] + 68 * flag[10] + 12 * flag[11] + 27 * flag[12] + 42 * flag[13] + 83 * flag[14] + 91 * flag[15] + 67 * flag[16] + 46 * flag[17] + 8 * flag[18] + 45 * flag[19] + 94 * flag[20] + 80 * flag[21] + 69 * flag[22] + 95 * flag[23] + 12 * flag[24] + 21 * flag[25] + 94 * flag[26] + 82 * flag[27] + 93 * flag[28] + 41 * flag[29] + 4 * flag[30] + 56 * flag[31] + 92 * flag[32] + 77 * flag[33] + 15 * flag[34] + 30 * flag[35] == 154690 and 33 * flag[0] + 49 * flag[1] + 56 * flag[2] + 40 * flag[3] + 90 * flag[4] + 59 * flag[5] + 82 * flag[6] + 6 * flag[7] + 81 * flag[8] + 32 * flag[9] + 23 * flag[10] + 76 * flag[11] + 93 * flag[12] + 83 * flag[13] + 10 * flag[14] + 44 * flag[15] + 58 * flag[16] + 33 * flag[17] + 79 * flag[18] + 77 * flag[19] + 82 * flag[20] + 56 * flag[21] + 70 * flag[22] + 34 * flag[23] + 45 * flag[24] + 76 * flag[25] + 57 * flag[26] + 43 * flag[27] + 100 * flag[28] + 19 * flag[29] + 11 * flag[30] + 90 * flag[31] + 3 * flag[32] + 60 * flag[33] + 57 * flag[34] + 23 * flag[35] == 172116 and 65 * flag[0] + 70 * flag[1] + 20 * flag[2] + 32 * flag[3] + 75 * flag[4] + 30 * flag[5] + 3 * flag[6] + 78 * flag[7] + 35 * flag[8] + 45 * flag[9] + 95 * flag[10] + 93 * flag[11] + 52 * flag[12] + 32 * flag[13] + 88 * flag[14] + 94 * flag[15] + 67 * flag[16] + 34 * flag[17] + 91 * flag[18] + 88 * flag[19] + 31 * flag[20] + 61 * flag[21] + 17 * flag[22] + 99 * flag[23] + 100 * flag[24] + 49 * flag[25] + 4 * flag[26] + 60 * flag[27] + 81 * flag[28] + 88 * flag[29] + 43 * flag[30] + 34 * flag[31] + 30 * flag[32] + 52 * flag[33] + 18 * flag[34] + 100 * flag[35] == 190544 and 81 * flag[0] + 42 * flag[1] + 28 * flag[2] + 98 * flag[3] + 31 * flag[4] + 46 * flag[5] + 64 * flag[6] + 15 * flag[7] + 49 * flag[8] + 13 * flag[9] + 100 * flag[10] + 81 * flag[11] + 32 * flag[12] + 52 * flag[13] + 59 * flag[14] + 24 * flag[15] + 94 * flag[16] + 32 * flag[17] + 93 * flag[18] + 32 * flag[19] + 13 * flag[20] + 89 * flag[21] + 37 * flag[22] + 30 * flag[23] + 78 * flag[24] + 81 * flag[25] + 9 * flag[26] + 45 * flag[27] + 93 * flag[28] + 100 * flag[29] + 97 * flag[30] + 10 * flag[31] + 80 * flag[32] + 54 * flag[33] + 88 * flag[34] + 85 * flag[35] == 190323 and 76 * flag[0] + 54 * flag[1] + 5 * flag[2] + 14 * flag[3] + 62 * flag[4] + 44 * flag[5] + 24 * flag[6] + 29 * flag[7] + 85 * flag[8] + 87 * flag[9] + 19 * flag[10] + 3 * flag[11] + 65 * flag[12] + 24 * flag[13] + 92 * flag[14] + 37 * flag[15] + 57 * flag[16] + 20 * flag[17] + 45 * flag[18] + 5 * flag[19] + 13 * flag[20] + 91 * flag[21] + 92 * flag[22] + 75 * flag[23] + 36 * flag[24] + 79 * flag[25] + 12 * flag[26] + 22 * flag[27] + 75 * flag[28] + 82 * flag[29] + 28 * flag[30] + 82 * flag[31] + 24 * flag[32] + 53 * flag[33] + 56 * flag[34] + 92 * flag[35] == 162017 and 53 * flag[0] + 52 * flag[1] + 72 * flag[2] + 23 * flag[3] + 26 * flag[4] + 13 * flag[5] + 62 * flag[6] + 96 * flag[7] + 67 * flag[8] + 96 * flag[9] + 66 * flag[10] + 41 * flag[11] + 5 * flag[12] + 18 * flag[13] + 37 * flag[14] + 13 * flag[15] + 61 * flag[16] + 71 * flag[17] + 91 * flag[18] + 96 * flag[19] + 56 * flag[20] + 3 * flag[21] + 65 * flag[22] + 14 * flag[23] + 57 * flag[24] + 69 * flag[25] + 75 * flag[26] + 68 * flag[27] + 10 * flag[28] + 60 * flag[29] + 62 * flag[30] + 95 * flag[31] + 53 * flag[32] + 19 * flag[33] + 7 * flag[34] + 56 * flag[35] == 165118 and 26 * flag[0] + 7 * flag[1] + 49 * flag[2] + 14 * flag[3] + 36 * flag[4] + 87 * flag[5] + 21 * flag[6] + 35 * flag[7] + 15 * flag[8] + 91 * flag[9] + 15 * flag[10] + 100 * flag[11] + 8 * flag[12] + 32 * flag[13] + 100 * flag[14] + 35 * flag[15] + 66 * flag[16] + 3 * flag[17] + 79 * flag[18] + 96 * flag[19] + 82 * flag[20] + 95 * flag[21] + 68 * flag[22] + 13 * flag[23] + 86 * flag[24] + 51 * flag[25] + 24 * flag[26] + 76 * flag[27] + 30 * flag[28] + 60 * flag[29] + 29 * flag[30] + 70 * flag[31] + 40 * flag[32] + 90 * flag[33] + 44 * flag[34] + 3 * flag[35] == 153332 and 47 * flag[0] + 19 * flag[1] + 37 * flag[2] + 93 * flag[3] + 73 * flag[4] + 30 * flag[5] + 45 * flag[6] + 47 * flag[7] + 72 * flag[8] + 85 * flag[9] + 37 * flag[10] + 68 * flag[11] + 89 * flag[12] + 34 * flag[13] + 4 * flag[14] + 50 * flag[15] + 87 * flag[16] + 33 * flag[17] + 87 * flag[18] + 43 * flag[19] + 9 * flag[20] + 61 * flag[21] + 93 * flag[22] + 49 * flag[23] + 74 * flag[24] + 49 * flag[25] + 68 * flag[26] + 29 * flag[27] + 54 * flag[28] + 54 * flag[29] + 37 * flag[30] + 79 * flag[31] + 33 * flag[32] + 65 * flag[33] + 59 * flag[34] + 15 * flag[35] == 168472 and 79 * flag[0] + 73 * flag[1] + 60 * flag[2] + 62 * flag[3] + 25 * flag[4] + 16 * flag[5] + 77 * flag[6] + 81 * flag[7] + 79 * flag[8] + 31 * flag[9] + 82 * flag[10] + 84 * flag[11] + 62 * flag[12] + 36 * flag[13] + 18 * flag[14] + 20 * flag[15] + 46 * flag[16] + 57 * flag[17] + 21 * flag[18] + 40 * flag[19] + 3 * flag[20] + 50 * flag[21] + 58 * flag[22] + 80 * flag[23] + 84 * flag[24] + 71 * flag[25] + 87 * flag[26] + 3 * flag[27] + 13 * flag[28] + 77 * flag[29] + 83 * flag[30] + 39 * flag[31] + 55 * flag[32] + 34 * flag[33] + 41 * flag[34] + 63 * flag[35] == 178706 and 7 * flag[0] + 50 * flag[1] + 26 * flag[2] + 79 * flag[3] + 21 * flag[4] + 42 * flag[5] + 83 * flag[6] + 94 * flag[7] + 63 * flag[8] + 83 * flag[9] + 3 * flag[10] + 68 * flag[11] + 25 * flag[12] + 91 * flag[13] + 3 * flag[14] + 5 * flag[15] + 17 * flag[16] + 61 * flag[17] + 3 * flag[18] + 40 * flag[19] + 87 * flag[20] + 11 * flag[21] + 27 * flag[22] + 74 * flag[23] + 73 * flag[24] + 21 * flag[25] + 56 * flag[26] + 46 * flag[27] + 36 * flag[28] + 24 * flag[29] + 14 * flag[30] + 63 * flag[31] + 21 * flag[32] + 71 * flag[33] + 30 * flag[34] + 53 * flag[35] == 143852 and 57 * flag[0] + 51 * flag[1] + 49 * flag[2] + 15 * flag[3] + 94 * flag[4] + 34 * flag[5] + 27 * flag[6] + 5 * flag[7] + 100 * flag[8] + 68 * flag[9] + 67 * flag[10] + 81 * flag[11] + 10 * flag[12] + 5 * flag[13] + 85 * flag[14] + 70 * flag[15] + 80 * flag[16] + 20 * flag[17] + 89 * flag[18] + 30 * flag[19] + 84 * flag[20] + 35 * flag[21] + 41 * flag[22] + 87 * flag[23] + 75 * flag[24] + 67 * flag[25] + 20 * flag[26] + 33 * flag[27] + 29 * flag[28] + 6 * flag[29] + 97 * flag[30] + 25 * flag[31] + 10 * flag[32] + 18 * flag[33] + 23 * flag[34] + 30 * flag[35] == 154052 and 97 * flag[0] + 93 * flag[1] + 10 * flag[2] + 44 * flag[3] + 28 * flag[4] + 22 * flag[5] + 17 * flag[6] + 41 * flag[7] + 47 * flag[8] + 62 * flag[9] + 42 * flag[10] + 47 * flag[11] + 61 * flag[12] + 32 * flag[13] + 31 * flag[14] + 52 * flag[15] + 47 * flag[16] + 92 * flag[17] + 42 * flag[18] + 37 * flag[19] + 7 * flag[20] + 40 * flag[21] + 48 * flag[22] + 40 * flag[23] + 11 * flag[24] + 96 * flag[25] + 51 * flag[26] + 42 * flag[27] + 66 * flag[28] + 8 * flag[29] + 89 * flag[30] + 64 * flag[31] + 30 * flag[32] + 11 * flag[33] + 8 * flag[34] + 83 * flag[35] == 147899 and 51 * flag[0] + 94 * flag[1] + 58 * flag[2] + 76 * flag[3] + 21 * flag[4] + 10 * flag[5] + 75 * flag[6] + 4 * flag[7] + 55 * flag[8] + 37 * flag[9] + 71 * flag[10] + 97 * flag[11] + 27 * flag[12] + 93 * flag[13] + 82 * flag[14] + 94 * flag[15] + 38 * flag[16] + 69 * flag[17] + 36 * flag[18] + 58 * flag[19] + 93 * flag[20] + 18 * flag[21] + 54 * flag[22] + 59 * flag[23] + 12 * flag[24] + 12 * flag[25] + 54 * flag[26] + 83 * flag[27] + 73 * flag[28] + 83 * flag[29] + 33 * flag[30] + 12 * flag[31] + 78 * flag[32] + 38 * flag[33] + 45 * flag[34] + 57 * flag[35] == 176754 and 78 * flag[0] + 29 * flag[1] + 8 * flag[2] + 47 * flag[3] + 48 * flag[4] + 88 * flag[5] + 18 * flag[6] + 88 * flag[7] + 50 * flag[8] + 58 * flag[9] + 36 * flag[10] + 88 * flag[11] + 9 * flag[12] + 74 * flag[13] + 85 * flag[14] + 5 * flag[15] + 91 * flag[16] + 58 * flag[17] + 85 * flag[18] + 46 * flag[19] + 89 * flag[20] + 76 * flag[21] + 61 * flag[22] + 6 * flag[23] + 61 * flag[24] + 78 * flag[25] + 4 * flag[26] + 48 * flag[27] + 50 * flag[28] + 69 * flag[29] + 23 * flag[30] + 70 * flag[31] + 23 * flag[32] + 15 * flag[33] + 22 * flag[34] + 68 * flag[35] == 171970 and 75 * flag[0] + 2 * flag[1] + 94 * flag[2] + 97 * flag[3] + 72 * flag[4] + 62 * flag[5] + 78 * flag[6] + 42 * flag[7] + 69 * flag[8] + 11 * flag[9] + 37 * flag[10] + 3 * flag[11] + 29 * flag[12] + 15 * flag[13] + 39 * flag[14] + 33 * flag[15] + 18 * flag[16] + 33 * flag[17] + 12 * flag[18] + 64 * flag[19] + 6 * flag[20] + 18 * flag[21] + 34 * flag[22] + 15 * flag[23] + 3 * flag[24] + 100 * flag[25] + 85 * flag[26] + 32 * flag[27] + 97 * flag[28] + 93 * flag[29] + 84 * flag[30] + 73 * flag[31] + 26 * flag[32] + 31 * flag[33] + 71 * flag[34] + 97 * flag[35] == 166497 and 59 * flag[0] + 26 * flag[1] + 48 * flag[2] + 86 * flag[3] + 58 * flag[4] + 70 * flag[5] + 61 * flag[6] + 100 * flag[7] + 63 * flag[8] + 74 * flag[9] + 26 * flag[10] + 38 * flag[11] + 24 * flag[12] + 45 * flag[13] + 52 * flag[14] + 32 * flag[15] + 91 * flag[16] + 89 * flag[17] + 19 * flag[18] + 59 * flag[19] + 87 * flag[20] + 5 * flag[21] + 15 * flag[22] + 68 * flag[23] + 72 * flag[24] + 67 * flag[25] + 2 * flag[26] + 65 * flag[27] + 46 * flag[28] + 10 * flag[29] + 33 * flag[30] + 79 * flag[31] + 11 * flag[32] + 16 * flag[33] + 73 * flag[34] + 53 * flag[35] == 173887 and 6 * flag[0] + 66 * flag[1] + 59 * flag[2] + 76 * flag[3] + 86 * flag[4] + 20 * flag[5] + 59 * flag[6] + 34 * flag[7] + 28 * flag[8] + 48 * flag[9] + 86 * flag[10] + 5 * flag[11] + 87 * flag[12] + 13 * flag[13] + 95 * flag[14] + 87 * flag[15] + 65 * flag[16] + 35 * flag[17] + 58 * flag[18] + 10 * flag[19] + 98 * flag[20] + 100 * flag[21] + 4 * flag[22] + 78 * flag[23] + 66 * flag[24] + 57 * flag[25] + 34 * flag[26] + 86 * flag[27] + 62 * flag[28] + 36 * flag[29] + 92 * flag[30] + 28 * flag[31] + 3 * flag[32] + 24 * flag[33] + 49 * flag[34] + 28 * flag[35] == 173189 and 25 * flag[0] + 48 * flag[1] + 44 * flag[2] + 16 * flag[3] + 99 * flag[4] + 100 * flag[5] + 69 * flag[6] + 26 * flag[7] + 65 * flag[8] + 32 * flag[9] + 18 * flag[10] + 65 * flag[11] + 58 * flag[12] + 72 * flag[13] + 61 * flag[14] + 56 * flag[15] + 10 * flag[16] + 78 * flag[17] + 93 * flag[18] + 98 * flag[19] + 39 * flag[20] + 43 * flag[21] + 87 * flag[22] + 12 * flag[23] + 42 * flag[24] + 100 * flag[25] + 100 * flag[26] + 47 * flag[27] + 31 * flag[28] + 51 * flag[29] + 75 * flag[30] + 10 * flag[31] + 63 * flag[32] + 48 * flag[33] + 22 * flag[34] + 87 * flag[35] == 174138 and 61 * flag[0] + 13 * flag[1] + 100 * flag[2] + 59 * flag[3] + 31 * flag[4] + 9 * flag[5] + 28 * flag[6] + 7 * flag[7] + 27 * flag[8] + 63 * flag[9] + 11 * flag[10] + 57 * flag[11] + 95 * flag[12] + 79 * flag[13] + 21 * flag[14] + 30 * flag[15] + 60 * flag[16] + 81 * flag[17] + 43 * flag[18] + 32 * flag[19] + 30 * flag[20] + 34 * flag[21] + 80 * flag[22] + 53 * flag[23] + 28 * flag[24] + 39 * flag[25] + 74 * flag[26] + 21 * flag[27] + 18 * flag[28] + 92 * flag[29] + 73 * flag[30] + 60 * flag[31] + 21 * flag[32] + 69 * flag[33] + 76 * flag[34] + 84 * flag[35] == 157623 and 22 * flag[0] + 62 * flag[1] + 61 * flag[2] + 20 * flag[3] + 66 * flag[4] + 2 * flag[5] + 11 * flag[6] + 82 * flag[7] + 93 * flag[8] + 13 * flag[9] + 69 * flag[10] + 37 * flag[11] + 92 * flag[12] + 80 * flag[13] + 66 * flag[14] + 47 * flag[15] + 28 * flag[16] + 14 * flag[17] + 62 * flag[18] + 56 * flag[19] + 89 * flag[20] + 29 * flag[21] + 39 * flag[22] + 38 * flag[23] + 46 * flag[24] + 10 * flag[25] + 6 * flag[26] + 82 * flag[27] + 77 * flag[28] + 78 * flag[29] + 45 * flag[30] + 50 * flag[31] + 5 * flag[32] + 73 * flag[33] + 17 * flag[34] + 65 * flag[35] == 154943 and 5 * flag[0] + 84 * flag[1] + 83 * flag[2] + 77 * flag[3] + 76 * flag[4] + 60 * flag[5] + 20 * flag[6] + 48 * flag[7] + 53 * flag[8] + 14 * flag[9] + 98 * flag[10] + 50 * flag[11] + 37 * flag[12] + 15 * flag[13] + 31 * flag[14] + 69 * flag[15] + 55 * flag[16] + 37 * flag[17] + 64 * flag[18] + 35 * flag[19] + 26 * flag[20] + 20 * flag[21] + 18 * flag[22] + 67 * flag[23] + 50 * flag[24] + 57 * flag[25] + 60 * flag[26] + 71 * flag[27] + 4 * flag[28] + 35 * flag[29] + 23 * flag[30] + 52 * flag[31] + 11 * flag[32] + 15 * flag[33] + 83 * flag[34] + 51 * flag[35] == 156078 and 33 * flag[0] + 47 * flag[1] + 89 * flag[2] + 52 * flag[3] + 89 * flag[4] + 55 * flag[5] + 98 * flag[6] + 28 * flag[7] + 48 * flag[8] + 90 * flag[9] + 69 * flag[10] + 29 * flag[11] + 68 * flag[12] + 24 * flag[13] + 19 * flag[14] + 18 * flag[15] + 44 * flag[16] + 27 * flag[17] + 14 * flag[18] + 64 * flag[19] + 15 * flag[20] + 31 * flag[21] + 23 * flag[22] + 2 * flag[23] + 36 * flag[24] + 45 * flag[25] + 37 * flag[26] + 71 * flag[27] + 61 * flag[28] + 92 * flag[29] + 28 * flag[30] + 64 * flag[31] + 13 * flag[32] + 66 * flag[33] + 98 * flag[34] + 3 * flag[35] == 156158 and 80 * flag[0] + 88 * flag[1] + 68 * flag[2] + 66 * flag[3] + 46 * flag[4] + 75 * flag[5] + 32 * flag[6] + 19 * flag[7] + 36 * flag[8] + 83 * flag[9] + 63 * flag[10] + 86 * flag[11] + 79 * flag[12] + 30 * flag[13] + 61 * flag[14] + 50 * flag[15] + 100 * flag[16] + 52 * flag[17] + 66 * flag[18] + 30 * flag[19] + 20 * flag[20] + 97 * flag[21] + 45 * flag[22] + 46 * flag[23] + 38 * flag[24] + 21 * flag[25] + 32 * flag[26] + 79 * flag[27] + 68 * flag[28] + 43 * flag[29] + 65 * flag[30] + 47 * flag[31] + 86 * flag[32] + 30 * flag[33] + 74 * flag[34] + 18 * flag[35] == 181770 and 11 * flag[0] + 58 * flag[1] + 95 * flag[2] + 67 * flag[3] + 96 * flag[4] + 74 * flag[5] + 60 * flag[6] + 11 * flag[7] + 21 * flag[8] + 14 * flag[9] + 100 * flag[10] + 60 * flag[11] + 70 * flag[12] + 92 * flag[13] + 92 * flag[14] + 39 * flag[15] + 43 * flag[16] + 52 * flag[17] + 5 * flag[18] + 22 * flag[19] + 90 * flag[20] + 70 * flag[21] + 12 * flag[22] + 52 * flag[23] + 36 * flag[24] + 21 * flag[25] + 45 * flag[26] + 59 * flag[27] + 74 * flag[28] + 46 * flag[29] + 11 * flag[30] + 60 * flag[31] + 8 * flag[32] + 52 * flag[33] + 14 * flag[34] + 77 * flag[35] == 173577 and 57 * flag[0] + 37 * flag[1] + 94 * flag[2] + 43 * flag[3] + 53 * flag[4] + 55 * flag[5] + 7 * flag[6] + 83 * flag[7] + 91 * flag[8] + 61 * flag[9] + 86 * flag[10] + 6 * flag[11] + 44 * flag[12] + 87 * flag[13] + 61 * flag[14] + 92 * flag[15] + 24 * flag[16] + 74 * flag[17] + 100 * flag[18] + 22 * flag[19] + 12 * flag[20] + 68 * flag[21] + 19 * flag[22] + 88 * flag[23] + 81 * flag[24] + 83 * flag[25] + 70 * flag[26] + 39 * flag[27] + 30 * flag[28] + 82 * flag[29] + 30 * flag[30] + 35 * flag[31] + 55 * flag[32] + 18 * flag[33] + 27 * flag[34] + 80 * flag[35] == 180922 and 80 * flag[0] + 14 * flag[1] + 5 * flag[2] + 89 * flag[3] + 71 * flag[4] + 82 * flag[5] + 44 * flag[6] + 8 * flag[7] + 33 * flag[8] + 26 * flag[9] + 77 * flag[10] + 49 * flag[11] + 36 * flag[12] + 90 * flag[13] + 73 * flag[14] + 71 * flag[15] + 66 * flag[16] + 4 * flag[17] + 37 * flag[18] + 78 * flag[19] + 38 * flag[20] + 18 * flag[21] + 15 * flag[22] + 79 * flag[23] + 6 * flag[24] + 74 * flag[25] + 18 * flag[26] + 85 * flag[27] + 56 * flag[28] + 53 * flag[29] + 90 * flag[30] + 75 * flag[31] + 52 * flag[32] + 2 * flag[33] + 13 * flag[34] + 54 * flag[35] == 158596 and 96 * flag[0] + 29 * flag[1] + 37 * flag[2] + 70 * flag[3] + 92 * flag[4] + 80 * flag[5] + 24 * flag[6] + 36 * flag[7] + 32 * flag[8] + 29 * flag[9] + 78 * flag[10] + 45 * flag[11] + 58 * flag[12] + 55 * flag[13] + 16 * flag[14] + 92 * flag[15] + 71 * flag[16] + 82 * flag[17] + 86 * flag[18] + 23 * flag[19] + 4 * flag[20] + 58 * flag[21] + 16 * flag[22] + 18 * flag[23] + 38 * flag[24] + 53 * flag[25] + 82 * flag[26] + 76 * flag[27] + 83 * flag[28] + 73 * flag[29] + 87 * flag[30] + 36 * flag[31] + 61 * flag[32] + 85 * flag[33] + 61 * flag[34] + 69 * flag[35] == 181072 and 14 * flag[0] + 71 * flag[1] + 53 * flag[2] + 46 * flag[3] + 59 * flag[4] + 53 * flag[5] + 22 * flag[6] + 69 * flag[7] + 67 * flag[8] + 43 * flag[9] + 23 * flag[10] + 14 * flag[11] + 77 * flag[12] + 95 * flag[13] + 19 * flag[14] + 83 * flag[15] + 79 * flag[16] + 41 * flag[17] + 12 * flag[18] + 53 * flag[19] + 3 * flag[20] + 4 * flag[21] + 65 * flag[22] + 92 * flag[23] + 64 * flag[24] + 52 * flag[25] + 3 * flag[26] + 59 * flag[27] + 89 * flag[28] + 75 * flag[29] + 12 * flag[30] + 46 * flag[31] + 61 * flag[32] + 53 * flag[33] + 97 * flag[34] + 43 * flag[35] == 163777 and 57 * flag[0] + 99 * flag[1] + 49 * flag[2] + 100 * flag[3] + 68 * flag[4] + 99 * flag[5] + 26 * flag[6] + 65 * flag[7] + 47 * flag[8] + 65 * flag[9] + 90 * flag[10] + 68 * flag[11] + 84 * flag[12] + 4 * flag[13] + 9 * flag[14] + 43 * flag[15] + 88 * flag[16] + 33 * flag[17] + 48 * flag[18] + 88 * flag[19] + 37 * flag[20] + 31 * flag[21] + 21 * flag[22] + 94 * flag[23] + 22 * flag[24] + 93 * flag[25] + 70 * flag[26] + 14 * flag[27] + 13 * flag[28] + 28 * flag[29] + 83 * flag[30] + 12 * flag[31] + 80 * flag[32] + 58 * flag[33] + 43 * flag[34] + 97 * flag[35] == 187620 and 33 * flag[0] + 94 * flag[1] + 56 * flag[2] + 48 * flag[3] + 13 * flag[4] + 44 * flag[5] + 81 * flag[6] + 42 * flag[7] + 19 * flag[8] + 96 * flag[9] + 67 * flag[10] + 79 * flag[11] + 12 * flag[12] + 67 * flag[13] + 34 * flag[14] + 72 * flag[15] + 45 * flag[16] + 48 * flag[17] + 24 * flag[18] + 71 * flag[19] + 65 * flag[20] + 13 * flag[21] + 32 * flag[22] + 97 * flag[23] + 48 * flag[24] + 42 * flag[25] + 65 * flag[26] + 95 * flag[27] + 54 * flag[28] + 9 * flag[29] + 35 * flag[30] + 57 * flag[31] + 18 * flag[32] + 20 * flag[33] + 83 * flag[34] + 76 * flag[35] == 169266 and 31 * flag[0] + 38 * flag[1] + 83 * flag[2] + 45 * flag[3] + 28 * flag[4] + 97 * flag[5] + 54 * flag[6] + 11 * flag[7] + 80 * flag[8] + 45 * flag[9] + 92 * flag[10] + 13 * flag[11] + 52 * flag[12] + 94 * flag[13] + 51 * flag[14] + 30 * flag[15] + 11 * flag[16] + 61 * flag[17] + 46 * flag[18] + 10 * flag[19] + 28 * flag[20] + 72 * flag[21] + 20 * flag[22] + 95 * flag[23] + 90 * flag[24] + 39 * flag[25] + 32 * flag[26] + 95 * flag[27] + 19 * flag[28] + 3 * flag[29] + 65 * flag[30] + 71 * flag[31] + 73 * flag[32] + 80 * flag[33] + 23 * flag[34] + 71 * flag[35] == 162587 and 9 * flag[0] + 81 * flag[1] + 80 * flag[2] + 37 * flag[3] + 96 * flag[4] + 72 * flag[5] + 95 * flag[6] + 93 * flag[7] + 26 * flag[8] + 98 * flag[9] + 50 * flag[10] + 79 * flag[11] + 57 * flag[12] + 13 * flag[13] + 49 * flag[14] + 96 * flag[15] + 82 * flag[16] + 84 * flag[17] + 89 * flag[18] + 40 * flag[19] + 38 * flag[20] + 66 * flag[21] + 81 * flag[22] + 81 * flag[23] + 79 * flag[24] + 77 * flag[25] + 86 * flag[26] + 68 * flag[27] + 26 * flag[28] + 37 * flag[29] + 15 * flag[30] + 56 * flag[31] + 13 * flag[32] + 17 * flag[33] + 50 * flag[34] + 37 * flag[35] == 198705 and 82 * flag[0] + 57 * flag[1] + 33 * flag[2] + 32 * flag[3] + 79 * flag[4] + 25 * flag[5] + 54 * flag[6] + 27 * flag[7] + 50 * flag[8] + 14 * flag[9] + 72 * flag[10] + 31 * flag[11] + 28 * flag[12] + 66 * flag[13] + 4 * flag[14] + 6 * flag[15] + 48 * flag[16] + 34 * flag[17] + 63 * flag[18] + 51 * flag[19] + 12 * flag[20] + 21 * flag[21] + 73 * flag[22] + 66 * flag[23] + 53 * flag[24] + 38 * flag[25] + 54 * flag[26] + 59 * flag[27] + 76 * flag[28] + 63 * flag[29] + 61 * flag[30] + 30 * flag[31] + 84 * flag[32] + 80 * flag[33] + 98 * flag[34] + 46 * flag[35] == 160349 and 69 * flag[0] + 15 * flag[1] + 23 * flag[2] + 8 * flag[3] + 46 * flag[4] + 55 * flag[5] + 21 * flag[6] + 91 * flag[7] + 37 * flag[8] + 9 * flag[9] + 61 * flag[10] + 20 * flag[11] + 23 * flag[12] + 96 * flag[13] + 28 * flag[14] + 67 * flag[15] + 19 * flag[16] + 50 * flag[17] + 18 * flag[18] + 71 * flag[19] + 30 * flag[20] + 14 * flag[21] + 10 * flag[22] + 24 * flag[23] + 100 * flag[24] + 15 * flag[25] + 91 * flag[26] + 15 * flag[27] + 93 * flag[28] + 24 * flag[29] + 46 * flag[30] + 61 * flag[31] + 67 * flag[32] + 60 * flag[33] + 56 * flag[34] + 81 * flag[35] == 148095: return True return False
def main(): flag = str(input('Input your flag: ')).encode() res = check(flag) if res: print('Right flag!') return None print('Wrong flag!')
if __name__ == '__main__': main() return None使用z3
from z3 import Solver, Int, And,sat
flag = [Int(f'f{i}') for i in range(36)]s = Solver()
for f in flag: s.add(And(f >= 32, f <= 126))
eqs = [ ([47, 41, 32, 56, 52, 67, 13, 25, 20, 98, 88, 65, 82, 92, 3, 29, 93, 88, 45, 58, 40, 72, 99, 10, 94, 62, 82, 92, 23, 46, 55, 72, 44, 9, 65, 42], 176386), ([10, 98, 5, 28, 68, 20, 2, 22, 65, 44, 85, 97, 33, 74, 93, 74, 41, 65, 32, 93, 22, 69, 68, 57, 47, 29, 74, 54, 91, 90, 26, 11, 89, 57, 100, 95], 186050), ([25, 22, 54, 5, 8, 3, 12, 70, 25, 61, 68, 12, 27, 42, 83, 91, 67, 46, 8, 45, 94, 80, 69, 95, 12, 21, 94, 82, 93, 41, 4, 56, 92, 77, 15, 30], 154690), ([33, 49, 56, 40, 90, 59, 82, 6, 81, 32, 23, 76, 93, 83, 10, 44, 58, 33, 79, 77, 82, 56, 70, 34, 45, 76, 57, 43, 100, 19, 11, 90, 3, 60, 57, 23], 172116), ([65, 70, 20, 32, 75, 30, 3, 78, 35, 45, 95, 93, 52, 32, 88, 94, 67, 34, 91, 88, 31, 61, 17, 99, 100, 49, 4, 60, 81, 88, 43, 34, 30, 52, 18, 100], 190544), ([81, 42, 28, 98, 31, 46, 64, 15, 49, 13, 100, 81, 32, 52, 59, 24, 94, 32, 93, 32, 13, 89, 37, 30, 78, 81, 9, 45, 93, 100, 97, 10, 80, 54, 88, 85], 190323), ([76, 54, 5, 14, 62, 44, 24, 29, 85, 87, 19, 3, 65, 24, 92, 37, 57, 20, 45, 5, 13, 91, 92, 75, 36, 79, 12, 22, 75, 82, 28, 82, 24, 53, 56, 92], 162017), ([53, 52, 72, 23, 26, 13, 62, 96, 67, 96, 66, 41, 5, 18, 37, 13, 61, 71, 91, 96, 56, 3, 65, 14, 57, 69, 75, 68, 10, 60, 62, 95, 53, 19, 7, 56], 165118), ([26, 7, 49, 14, 36, 87, 21, 35, 15, 91, 15, 100, 8, 32, 100, 35, 66, 3, 79, 96, 82, 95, 68, 13, 86, 51, 24, 76, 30, 60, 29, 70, 40, 90, 44, 3], 153332), ([47, 19, 37, 93, 73, 30, 45, 47, 72, 85, 37, 68, 89, 34, 4, 50, 87, 33, 87, 43, 9, 61, 93, 49, 74, 49, 68, 29, 54, 54, 37, 79, 33, 65, 59, 15], 168472), ([79, 73, 60, 62, 25, 16, 77, 81, 79, 31, 82, 84, 62, 36, 18, 20, 46, 57, 21, 40, 3, 50, 58, 80, 84, 71, 87, 3, 13, 77, 83, 39, 55, 34, 41, 63], 178706), ([7, 50, 26, 79, 21, 42, 83, 94, 63, 83, 3, 68, 25, 91, 3, 5, 17, 61, 3, 40, 87, 11, 27, 74, 73, 21, 56, 46, 36, 24, 14, 63, 21, 71, 30, 53], 143852), ([57, 51, 49, 15, 94, 34, 27, 5, 100, 68, 67, 81, 10, 5, 85, 70, 80, 20, 89, 30, 84, 35, 41, 87, 75, 67, 20, 33, 29, 6, 97, 25, 10, 18, 23, 30], 154052), ([97, 93, 10, 44, 28, 22, 17, 41, 47, 62, 42, 47, 61, 32, 31, 52, 47, 92, 42, 37, 7, 40, 48, 40, 11, 96, 51, 42, 66, 8, 89, 64, 30, 11, 8, 83], 147899), ([51, 94, 58, 76, 21, 10, 75, 4, 55, 37, 71, 97, 27, 93, 82, 94, 38, 69, 36, 58, 93, 18, 54, 59, 12, 12, 54, 83, 73, 83, 33, 12, 78, 38, 45, 57], 176754), ([78, 29, 8, 47, 48, 88, 18, 88, 50, 58, 36, 88, 9, 74, 85, 5, 91, 58, 85, 46, 89, 76, 61, 6, 61, 78, 4, 48, 50, 69, 23, 70, 23, 15, 22, 68], 171970), ([75, 2, 94, 97, 72, 62, 78, 42, 69, 11, 37, 3, 29, 15, 39, 33, 18, 33, 12, 64, 6, 18, 34, 15, 3, 100, 85, 32, 97, 93, 84, 73, 26, 31, 71, 97], 166497), ([59, 26, 48, 86, 58, 70, 61, 100, 63, 74, 26, 38, 24, 45, 52, 32, 91, 89, 19, 59, 87, 5, 15, 68, 72, 67, 2, 65, 46, 10, 33, 79, 11, 16, 73, 53], 173887), ([6, 66, 59, 76, 86, 20, 59, 34, 28, 48, 86, 5, 87, 13, 95, 87, 65, 35, 58, 10, 98, 100, 4, 78, 66, 57, 34, 86, 62, 36, 92, 28, 3, 24, 49, 28], 173189), ([25, 48, 44, 16, 99, 100, 69, 26, 65, 32, 18, 65, 58, 72, 61, 56, 10, 78, 93, 98, 39, 43, 87, 12, 42, 100, 100, 47, 31, 51, 75, 10, 63, 48, 22, 87], 174138), ([61, 13, 100, 59, 31, 9, 28, 7, 27, 63, 11, 57, 95, 79, 21, 30, 60, 81, 43, 32, 30, 34, 80, 53, 28, 39, 74, 21, 18, 92, 73, 60, 21, 69, 76, 84], 157623), ([22, 62, 61, 20, 66, 2, 11, 82, 93, 13, 69, 37, 92, 80, 66, 47, 28, 14, 62, 56, 89, 29, 39, 38, 46, 10, 6, 82, 77, 78, 45, 50, 5, 73, 17, 65], 154943), ([5, 84, 83, 77, 76, 60, 20, 48, 53, 14, 98, 50, 37, 15, 31, 69, 55, 37, 64, 35, 26, 20, 18, 67, 50, 57, 60, 71, 4, 35, 23, 52, 11, 15, 83, 51], 156078), ([33, 47, 89, 52, 89, 55, 98, 28, 48, 90, 69, 29, 68, 24, 19, 18, 44, 27, 14, 64, 15, 31, 23, 2, 36, 45, 37, 71, 61, 92, 28, 64, 13, 66, 98, 3], 156158), ([80, 88, 68, 66, 46, 75, 32, 19, 36, 83, 63, 86, 79, 30, 61, 50, 100, 52, 66, 30, 20, 97, 45, 46, 38, 21, 32, 79, 68, 43, 65, 47, 86, 30, 74, 18], 181770), ([11, 58, 95, 67, 96, 74, 60, 11, 21, 14, 100, 60, 70, 92, 92, 39, 43, 52, 5, 22, 90, 70, 12, 52, 36, 21, 45, 59, 74, 46, 11, 60, 8, 52, 14, 77], 173577), ([57, 37, 94, 43, 53, 55, 7, 83, 91, 61, 86, 6, 44, 87, 61, 92, 24, 74, 100, 22, 12, 68, 19, 88, 81, 83, 70, 39, 30, 82, 30, 35, 55, 18, 27, 80], 180922), ([80, 14, 5, 89, 71, 82, 44, 8, 33, 26, 77, 49, 36, 90, 73, 71, 66, 4, 37, 78, 38, 18, 15, 79, 6, 74, 18, 85, 56, 53, 90, 75, 52, 2, 13, 54], 158596), ([96, 29, 37, 70, 92, 80, 24, 36, 32, 29, 78, 45, 58, 55, 16, 92, 71, 82, 86, 23, 4, 58, 16, 18, 38, 53, 82, 76, 83, 73, 87, 36, 61, 85, 61, 69], 181072), ([14, 71, 53, 46, 59, 53, 22, 69, 67, 43, 23, 14, 77, 95, 19, 83, 79, 41, 12, 53, 3, 4, 65, 92, 64, 52, 3, 59, 89, 75, 12, 46, 61, 53, 97, 43], 163777), ([57, 99, 49, 100, 68, 99, 26, 65, 47, 65, 90, 68, 84, 4, 9, 43, 88, 33, 48, 88, 37, 31, 21, 94, 22, 93, 70, 14, 13, 28, 83, 12, 80, 58, 43, 97], 187620), ([33, 94, 56, 48, 13, 44, 81, 42, 19, 96, 67, 79, 12, 67, 34, 72, 45, 48, 24, 71, 65, 13, 32, 97, 48, 42, 65, 95, 54, 9, 35, 57, 18, 20, 83, 76], 169266), ([31, 38, 83, 45, 28, 97, 54, 11, 80, 45, 92, 13, 52, 94, 51, 30, 11, 61, 46, 10, 28, 72, 20, 95, 90, 39, 32, 95, 19, 3, 65, 71, 73, 80, 23, 71], 162587), ([9, 81, 80, 37, 96, 72, 95, 93, 26, 98, 50, 79, 57, 13, 49, 96, 82, 84, 89, 40, 38, 66, 81, 81, 79, 77, 86, 68, 26, 37, 15, 56, 13, 17, 50, 37], 198705), ([82, 57, 33, 32, 79, 25, 54, 27, 50, 14, 72, 31, 28, 66, 4, 6, 48, 34, 63, 51, 12, 21, 73, 66, 53, 38, 54, 59, 76, 63, 61, 30, 84, 80, 98, 46], 160349), ([69, 15, 23, 8, 46, 55, 21, 91, 37, 9, 61, 20, 23, 96, 28, 67, 19, 50, 18, 71, 30, 14, 10, 24, 100, 15, 91, 15, 93, 24, 46, 61, 67, 60, 56, 81], 148095)]
for coefs, rhs in eqs: s.add(sum(flag[i]*coefs[i] for i in range(36)) == rhs)
if s.check() == sat: m = s.model() flag_bytes = [m[f].as_long() for f in flag] print("flag:", ''.join(chr(b) for b in flag_bytes))else: print("No solution found.")flag: flag{PytH0n_R3v3rs1Ng_4nd_Z3_s0lV3r}
4.Dancing Function
IDA打开,重点先去看keygen函数

发现是I_Can_Run_Before_Main调用了他,他分为两种情况,如果是调试器直接用

他分为两种情况,如果是调试器直接用sub_7FF60DE816DD函数生成key

如果是静态分析,就将0x1400017DB..0x1400018D2的字节码异或0xcc

我选择静态分析,我们先去dump出这段字节码

然后异或

我们使用Capstone对其进行反汇编
from capstone import Cs, CS_ARCH_X86, CS_MODE_64
path = r"E:\ctf\newstarctf2025\week3\Dancing_Functions\decoded.bin"
with open(path, "rb") as f: code = f.read()
md = Cs(CS_ARCH_X86, CS_MODE_64)md.detail = True
base = 0x1400017DBfor i, ins in enumerate(md.disasm(code, base)): ops = ", ".join(op.__repr__() for op in ins.operands) if hasattr(ins, 'operands') else "" print(f"{ins.address:016X}: {ins.mnemonic} {ins.op_str}")看到他使用的种子是0x114514,每个字符从 81 字符字典 Str 按 rand() % 81 取值

00000001400017DB: push rbp00000001400017DC: mov rbp, rsp00000001400017DF: sub rsp, 0x3000000001400017E3: mov ecx, 0x11451400000001400017E8: call 0x1400033f800000001400017ED: mov dword ptr [rbp - 8], 000000001400017F4: call 0x1400033f000000001400017F9: mov edx, eax00000001400017FB: movsxd rax, edx00000001400017FE: imul rax, rax, 0x1948b0fd0000000140001805: shr rax, 0x200000000140001809: sar eax, 3000000014000180C: mov ecx, edx000000014000180E: sar ecx, 0x1f0000000140001811: sub eax, ecx0000000140001813: mov dword ptr [rbp - 8], eax0000000140001816: mov ecx, dword ptr [rbp - 8]0000000140001819: mov eax, ecx000000014000181B: shl eax, 3000000014000181E: add eax, ecx0000000140001820: lea ecx, [rax*8]0000000140001827: add eax, ecx0000000140001829: sub edx, eax000000014000182B: mov dword ptr [rbp - 8], edx000000014000182E: cmp dword ptr [rbp - 8], 0xb0000000140001832: jle 0x1400017f40000000140001834: cmp dword ptr [rbp - 8], 0x100000000140001838: jle 0x14000183c000000014000183A: jmp 0x1400017f4000000014000183C: nop000000014000183D: mov eax, dword ptr [rbp - 8]0000000140001840: add eax, 10000000140001843: cdqe0000000140001845: mov rcx, rax0000000140001848: call 0x140003548000000014000184D: mov qword ptr [rbp - 0x10], rax0000000140001851: mov dword ptr [rbp - 4], 00000000140001858: jmp 0x1400018b1000000014000185A: call 0x1400033f0000000014000185F: mov ecx, eax0000000140001861: movsxd rax, ecx0000000140001864: imul rax, rax, 0x1948b0fd000000014000186B: shr rax, 0x20000000014000186F: mov edx, eax0000000140001871: sar edx, 30000000140001874: mov eax, ecx0000000140001876: sar eax, 0x1f0000000140001879: sub edx, eax000000014000187B: mov eax, edx000000014000187D: shl eax, 30000000140001880: add eax, edx0000000140001882: lea edx, [rax*8]0000000140001889: add eax, edx000000014000188B: sub ecx, eax000000014000188D: mov edx, ecx000000014000188F: movsxd rax, edx0000000140001892: lea rdx, [rip + 0x3767]0000000140001899: movzx ecx, byte ptr [rax + rdx]000000014000189D: mov eax, dword ptr [rbp - 4]00000001400018A0: cdqe00000001400018A2: mov rdx, qword ptr [rbp - 0x10]00000001400018A6: add rax, rdx00000001400018A9: mov edx, ecx00000001400018AB: mov byte ptr [rax], dl00000001400018AD: add dword ptr [rbp - 4], 100000001400018B1: mov eax, dword ptr [rbp - 4]00000001400018B4: cmp eax, dword ptr [rbp - 8]00000001400018B7: jl 0x14000185a00000001400018B9: mov eax, dword ptr [rbp - 8]00000001400018BC: cdqe00000001400018BE: mov rdx, qword ptr [rbp - 0x10]00000001400018C2: add rax, rdx00000001400018C5: mov byte ptr [rax], 000000001400018C8: mov rax, qword ptr [rbp - 0x10]00000001400018CC: add rsp, 0x3000000001400018D0: pop rbp00000001400018D1: ret加密算法在sub_7FF60DE81C42函数里

之后与str2对比

脚本
STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&*+-.<=>?@_{|}~"STR2 = ".sBtQ=0JEhC#sbw=Q-Y*3h-PGpcvZ9SbU+9F5tH96e>-5hMF"
IDX = {c: i for i, c in enumerate(STR)}
class MSVCRand: def __init__(self): self.seed = 0
def srand(self, seed: int): self.seed = seed & 0xFFFFFFFF
def rand(self) -> int: self.seed = (self.seed * 214013 + 2531011) & 0xFFFFFFFF return (self.seed >> 16) & 0x7FFF
def keygen() -> str: r = MSVCRand() r.srand(0x114514) while True: v2 = r.rand() % 81 if 12 <= v2 <= 16: break out = [] for _ in range(v2): out.append(STR[r.rand() % 81]) return "".join(out)
def to_indices(s: str): try: return [IDX[ch] for ch in s] except KeyError as e: raise ValueError("Input contains char outside dictionary") from e
def ksa(key: str): N = len(STR) S = [80 - i for i in range(N)] j = 0 kl = len(key) for i in range(N): j = (j + S[i] + (ord(key[i % kl]) & 0xFF)) % N S[i], S[j] = S[j], S[i] return S
def prga_t_stream(S, length: int): N = len(STR) u = 0 v = 0 ts = [] for _ in range(length): u = (v ^ u) % N v = (v + S[u]) % N S[u], S[v] = S[v], S[u] t = S[(S[u] ^ S[v]) % N] ts.append(t) return ts
def encrypt(key: str, msg: str) -> str: N = len(STR) S = ksa(key) u = 0 v = 0 out = [] for idx in to_indices(msg): u = (v ^ u) % N v = (v + S[u]) % N S[u], S[v] = S[v], S[u] t = S[(S[u] ^ S[v]) % N] out.append(STR[(idx + t) % N]) return "".join(out)
def decrypt(key: str, cipher: str) -> str: N = len(STR) S = ksa(key) c_idx = to_indices(cipher) ts = prga_t_stream(S, len(c_idx)) out = [] for idx, t in zip(c_idx, ts): out.append(STR[(idx - t) % N]) return "".join(out)
if __name__ == "__main__": key = keygen() plain = decrypt(key, STR2) check = encrypt(key, plain) print("Key:", key) print("Plain:", plain) print("Match:", check == STR2)flag{D4nc1Ng_K3yG3N_fUnct10n5_wItH_r4nD_4Nd_5Mc}
5.changemykey
JADX打开mainactivity,是一个标准的app首页

去FirstFragment看看,它实现了一个flag校验页面,配合 JNI(native 层)做本地校验
![]()

反编译apk文件,ida打开相应架构的so文件,找到Java_work_pangbai_changemykey_FirstFragment_checkFlag校验函数

这个函数只取我们输入的前16字节,然后将MK与xmmword_940异或,然后在extendsecond里对密钥进行扩展,然后是32轮加密,最后与mm数组对比

密钥扩展

32轮加密

脚本
SBOX = [ 0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05, 0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99, 0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62, 0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6, 0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8, 0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35, 0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87, 0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e, 0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1, 0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3, 0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f, 0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51, 0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8, 0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0, 0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84, 0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48,]
FK = [0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]CK = [ 0x00070e15,0x1c232a31,0x383f464d,0x545b6269,0x70777e85,0x8c939aa1,0xa8afb6bd,0xc4cbd2d9, 0xe0e7eef5,0xfc030a11,0x181f262d,0x343b4249,0x50575e65,0x6c737a81,0x888f969d,0xa4abb2b9, 0xc0c7ced5,0xdce3eaf1,0xf8ff060d,0x141b2229,0x30373e45,0x4c535a61,0x686f767d,0x848b9299, 0xa0a7aeb5,0xbcc3cad1,0xd8dfe6ed,0xf4fb0209,0x10171e25,0x2c333a41,0x484f565d,0x646b7279,]
def rotl(x, n): return ((x << n) & 0xffffffff) | (x >> (32 - n))
def tau(x): return ( SBOX[(x >> 24) & 0xff] << 24 | SBOX[(x >> 16) & 0xff] << 16 | SBOX[(x >> 8) & 0xff] << 8 | SBOX[x & 0xff] )
def L(x): return x ^ rotl(x, 2) ^ rotl(x, 10) ^ rotl(x, 18) ^ rotl(x, 24)
def Lp(x): return x ^ rotl(x, 13) ^ rotl(x, 23)
def T(x): return L(tau(x))
def Tp(x): return Lp(tau(x))
def le32(b): return b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)
def to_le_bytes(w): return bytes([w & 0xff, (w >> 8) & 0xff, (w >> 16) & 0xff, (w >> 24) & 0xff])
def key_schedule(key_bytes): assert len(key_bytes) == 16 MK = [le32(key_bytes[0:4]), le32(key_bytes[4:8]), le32(key_bytes[8:12]), le32(key_bytes[12:16])] K = [MK[0] ^ FK[0], MK[1] ^ FK[1], MK[2] ^ FK[2], MK[3] ^ FK[3]] rk = [] for i in range(32): t = K[i] ^ Tp(K[i+1] ^ K[i+2] ^ K[i+3] ^ CK[i]) rk.append(t) K.append(t) return rk
def sm4_encrypt(block, rk): X = [le32(block[0:4]), le32(block[4:8]), le32(block[8:12]), le32(block[12:16])] for i in range(32): X.append(X[i] ^ T(X[i+1] ^ X[i+2] ^ X[i+3] ^ rk[i])) out = to_le_bytes(X[35]) + to_le_bytes(X[34]) + to_le_bytes(X[33]) + to_le_bytes(X[32]) return out
def sm4_decrypt(block, rk): return sm4_encrypt(block, list(reversed(rk)))
def main():
MK_bytes = bytes([ 0x01,0x00,0x00,0x00, 0x01,0x00,0x00,0x00, 0x04,0x00,0x00,0x00, 0x05,0x00,0x00,0x00, ]) mm = bytes([ 0xb3,0xe9,0x0d,0xb6,0x4c,0x7b,0x7a,0x7a,0x89,0x37,0xd0,0xc7,0x6c,0x8e,0x27,0x2a, ])
assert len(SBOX) == 256, f"SBOX length wrong: {len(SBOX)}" rk = key_schedule(MK_bytes) pt = sm4_decrypt(mm, rk)
try: s = pt.decode('utf-8') except UnicodeDecodeError: s = None
print("Plaintext hex:", pt.hex()) if s is not None: print("Plaintext str:", s) else: print("Plaintext bytes:", list(pt))
if __name__ == '__main__': main()flag{1n1t_@rr@y}
6.changemykey-rev
在JADX中,同过FirstFragment函数看到flag的验证逻辑在native层

直接反编译apk,在lib目录里找到自己架构的so文件,IDA打开
字符串查看
![]()
调用函数

密钥生成在getRk,加密过程在encryptSM4,最后进行密文比对与mm数组

先看密钥生成

extendFirst,K[i] = MK[i] ^ FK[i],FK[]为dword_D70


再看extendSecond
- t = K[(i+1)%4] ^ K[(i+2)%4] ^ K[(i+3)%4] ^ CK[i]
- K[(i+4)%4] = K[i%4] ^ L2(SBOX(t))
- RK[i] = K[(i+4)%4]
dword_D80为SM4 标准常量数组

我们在这里对functionT这个函数也做下分析,他会接受两个参数,其中第二个参数,决定函数返回结果,如果a2为1,返回functionL1(v5),其他返回functionL2(v5)

在看下这三个function函数
1.functionB,byte_C70为标准的SM4box

2.functionL1,

3.functionL2,

第四周
1.hookme
JADX打开apk文件

2.尤皮.艾克斯历险记(3)
先用DIE和exeinfo查看一下文件信息


010改一下

脱壳

IDA打开,字符串搜索,定位到sub_1400023D6函数

这两个函数分别处理你输入的key和flag

最后与密文比较

.rdata:0000000140005000 unk_140005000 db 0B4h ; DATA XREF: sub_1400023D6+158↑o.rdata:0000000140005001 db 6Eh ; n.rdata:0000000140005002 db 0Fh.rdata:0000000140005003 db 0E7h.rdata:0000000140005004 db 0EEh.rdata:0000000140005005 db 1Ah.rdata:0000000140005006 db 74h ; t.rdata:0000000140005007 db 0B7h.rdata:0000000140005008 db 6Ch ; l.rdata:0000000140005009 db 0F9h.rdata:000000014000500A db 0B3h.rdata:000000014000500B db 77h ; w.rdata:000000014000500C db 0E4h.rdata:000000014000500D db 82h.rdata:000000014000500E db 7Dh ; }.rdata:000000014000500F db 3Ah ; :.rdata:0000000140005010 db 70h ; p.rdata:0000000140005011 db 9Eh.rdata:0000000140005012 db 0F8h.rdata:0000000140005013 db 0Dh.rdata:0000000140005014 db 0ECh.rdata:0000000140005015 db 3Ch ; <.rdata:0000000140005016 db 0C1h.rdata:0000000140005017 db 70h ; p.rdata:0000000140005018 db 56h ; V.rdata:0000000140005019 db 26h ; &.rdata:000000014000501A db 60h ; `.rdata:000000014000501B db 55h ; U.rdata:000000014000501C db 8Ah.rdata:000000014000501D db 0BCh.rdata:000000014000501E db 0B4h.rdata:000000014000501F db 94h.rdata:0000000140005020 db 0E4h.rdata:0000000140005021 db 0Ch.rdata:0000000140005022 db 31h ; 1.rdata:0000000140005023 db 43h ; C.rdata:0000000140005024 db 76h ; v.rdata:0000000140005025 db 74h ; t.rdata:0000000140005026 db 35h ; 5.rdata:0000000140005027 db 5Fh ; _.rdata:0000000140005028 db 3Ah ; :.rdata:0000000140005029 db 0D5h.rdata:000000014000502A db 24h ; $.rdata:000000014000502B db 0D7h.rdata:000000014000502C db 0B0h.rdata:000000014000502D db 1Bh.rdata:000000014000502E db 0E3h.rdata:000000014000502F db 6Dh ; m.rdata:0000000140005030 db 0Eh.rdata:0000000140005031 db 0Bh.rdata:0000000140005032 db 21h ; !.rdata:0000000140005033 db 0E5h.rdata:0000000140005034 db 7Ah ; z.rdata:0000000140005035 db 0F7h.rdata:0000000140005036 db 9Bh.rdata:0000000140005037 db 0A4h.rdata:0000000140005038 db 0.rdata:0000000140005039 db 1Fh.rdata:000000014000503A db 38h ; 8.rdata:000000014000503B db 0CFh.rdata:000000014000503C db 66h ; f.rdata:000000014000503D db 0D0h.rdata:000000014000503E db 3Eh ; >.rdata:000000014000503F db 36h ; 63.ezrust
main函数,sub_140001DD0是核心校验函数,sub_140004620是包装调用

看下校验过程,这里提示你输入flag


输入通道初始化与错误日志

这里检查我们输入的长度是不是40,不是就会打印Wrong flag! Try again!


sub_140002910把40字节分成16+16+8


expand 32-byte kString_Theocracy,前 16 字节为常量 ,后 16 字节为 key 前半 “String_Theocracy”
xmmword_14001B600为”ycarcoehT_gnirtS”,为key的后半

接下里就是选择计算路径了,取决于off_140025008,为1则调用sub_14001B30生成 ChaCha20 block 输出,否则,在当前函数内用 SSE 实现 10 次双轮

构造前40字节密钥流并异或

最后比较


最终正确输入为 input[0..39] = asc_14001B6F0 XOR keystream[0..39]
import struct
CONST=(0x61707865,0x3320646e,0x79622d32,0x6b206574)KEY1=b"String_Theocracy"; KEY2=b"ycarcoehT_gnirtS"NONCE=b"NewStar 2025"; COUNTER=0TARGET=bytes([0xA3,0x62,0x58,0xDB,0x4B,0x82,0x4F,0xCE,0x48,0xDA,0xBE,0x42,0x1C,0xD8,0x59,0x6B, 0xC7,0xB2,0xCA,0x02,0x0B,0x21,0x6B,0x10,0x4D,0x4E,0x7B,0xEB,0xCE,0x9F,0xFB,0x21, 0xE9,0xCF,0x6B,0xC2,0xC2,0x4C,0xB3,0x4D])
def le32(b,i): return struct.unpack_from("<I",b,i)[0]def r(x,n): return ((x<<n)&0xffffffff)|(x>>(32-n))def qr(s,a,b,c,d): s[a]=(s[a]+s[b])&0xffffffff; s[d]^=s[a]; s[d]=r(s[d],16) s[c]=(s[c]+s[d])&0xffffffff; s[b]^=s[c]; s[b]=r(s[b],12) s[a]=(s[a]+s[b])&0xffffffff; s[d]^=s[a]; s[d]=r(s[d],8) s[c]=(s[c]+s[d])&0xffffffff; s[b]^=s[c]; s[b]=r(s[b],7)
def block(): s=[0]*16; s[:4]=CONST key=KEY1+KEY2 for i in range(8): s[4+i]=le32(key,i*4) s[12]=COUNTER; s[13]=le32(NONCE,0); s[14]=le32(NONCE,4); s[15]=le32(NONCE,8) w=s[:] for _ in range(10): qr(w,0,4,8,12); qr(w,1,5,9,13); qr(w,2,6,10,14); qr(w,3,7,11,15) qr(w,0,5,10,15); qr(w,1,6,11,12); qr(w,2,7,8,13); qr(w,3,4,9,14) for i in range(16): w[i]=(w[i]+s[i])&0xffffffff return b"".join(struct.pack("<I",w[i]) for i in range(16))
def main(): ks=block()[:40] flag=bytes(TARGET[i]^ks[i] for i in range(40)) print(flag.decode())
if __name__=="__main__": main()flag{rUS7_ReveRse_1s_MY_n19h7m4rE_eW2fZ}
4.Dancingkeys
IDA中打开,flag长度为48
sub_4015EB函数将 48 字节按固定字节序打包为 12 个 DWORD
基准密钥在 main 的状态机里初始化为:
- dword_404070 = 0x12345678
- dword_404074 = 0x90ABCDEF
- dword_404078 = 0x11451419
- dword_40407C = 0x19810114

sub_4015EB函数对这 12 个 DWORD ,按两两一组执行一段 0x72 轮的“对变换”

sub_4013F3 函数将变换结果再按固定字节序“展开”成 48 字节

种子的计算在start_routine中

sub_40128A函数
- v3 = Σ (i * byte[i]) (32 位环绕)
- v4 = XOR 所有字节

对比密文
rodata:0000000000402020 ; _BYTE byte_402020[48].rodata:0000000000402020 byte_402020 db 6Eh, 0AAh, 0B2h, 46h, 14h, 0A4h, 7Eh, 60h, 0BAh, 44h.rodata:0000000000402020 ; DATA XREF: main+21E↑o.rodata:000000000040202A db 4Eh, 0CCh, 43h, 2 dup(0AAh), 0CDh, 0D4h, 0FCh, 71h.rodata:0000000000402033 db 0AAh, 0F6h, 7Dh, 4Bh, 9Bh, 0E6h, 7Dh, 0EFh, 4Eh, 3Dh.rodata:000000000040203D db 43h, 0Bh, 0BFh, 28h, 14h, 85h, 0B2h, 0CFh, 62h, 0A2h.rodata:0000000000402047 db 0C5h, 0EAh, 7Dh, 0EBh, 5Eh, 0D6h, 0FCh, 3Ch, 0BFh解密脚本
import os, structBIN_PATH = os.path.join('key')C_FINAL = bytes([ 0x6e,0xaa,0xb2,0x46, 0x14,0xa4,0x7e,0x60, 0xba,0x44,0x4e,0xcc, 0x43,0xaa,0xaa,0xcd, 0xd4,0xfc,0x71,0xaa, 0xf6,0x7d,0x4b,0x9b, 0xe6,0x7d,0xef,0x4e, 0x3d,0x43,0x0b,0xbf, 0x28,0x14,0x85,0xb2, 0xcf,0x62,0xa2,0xc5, 0xea,0x7d,0xeb,0x5e, 0xd6,0xfc,0x3c,0xbf])START_ADDR = 0x401130END_ADDR = 0x4019EDBASE_KEYS = [0x12345678, 0x90ABCDEF, 0x11451419, 0x19810114]MASK32 = 0xFFFFFFFFdef u32(x): return x & MASK32def xorshift32(state): d = state & MASK32 d ^= (d << 11) & MASK32 d ^= (d >> 4) & MASK32 d ^= (d << 5) & MASK32 d ^= (d >> 14) & MASK32 return d & MASK32def compute_seed_from_elf(path, start_addr, end_addr): with open(path, 'rb') as f: e_ident = f.read(16) if len(e_ident) < 16 or e_ident[0:4] != b'\x7fELF': raise RuntimeError('Not ELF') is_64 = (e_ident[4] == 2) is_le = (e_ident[5] == 1) if not is_64 or not is_le: raise RuntimeError('Expect ELF64 LE') hdr = f.read(48) e_type, e_machine, e_version, e_entry, e_phoff, e_shoff, e_flags, e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx = struct.unpack('<HHIQQQIHHHHHH', hdr) f.seek(e_phoff) phdrs = [] for _ in range(e_phnum): p = f.read(e_phentsize) p_type, p_flags, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_align = struct.unpack('<IIQQQQQQ', p) phdrs.append((p_type, p_offset, p_vaddr, p_memsz)) start_off = None length = end_addr - start_addr for p_type, p_offset, p_vaddr, p_memsz in phdrs: if p_type == 1 and start_addr >= p_vaddr and end_addr <= (p_vaddr + p_memsz): start_off = p_offset + (start_addr - p_vaddr) break if start_off is None: raise RuntimeError('Map VA range failed') f.seek(start_off) data = f.read(length) v3 = 0 v4 = 0 for i, b in enumerate(data): v3 = u32(v3 + u32(i * b)) v4 = u32(v4 ^ b) return u32(u32(v3) * u32(v4))def dwords_to_input_bytes(D): out = bytearray(48) for i in range(12): d = D[i] & MASK32 out[4*i+0] = (d >> 8) & 0xFF out[4*i+1] = (d >> 24) & 0xFF out[4*i+2] = (d >> 16) & 0xFF out[4*i+3] = d & 0xFF return bytes(out)def cbytes_to_dwords(C): T = [] for i in range(12): c0 = C[4*i+0] c1 = C[4*i+1] c2 = C[4*i+2] c3 = C[4*i+3] T.append((c2) | (c3<<8) | (c0<<16) | (c1<<24)) return Tdef F(v4, v5, i, K0, K2): return u32(u32(v4 - v5) ^ K2 ^ u32(v4 << ((i+1)%5)) ^ (v4 >> ((i+4)&7)) ^ K0)def G(v3, v5, i, K1, K3): return u32(u32(v3 - v5) ^ K1 ^ u32(v3 << ((i+2)%6)) ^ (v3 >> ((i+3)%7)) ^ K3)def invert_pair(v3_final, v4_final, keys, v7): K0, K1, K2, K3 = keys v5_list = [] v5 = 0xDEADBEEF for i in range(0x72): v5 = u32(v5 + u32(v7 * i)) v5_list.append(v5) v3 = v3_final & MASK32 v4 = v4_final & MASK32 for i in reversed(range(0x72)): v5_i = v5_list[i] v4 = u32(v4 - G(v3, v5_i, i, K1, K3)) v3 = u32(v3 - F(v4, v5_i, i, K0, K2)) return v3, v4def main(): bin_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), BIN_PATH) try: seed0 = compute_seed_from_elf(bin_path, START_ADDR, END_ADDR) except Exception: seed0 = 0xCCED8DC0 s = seed0 r = [] for _ in range(4): s = xorshift32(s) r.append(s) mutated_keys = [u32(BASE_KEYS[i] ^ r[i]) for i in range(4)] state = s T = cbytes_to_dwords(C_FINAL) orig = [0]*12 for k in range(6): v7 = xorshift32(state) state = v7 orig[2*k], orig[2*k+1] = invert_pair(T[2*k], T[2*k+1], mutated_keys, v7) flag_bytes = dwords_to_input_bytes(orig) try: print(flag_bytes.decode('utf-8')) except Exception: print(flag_bytes.hex())if __name__ == '__main__': main()flag{1_h4t3_h4sH_ch3cK1ng_4Nd_r4Nd0m_t3AenCRypt}
5.NOT_TUI
sub_1400015C6函数窗口过程函数,flag总长度必须为 38

把内部 32 字节逐字节用表 byte_140005000 做 S-Box 替换(正向 AES S‑Box)


把替换后的 32 字节按小端视为 8 个 DWORD ,进行链式两两加密:对 (dword[j], dword[j+1]) 依次调用 sub_140001450

sub_140001450 函数
- 偶轮用 aStringTheocrac
- 奇轮用 aPaperBouquetMi

最后比较
data:0000000140004040 ; _DWORD dword_140004040[8].data:0000000140004040 dword_140004040 dd 5AF4429Ch, 0BAA6B51Bh, 5CDECA1Fh, 0AF439534h, 8B07D489h.data:0000000140004040 ; DATA XREF: sub_1400015C6+3B6↑o.data:0000000140004054 dd 0CC2048AFh, 957F02B6h, 9C4988FDh解密脚本
MASK = 0xFFFFFFFF
AES_SBOX = [ 0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76, 0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0, 0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15, 0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75, 0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84, 0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF, 0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8, 0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2, 0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73, 0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB, 0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79, 0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08, 0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A, 0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E, 0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF, 0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,]
INV_SBOX = [0]*256for x, s in enumerate(AES_SBOX): INV_SBOX[s] = xINV_SBOX = bytes(INV_SBOX)
def to_le_dwords(b32): return [int.from_bytes(b32[i*4:(i+1)*4], 'little') for i in range(8)]
def from_le_dwords(dw8): return b''.join(d.to_bytes(4, 'little') for d in dw8)
def key_to_dwords(key16): return [int.from_bytes(key16[i*4:(i+1)*4], 'little') for i in range(4)]
K_even = key_to_dwords(b"String_Theocracy")K_odd = key_to_dwords(b"Paper_Bouquet_Mili"[:16])
def decrypt_pair(v5, v4): for i in range(0x71, -1, -1): sumv = (i + 1) * 1131796 K = K_odd if (i & 1) else K_even t = ((v5 + sumv) & MASK) ^ ((K[2] + ((v5 << 4) & MASK)) & MASK) ^ (((v5 >> 5) + K[3]) & MASK) v4 = (v4 - t) & MASK t = ((v4 + sumv) & MASK) ^ ((K[0] + ((v4 << 4) & MASK)) & MASK) ^ (((v4 >> 5) + K[1]) & MASK) v5 = (v5 - t) & MASK return v5, v4
C_BYTES = bytes.fromhex("9c42f45a1bb5a6ba1fcade5c349543af89d4078baf4820ccb6027f95fd88499c")
C = to_le_dwords(C_BYTES)B = C[:]for j in range(6, -1, -1): B[j], B[j+1] = decrypt_pair(B[j], B[j+1])
plain = bytes(INV_SBOX[b] for b in from_le_dwords(B))print("flag{" + plain.decode("ascii") + "}")flag{bbbd719a361123014e77006476205f73}
第五周
1.天才的认证
main函数

打开sub_140003E80函数

这个程序是一个PyInstaller打包的程序

把chall.pyc编译为py文件,这里使用Pylingual
- 先把输入按字节放到内存
mem[16+i],要求长度为 31。 - 对每个索引
i的输入字节x,计算:
t = (x + i) ^ 75C[i] = rol8(t, 3) # 8-bit 循环左移 3 位最终把 C 存为程序里的常量表,用来比对。
# Decompiled with PyLingual (https://pylingual.io)# Bytecode version: 3.8.0rc1+ (3413)# Source timestamp: 1970-01-01 00:00:00 UTC (0)
class TinyVM:
def __init__(self, bytecode, user_input): self.bytecode = bytecode self.user_input = user_input self.mem = [0] * 100 self.ip = 0 self.stack = [] self.f = False self.halted = False for i, char_code in enumerate(self.user_input): self.mem[16 + i] = char_code
def push(self, value): self.stack.append(value & 255)
def pop(self): return self.stack.pop() if self.stack else 0
def run(self): while not self.halted and self.ip < len(self.bytecode): opcode = self.bytecode[self.ip] self.ip += 1 if opcode == 1: self.push(self.bytecode[self.ip]) self.ip += 1 elif opcode == 2: self.push(self.mem[self.bytecode[self.ip]]) self.ip += 1 elif opcode == 3: self.mem[self.bytecode[self.ip]] = self.pop() self.ip += 1 elif opcode == 4: self.push(self.pop() + self.pop()) elif opcode == 5: self.push(self.pop() ^ self.pop()) elif opcode == 6: n, v = (self.pop(), self.pop()) self.push(v << n) elif opcode == 7: n, v = (self.pop(), self.pop()) self.push(v >> n) elif opcode == 8: self.push(self.pop() | self.pop()) elif opcode == 9: self.f = self.pop() == self.pop() elif opcode in [10, 11, 12]: offset = self.bytecode[self.ip] self.ip += 1 should_jump = opcode == 12 or (opcode == 10 and (not self.f)) or (opcode == 11 and self.f) if should_jump: if offset > 127: offset -= 256 self.ip += offset elif opcode == 13: self.push(len(self.user_input)) elif opcode == 14: addr = self.pop() self.push(self.mem[addr]) elif opcode == 15: addr = self.pop() val = self.pop() self.mem[addr] = val elif opcode == 255: self.halted = True else: self.halted = True return bool(self.pop())
def check_flag(s): BYTECODE = b'\x01i\x032\x011\x033\x01A\x034\x01\t\x035\x01\xa1\x036\x01`\x037\x01\xa1\x038\x01\x81\x039\x011\x03:\x019\x03;\x01\x8b\x03<\x01!\x03=\x01\xd1\x03>\x019\x03?\x01 \x03@\x01\xb1\x03A\x01\xf9\x03B\x01\xd9\x03C\x01q\x03D\x01f\x03E\x01\x18\x03F\x01\x99\x03G\x01V\x03H\x01\xe9\x03I\x01q\x03J\x010\x03K\x01V\x03L\x018\x03M\x01\xa1\x03N\x01\xab\x03O\x01\x86\x03P\r\x01\x1f\t\n=\x01K\x03\x02\x01\x00\x03\x00\x02\x00\x01\x1f\t\x0b+\x01\x10\x02\x00\x04\x0e\x02\x00\x04\x02\x02\x05\x03\x01\x02\x01\x01\x03\x06\x02\x01\x01\x05\x07\x08\x012\x02\x00\x04\x0e\t\n\x0c\x02\x00\x01\x01\x04\x03\x00\x0c\xce\x01\x01\xff\x01\x00\xff' vm = TinyVM(BYTECODE, s.encode('utf-8')) return vm.run()
def main(): print('「欢迎,开拓者。这里是一个被星核污染的赛博空间。」') print('「检测到未知访问者...」机械女声响起,像是黑塔空间站的自动防御系统') print('「哼,又一个被星核吸引来的家伙。想通过验证?先证明你不是个笨蛋吧。」——某位不愿透露姓名的天才俱乐部成员留言') try: user_flag = input('请输入正确的星核密语:') if check_flag(user_flag): print('\n「...有意思的访客。」空间站的灯光突然变成柔和的蓝色') print('「访问权限已授予。」黑塔的全息影像优雅地行了一礼') print(f'「这是你要的星核密钥:{user_flag}。不过要小心,它比你想象的要危险得多...」') print('「警告:检测到异常数据流...系统正在隔离污染区域...」') print('✅ 验证通过!螺丝咕姆的虚拟助手从控制台浮现:「建议您立即备份数据」✅') else: print('\n❌ 错误!空间站的防御炮台突然转向你 ❌') print('「哈!果然是个笨蛋~」——来自某位正通过监控看戏的少女声音') print("「建议:下次试试输入'黑塔女士天下第一'?」——系统自动生成的恶意提示") except Exception as e: print(f'\n[!] 星核能量不稳定!虚拟空间发生异常: {e}') print('「这种情况...难道是记忆星神的力量?」')if __name__ == '__main__': main()脚本
def ror(v, n): return ((v >> n) | ((v << (8-n)) & 0xff)) & 0xff
consts = [105,49,65,9,161,96,161,129,49,57,139,33,209,57,32,217,113,102,24,153,86,233,113,48,86,56,161,171,134]
res_bytes = []for i, c in enumerate(consts): t = ror(c, 3) x = ((t ^ 75) - i) & 0xff res_bytes.append(x)
flag = bytes(res_bytes).decode('utf-8')print(flag)flag{Bytec0de_And_St4ck_M4g1c!}
2.AnEasySystem
先将hap文件解压缩

ets是源码文件,libs是依赖库,module.json是描述文件入口,整体跟apk文件差不多
打开ets文件夹,找到这个modules.abc,然后用abc-decompiler 打开这个abc文件,主要逻辑在p001entry/src/main/ets/pages/Index,



但最终的加密算法还是由modifiedAESEncrypt补充出来

用IDA打开libentry.so

import hashlib
# Standard AES S-box and inverse S-boxs_box = [ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]
inv_s_box = [ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D]
# Rcon for key expansionrcon = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36]
def sub_word(word): return [s_box[b] for b in word]
def rot_word(word): return word[1:] + word[:1]
def key_expansion(key): key_bytes = list(key) w = [0] * 44 * 4 for i in range(16): w[i] = key_bytes[i]
for i in range(4, 44): temp = w[(i - 1) * 4: i * 4] if i % 4 == 0: temp = sub_word(rot_word(temp)) temp[0] ^= rcon[i // 4] w[i * 4: (i + 1) * 4] = [w[(i - 4) * 4 + j] ^ temp[j] for j in range(4)]
round_keys = [] for i in range(11): round_keys.append(bytes(w[i * 16: i * 16 + 16])) return round_keys
def inv_shift_rows(state): state_list = list(state) s = [0] * 16
# 基于正向变换推导逆变换 s[0] = state_list[0] ^ 0xB7 s[4] = (state_list[4] - 70) & 0xFF s[8] = state_list[8] ^ 0xD4 s[12] = (state_list[12] + 41) & 0xFF s[5] = (state_list[1] - 29) & 0xFF s[9] = state_list[5] ^ 0x37 s[13] = (state_list[9] + 113) & 0xFF s[1] = (state_list[13] + 7) & 0xFF s[10] = (state_list[2] - 91) & 0xFF s[14] = state_list[6] ^ 0xC3 s[2] = state_list[10] ^ 0x0D s[6] = (state_list[14] + 107) & 0xFF s[15] = (state_list[3] - 78) & 0xFF s[3] = state_list[7] ^ 0x43 s[7] = (state_list[11] - 36) & 0xFF s[11] = (state_list[15] - 125) & 0xFF
return bytes(s)
def inv_sub_bytes(state): return bytes([inv_s_box[b] for b in state])
def gf_multiply(a, b): """GF(2^8) multiplication with irreducible polynomial x^8 + x^4 + x^3 + x + 1 (0x11B)""" p = 0 for _ in range(8): if b & 1: p ^= a carry = a & 0x80 a = (a << 1) & 0xFF if carry: a ^= 0x1B b >>= 1 return p
def inv_mix_columns(state): state_arr = list(state) new_state = [0] * 16 for i in range(4): col = state_arr[i * 4: i * 4 + 4] a0, a1, a2, a3 = col new_state[i * 4] = gf_multiply(0x0e, a0) ^ gf_multiply(0x0b, a1) ^ gf_multiply(0x0d, a2) ^ gf_multiply(0x09, a3) new_state[i * 4 + 1] = gf_multiply(0x09, a0) ^ gf_multiply(0x0e, a1) ^ gf_multiply(0x0b, a2) ^ gf_multiply(0x0d, a3) new_state[i * 4 + 2] = gf_multiply(0x0d, a0) ^ gf_multiply(0x09, a1) ^ gf_multiply(0x0e, a2) ^ gf_multiply(0x0b, a3) new_state[i * 4 + 3] = gf_multiply(0x0b, a0) ^ gf_multiply(0x0d, a1) ^ gf_multiply(0x09, a2) ^ gf_multiply(0x0e, a3) return bytes(new_state)
def aes_decrypt_block(ciphertext, round_keys): state = ciphertext
# 初始轮密钥加 state = bytes([state[i] ^ round_keys[10][i] for i in range(16)])
# 9轮完整解密 for round in range(9, 0, -1): state = inv_shift_rows(state) state = inv_sub_bytes(state) state = bytes([state[i] ^ round_keys[round][i] for i in range(16)]) state = inv_mix_columns(state)
# 最后一轮(无MixColumns) state = inv_shift_rows(state) state = inv_sub_bytes(state) state = bytes([state[i] ^ round_keys[0][i] for i in range(16)])
return state
def decrypt_cbc(ciphertext, key, iv): round_keys = key_expansion(key) blocks = [ciphertext[i:i + 16] for i in range(0, len(ciphertext), 16)] plaintext = b'' prev = iv for block in blocks: decrypted = aes_decrypt_block(block, round_keys) plaintext += bytes([decrypted[i] ^ prev[i] for i in range(16)]) prev = block return plaintext
def pkcs7_unpad(data): """PKCS7去填充""" if len(data) == 0: return data padding_len = data[-1] if padding_len > len(data): return data # 检查填充是否有效 for i in range(1, padding_len + 1): if data[-i] != padding_len: return data return data[:-padding_len]
def main(): target_cipher = bytes.fromhex( "b250062307bbe0216de2fe549c9a768ff67e1063c1e1dfb38265ded7610603514c3e3951c392f403cce40b5be0adf5c03cd1a8d035892c1b1b5f3579127a45e843d99b87b45d292fff75cb2332f1b59c")
print("Starting brute force attack...")
found = False for key_num in range(1000000): key_str = str(key_num).zfill(6) key_bytes = key_str.encode() hash_obj = hashlib.sha256(key_bytes) hash_bytes = hash_obj.digest() aes_key = hash_bytes[:16] iv = hash_bytes[16:32]
try: plaintext = decrypt_cbc(target_cipher, aes_key, iv) plaintext = pkcs7_unpad(plaintext)
# 更宽松的检查条件 if len(plaintext) > 0: # 检查是否为可打印ASCII if all(32 <= b < 127 for b in plaintext): text = plaintext.decode('ascii', errors='ignore') if 'flag' in text.lower() or 'FLAG' in text: print(f"Found potential key: {key_str}") print(f"Plaintext: {plaintext}") print(f"Decrypted: {text}") found = True break
# 也检查常见的CTF flag格式 if text.startswith('flag{') or text.startswith('FLAG{') or text.startswith('ctf{'): print(f"Found key: {key_str}") print(f"Plaintext: {plaintext}") print(f"Decrypted: {text}") found = True break
except Exception as e: pass
if key_num % 10000 == 0: print(f"Tried {key_num} keys")
if not found: print("Key not found in range 000000-999999") print("The issue might be in the decryption implementation.") print("Please verify the ShiftRows and MixColumns implementations.")
if __name__ == '__main__': main()
flag{r3v3Rs1Ng_7h3_H4rm0nY_05_1s_n07_4S_d1Ff1cUl7_45_y0U_7h1nK!}
3.河图洛书
一个用pyinstxtractor打包的程序,用的是py3.12

使用PyLingual来使pyc文件转为py文件
# Decompiled with PyLingual (https://pylingual.io)# Bytecode version: 3.12.0rc2 (3531)# Source timestamp: 1970-01-01 00:00:00 UTC (0)
global input_buffer # insertedglobal stop_animation # insertedimport sysimport osimport timeimport randomimport threadingimport msvcrtfrom colorama import init, Fore, Styleinit()magic_square = [[4, 9, 2], [3, 5, 7], [8, 1, 6]]input_buffer = ''stop_animation = FalseCOLOR_MAP = {1: Fore.RED + Style.BRIGHT, 2: Fore.GREEN + Style.BRIGHT, 3: Fore.BLUE + Style.BRIGHT, 4: Fore.YELLOW, 5: Fore.WHITE + Style.BRIGHT, 6: Fore.CYAN, 7: Fore.MAGENTA, 8: Fore.RED, 9: Fore.GREEN}
def clear_lines(n): for _ in range(n): sys.stdout.write('[1A') sys.stdout.write('[2K') sys.stdout.flush()
def goto_line(line): sys.stdout.write(f'[{line + 1};1H')
def clear_line(): sys.stdout.write('[2K') return
def print_magic_square(): clear_lines(10) goto_line(0) top = ' ┌───┬───┬───┐' middle = ' ├───┼───┼───┤' bottom = ' └───┴───┴───┘' sys.stdout.write(top + '\n') for i in range(3): line = ' │' for j in range(3): num = magic_square[i][j] color = COLOR_MAP.get(num, Fore.WHITE) line += f' {color}{num}{Style.RESET_ALL} │' sys.stdout.write(line + '\n') if i < 2: sys.stdout.write(middle + '\n') sys.stdout.write(bottom + '\n') sys.stdout.write('\n') sys.stdout.flush()
def shift_row_left(row): magic_square[row] = magic_square[row][1:] + [magic_square[row][0]]
def shift_row_right(row): magic_square[row] = [magic_square[row][(-1)]] + magic_square[row][:(-1)]
def shift_col_up(col): t = magic_square[0][col] magic_square[0][col] = magic_square[1][col] magic_square[1][col] = magic_square[2][col] magic_square[2][col] = t
def shift_col_down(col): t = magic_square[2][col] magic_square[2][col] = magic_square[1][col] magic_square[1][col] = magic_square[0][col] magic_square[0][col] = t
def random_transform(): op = random.randint(0, 3) idx = random.randint(0, 2) if op == 0: shift_row_left(idx) else: # inserted if op == 1: shift_row_right(idx) else: # inserted if op == 2: shift_col_up(idx) else: # inserted shift_col_down(idx)
def animation_loop(): while not stop_animation: time.sleep(0.5) if not stop_animation: random_transform() print_magic_square() goto_line(10) clear_line() sys.stdout.write(f'Input your flag: {input_buffer}') sys.stdout.flush()if __name__ == '__main__': os.system('cls') for _ in range(12): print() goto_line(0) print_magic_square() goto_line(10) sys.stdout.write('Input your flag: ') sys.stdout.flush() target_hex = '490e0ad0374f2cdd126e5b184bf4e6da669a4cbea88fac916494edd90149809a7c92eec2e82ed3fca5812d9f69' anim_thread = threading.Thread(target=animation_loop, daemon=True) anim_thread.start() try: while True: if msvcrt.kbhit(): ch = msvcrt.getch() if ch in {b'\n', b'\r'}: if len(input_buffer)!= 45: goto_line(11) sys.stdout.write(Fore.RED + 'Length wrong!' + Style.RESET_ALL + ' ') sys.stdout.flush() time.sleep(1.5) goto_line(11) clear_line() goto_line(10) clear_line() sys.stdout.write(f'Input your flag: {input_buffer}') sys.stdout.flush() finally: # inserted try: import luo_shu msg = input_buffer.encode() key = b'LESCBCKEY' iv = b'LESCBC_iv' cipher = luo_shu.encrypt(msg, 1, key, iv) result_hex = cipher.hex() except Exception as e: else: # inserted goto_line(11) if result_hex == target_hex: sys.stdout.write(Fore.GREEN + 'Right flag! Congratulations!' + Style.RESET_ALL + ' ') else: # inserted sys.stdout.write(Fore.RED + 'Wrong flag! Try again.' + Style.RESET_ALL + ' ') sys.stdout.flush() time.sleep(2) else: # inserted if ch == b'\x08': if input_buffer: input_buffer = input_buffer[:(-1)] goto_line(10) clear_line() sys.stdout.write(f'Input your flag: {input_buffer}') sys.stdout.flush() else: # inserted if len(input_buffer) < 45: char = ch.decode('ascii', errors='ignore') if char and 32 <= ord(char) <= 126: input_buffer += char sys.stdout.write(char) sys.stdout.flush() time.sleep(0.01) finally: # inserted stop_animation = True anim_thread.join(timeout=0.1) print('\n') result_hex = ''这里只有密文,密钥和IV,加密算法的具体实现没有,但看到导入了这个库

我们用IDA打开这个pyd文件,字符串中看到
![]()
点进去,被调用在sub_180006008函数中
加密在sub_180001510函数中的这两个函数


sub_1800050E0函数 把轮密钥/状态表造出来了

sub_1800052A0函数 真正的轮函数

然后sub_180004E20和sub_180004F80函数
E20:对 9 个字节逐个 左循环位移(ROL8),位数来自ptr[i] & 7F80:对 9 个字节逐个 右循环位移(ROR8),位数也来自ptr[i] & 7
重要的数据: byte_1800084A0[256] 和 byte_180008488[9]

脚本,放在与luo_shu.pyd同目录下运行
from typing import List
C9 = [4, 9, 2, 3, 5, 7, 8, 1, 6]
SBOX = [0x38,0xD6,0x18,0x0E,0xC6,0xA4,0x47,0x4A,0x97,0xA1,0xA2,0x79,0xE3,0xF9,0x61,0x0B,0xC3,0xFA,0x08,0x32,0x5F,0x73,0x4F,0x6C,0xBE,0x68,0x7B,0xB3,0x4C,0x1B,0x8D,0x3C,0x63,0xF5,0xE8,0xD8,0xCB,0xCF,0xBC,0xC1,0x9A,0x3F,0x6F,0x9F,0x70,0xCA,0x60,0x49,0x30,0xE6,0x86,0x90,0xC8,0x1F,0xE5,0x6E,0x8E,0x00,0x2E,0x36,0xEA,0x91,0x5D,0x92,0x2D,0x6B,0xEF,0xC9,0xDF,0xAC,0xF7,0x20,0x9B,0x99,0x58,0xB8,0x74,0x16,0x42,0xF3,0xB5,0x89,0x2C,0xDA,0x12,0x87,0xE1,0xAD,0xFF,0x19,0x9E,0x80,0x27,0xB6,0x8F,0x53,0x65,0xDE,0x24,0x2A,0x78,0x82,0x95,0x09,0x34,0x48,0xD2,0x33,0xE2,0x3D,0x55,0xBB,0x0D,0x6A,0x8A,0x6D,0xAB,0x02,0x59,0x01,0x2B,0x56,0xDC,0x14,0x72,0xB0,0x15,0x37,0xCE,0x8B,0xB4,0x39,0xAF,0x83,0x10,0x88,0x26,0xF2,0x40,0x84,0x98,0xC2,0x5B,0xDB,0x46,0x51,0x7E,0xA0,0xA3,0xD4,0x85,0x43,0xDD,0xE0,0x3A,0x17,0xD9,0xAA,0x23,0x4D,0xFE,0x21,0x44,0xC5,0x1A,0x31,0x9D,0x2F,0xA5,0xA7,0x71,0x54,0x5C,0x5E,0xC4,0x41,0xB7,0xB1,0xF0,0xC0,0x05,0x1C,0x66,0x7F,0x29,0x77,0xCC,0x57,0xFD,0x4E,0x13,0x28,0x5A,0xF4,0xD1,0x50,0x96,0xD7,0x52,0xD3,0xBD,0xEE,0x9C,0x7A,0xF8,0xEB,0x93,0x3B,0xD0,0x69,0x81,0x03,0x22,0x45,0xE4,0x0A,0x7C,0xA9,0xF6,0x62,0xA8,0x3E,0xBF,0x7D,0x67,0xEC,0x0C,0x1D,0xE7,0x4B,0xCD,0xED,0x94,0xA6,0x8C,0x04,0x75,0xFC,0x1E,0xFB,0xB2,0x07,0x0F,0xD5,0xB9,0x76,0x11,0x25,0x35,0xBA,0xF1,0xC7,0x64,0xAE,0x06,0xE9]INV_SBOX = [0]*256for i,v in enumerate(SBOX): INV_SBOX[v] = i
def rol8(x, r): r &= 7; x &= 0xFF; return ((x << r) | (x >> (8 - r))) & 0xFFdef ror8(x, r): r &= 7; x &= 0xFF; return ((x >> r) | (x << (8 - r))) & 0xFF
def E20(v9: List[int], ptr: List[int]): for i in range(9): v9[i] = rol8(v9[i], ptr[i] & 7)def E20_inv(v9: List[int], ptr: List[int]): for i in range(9): v9[i] = ror8(v9[i], ptr[i] & 7)def F80(v9: List[int], ptr: List[int]): for i in range(9): v9[i] = ror8(v9[i], ptr[i] & 7)def F80_inv(v9: List[int], ptr: List[int]): for i in range(9): v9[i] = rol8(v9[i], ptr[i] & 7)
CONST9 = [4,9,2,3,5,7,8,1,6]
def xor_mix_inverse(v, Sbytes, Sm2, Sm1): t0,t1,t2,t3,t4,t5,t6,t7,t8 = v v3 = Sm2 ^ t0; v8 = Sm1 ^ t1 v1 = Sbytes[0] ^ t2; v2 = Sbytes[1] ^ t3 v4 = t4 ^ Sbytes[2]; v6 = Sbytes[3] ^ t5; v7 = Sbytes[4] ^ t6 v0 = Sbytes[5] ^ t7; v5 = Sbytes[6] ^ t8 return [v0,v1,v2,v3,v4,v5,v6,v7,v8]
def key_schedule(key9: bytes, iv9: bytes, mode: int) -> bytes: st = bytearray(432) if key9 and key9[0] != 0: st[0:9] = key9[:9] if iv9 and iv9[0] != 0: st[9:18] = iv9[:9] st[18:27] = st[0:9] st[424:428] = mode.to_bytes(4, 'little') idx = 27 for v in range(9, 405, 6): for t in range(6): k = (v + t) % 9 st[idx] = (45 * ((st[idx-9] + C9[k]) & 0xFF)) & 0xFF idx += 1 return bytes(st)
def decrypt_block(block: bytes, st: bytes) -> bytes: v = list(block) for rnd in range(44, -1, -1): v = [INV_SBOX[x] for x in v] if rnd % 2 == 0: E20_inv(v, C9) else: F80_inv(v, C9) base = 20 + 9*rnd Sbytes = st[base : base+7] Sm2 = st[base-2]; Sm1 = st[base-1] v = xor_mix_inverse(v, Sbytes, Sm2, Sm1) ptr = [st[base-2 + i] for i in range(9)] if rnd % 2 == 0: F80_inv(v, ptr) else: E20_inv(v, ptr) for i in range(9): v[i] ^= CONST9[i] return bytes(v)
def decrypt(cipher: bytes, key: bytes, iv: bytes, mode: int = 1) -> bytes: assert len(cipher) % 9 == 0 st = key_schedule(key[:9], iv[:9], mode) nblocks = len(cipher) // 9 blocks = [cipher[i*9:(i+1)*9] for i in range(nblocks)] plain_blocks = [] for j in range(nblocks): X = decrypt_block(blocks[j], st) if mode == 1: if j == 0: X = bytes((X[i] ^ st[9+i]) & 0xFF for i in range(9)) else: X = bytes((X[i] ^ blocks[j-1][i]) & 0xFF for i in range(9)) plain_blocks.append(X) P = b"".join(plain_blocks) if P: pad = P[-1] if 1 <= pad <= 9 and P.endswith(bytes([pad])*pad): P = P[:-pad] return P
if __name__ == "__main__": target_hex = "490e0ad0374f2cdd126e5b184bf4e6da669a4cbea88fac916494edd90149809a7c92eec2e82ed3fca5812d9f69" C = bytes.fromhex(target_hex) KEY = b"LESCBCKEY" IV = b"LESCBC_iv" P = decrypt(C, KEY, IV, mode=1) print("Plain (raw):", P) try: print("Plain (utf-8):", P.decode("utf-8")) except Exception: print("Plain (hex):", P.hex())flag{7H3_Lu0_5hu_3nCrYP710n_1s_b10Ck_C1ph3R!}
4.魔法少女的秘密
5.Jvav Master
在运行该程序是提取出内置的jar包
准备环境,设置工作目录变量,后续命令都基于这个路径
"$Workspace = 'e:\ctf\newstarctf2025\week5\Jvav_Master'"拼出本地临时目录路径
"$tmp = Join-Path $Workspace 'tmp'"创建(或覆盖)临时目录,确保可写入
"New-Item -ItemType Directory -Force -Path $tmp | Out-Null"让 exe4j 和install4j将运行时临时文件写到你指定目录
"$env:EXE4J_TEMPDIR = $tmp""$env:INSTALL4J_TEMPDIR = $tmp"启用
"$env:EXE4J_LOG = Join-Path $tmp 'exe4j.log'""$env:INSTALL4J_LOG = Join-Path $tmp 'install4j.log'"启动程序以触发将内置资源解压到临时目录
"$p = Start-Process -FilePath (Join-Path $Workspace 'Jvav_master.exe') -PassThru"等待几秒让解压完成
"Start-Sleep -Seconds 3"停止主进程,避免继续运行占用资源
"if ($p -and !$p.HasExited) { Stop-Process -Id $p.Id -Force }"在目录下看到

把jvav.jar包改为zip打开
main.class
// Source code is decompiled from a .class file using FernFlower decompiler (from Intellij IDEA).import java.util.Scanner;
public class Main { public Main() { }
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("please input your key: "); String keyStr = scanner.nextLine(); byte[] key = keyStr.getBytes(); if (!KeyChecker.checkKey(key)) { System.out.println("wrong key!"); } else { System.out.print("please input your flag: "); String plainText = scanner.nextLine(); byte[] encrypted = RC4.encrypt(plainText.getBytes(), key); if (encrypted.length != 48) { System.out.println("wrong flag!"); } else { if (FlagChecker.Checker(encrypted)) { System.out.println("right flag!"); } else { System.out.println("wrong flag!"); }
} } }}rc4.class
// Source code is decompiled from a .class file using FernFlower decompiler (from Intellij IDEA).public class RC4 { public RC4() { }
public static byte[] encrypt(byte[] plaintext, byte[] key) { int[] box = new int[256];
int x; for(x = 0; x < 256; ++x) { box[x] = 255 - x ^ 131; }
x = 0;
int y; for(y = 0; y < 256; ++y) { x = (x + box[y] + key[(y + 72) % key.length]) % 256; int temp = box[y]; box[y] = box[x]; box[x] = temp; }
x = 0; y = 0; byte[] output = new byte[plaintext.length];
for(int i = 0; i < plaintext.length; ++i) { x = (x + 3) % 256; y = y - box[x] & 255; int temp = box[x]; box[x] = box[y]; box[y] = temp; int index = (box[x] ^ box[y]) % 256; output[i] = (byte)(plaintext[i] + box[index] ^ 119); }
return output; }}keychecker.class
// Source code is decompiled from a .class file using FernFlower decompiler (from Intellij IDEA).public class KeyChecker { private static final byte[] MASK = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(); private static final int[] TARGET = new int[]{107655, 99322, 95708, 87877, 85730, 80988, 72416, 76077, 74252, 70300, 68724, 68020, 63439, 53540, 51340, 42431, 37382, 28611, 25737, 18364, 9711, 9030};
public KeyChecker() { }
public static boolean checkKey(byte[] key) { if (key != null && key.length == 22) { for(int i = 0; i < 22; ++i) { long sum = 0L; int mask_i = MASK[i] & 255;
for(int j = i; j < 22; ++j) { int mask_j = MASK[j] & 255; int key_j = key[j] & 255; int xor = (key_j ^ mask_i) & 255; sum += (long)xor * (long)mask_j; }
if (sum != (long)TARGET[i]) { return false; } }
return true; } else { return false; } }
public static void main(String[] args) { byte[] testKey = new byte[22]; System.out.println("Check result: " + checkKey(testKey)); }}flagchecker.class
// Source code is decompiled from a .class file using FernFlower decompiler (from Intellij IDEA).public class FlagChecker { public FlagChecker() { }
public static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); byte[] var2 = bytes; int var3 = bytes.length;
for(int var4 = 0; var4 < var3; ++var4) { byte b = var2[var4]; sb.append(String.format("%02x", b & 255)); }
return sb.toString(); }
public static int random(int seed) { int x = seed ^ seed << 19 & -119793247; x ^= x >>> 1 | 469912079; x ^= x << 9 ^ 663526098; x ^= x >>> 8 & -886859118; x ^= x << 10 | 846897082; return x ^ 592136849; }
public static byte rol(byte b, int shift) { shift &= 7; int unsigned = b & 255; return (byte)((unsigned << shift | unsigned >> 8 - shift) & 255); }
public static byte ror(byte b, int shift) { shift &= 7; int unsigned = b & 255; return (byte)((unsigned >> shift | unsigned << 8 - shift) & 255); }
public static boolean Checker(byte[] data) { byte[] opcode = new byte[3]; byte[] results = new byte[48]; int i = 0;
while(true) { getInstruction(random(i), opcode); int idx; int param; if (opcode[0] == -1) { byte[] var8 = results; idx = results.length;
for(param = 0; param < idx; ++param) { byte result = var8[param]; if (result == -1) { return false; } }
return true; }
int op = opcode[0] & 255; idx = opcode[1] & 255; param = opcode[2] & 255; switch (op) { case 1: data[idx] = (byte)(data[idx] + param & 255); break; case 2: data[idx] = (byte)(data[idx] - param & 255); break; case 3: data[idx] = (byte)((data[idx] ^ param) & 255); break; case 4: data[idx] = rol(data[idx], param); break; case 5: data[idx] = ror(data[idx], param); break; case 204: results[idx] = (byte)(data[idx] == (byte)param ? -52 : -1); }
++i; } }
public static void getInstruction(int index, byte[] opcode) { switch (index) { case -2105780347: opcode[0] = 4; opcode[1] = 23; opcode[2] = 5; break; case -2105778303: opcode[0] = 5; opcode[1] = 12; opcode[2] = 4; break; case -2097301675: opcode[0] = 1; opcode[1] = 41; opcode[2] = -76; break; case -2097299631: opcode[0] = 2; opcode[1] = 33; opcode[2] = 121; break; case -2088921243: opcode[0] = 1; opcode[1] = 32; opcode[2] = 47; break; case -2088919199: opcode[0] = 5; opcode[1] = 8; opcode[2] = 6; break; case -2080606283: opcode[0] = 2; opcode[1] = 3; opcode[2] = -97; break; case -2080604239: opcode[0] = -52; opcode[1] = 41; opcode[2] = 53; break; case -2038638651: opcode[0] = -52; opcode[1] = 7; opcode[2] = -128; break; case -2038636607: opcode[0] = 5; opcode[1] = 8; opcode[2] = 5; break; case -2030225643: opcode[0] = -52; opcode[1] = 37; opcode[2] = 4; break; case -2030223599: opcode[0] = 3; opcode[1] = 9; opcode[2] = 82; break; case -2021845211: opcode[0] = 4; opcode[1] = 36; opcode[2] = 2; break; case -2021843167: opcode[0] = -52; opcode[1] = 46; opcode[2] = 51; break; case -1703914110: opcode[0] = 2; opcode[1] = 0; opcode[2] = 27; break; case -1703912058: opcode[0] = 3; opcode[1] = 17; opcode[2] = 103; break; case -1695435438: opcode[0] = 3; opcode[1] = 24; opcode[2] = -97; break; case -1695433386: opcode[0] = 4; opcode[1] = 21; opcode[2] = 5; break; case -1687055006: opcode[0] = 4; opcode[1] = 5; opcode[2] = 7; break; case -1687052954: opcode[0] = 5; opcode[1] = 12; opcode[2] = 3; break; case -1678740046: opcode[0] = 3; opcode[1] = 41; opcode[2] = -99; break; case -1678737994: opcode[0] = 1; opcode[1] = 29; opcode[2] = -116; break; case -1636772414: opcode[0] = -52; opcode[1] = 30; opcode[2] = -7; break; case -1636770362: opcode[0] = 2; opcode[1] = 7; opcode[2] = 30; break; case -1628359406: opcode[0] = 4; opcode[1] = 1; opcode[2] = 1; break; case -1628357354: opcode[0] = 2; opcode[1] = 37; opcode[2] = -117; break; case -1619978974: opcode[0] = 2; opcode[1] = 46; opcode[2] = -103; break; case -1619976922: opcode[0] = 4; opcode[1] = 40; opcode[2] = 1; break; case -1435971188: opcode[0] = 5; opcode[1] = 19; opcode[2] = 4; break; case -1435969144: opcode[0] = 1; opcode[1] = 22; opcode[2] = -84; break; case -1427558052: opcode[0] = 5; opcode[1] = 19; opcode[2] = 4; break; case -1427556008: opcode[0] = 3; opcode[1] = 13; opcode[2] = -68; break; case -1419177620: opcode[0] = 2; opcode[1] = 41; opcode[2] = -123; break; case -1419175576: opcode[0] = 1; opcode[1] = 46; opcode[2] = 39; break; case -1410797124: opcode[0] = 5; opcode[1] = 42; opcode[2] = 7; break; case -1410795080: opcode[0] = 2; opcode[1] = 15; opcode[2] = -45; break; case -1368895028: opcode[0] = 2; opcode[1] = 27; opcode[2] = -57; break; case -1368892984: opcode[0] = 2; opcode[1] = 38; opcode[2] = -19; break; case -1360416484: opcode[0] = 4; opcode[1] = 39; opcode[2] = 5; break; case -1360414440: opcode[0] = -52; opcode[1] = 4; opcode[2] = 12; break; case -1352036052: opcode[0] = 4; opcode[1] = 4; opcode[2] = 5; break; case -1352034008: opcode[0] = -52; opcode[1] = 21; opcode[2] = 20; break; case -1343720964: opcode[0] = 3; opcode[1] = 25; opcode[2] = -25; break; case -1343718920: opcode[0] = 4; opcode[1] = 15; opcode[2] = 2; break; case -1302015093: opcode[0] = 3; opcode[1] = 22; opcode[2] = 84; break; case -1302013041: opcode[0] = 3; opcode[1] = 13; opcode[2] = -95; break; case -1293601957: opcode[0] = 2; opcode[1] = 12; opcode[2] = 27; break; case -1293599905: opcode[0] = 5; opcode[1] = 14; opcode[2] = 4; break; case -1285221525: opcode[0] = 3; opcode[1] = 5; opcode[2] = 124; break; case -1285219473: opcode[0] = 5; opcode[1] = 0; opcode[2] = 5; break; case -1276841029: opcode[0] = 2; opcode[1] = 28; opcode[2] = 16; break; case -1276838977: opcode[0] = -52; opcode[1] = 42; opcode[2] = 58; break; case -1234938933: opcode[0] = -52; opcode[1] = 38; opcode[2] = 93; break; case -1234936881: opcode[0] = -52; opcode[1] = 27; opcode[2] = -27; break; case -1226460389: opcode[0] = 5; opcode[1] = 7; opcode[2] = 6; break; case -1226458337: opcode[0] = 4; opcode[1] = 20; opcode[2] = 4; break; case -1218079957: opcode[0] = 5; opcode[1] = 32; opcode[2] = 4; break; case -1218077905: opcode[0] = 4; opcode[1] = 6; opcode[2] = 3; break; case -1209764869: opcode[0] = -52; opcode[1] = 15; opcode[2] = -119; break; case -1209762817: opcode[0] = -52; opcode[1] = 25; opcode[2] = -97; break; case -1038342243: opcode[0] = 5; opcode[1] = 20; opcode[2] = 6; break; case -1038340199: opcode[0] = -52; opcode[1] = 17; opcode[2] = 49; break; case -1029847219: opcode[0] = 3; opcode[1] = 36; opcode[2] = 114; break; case -1029845175: opcode[0] = 5; opcode[1] = 40; opcode[2] = 4; break; case -1021450371: opcode[0] = 1; opcode[1] = 11; opcode[2] = 109; break; case -1021448327: opcode[0] = 3; opcode[1] = 27; opcode[2] = -88; break; case -1013184595: opcode[0] = 3; opcode[1] = 39; opcode[2] = -54; break; case -1013182551: opcode[0] = 2; opcode[1] = 35; opcode[2] = 74; break; case -971200547: opcode[0] = -52; opcode[1] = 9; opcode[2] = 81; break; case -971198503: opcode[0] = -52; opcode[1] = 31; opcode[2] = 58; break; case -962771187: opcode[0] = 3; opcode[1] = 33; opcode[2] = 126; break; case -962769143: opcode[0] = 2; opcode[1] = 34; opcode[2] = -84; break; case -954374339: opcode[0] = 2; opcode[1] = 34; opcode[2] = -59; break; case -954372295: opcode[0] = 4; opcode[1] = 36; opcode[2] = 7; break; case -636476006: opcode[0] = 3; opcode[1] = 17; opcode[2] = -25; break; case -636473954: opcode[0] = 4; opcode[1] = 6; opcode[2] = 5; break; case -627980982: opcode[0] = 3; opcode[1] = 42; opcode[2] = 93; break; case -627978930: opcode[0] = 1; opcode[1] = 10; opcode[2] = 38; break; case -619584134: opcode[0] = 5; opcode[1] = 7; opcode[2] = 4; break; case -619582082: opcode[0] = 5; opcode[1] = 32; opcode[2] = 2; break; case -611318358: opcode[0] = 3; opcode[1] = 27; opcode[2] = 118; break; case -611316306: opcode[0] = 4; opcode[1] = 5; opcode[2] = 7; break; case -569334310: opcode[0] = 2; opcode[1] = 31; opcode[2] = 83; break; case -569332258: opcode[0] = 5; opcode[1] = 9; opcode[2] = 3; break; case -560904950: opcode[0] = -52; opcode[1] = 3; opcode[2] = 89; break; case -560902898: opcode[0] = 1; opcode[1] = 25; opcode[2] = 79; break; case -552508102: opcode[0] = 4; opcode[1] = 44; opcode[2] = 6; break; case -552506050: opcode[0] = -52; opcode[1] = 10; opcode[2] = -95; break; case -368533100: opcode[0] = 2; opcode[1] = 2; opcode[2] = -77; break; case -368531056: opcode[0] = 2; opcode[1] = 22; opcode[2] = -96; break; case -360103612: opcode[0] = 5; opcode[1] = 2; opcode[2] = 5; break; case -360101568: opcode[0] = 5; opcode[1] = 34; opcode[2] = 2; break; case -351706764: opcode[0] = 5; opcode[1] = 43; opcode[2] = 1; break; case -351704720: opcode[0] = 3; opcode[1] = 35; opcode[2] = 4; break; case -343375452: opcode[0] = 5; opcode[1] = 47; opcode[2] = 6; break; case -343373408: opcode[0] = 1; opcode[1] = 6; opcode[2] = 12; break; case -301456940: opcode[0] = 5; opcode[1] = 18; opcode[2] = 7; break; case -301454896: opcode[0] = -52; opcode[1] = 23; opcode[2] = -51; break; case -292962044: opcode[0] = -52; opcode[1] = 36; opcode[2] = -106; break; case -292960000: opcode[0] = 5; opcode[1] = 33; opcode[2] = 7; break; case -284565196: opcode[0] = -52; opcode[1] = 35; opcode[2] = -37; break; case -284563152: opcode[0] = 4; opcode[1] = 28; opcode[2] = 2; break; case -276299292: opcode[0] = 2; opcode[1] = 45; opcode[2] = 88; break; case -276297248: opcode[0] = 1; opcode[1] = 0; opcode[2] = 54; break; case -234577005: opcode[0] = 1; opcode[1] = 15; opcode[2] = -64; break; case -234574953: opcode[0] = 4; opcode[1] = 35; opcode[2] = 5; break; case -226147517: opcode[0] = 2; opcode[1] = 4; opcode[2] = -58; break; case -226145465: opcode[0] = 2; opcode[1] = 4; opcode[2] = -51; break; case -217750669: opcode[0] = 4; opcode[1] = 35; opcode[2] = 5; break; case -217748617: opcode[0] = 5; opcode[1] = 26; opcode[2] = 5; break; case -209419357: opcode[0] = 5; opcode[1] = 8; opcode[2] = 4; break; case -209417305: opcode[0] = 1; opcode[1] = 15; opcode[2] = -75; break; case -167500845: opcode[0] = 1; opcode[1] = 9; opcode[2] = -109; break; case -167498793: opcode[0] = -52; opcode[1] = 18; opcode[2] = -41; break; case -159005949: opcode[0] = 4; opcode[1] = 23; opcode[2] = 5; break; case -159003897: opcode[0] = 5; opcode[1] = 16; opcode[2] = 2; break; case -150609101: opcode[0] = 4; opcode[1] = 26; opcode[2] = 5; break; case -150607049: opcode[0] = 5; opcode[1] = 31; opcode[2] = 2; break; case -142343197: opcode[0] = -52; opcode[1] = 0; opcode[2] = 59; break; case -142341145: opcode[0] = -52; opcode[1] = 45; opcode[2] = 120; break; case 37533589: opcode[0] = -52; opcode[1] = 2; opcode[2] = -31; break; case 37535633: opcode[0] = 5; opcode[1] = 21; opcode[2] = 5; break; case 45963077: opcode[0] = 5; opcode[1] = 12; opcode[2] = 3; break; case 45965121: opcode[0] = 4; opcode[1] = 36; opcode[2] = 2; break; case 54359925: opcode[0] = 3; opcode[1] = 17; opcode[2] = -127; break; case 54361969: opcode[0] = 3; opcode[1] = 46; opcode[2] = 26; break; case 62691237: opcode[0] = 1; opcode[1] = 37; opcode[2] = -21; break; case 62693281: opcode[0] = 3; opcode[1] = 9; opcode[2] = 112; break; case 104609749: opcode[0] = 1; opcode[1] = 23; opcode[2] = 127; break; case 104611793: opcode[0] = -52; opcode[1] = 14; opcode[2] = -90; break; case 113104645: opcode[0] = 1; opcode[1] = 29; opcode[2] = 96; break; case 113106689: opcode[0] = -52; opcode[1] = 40; opcode[2] = -108; break; case 121501493: opcode[0] = -52; opcode[1] = 5; opcode[2] = 92; break; case 121503537: opcode[0] = 4; opcode[1] = 25; opcode[2] = 7; break; case 129767397: opcode[0] = -52; opcode[1] = 43; opcode[2] = 68; break; case 129769441: opcode[0] = -52; opcode[1] = 1; opcode[2] = 98; break; case 439399826: opcode[0] = 3; opcode[1] = 38; opcode[2] = 94; break; case 439401878: opcode[0] = 3; opcode[1] = 2; opcode[2] = -43; break; case 447829314: opcode[0] = 2; opcode[1] = 42; opcode[2] = -35; break; case 447831366: opcode[0] = 1; opcode[1] = 28; opcode[2] = 54; break; case 456226162: opcode[0] = 1; opcode[1] = 25; opcode[2] = -27; break; case 456228214: opcode[0] = 1; opcode[1] = 24; opcode[2] = 74; break; case 464557474: opcode[0] = 5; opcode[1] = 33; opcode[2] = 7; break; case 464559526: opcode[0] = 1; opcode[1] = 30; opcode[2] = 15; break; case 506475986: opcode[0] = 1; opcode[1] = 14; opcode[2] = -47; break; case 506478038: opcode[0] = 5; opcode[1] = 38; opcode[2] = 7; break; case 514970882: opcode[0] = 4; opcode[1] = 40; opcode[2] = 4; break; case 514972934: opcode[0] = -52; opcode[1] = 16; opcode[2] = 51; break; case 523367730: opcode[0] = -52; opcode[1] = 26; opcode[2] = 75; break; case 523369782: opcode[0] = 1; opcode[1] = 5; opcode[2] = -12; break; case 531633634: opcode[0] = 3; opcode[1] = 1; opcode[2] = 33; break; case 531635686: opcode[0] = 5; opcode[1] = 43; opcode[2] = 1; break; case 707277212: opcode[0] = -52; opcode[1] = 12; opcode[2] = -17; break; case 707279256: opcode[0] = 2; opcode[1] = 16; opcode[2] = 88; break; case 715772236: opcode[0] = 5; opcode[1] = 44; opcode[2] = 1; break; case 715774280: opcode[0] = 2; opcode[1] = 45; opcode[2] = -100; break; case 724169084: opcode[0] = 4; opcode[1] = 39; opcode[2] = 5; break; case 724171128: opcode[0] = 2; opcode[1] = 16; opcode[2] = 34; break; case 732434860: opcode[0] = 3; opcode[1] = 24; opcode[2] = -110; break; case 732436904: opcode[0] = 5; opcode[1] = 31; opcode[2] = 7; break; case 774418908: opcode[0] = 5; opcode[1] = 8; opcode[2] = 4; break; case 774420952: opcode[0] = 4; opcode[1] = 22; opcode[2] = 2; break; case 782848268: opcode[0] = 5; opcode[1] = 47; opcode[2] = 6; break; case 782850312: opcode[0] = -52; opcode[1] = 33; opcode[2] = 57; break; case 791245116: opcode[0] = 3; opcode[1] = 45; opcode[2] = 118; break; case 791247160: opcode[0] = 3; opcode[1] = 44; opcode[2] = 32; break; case 841233307: opcode[0] = 3; opcode[1] = 6; opcode[2] = -24; break; case 841235359: opcode[0] = 1; opcode[1] = 27; opcode[2] = 119; break; case 849728331: opcode[0] = 1; opcode[1] = 16; opcode[2] = -81; break; case 849730383: opcode[0] = 5; opcode[1] = 10; opcode[2] = 3; break; case 858125179: opcode[0] = 4; opcode[1] = 1; opcode[2] = 1; break; case 858127231: opcode[0] = 1; opcode[1] = 37; opcode[2] = -19; break; case 866390955: opcode[0] = 3; opcode[1] = 3; opcode[2] = -71; break; case 866393007: opcode[0] = -52; opcode[1] = 24; opcode[2] = 21; break; case 908375003: opcode[0] = -52; opcode[1] = 22; opcode[2] = -82; break; case 908377055: opcode[0] = -52; opcode[1] = 8; opcode[2] = -35; break; case 916804363: opcode[0] = 3; opcode[1] = 3; opcode[2] = 21; break; case 916806415: opcode[0] = -52; opcode[1] = 47; opcode[2] = 87; break; case 925201211: opcode[0] = 1; opcode[1] = 11; opcode[2] = 27; break; case 925203263: opcode[0] = 4; opcode[1] = 10; opcode[2] = 5; break; case 1113376653: opcode[0] = 3; opcode[1] = 18; opcode[2] = 55; break; case 1113378697: opcode[0] = 5; opcode[1] = 43; opcode[2] = 1; break; case 1121789789: opcode[0] = 1; opcode[1] = 26; opcode[2] = 14; break; case 1121791833: opcode[0] = 5; opcode[1] = 29; opcode[2] = 1; break; case 1130170221: opcode[0] = 4; opcode[1] = 45; opcode[2] = 6; break; case 1130172265: opcode[0] = 3; opcode[1] = 2; opcode[2] = 56; break; case 1138550717: opcode[0] = 3; opcode[1] = 24; opcode[2] = 65; break; case 1138552761: opcode[0] = -52; opcode[1] = 19; opcode[2] = -38; break; case 1180452813: opcode[0] = -52; opcode[1] = 29; opcode[2] = 40; break; case 1180454857: opcode[0] = -52; opcode[1] = 44; opcode[2] = -59; break; case 1188931357: opcode[0] = 3; opcode[1] = 4; opcode[2] = 108; break; case 1188933401: opcode[0] = -52; opcode[1] = 13; opcode[2] = -42; break; case 1197311789: opcode[0] = 4; opcode[1] = 21; opcode[2] = 5; break; case 1197313833: opcode[0] = 4; opcode[1] = 14; opcode[2] = 1; break; case 1205626877: opcode[0] = -52; opcode[1] = 28; opcode[2] = 55; break; case 1205628921: opcode[0] = -52; opcode[1] = 39; opcode[2] = -91; break; case 1515242890: opcode[0] = 2; opcode[1] = 19; opcode[2] = 89; break; case 1515244942: opcode[0] = 2; opcode[1] = 20; opcode[2] = -44; break; case 1523656026: opcode[0] = 2; opcode[1] = 1; opcode[2] = -78; break; case 1523658078: opcode[0] = 3; opcode[1] = 46; opcode[2] = 60; break; case 1532036458: opcode[0] = 5; opcode[1] = 30; opcode[2] = 4; break; case 1532038510: opcode[0] = 4; opcode[1] = 43; opcode[2] = 4; break; case 1540416954: opcode[0] = 3; opcode[1] = 19; opcode[2] = -45; break; case 1540419006: opcode[0] = 3; opcode[1] = 40; opcode[2] = -20; break; case 1582319050: opcode[0] = 1; opcode[1] = 44; opcode[2] = -21; break; case 1582321102: opcode[0] = 2; opcode[1] = 29; opcode[2] = -18; break; case 1590797594: opcode[0] = 4; opcode[1] = 13; opcode[2] = 3; break; case 1590799646: opcode[0] = -52; opcode[1] = 20; opcode[2] = 1; break; case 1599178026: opcode[0] = -52; opcode[1] = 32; opcode[2] = -85; break; case 1599180078: opcode[0] = -52; opcode[1] = 6; opcode[2] = -15; break; case 1607493114: opcode[0] = 4; opcode[1] = 39; opcode[2] = 7; break; case 1607495166: opcode[0] = 3; opcode[1] = 28; opcode[2] = -14; break; case 1783120260: opcode[0] = 2; opcode[1] = 38; opcode[2] = 20; break; case 1783122304: opcode[0] = 4; opcode[1] = 47; opcode[2] = 5; break; case 1791598932: opcode[0] = 3; opcode[1] = 18; opcode[2] = -22; break; case 1791600976: opcode[0] = 2; opcode[1] = 3; opcode[2] = 32; break; case 1799979364: opcode[0] = 5; opcode[1] = 32; opcode[2] = 3; break; case 1799981408: opcode[0] = 5; opcode[1] = 42; opcode[2] = 3; break; case 1808294324: opcode[0] = 5; opcode[1] = 41; opcode[2] = 1; break; case 1808296368: opcode[0] = 4; opcode[1] = 10; opcode[2] = 7; break; case 1850261956: opcode[0] = 3; opcode[1] = 34; opcode[2] = -105; break; case 1850264000: opcode[0] = 4; opcode[1] = 0; opcode[2] = 3; break; case 1858674964: opcode[0] = 1; opcode[1] = 47; opcode[2] = -48; break; case 1858677008: opcode[0] = 2; opcode[1] = 11; opcode[2] = 45; break; case 1867055396: opcode[0] = 2; opcode[1] = 7; opcode[2] = 12; break; case 1867057440: opcode[0] = 5; opcode[1] = 31; opcode[2] = 6; break; case 1875436020: opcode[0] = -1; opcode[1] = 0; opcode[2] = 0; break; case 1917076355: opcode[0] = 1; opcode[1] = 23; opcode[2] = 85; break; case 1917078407: opcode[0] = 4; opcode[1] = 26; opcode[2] = 3; break; case 1925555027: opcode[0] = 4; opcode[1] = 17; opcode[2] = 7; break; case 1925557079: opcode[0] = 4; opcode[1] = 21; opcode[2] = 2; break; case 1933935459: opcode[0] = 2; opcode[1] = 13; opcode[2] = -28; break; case 1933937511: opcode[0] = 4; opcode[1] = 30; opcode[2] = 7; break; case 1942250419: opcode[0] = 4; opcode[1] = 18; opcode[2] = 6; break; case 1942252471: opcode[0] = 4; opcode[1] = 20; opcode[2] = 6; break; case 1984218051: opcode[0] = 2; opcode[1] = 30; opcode[2] = -39; break; case 1984220103: opcode[0] = -52; opcode[1] = 34; opcode[2] = -112; break; case 1992631059: opcode[0] = -52; opcode[1] = 11; opcode[2] = 49; break; case 1992633111: opcode[0] = 1; opcode[1] = 11; opcode[2] = 84; break; case 2001011491: opcode[0] = 4; opcode[1] = 37; opcode[2] = 5; break; case 2001013543: opcode[0] = 2; opcode[1] = 14; opcode[2] = 97; }
}}key为 4r3_y0U_a_Jv4V_m4s73R?
密文为
77a9c4b496ddd63beed5a78246abb1c097e27262e428f3e80f6da7cb4b5478c6dd4ae14d4ea467848422e8229609d30a解密脚本
from typing import List
MASK = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"TARGET: List[int] = [ 107655, 99322, 95708, 87877, 85730, 80988, 72416, 76077, 74252, 70300, 68724, 68020, 63439, 53540, 51340, 42431, 37382, 28611, 25737, 18364, 9711, 9030]
def solve_key_from_equations() -> bytes: # 与 1.py 相同的三角回代求解 mask = list(MASK) key = [0] * 22 for i in reversed(range(22)): s = TARGET[i] mi = mask[i] for j in range(i + 1, 22): s -= ((key[j] ^ mi) & 0xff) * mask[j] val = (s // mi) & 0xff key[i] = val ^ mi return bytes(key)
def keychecker_check(key: bytes) -> bool: if key is None or len(key) != 22: return False for i in range(22): mi = MASK[i] & 0xFF sm = 0 for j in range(i, 22): mj = MASK[j] & 0xFF kj = key[j] & 0xFF x = (kj ^ mi) & 0xFF sm += x * mj if sm != TARGET[i]: return False return True
def main(): key = solve_key_from_equations() print("Solved key:", key.decode('latin1')) print("Key hex:", key.hex()) print("Length:", len(key)) ok = keychecker_check(key) print("KeyChecker check:", ok) with open("key.txt", "wb") as f: f.write(key) print("Written to: key.txt")
if __name__ == "__main__": main()flag{4r3_y0U_g0oD_a7_j4vA?I’m_V3rY_Go0d_47_JvaV}