JustCTF 2025 WP
20th,re 4/5
baby-goes-re
go逆向,检查flag长度为53,然后main_CheckFlag gemini秒了
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里找关键字符串,定位到解密函数
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解密
__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;
}
直接脚本一把梭
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
题目顾名思义,就是跑的慢。这题最快的做法就是一个个函数交给大模型,让他分析是做什么运算的
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是做一些初步处理,转为大整数的字符串形式
_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,往里面不断分析可以发现多种运算,还原后如下
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
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,后者不包含)
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里的内容
__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加密
__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可以正常返回,但不一定是答案还需要结合动态调试逐一确认
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
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函数
_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并和硬编码数据比较,直接写表爆破即可
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