【春节】解题领红包之一 {送分题}

关注论坛微信公众号:吾爱破解论坛,回复“52TDL”获得口令。
口令:论坛禁止留联系方式
【春节】解题领红包之二 {Windows 初级题}
首先分析主验证函数sub_4CD130:
int __cdecl sub_4CD130(char a1)
{
__time32_t Seed; // eax
char v2; // al
char v3; // al
char n53; // dl
char v5; // cl
int v6; // eax
unsigned __int8 v8; // al
int v9; // edx
int v10; // edx
int v11; // eax
__time32_t *Time; // [esp+0h] [ebp-78h] BYREF
char **p_p_Str; // [esp+14h] [ebp-64h]
char *Str; // [esp+18h] [ebp-60h]
char v15[4]; // [esp+1Ch] [ebp-5Ch] BYREF
int v16; // [esp+20h] [ebp-58h]
int (__cdecl *p_sub_4CC800)(int, int, int, int, int, int); // [esp+34h] [ebp-44h]
int *v18; // [esp+38h] [ebp-40h]
int *v19; // [esp+3Ch] [ebp-3Ch]
void (__noreturn *p_sub_4CD4EA)(); // [esp+40h] [ebp-38h]
__time32_t **p_Time; // [esp+44h] [ebp-34h]
char *p_Str; // [esp+58h] [ebp-20h] BYREF
int v23; // [esp+5Ch] [ebp-1Ch]
char v24; // [esp+60h] [ebp-18h] BYREF
char *v25; // [esp+70h] [ebp-8h]
int savedregs; // [esp+78h] [ebp+0h] BYREF
v25 = &a1;
p_sub_4CC800 = sub_4CC800;
p_Time = &Time;
v18 = dword_4CE3D4;
v19 = &savedregs;
p_sub_4CD4EA = sub_4CD4EA;
sub_40C330(v15);
sub_40A650();
v16 = -1;
Seed = time(0);
srand(Seed);
SetConsoleOutputCP(0xFDE9u);
sub_4C7E50((int)&dword_4D27C0, "========================================");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, " CrackMe Challenge v2.5 - 2026 ");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "========================================");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "Keywords: 52pojie, 2026, Happy new year");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "Hint: Fake flag; length is key");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "----------------------------------------");
sub_4015B0(Time);
p_Str = &v24;
v23 = 0;
v24 = 0;
v16 = 1;
p_p_Str = &p_Str;
sub_4C7E50((int)&dword_4D27C0, "\n[?] Enter the password: ");
p_p_Str = &p_Str;
v2 = sub_401560();
p_p_Str = &p_Str;
sub_4C5840(&dword_4D25E0, &p_Str, v2);
Str = p_Str;
v3 = sub_401740(p_Str);
n53 = 53;
v5 = v3;
v6 = 0;
if ( !v5 )
{
while ( Str[v6] == n53 )
{
if ( ++v6 == 16 )
{
v16 = 1;
sub_4C7E50((int)&dword_4D27C0, "\n[!] You're getting closer...");
v16 = 1;
goto LABEL_9;
}
n53 = byte_4D3032[v6];
}
if ( strlen(Str) != 31 )
{
v16 = 1;
sub_4C7E50((int)&dword_4D27C0, "\n[!] Hint: The length is your first real challenge.");
goto LABEL_9;
}
v16 = 1;
if ( sub_4016D0(Str, 31) )
{
Str = 0;
v8 = *p_Str;
if ( !*p_Str )
goto LABEL_16;
v9 = 0;
do
{
Str += ++v9 * v8;
v8 = p_Str[v9];
}
while ( v8 );
if ( Str != (char *)44709 )
{
LABEL_16:
v16 = 1;
sub_4C7E50((int)&dword_4D27C0, "\n[!] Checksum failed! Something is wrong...");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "[!] Expected: 44709, Got: ");
sub_47DE70(Str);
sub_4015B0(v10);
LABEL_17:
v16 = 1;
goto LABEL_10;
}
v16 = 1;
sub_4C7E50((int)&dword_4D27C0, "\n========================================");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, " *** SUCCESS! *** ");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "========================================");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "[+] Congratulations! You cracked it!");
sub_4015B0(Time);
v11 = sub_4C7E50((int)&dword_4D27C0, "[+] Correct flag: ");
sub_4C4330(v11, p_Str, v23);
}
else
{
v16 = 1;
sub_4C7E50((int)&dword_4D27C0, "\n[X] Access Denied!");
sub_4015B0(Time);
sub_4C7E50((int)&dword_4D27C0, "[X] Wrong password. Keep trying!");
}
sub_4015B0(Time);
goto LABEL_17;
}
sub_4C7E50((int)&dword_4D27C0, "\n[!] Nice try, but not quite right...");
LABEL_9:
sub_4015B0(Time);
LABEL_10:
sub_4017C0();
sub_4B1AE0(p_p_Str);
sub_40C600(v15);
return 0;
}程序接收用户输入后,进行了一次循环比对:
Fake Flag 陷阱:如果输入的前 16 个字符匹配内置数组
byte_4D3032(首字符为ASCII码53即“5”),程序会打印“You’re getting closer…”然后直接跳出结束。这是出题人设下的心理战干扰项。长度限制:紧接着程序执行了
strlen(Str) != 31的判断,这为我们提供了第一个硬性约束条件:真正的Flag长度严格等于31位。
在程序的导出/入口表中观察到一个TlsCallback_0函数。TLS(Thread Local Storage)回调在执行时机上早于main函数,常被恶意软件或CTF用来埋设反调试(Anti-Debug)逻辑。但经仔细静态分析,该函数仅包含__mingw_TLScallback的标准编译器初始化代码,并无“藏毒”,可放心忽略。
在main函数尾部,有一个复杂的校验和逻辑用来验证最终结果:
但在此之前,程序必须先通过关键的一行判定:
if ( (unsigned __int8)sub_4016D0(Str, 31) )跟进sub_4016D0:
bool __cdecl sub_4016D0(char *Str, int n31)
{
unsigned __int8 *Block; // ebp
int n31_1; // eax
int n31_2; // ebx
bool v5; // dl
Block = (unsigned __int8 *)sub_4CB710(0x64u);
sub_401620(Block);
if ( n31 <= 0 )
{
n31_2 = 0;
}
else
{
n31_1 = 0;
n31_2 = 0;
do
{
v5 = Str[n31_1] == Block[n31_1];
++n31_1;
n31_2 += v5;
}
while ( n31 != n31_1 );
}
j_j_free(Block);
return n31 == n31_2;
}我们发现,它在堆上malloc了一段100字节的内存空间(变量Block),将其传给sub_401620函数处理,随后用自定义的do-while do-while循环将用户输入与这段Block内存逐字节比对。这说明真实的Flag是在运行时动态解密并写入内存的。
进入造旗工厂sub_401620,我们找到了纯粹的底层数据操作逻辑:
_BYTE *__cdecl sub_401620(int a1)
{
_BYTE *result; // eax
*(_DWORD *)a1 = 758280311;
*(_DWORD *)(a1 + 4) = 1663511336;
*(_DWORD *)(a1 + 8) = 1880974179;
*(_DWORD *)(a1 + 12) = 494170226;
*(_DWORD *)(a1 + 16) = 842146570;
*(_DWORD *)(a1 + 20) = 657202491;
*(_DWORD *)(a1 + 24) = 658185525;
*(_BYTE *)(a1 + 30) = 99;
*(_WORD *)(a1 + 28) = 12323;
result = (_BYTE *)a1;
do
*result++ ^= 0x42u;
while ( result != (_BYTE *)(a1 + 31) );
*(_BYTE *)(a1 + 31) = 0;
return result;
}内存硬编码拼接:程序将7个
DWORD(32位)、1个WORD(16位)和1个BYTE(8位)整型数据,硬生生地连续赋值给刚才分配的内存指针。小端序存储:在x86/x64架构下,这些多字节整数在内存中是以小端序(Little-Endian)排列的(低位字节存放在低地址处)。
异或解密:最后,通过一个经典的单字节
XOR循环*result++ ^= 0x42u;*result++ ^= 0x42u;,将这31个字节依次与0x42异或,还原出真正的Flag明文。
利用Python的struct模块可以完美模拟C语言底层的内存分配规则,精准还原原始字节流并进行异或:
import struct
def solve():
data = bytearray(31)
# '<I' 表示小端序无符号 32 位整数 (DWORD)
data[0:4] = struct.pack('<I', 758280311)
data[4:8] = struct.pack('<I', 1663511336)
data[8:12] = struct.pack('<I', 1880974179)
data[12:16] = struct.pack('<I', 494170226)
data[16:20] = struct.pack('<I', 842146570)
data[20:24] = struct.pack('<I', 657202491)
data[24:28] = struct.pack('<I', 658185525)
# '<H' 表示小端序无符号 16 位整数 (WORD)
data[28:30] = struct.pack('<H', 12323)
# '<B' 表示无符号 8 位整数 (BYTE)
data[30:31] = struct.pack('<B', 99)
# 逐字节 XOR 0x42 解密
flag = "".join([chr(b ^ 0x42) for b in data])
return flag
if __name__ == '__main__':
real_flag = solve()
print(f"[+] 成功解密 Flag: {real_flag}")
# 验证最外层的冗余校验和机制
checksum = sum((i + 1) * ord(c) for i, c in enumerate(real_flag))
if checksum == 44709:
print("[+] 校验和匹配 (44709),答案完全正确!")口令:52pojie!!!_2026_Happy_new_year!
【春节】解题领红包之三 {Android 初级题}
直接玩通关,新(第一行第一列)、年(第一行第二列)、别(第一行第三列)、感(第二行第三列)。
口令:flag{Wu41_P0j13_2026_Spr1ng_F3st1v4l}
【春节】解题领红包之四 {Windows 初级题}
双击运行【2026春节】解题领红包之四 {Windows 初级题} 出题老师:云在天.exe,得到提示:去反编译它。这是一个Python编写的CrackMe,我们需要使用PyInstaller Extractor,为了后续命令执行方便,我们将源文件重命名为4.exe,然后在终端运行python pyinstxtractor.py 4.exe。在4.exe_extracted文件夹下,我们发现了crackme_easy.pyc,使用
# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: 'crackme_easy.py'
# Bytecode version: 3.14rc3 (3627)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)
import hashlib
import base64
import sys
def xor_decrypt(data, key):
"""XOR解密"""
result = bytearray()
for i, byte in enumerate(data):
result.append(byte ^ key ^ i & 255)
return result.decode('utf-8', errors='ignore')
def get_encrypted_flag():
"""获取加密的flag"""
enc_data = 'e3w+fiRvfW18fnx4ZAZ6Pj43YwB9OWMXfXo8Dg4O'
return base64.b64decode(enc_data)
def generate_flag():
"""动态生成flag"""
encrypted = get_encrypted_flag()
key = 78
result = bytearray()
for i, byte in enumerate(encrypted):
result.append(byte ^ key)
return result.decode('utf-8')
def calculate_checksum(s):
"""计算校验和"""
total = 0
for i, c in enumerate(s):
total += ord(c) * (i + 1)
return total
def hash_string(s):
"""计算字符串哈希"""
return hashlib.sha256(s.encode()).hexdigest()
def verify_flag(user_input):
"""验证flag"""
correct_flag = generate_flag()
if len(user_input)!= len(correct_flag):
return False
else:
for i in range(len(correct_flag)):
if user_input[i]!= correct_flag[i]:
return False
return True
def fake_check_1(user_input):
"""假检查1"""
fake_hash = 'a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890'
return hash_string(user_input) == fake_hash
def fake_check_2(user_input):
"""假检查2"""
fake_hash = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'
return hash_string(user_input) == fake_hash
def main():
"""主函数"""
print('==================================================')
print(' CrackMe Challenge - Python Edition')
print('==================================================')
print('Keywords: 52pojie, 2026, Happy New Year')
print('Hint: Decompile me if you can!')
print('--------------------------------------------------')
user_input = input('\n[?] Enter the password: ').strip()
if fake_check_1(user_input):
print('\n[!] Nice try, but not quite right...')
input('\nPress Enter to exit...')
return None
else:
if fake_check_2(user_input):
print('\n[!] You\'re getting closer...')
input('\nPress Enter to exit...')
else:
if verify_flag(user_input):
checksum = calculate_checksum(user_input)
expected_checksum = calculate_checksum(generate_flag())
if checksum == expected_checksum:
print('\n==================================================')
print(' *** SUCCESS! ***')
print('==================================================')
print('[+] Congratulations! You cracked it!')
print(f'[+] Correct flag: {user_input}')
else:
print('\n[!] Checksum failed!')
else:
print('\n[X] Access Denied!')
print('[X] Wrong password. Keep trying!')
input('\nPress Enter to exit...')
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\n\n[!] Interrupted by user')
sys.exit(0)写出解密脚本:
import base64
# 1. 提取硬编码的 Base64 密文
enc_data = 'e3w+fiRvfW18fnx4ZAZ6Pj43YwB9OWMXfXo8Dg4O'
# 2. Base64 解码
decoded_bytes = base64.b64decode(enc_data)
# 3. 异或解密 (Key = 78)
key = 78
flag = bytearray()
for byte in decoded_bytes:
flag.append(byte ^ key)
# 4. 打印最终结果
print("The Flag is:", flag.decode('utf-8'))口令:52p0j!3#2026*H4ppy-N3w-Y34r@@@