zer0pts CTF
64bit ELF. its main function is pretty simple.
__int64 __fastcall main(int a1, char **a2, char **a3)
{
if ( a1 > 1 )
{
if ( !strcmp(a2[1], "zer0pts{********CENSORED********}") )
puts("Correct!");
else
puts("Wrong!");
}
else
{
printf("Usage: %s <FLAG>\n", *a2);
}
return 0LL;
}
There was a suspicious function sub_6EA
. Let's decompile with IDA demo.
_int64 __fastcall sub_6EA(__int64 a1, __int64 a2)
{
int i; // [rsp+18h] [rbp-8h]
int v4; // [rsp+18h] [rbp-8h]
int j; // [rsp+1Ch] [rbp-4h]
for ( i = 0; *(_BYTE *)(i + a1); ++i )
;
v4 = (i >> 3) + 1;
for ( j = 0; j < v4; ++j )
*(_QWORD *)(8 * j + a1) -= qword_201060[j];
return qword_201090(a1, a2);
}
This function process char[]
as long[]
to get difference with qword_201060
. To recover the correct input, we can recover the difference from zer0pts{********CENSORED********}
.
from struct import pack, unpack
bs = bytes([0x00,(...snip...),0x00]) # qword_201060
flag = "zer0pts{********CENSORED********}"
while len(flag) % 8 != 0:
flag += "\0"
size = len(flag) // 8
# intepreted bytes array as long[]
xs = unpack("q" * size, bs[: size * 8])
ys = unpack("q" * size, flag[: size * 8].encode())
# adding two long values, then cast to bytes
result = b""
for x, y in zip(xs, ys):
result += b"".join(unpack("8c", int.to_bytes(y + x, 8, "little")))
print(result)
then got the flag zer0pts{l3ts_m4k3_4_DETOUR_t0d4y}