NahamCon CTF 2025

NahamCon CTF 2025

August 10, 2025
3 min read
index

Introduction

Rev

What’s a Base?

What’s a base amongst friends though, really?

let’s throw the binary at IDA. personally i like to do a quick glance at strings, and sometimes FLARE CAPA if i want, and we learn that its a rust binary.

btw i quickly ran it, it asks for a password.

found the function of interest and decompiled:

__int64 sub_79B0()
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]
*&v28 = &off_57D18;
*(&v28 + 1) = 1;
v29.m256i_i64[0] = 8;
*&v29.m256i_u64[1] = 0;
std::io::stdio::_print(&v28);
v25 = 0;
v26 = 1;
v27 = 0;
*&v36[0] = unknown_libname_61();
if ( (sub_25960(v36, &v25) & 1) != 0 )
{
*&v28 = v0;
core::result::unwrap_failed(aCalledResultUn, 43, &v28, &off_57CF8, &off_57D28);
}
v1 = (v26 + v27);
if ( v27 )
{
v2 = 0;
v3 = v26;
while ( 1 )
{
v5 = v3;
v6 = v2;
v7 = *v3;
if ( (v7 & 0x80u) != 0 )
{
v8 = v7 & 0x1F;
v9 = v3[1] & 0x3F;
if ( v7 <= 0xDFu )
{
v3 += 2;
v7 = v9 | (v8 << 6);
}
else
{
v10 = (v9 << 6) | v3[2] & 0x3F;
if ( v7 < 0xF0u )
{
v3 += 3;
v7 = (v8 << 12) | v10;
}
else
{
v3 += 4;
v7 = ((v7 & 7) << 18) | (v10 << 6) | v5[3] & 0x3F;
}
}
}
else
{
++v3;
}
v2 += v3 - v5;
if ( v7 - 9 >= 5 && v7 != 32 )
{
if ( v7 < 0x80 )
goto LABEL_26;
v11 = v7 >> 8;
if ( v7 >> 8 > 0x1F )
{
if ( v11 == 32 )
{
v4 = byte_4E857[v7] >> 1;
}
else
{
if ( v11 != 48 )
goto LABEL_26;
v4 = v7 == 12288;
}
}
else if ( v11 )
{
if ( v11 != 22 )
goto LABEL_26;
v4 = v7 == 5760;
}
else
{
v4 = byte_4E857[v7];
}
if ( (v4 & 1) == 0 )
goto LABEL_26;
}
if ( v3 == v1 )
goto LABEL_52;
}
}
v6 = 0;
v2 = 0;
v3 = v26;
LABEL_26:
while ( v3 != v1 )
{
v13 = v1;
v14 = *(v1 - 1);
if ( (v14 & 0x80000000) != 0 )
{
v15 = *(v1 - 2);
if ( v15 >= -64 )
{
v1 -= 2;
v18 = v15 & 0x1F;
}
else
{
v16 = *(v1 - 3);
if ( v16 >= -64 )
{
v1 -= 3;
v17 = v16 & 0xF;
}
else
{
v1 -= 4;
v17 = ((*(v13 - 4) & 7) << 6) | v16 & 0x3F;
}
v18 = (v17 << 6) | v15 & 0x3F;
}
v14 = (v18 << 6) | v14 & 0x3F;
if ( v14 - 9 < 5 )
continue;
}
else
{
--v1;
if ( v14 - 9 < 5 )
continue;
}
if ( v14 != 32 )
{
if ( v14 < 0x80 )
goto LABEL_66;
v19 = v14 >> 8;
if ( v14 >> 8 > 0x1F )
{
if ( v19 == 32 )
{
v12 = byte_4E857[v14] >> 1;
}
else
{
if ( v19 != 48 )
{
LABEL_66:
v2 = &v13[v2 - v3];
goto LABEL_53;
}
v12 = v14 == 12288;
}
}
else if ( v19 )
{
if ( v19 != 22 )
goto LABEL_66;
v12 = v14 == 5760;
}
else
{
v12 = byte_4E857[v14];
}
if ( (v12 & 1) == 0 )
goto LABEL_66;
}
}
if ( !v27 )
{
LABEL_52:
v6 = 0;
v2 = 0;
}
LABEL_53:
v20 = v2 - v6;
v21 = &v6[v26];
sub_8B40(&v33, &v6[v26], v20);
v22 = s1;
if ( v35 == 88 && !bcmp(s1, aM7xzr7muqtxsr3, 0x58u) )
{
v37 = 0;
memset(v36, 0, sizeof(v36));
v39 = 0;
for ( i = xmmword_49000; v20; v20 -= v24 )
{
v24 = 0xFFFFFFFFLL;
if ( v20 < 0xFFFFFFFF )
v24 = v20;
sub_80F0(v36, v21, v24);
v21 += v24;
}
v32 = v39;
v31 = i;
v30 = v37;
v29 = *&v36[1];
v28 = v36[0];
sub_8000(v40, &v28);
*&v36[0] = v40;
*(&v36[0] + 1) = sub_8920;
*&v28 = &off_57D50;
*(&v28 + 1) = 2;
v29.m256i_i64[0] = v36;
*&v29.m256i_u64[1] = 1u;
result = std::io::stdio::_print(&v28);
}
else
{
*&v28 = &off_57D40;
*(&v28 + 1) = 1;
v29.m256i_i64[0] = 8;
*&v29.m256i_u64[1] = 0;
result = std::io::stdio::_print(&v28);
}
if ( v33 )
result = j___rdl_dealloc(v22, v33, 1);
if ( v25 )
return j___rdl_dealloc(v26, v25, 1);
return result;
}

from this, we can note one important thing: it’s using bcmp (a way to compare things) against a string. let’s look at that string:

m7xzr7muqtxsr3m8pfzf6h5ep738ez5ncftss7d1cftskz49qj4zg7n9cizgez5up

due to the name of the challenge, i first tried base64, but even my brain heuristic tells me it’s probably not base64, and i was right. it gave only garbage.

so we head over to the dcode.fr cipher identifier and see that it is Z-Base-32, and decoding it gives us our intended password:

__rust_begin_short_backtrace__rust_end_short_backtraces

(im sure you could have reimplemented the operations being performed by the binary, but nah im too lazy, its just zbase32)

once we feed that password into the binary we get the flag:

flag{50768fcb270edc499750ea64dc45ee92}

Misc

Cube

Astronomical.

the challenge gives you a nc connection to a server. in this server we have the options to move around in 3D, there are rooms with IDs.

the challenge premise is that you can move into any room, but if the room id (which looks like 049-125-625) has any numbers that are any number raised to a power (a “perfect exponent”), then it will kill you instantly. note that the example room id is deadly for sure cuz 49=72,125=53,625=5449 = 7^2, 125 = 5^3, 625 = 5^4. we needed to navigate to a certain spot so a pwntools script does it.

sadly i couldnt dig up the script cuz too lazy. womp womp