roaris / ctf-log

0 stars 0 forks source link

SECCON Beginners CTF 2023: three #53

Open roaris opened 1 month ago

roaris commented 1 month ago

https://github.com/SECCON/SECCON_Beginners_CTF_2023/tree/main/reversing/three

roaris commented 1 month ago
$ ./three
Enter the FLAG: test
Invalid FLAG
roaris commented 1 month ago

IDAでmain関数を確認する validate_flagという関数が呼ばれている

image

roaris commented 1 month ago

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;
}
roaris commented 1 month ago

flag_0, flag_1, flag_2はGhidraでも確認出来るが、IDAの方がASCII文字に変換してくれるので分かりやすい 4バイト間隔で、文字が配置されており、flag_0 + (long)(local_c / 3) * 4* 4はこれが理由

image

image

roaris commented 1 month ago

以下のプログラムで解ける

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)
roaris commented 1 month ago

元のプログラムを見ると、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};