Try   HackMD

[zer0pts CTF] easy strcmp

tags: zer0pts CTF

overview

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; }

solution

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}