Open roaris opened 5 months ago
$ ./three
Enter the FLAG: test
Invalid FLAG
IDAでmain関数を確認する validate_flagという関数が呼ばれている
validate_flagはIDAで見てもどういう処理になっているのか分からなかったので、Ghidraでデコンパイルする 以下の結果が得られた
undefined8 validate_flag(char *param_1)
{
char cVar1;
size_t sVar2;
undefined8 uVar3;
int local_c;
sVar2 = strlen(param_1);
if (sVar2 == 0x31) {
for (local_c = 0; local_c < 0x31; local_c = local_c + 1) {
if (local_c % 3 == 0) {
cVar1 = (char)*(undefined4 *)(flag_0 + (long)(local_c / 3) * 4);
}
else if (local_c % 3 == 1) {
cVar1 = (char)*(undefined4 *)(flag_1 + (long)(local_c / 3) * 4);
}
else {
cVar1 = (char)*(undefined4 *)(flag_2 + (long)(local_c / 3) * 4);
}
if (cVar1 != param_1[local_c]) {
puts("Invalid FLAG");
return 1;
}
}
puts("Correct!");
uVar3 = 0;
}
else {
puts("Invalid FLAG");
uVar3 = 1;
}
return uVar3;
}
flag_0, flag_1, flag_2はGhidraでも確認出来るが、IDAの方がASCII文字に変換してくれるので分かりやすい
4バイト間隔で、文字が配置されており、flag_0 + (long)(local_c / 3) * 4
の* 4
はこれが理由
以下のプログラムで解ける
flag_0 = 'c4c_ub__dt_r_1_4}'
flag_1 = 'tb4y_1tu04tesifg'
flag_2 = 'f{n0ae0n_e4ept13'
flag = ''
for i in range(0x31):
if i % 3 == 0:
flag += flag_0[i // 3]
elif i % 3 == 1:
flag += flag_1[i // 3]
else:
flag += flag_2[i // 3]
print(flag)
元のプログラムを見ると、flag_0, flag_1, flag_2はint型の配列になっていた 配列1つの要素に32ビット確保され、リトルエンディアンで並ぶので、IDAで見たようになるのが納得できる
const int flag_0[17] = {99, 52, 99, 95, 117, 98, 95, 95, 100,
116, 95, 114, 95, 49, 95, 52, 125};
const int flag_1[16] = {116, 98, 52, 121, 95, 49, 116, 117,
48, 52, 116, 101, 115, 105, 102, 103};
const int flag_2[16] = {102, 123, 110, 48, 97, 101, 48, 110,
95, 101, 52, 101, 112, 116, 49, 51};
https://github.com/SECCON/SECCON_Beginners_CTF_2023/tree/main/reversing/three