Loading... # JustCTF 2025 WP 20th,re 4/5 ## baby-goes-re go逆向,检查flag长度为53,然后main_CheckFlag gemini秒了 ~~~python s = "..." def solve_flag(): """ 模拟 main.CheckFlag 的逻辑来重建正确的 Flag。 """ a3_data = s.encode() # 2. 初始化与汇编代码中完全相同的变量 v10 = 0 v11 = 0 flag = [] # 用来存储我们生成的 Flag 字符 # 3. 循环生成 Flag。我们不知道确切长度,所以先假设一个足够大的长度, # 例如 100。如果 Flag 更长,可以增加这个数字。 for i in range(100): # 4. 完全按照汇编的逻辑计算偏移量 # v16 = v11 + v10 # v15 = v11 + v10 + 4919 (这是索引) offset = v11 + v10 + 4919 # 检查偏移量是否超出了我们 dump 的数据范围 if offset >= len(a3_data): print(f"计算出的偏移量 ({offset}) 超出数据块大小 ({len(a3_data)}),可能已到达 Flag 末尾。") break # 5. 从数据块中获取“正确的”字符 # v18 = *(unsigned __int8 *)(v16 + a3 + 4919); expected_char_code = a3_data[offset] flag.append(chr(expected_char_code)) # 6. 完全按照汇编的逻辑更新下一次循环的变量 # v34 = v11 + v10 + 4920 # v11 = v33 + 51 (v33 是 v11 的旧值) v10_old = v10 v11_old = v11 v10 = v11_old + v10_old + 4920 v11 = v11_old + 51 # 7. 打印结果 final_flag = "".join(flag) print(f"成功生成 Flag: {final_flag}") print(f"Flag 长度: {len(final_flag)}") if __name__ == "__main__": solve_flag() ~~~ `justCTF{W3lc0m3_t0_R3v1NG!_Th4t_w45nt-s0-B4d-w45_1t?}` ## Satellite 给的流量包里出现了,post flag  直接去elf里找关键字符串,定位到解密函数 ~~~python int __fastcall sub_45EC(int a1) { int v2; // r4 int v3; // r6 int v4; // r5 int v5; // r7 int i; // r8 int j; // r9 int v8; // r0 char *v9; // r1 _BYTE v11[8]; // [sp+0h] [bp-38h] BYREF int v12; // [sp+8h] [bp-30h] _DWORD v13[11]; // [sp+Ch] [bp-2Ch] BYREF sub_D9A4(&unk_20000854); sub_D9C4(&unk_20000854, "Decrypting hex data..."); v2 = *(_DWORD *)(a1 + 8) >> 1; v3 = 0; v4 = sub_10964(v2); v5 = v4 - 1; while ( v3 < v2 ) { sub_DCE4(v13, a1, 2 * v3, 2 * v3 + 2); *(_BYTE *)++v5 = sub_12594(v13[0], 0, 16); ++v3; sub_DABA(v13); } sub_DB50(v11, 85326); for ( i = 0; i < v2; i += 8 ) { if ( i + 7 < v2 ) { v13[0] = (*(unsigned __int8 *)(v4 + i + 2) << 16) | (*(unsigned __int8 *)(v4 + i + 1) << 8) | *(unsigned __int8 *)(v4 + i) | (*(unsigned __int8 *)(v4 + i + 3) << 24); v13[1] = (*(unsigned __int8 *)(v4 + i + 6) << 16) | (*(unsigned __int8 *)(v4 + i + 5) << 8) | *(unsigned __int8 *)(v4 + i + 4) | (*(unsigned __int8 *)(v4 + i + 7) << 24); sub_4594(v13, &dword_14B98[98]); for ( j = 0; j != 8; ++j ) { if ( (unsigned __int8)(*((_BYTE *)v13 + j) - 32) <= 0x5Eu ) sub_DC42(v11); } } } sub_10920(v4); if ( v12 ) { sub_DD24(v11); sub_DC8A(v11, aSatellite, 100, 0); dword_200003BC = v12; dword_2000031C = 0; dword_20000320 = 0; sub_42F4(&dword_20000358); sub_DB50(v13, "Decrypted message: "); v8 = sub_DC58(v13, v11); sub_D9B0(&unk_20000854, v8); sub_DABA(v13); v9 = "Displaying on matrix..."; } else { v9 = "Failed to decrypt data or no printable characters found."; } sub_D9C4(&unk_20000854, v9); return sub_DABA(v11); } ~~~ sub_4594是TEA解密 ~~~c __int64 *__fastcall sub_4594(__int64 *result, __int64 *a2) { __int64 v2; // r2 __int64 v3; // kr00_8 __int64 v4; // kr08_8 int v5; // r1 int v6; // r4 v2 = *result; v3 = a2[1]; v4 = *a2; v5 = -957401312; do { HIDWORD(v2) -= (v3 + 16 * v2) ^ (HIDWORD(v3) + ((unsigned int)v2 >> 5)) ^ (v2 + v5); v6 = (v4 + 16 * HIDWORD(v2)) ^ (HIDWORD(v4) + (HIDWORD(v2) >> 5)) ^ (HIDWORD(v2) + v5); v5 += 1640531527; LODWORD(v2) = v2 - v6; } while ( v5 ); *result = v2; return result; } ~~~ 直接脚本一把梭 ~~~python from ctypes import c_uint32 def tea_decrypt(r, v, key, delta): v0, v1 = c_uint32(v[0]), c_uint32(v[1]) total = c_uint32(0xC6EF3720) for i in range(r): v1.value -= ((v0.value << 4) + key[2]) ^ (v0.value + total.value) ^ ((v0.value >> 5) + key[3]) v0.value -= ((v1.value << 4) + key[0]) ^ (v1.value + total.value) ^ ((v1.value >> 5) + key[1]) total.value += delta return v0.value, v1.value k = [0x12345678, 0x9ABCDEF0, 0x11111111, 0x22222222] v = bytes.fromhex("5771D410CFFE844D24B50FCBBBDC1973A7A935E5C3468242950DFCCE94794B067F876A215D96EE09") v = [int.from_bytes(v[i:i+4], byteorder="little") for i in range(0, len(v), 4)] delta = 1640531527 for i in range(0, len(v), 2): v[i:i+2] = tea_decrypt(32, v[i:i+2], k, delta) # print(list(map(hex, v))) v = "".join([int.to_bytes(v[i], byteorder='little', length=4).decode() for i in range(len(v))]) print(v) ~~~ `justCTF{TheConnection_w4s_interrupted} ` ## slowrun 题目顾名思义,就是跑的慢。这题最快的做法就是一个个函数交给大模型,让他分析是做什么运算的 ~~~c int __fastcall main(int argc, const char **argv, const char **envp) { __int64 v4; // [rsp+18h] [rbp-18h] __int64 v5; // [rsp+20h] [rbp-10h] char *ptr; // [rsp+28h] [rbp-8h] if ( argc == 2 ) { v4 = sub_1DEC(argv[1], argv, envp); if ( v4 ) { if ( (int)sub_21E1(v4, 0LL) >= 0 ) { puts("allocating memory... lots... of... memory..."); sleep(3u); puts("warming up the CPU..."); sleep(3u); puts("increasing fan speed..."); sleep(3u); puts("calculating..."); v5 = sub_1878(v4); ptr = (char *)sub_34CC(v5); printf("flag: %s\n", ptr); sub_1F42(v5); sub_1F42(v4); free(ptr); return 0; } else { fprintf(stderr, "Invalid number: %s\n", argv[1]); sub_1F42(v4); return 1; } } else { fprintf(stderr, "Invalid number: %s\n", argv[1]); return 1; } } else { fprintf(stderr, "Usage: %s <number>\n", *argv); return 1; } } ~~~ 由题目给的dockerfile可知传参13337 sub_1DEC是做一些初步处理,转为大整数的字符串形式 ~~~c _BYTE *__fastcall sub_1DEC(char *a1) { unsigned __int8 *v2; // rax _BYTE *v3; // rax char *s; // [rsp+8h] [rbp-28h] bool v5; // [rsp+12h] [rbp-1Eh] unsigned __int8 v6; // [rsp+13h] [rbp-1Dh] unsigned int size; // [rsp+14h] [rbp-1Ch] size_t size_4; // [rsp+18h] [rbp-18h] _BYTE *v9; // [rsp+20h] [rbp-10h] _BYTE *ptr; // [rsp+28h] [rbp-8h] s = a1; v5 = *a1 == 45; // 负号 if ( *a1 == 45 ) s = a1 + 1; while ( *s == 48 ) // 开头的0忽略 ++s; size = strlen(s); ptr = malloc(0x18uLL); if ( !ptr ) return 0LL; ptr[16] = v5; *((_DWORD *)ptr + 3) = size; *(_QWORD *)ptr = malloc(size); if ( *(_QWORD *)ptr ) { size_4 = (size_t)&s[size - 1]; v9 = *(_BYTE **)ptr; while ( size_4 >= (unsigned __int64)s ) { v2 = (unsigned __int8 *)size_4--; v6 = *v2; if ( *v2 <= 0x2Fu || v6 > 0x39u ) // 0x30-0x39 0-9 { sub_1F42(ptr); *__errno_location() = 22; return 0LL; } v3 = v9++; *v3 = v6 - 48; } *((_DWORD *)ptr + 2) = (_DWORD)v9 - *(_DWORD *)ptr; return ptr; } else { free(ptr); return 0LL; } } ~~~ sub_21E1结合动态调试和ai分析可知是个把大整数(字符串)转为int,用在作比较的地方,上面就是看是否大于等于0 接着直接看sub_1878,往里面不断分析可以发现多种运算,还原后如下 ~~~c void **__fastcall sub_1878(__int64 a1) { void **v2; // [rsp+10h] [rbp-20h] void **v3; // [rsp+18h] [rbp-18h] void **v4; // [rsp+20h] [rbp-10h] __int64 v5; // [rsp+28h] [rbp-8h] v2 = (void **)func1(a1); if ( (int)str2int(a1, 100) <= 0 ) return v2; v3 = (void **)str2big(off_6010); v4 = (void **)str2big(off_6018); v5 = mod((__int64)v2, (__int64)v3); add(v5, v4); free1(v3); free1(v4); free1(v2); return (void **)v5; } __int64 __fastcall func1(__int64 a1) { int v2; // eax __int64 v3; // [rsp+18h] [rbp-28h] __int64 v4; // [rsp+20h] [rbp-20h] __int64 v5; // [rsp+28h] [rbp-18h] __int64 v6; // [rsp+30h] [rbp-10h] __int64 v7; // [rsp+38h] [rbp-8h] if ( !(unsigned int)str2int(a1, 0) ) return int2big(2LL); if ( (int)str2int(a1, 1) <= 0 ) return int2big(1LL); v3 = int2big(0LL); v4 = int2big(73LL); mul(v4, a1); mul(v4, a1); mul(v4, a1); mul(v4, a1); mul(v4, a1); v6 = int2big(8LL); mul(v6, a1); mul(v6, a1); mul(v6, a1); v2 = sub_33A9(a1); v7 = sub_1D21(a1, (unsigned int)(v2 + 1)); sub(v7, 1LL); v5 = func2(v7); add(v3, a1); sub(v3, 4LL); add(v3, v4); add(v3, v5); add(v3, v6); free1(v4); free1(v5); free1(v6); free1(v7); return v3; } __int64 __fastcall func2(__int64 a1) { int v2; // eax int v3; // eax int v4; // eax __int64 v5; // [rsp+10h] [rbp-40h] __int64 v6; // [rsp+18h] [rbp-38h] __int64 v7; // [rsp+20h] [rbp-30h] __int64 v8; // [rsp+28h] [rbp-28h] __int64 v9; // [rsp+30h] [rbp-20h] __int64 v10; // [rsp+38h] [rbp-18h] __int64 v11; // [rsp+40h] [rbp-10h] __int64 v12; // [rsp+48h] [rbp-8h] if ( (int)str2int(a1, 1) <= 0 ) return int2big(1LL); v5 = int2big(0LL); v2 = sub_33A9(a1); v10 = sub_1D21(a1, (unsigned int)(v2 + 1)); sub(v10, 1LL); v6 = func1(v10); v3 = sub_33A9(a1); v11 = sub_1D21(a1, (unsigned int)(v3 + 1)); sub(v11, 2LL); v7 = func1(v11); mul1(v7, 3LL); v4 = sub_33A9(a1); v12 = sub_1D21(a1, (unsigned int)(v4 + 1)); sub(v12, 3LL); v8 = func1(v12); mul1(v8, 5LL); v9 = int2big(3LL); mul(v9, a1); mul(v9, a1); mul(v9, a1); mul(v9, a1); add(v5, v6); add(v5, v7); sub1(v5, v8); add(v5, v9); free1(v7); free1(v8); free1(v9); free1(v10); free1(v11); free1(v12); return v5; } ~~~ 总结如下: $$ f(x)=73x^5+8x^3+g(x-1)+x-4 $$ $$ h(x)=f(x-1)+3f(x-2)-5f(x-3)+3x^4 $$ 如果按照他的做法确实计算很长时间,要想加速可以利用缓存表(算法题思路),把每个计算好的func1(x)和func2(x)存储起来,下次调用直接查表 只需要计算出f(13337)再做个模运算和加法即可得到flag ~~~python import time def solve_f_and_h(n_target): """ 使用迭代和记忆化(查表)来计算 f(n) 和 h(n) """ # 初始化缓存,用于存储已计算的值 f_cache = {-1: 1, 0: 2, 1: 1} h_cache = {0: 1, 1: 1} start_time = time.time() for k in range(2, n_target + 1): # 计算 f(k),它依赖 h(k-1) # f(k) = 73k^5 + 8k^3 + k - 4 + h(k-1) poly_f = 73 * (k ** 5) + 8 * (k ** 3) + k - 4 f_cache[k] = poly_f + h_cache[k - 1] # 计算 h(k),它依赖 f(k-1), f(k-2), f(k-3) # h(k) = f(k-1) + 3*f(k-2) - 5*f(k-3) + 3k^4 term1 = f_cache[k - 1] term2 = 3 * f_cache[k - 2] term3 = 5 * f_cache[k - 3] term4 = 3 * (k ** 4) h_cache[k] = term1 + term2 - term3 + term4 end_time = time.time() print(f"计算耗时: {end_time - start_time:.4f} 秒") return f_cache[n_target] # --- 主程序 --- n = 13337 final_result = solve_f_and_h(n) print("-" * 50) print(f"f({n}) 的最终计算结果是:") print(final_result) print("-" * 50) a = int("12871709638832864416674237492708808074465131233250468097567609804146306910998417223517320307084142930385333755674444057095681119233485961920941215894136808839080569675919567597231") b = int("805129649450289111374098215345043938348341847793365469885914570440914675704049341968773123354333661444680237475120349087680072042981825910641377252873686258216120616639500404381") final_result = (a+final_result % a)%a + b from Crypto.Util.number import long_to_bytes print(long_to_bytes(final_result).decode()) ~~~ `justCTF{1n_0rd3r_70_und3r574nd_r3cur510n_y0u_h4v3_t0_und3r574nd_r3cur510n}` ## 6pack MiscRE!不过感觉主要还是RE,给了个go流量过滤什么的,挺难读懂,最后从流量包ipv6数据包里提取出了一个带upx壳的exe 题目要求带两个参数,第一个是flag第二个是满足v13 >> 11 == 0xF的数(可知范围为0b111100000000000~0b1111000000000000,后者不包含) ~~~c int __fastcall main(int argc, const char **argv, const char **envp) { int v3; // ebx void *v4; // rsi const char *v7; // rbp int v8; // eax void *v9; // rax int v10; // eax const char *v11; // rcx unsigned __int16 v13; // [rsp+2Eh] [rbp-4Ah] BYREF SIZE_T dwSize; // [rsp+30h] [rbp-48h] BYREF void *Src; // [rsp+38h] [rbp-40h] int v16; // [rsp+40h] [rbp-38h] BYREF unsigned __int16 *v17; // [rsp+48h] [rbp-30h] sub_7FF726F41550(); if ( argc != 3 ) { LABEL_9: VirtualFree(v4, 0LL, 0x8000u); goto LABEL_11; } v7 = argv[1]; v13 = atoi(argv[2]); dwSize = 0LL; Src = 0LL; v3 = sub_7FF726F42730(&dwSize); if ( !v3 ) { v16 = 2; v17 = &v13; if ( v13 >> 11 == 0xF ) { v8 = sub_7FF726F426E0(&dwSize, &v16); if ( !v8 ) { v9 = VirtualAlloc(0LL, dwSize, 0x3000u, 0x40u); v4 = v9; if ( !v9 ) goto LABEL_11; memcpy(v9, Src, dwSize); v10 = (v4)(v7); v11 = "correct"; v3 = v10; if ( v10 ) v11 = "nope"; puts(v11); goto LABEL_9; } v3 = v8; } } LABEL_11: if ( Src ) free(Src); return v3; } ~~~ 其中sub_7FF726F42730函数读取6-pack里的内容 ~~~c __int64 __fastcall sub_7FF726F42730(__int64 a1) { FILE *v2; // rax FILE *v3; // rbx void *v4; // rsi int v5; // r14d void *v6; // rax int v7; // edx _BYTE Buffer[40]; // [rsp+20h] [rbp-F0h] BYREF int v10; // [rsp+48h] [rbp-C8h] unsigned __int16 v11; // [rsp+5Ah] [rbp-B6h] unsigned __int16 v12; // [rsp+5Ch] [rbp-B4h] unsigned __int16 v13; // [rsp+5Eh] [rbp-B2h] _BYTE v14[24]; // [rsp+60h] [rbp-B0h] BYREF int Offset; // [rsp+78h] [rbp-98h] size_t Size; // [rsp+80h] [rbp-90h] _DWORD v17[8]; // [rsp+A0h] [rbp-70h] BYREF size_t ElementSize; // [rsp+C0h] [rbp-50h] v2 = fopen("./6-pack", "rb"); if ( !v2 ) return 1LL; v3 = v2; fread(Buffer, 0x40uLL, 1uLL, v2); if ( fseek(v3, v10 + v11 * v13, 0) < 0 ) goto LABEL_3; fread(v14, 0x40uLL, 1uLL, v3); v4 = malloc(Size); if ( fseek(v3, Offset, 0) < 0 ) goto LABEL_3; v5 = 0; fread(v4, Size, 1uLL, v3); while ( 1 ) { if ( v12 <= v5 ) goto LABEL_12; if ( fseek(v3, v10 + v5 * v11, 0) < 0 ) goto LABEL_3; fread(v17, 0x40uLL, 1uLL, v3); if ( !strcmp(v4 + v17[0], ".go.runtimeinfo") ) break; ++v5; } v6 = malloc(ElementSize); v7 = v17[6]; *(a1 + 8) = v6; if ( fseek(v3, v7, 0) < 0 ) LABEL_3: exit(1); fread(*(a1 + 8), ElementSize, 1uLL, v3); *a1 = ElementSize; LABEL_12: free(v4); fclose(v3); return 0LL; } ~~~ sub_7FF726F426E0调用了advapi32.dll的SystemFunction033,查询可知是一个RC4加密 ~~~c __int64 __fastcall sub_7FF726F426E0(__int64 a1, __int64 a2) { HMODULE LibraryA; // rax FARPROC SystemFunction033; // rax LibraryA = LoadLibraryA("advapi32.dll"); if ( !LibraryA ) return 1LL; SystemFunction033 = GetProcAddress(LibraryA, "SystemFunction033"); if ( !SystemFunction033 ) return 1LL; (SystemFunction033)(a1, a2); return 0LL; } ~~~ 由`(v4)(v7)`可以知道必须输入正确的数字才能进入正常的函数,需要爆破,思路是逐个尝试如果能返回nop说明进入v4可以正常返回,但不一定是答案还需要结合动态调试逐一确认 ~~~python import threading import subprocess import time # 1. 导入 time 模块 # --- 共享资源 --- executable = "./download.exe" arg1 = "aaaa" stop_event = threading.Event() found_key = None def brute_force_worker(key_list): """每个工作线程执行这个函数,并增加了计时功能""" global found_key for key in key_list: if stop_event.is_set(): return command = [executable, arg1, str(key)] try: # 2. 记录命令执行前的开始时间 start_time = time.monotonic() result = subprocess.run(command, capture_output=True, text=True, check=False, timeout=10) # 3. 记录命令执行完毕后的结束时间 end_time = time.monotonic() # 4. 计算执行耗时 duration = end_time - start_time # 将标准输出和标准错误合并检查 output = result.stdout + result.stderr # 在打印信息中加入耗时 print(f"[*] 线程 {threading.current_thread().name} 尝试密钥: {key} (耗时: {duration:.4f} 秒)") if "nope" in output and output.strip(): print("\n" + "=" * 40) print(f"[!!!] 线程 {threading.current_thread().name} 成功!找到密钥: {key} (总耗时: {duration:.4f} 秒)") print(f"[*] 程序输出: \n{output}") print("=" * 40) except subprocess.TimeoutExpired: # 如果超时,也打印一下耗时信息 duration = time.monotonic() - start_time print(f"[警告] 线程 {threading.current_thread().name} 尝试密钥: {key} 超时! (已运行超过 {duration:.2f} 秒)") continue except Exception as e: # print(f"尝试密钥 {key} 时出错: {e}") continue # --- 主线程逻辑 (保持不变) --- if __name__ == "__main__": keys_to_check = list(range(30720, 32768)) num_threads = 16 chunk_size = len(keys_to_check) // num_threads if len(keys_to_check) % num_threads != 0: chunk_size += 1 # 确保能覆盖所有密钥 chunks = [keys_to_check[i:i + chunk_size] for i in range(0, len(keys_to_check), chunk_size)] threads = [] for i, chunk in enumerate(chunks): thread = threading.Thread(target=brute_force_worker, args=(chunk,), name=f"Worker-{i + 1}") threads.append(thread) print(f"启动线程 Worker-{i + 1},负责 {len(chunk)} 个密钥。") thread.start() for thread in threads: thread.join() if found_key is None: print("\n所有密钥尝试完毕,未找到正确密钥。") ~~~ 最后确认31337是正确的,动调跑进去看,可以看到获取了输入长度要求36 ~~~c debug030:0000027357E40000 mov r15, rcx debug030:0000027357E40003 call loc_27357E4002D debug030:0000027357E40008 mov r14, rax debug030:0000027357E4000B cmp r14, 24h ; '$' debug030:0000027357E4000F jz short loc_27357E40017 debug030:0000027357E40011 mov eax, 1 debug030:0000027357E40016 retn debug030:0000027357E40017 ; --------------------------------------------------------------------------- debug030:0000027357E40017 debug030:0000027357E40017 loc_27357E40017: ; CODE XREF: debug030:0000027357E4000F↑j debug030:0000027357E40017 call loc_27357E40046 debug030:0000027357E4001C call loc_27357E4006C debug030:0000027357E40021 mov rcx, r15 debug030:0000027357E40024 mov rdx, r14 debug030:0000027357E40027 call near ptr unk_27357E40100 debug030:0000027357E4002C retn debug030:0000027357E4002D ; --------------------------------------------------------------------------- debug030:0000027357E4002D debug030:0000027357E4002D loc_27357E4002D: ; CODE XREF: debug030:0000027357E40003↑p debug030:0000027357E4002D mov rdi, rcx debug030:0000027357E40030 xor rax, rax debug030:0000027357E40033 mov ecx, 100h debug030:0000027357E40038 repne scasb debug030:0000027357E4003A mov eax, 100h debug030:0000027357E4003F sub rax, rcx debug030:0000027357E40042 dec rax debug030:0000027357E40045 retn debug030:0000027357E40046 ; --------------------------------------------------------------------------- debug030:0000027357E40046 debug030:0000027357E40046 loc_27357E40046: ; CODE XREF: debug030:loc_27357E40017↑p debug030:0000027357E40046 lea rdi, [r15] debug030:0000027357E40049 lea rsi, [r15+r14-1] debug030:0000027357E4004E mov rcx, r14 debug030:0000027357E40051 shr rcx, 1 debug030:0000027357E40054 debug030:0000027357E40054 loc_27357E40054: ; CODE XREF: debug030:0000027357E40066↓j debug030:0000027357E40054 movzx rax, byte ptr [rdi] debug030:0000027357E40058 movzx rbx, byte ptr [rsi] debug030:0000027357E4005C mov [rsi], al debug030:0000027357E4005E mov [rdi], bl debug030:0000027357E40060 inc rdi debug030:0000027357E40063 dec rsi debug030:0000027357E40066 loop loc_27357E40054 debug030:0000027357E40068 xor rax, rax debug030:0000027357E4006B retn debug030:0000027357E4006C ; --------------------------------------------------------------------------- debug030:0000027357E4006C debug030:0000027357E4006C loc_27357E4006C: ; CODE XREF: debug030:0000027357E4001C↑p debug030:0000027357E4006C mov ecx, 700h debug030:0000027357E40071 lea rdi, unk_27357E40100 debug030:0000027357E40078 debug030:0000027357E40078 loc_27357E40078: ; CODE XREF: debug030:0000027357E4007D↓j debug030:0000027357E40078 xor byte ptr [rdi+rcx-1], 17h debug030:0000027357E4007D loop loc_27357E40078 debug030:0000027357E4007F retn ~~~ 然后跳转loc_27357E40017,调用loc_27357E40046,然后继续调用loc_27357E4006C,该地方对unk_27357E40100做了循环异或0x17,即SMC;结束后即可进入check函数 ~~~c _BOOL8 __fastcall sub_27357E40100(__int64 a1, unsigned __int64 a2) { void (__fastcall *v2)(char *); // rax __int64 v3; // rcx __int64 v4; // rax __int64 v6; // [rsp+28h] [rbp-48h] _QWORD v7[4]; // [rsp+30h] [rbp-40h] BYREF unsigned __int64 v8; // [rsp+50h] [rbp-20h] __int64 v9; // [rsp+58h] [rbp-18h] unsigned __int64 v10; // [rsp+60h] [rbp-10h] __int64 v11; // [rsp+68h] [rbp-8h] v11 = a1; v10 = a2; v9 = 0LL; v8 = 0LL; memset(v7, 0, sizeof(v7)); v6 = 0LL; v2 = (sub_27357E401F8)(NtCurrentPeb()->Ldr->InMemoryOrderModuleList.Flink->Flink->Flink[2].Flink, dword_27357E40253); v2(aBcryptDll); v8 = v10 / 3; do { v3 = v11; v11 += 3LL; sub_27357E4026F(v3, v7); // sha256 v4 = v9; LOBYTE(v4) = memcmp(&unk_27357E403D0 + 8 * v9, v7, 0x20uLL) == 0; v6 += v4; v9 += 4LL; --v8; } while ( v8 ); return v6 != 12; } ~~~ 稍微跟进可知对每三位进行sha256并和硬编码数据比较,直接写表爆破即可 ~~~python import hashlib import time def create_reverse_hash_map(): """ 创建从 SHA-256 哈希值到原始3字符的反向映射表。 我们假设字符集为所有可见的ASCII字符(从空格到~)。 """ print("[-] 正在创建3字符的SHA-256哈希映射表,请稍候...") start_time = time.time() # 字符集:ASCII码从32 (空格) 到 126 (~) possible_chars = [chr(i) for i in range(32, 127)] hash_to_string_map = {} count = 0 total = len(possible_chars) ** 3 # 生成所有可能的3字符组合 for c1 in possible_chars: for c2 in possible_chars: for c3 in possible_chars: original_string = c1 + c2 + c3 # 字符串需要编码成字节才能进行哈希 encoded_string = original_string.encode('ascii') # 计算SHA-256哈希值并转为十六进制字符串 sha256_hash = hashlib.sha256(encoded_string).hexdigest() # 存入映射表 hash_to_string_map[sha256_hash] = original_string count += 1 if count % 100000 == 0: print(f" ...已生成 {count}/{total} 个哈希", end='\r') end_time = time.time() print(f"\n[+] 映射表创建完毕,共计 {len(hash_to_string_map)} 个条目,耗时 {end_time - start_time:.2f} 秒。") return hash_to_string_map def find_original_string(target_hash_concat, hash_map): """ 根据拼接的哈希字符串和映射表,找出原始字符串。 """ print("[-] 正在解析并查找原始字符串...") if len(target_hash_concat) % 64 != 0: print("[错误] 目标哈希字符串的长度不是64的倍数。") return None # 将长字符串分割成单个SHA-256哈希值的列表 target_hashes = [target_hash_concat[i:i + 64] for i in range(0, len(target_hash_concat), 64)] original_parts = [] all_found = True for i, target_hash in enumerate(target_hashes): # 在映射表中查找 original_chunk = hash_map.get(target_hash.lower()) # 将目标哈希转为小写以匹配 if original_chunk: original_parts.append(original_chunk) else: print(f"[警告] 未能找到第 {i + 1} 个哈希值 '{target_hash[:16]}...' 对应的原始字符。") original_parts.append("???") # 用'???'作为占位符 all_found = False if all_found: print("[+] 所有哈希值均已成功匹配!") # 拼接所有找到的部分 return "".join(original_parts) # --- 主程序 --- if __name__ == "__main__": # 您提供的拼接起来的哈希值表 long_hash_string = "204001DE61EE2B59F771F53FEB640F350932C5CDE699E23B27662995D4BD041673FE4A5E486AE1F4D033C595C5AAC79E6AFEAE7A28B7829C3EA97F0C7475FF30A38DF01B42FE1009F1DA3C3BF7787BEACD5CE1743E6D19F6D46D096FD0BBA90A677562C4990949FB8E8C2F8166F80D8151A4A1C0E0679AC24D454633C1709C2916DB9AE9D8A6B5DC7616FB3B0B74E287E492E7D295961A0A14B9EE935C825D59AAC513EA306B59B9AA9AF987D390E38DF0928918B25656C180C235B9AF7BE296B7CF5A8D7EB93D4D825A400FA173020A0D5CD34A8C2F4F818D01CA2BD991C215487D3CFD82C3915466513E097C6B00593D8C677CE54B2A292FDE8B14F88CCB89933130B10131093C4463F7C372BA435C091A87A9B77803853F2C5AB5A3F33CAA547D5E2A740B5D7D7C94C9B9333C8183E13A858A528C8188FDDD2FE187A07CC07C5CD81D84046CAAC335C2AFD9673729BA0FBA09FB7CB225FEDB6499BE5EFC29EE340EA3ECF77D89247E264015C071D8BBD66B30FB49479A55C9225282B19287" # 1. 创建反向映射表 reverse_map = create_reverse_hash_map() # 2. 查找原始字符串 original_string = find_original_string(long_hash_string, reverse_map) if original_string: print("\n" + "=" * 50) print("还原后的原始字符串是:") print(original_string[::-1]) print("=" * 50) ~~~ `justCTF{ipv6_ch4t___h0w_b4d_1s_th4t}` ## java > what the fxxk is this?好吧菜的根本没法做,一直在试图找工具,但实际上需要你编译一个新java版本来debug;过于超模了,pass 最后修改:2025 年 08 月 05 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏