Hackappatoi CTF '22 Writeup

この大会は2022/12/10 3:00(JST)~2022/12/12 0:00(JST)に開催されました。
今回もチームで参戦。結果は2876点で293チーム中19位でした。
自分で解けた問題をWriteupとして書いておきます。

Drunk check (Misc)

Discordに入り、#cocktail-barチャネルのメッセージの先頭を見たら、フラグが書いてあった。

HCTF{Hackappatoi_2022}

Qrunk (Misc)

StegSolveで開き、Blue plane 0を見ると、QRコードの白黒反転したものが表示された。

QRコードをデコードすると、以下のURLが読み取れた。

https://raw.githubusercontent.com/1vcian/90-45/main/90%2C45.txt

ここにアクセスすると、90*45,の後に0, 1が並んでいるテキストが書いてあった。

90*45,000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111111111100110000111100001111000000111111110011110000001111111111111100000000000000001100000000001100001111000000000011001111001100001111000011001100000000001100000000000000001100111111001100000011001100001111001100111100001111001100001100111111001100000000000000001100111111001100000000001100000011000011000000111100001100001100111111001100000000000000001100111111001100001100110000111111110000001111110000000000001100111111001100000000000000001100000000001100000011001100001111001100110000110000000011001100000000001100000000000000001111111111111100110011001100110011001100110011001100110011001111111111111100000000000000000000000000000000110011110011001111001111000000000011001111000000000000000000000000000000001111001111001100001111110011000011110011001100110000111100001100000000001100000000000000000000001111110000000000001111000011000011000011111100001100000011110000110000000000000000000000110000001111001100110011001111110000110011110011001111001100001111111100000000000000000000111111110011000000111111000000110011110011000000111100001100000011000000000000000000001100000000001100110000111111000000110000110000111100110000111111001100111100000000000000000000000011000011110000000011111111111111001111110011001100000000111111110000000000000000000011110011001111001100111111001100001111110011000011111111110000000000111100000000000000001100001100110011111100110000001100001111000000001100110011000011110011001100000000000000000011110000001111110000000000111111110011110011111111000000001111001111111100000000000000001111000000000011111100111111111111000011110000000000111100110011001100000000000000000000001100110000111111001100110000001100000011110000111100001100111111110000001100000000000000001111001111110011111100001100110000000011000011000011001100110000111100001100000000000000000011000011001100000011001111111100000011000011111100001111111100110000111100000000000000000000001100000000000000000000111111110011000000110011001100000011111111110000000000000000001100001100001111001111001100111111111100001100111100111100000011110011001100000000000000001100110000110011000000000000111100110011110011000000110000000011001111111100000000000000001111111111111100110011000011110000001100000000111111001100001100000000001100000000000000001100111111000000110011001100000011000011000011110011001111000000111100110000000000000000001111111100111100110000000000111111001111000000000000111100110000110000111100000000000000001100001100000011110011001111110000001100000000110000000011111111001111001100000000000000001100001111111100000011111100001111000011111111000011001111111111110011110000000000000000000000000000000000110000110000001100110011111100001100000011000000111111110000000000000000001111111111111100000011001111111111110011110000110000000011001100110000001100000000000000001100000000001100001100110011000000000011000011001111001111000000110000001100000000000000001100111111001100111111110011001100000000001100000011111111111111111100111100000000000000001100111111001100110011001111001111110011000000000011001100001100001100111100000000000000001100111111001100001111110011001111000000000011110000110000110011111111001100000000000000001100000000001100111111111111001100110011000000001100001100000011001111111100000000000000001111111111111100111100111111001111110011000011111100000011000011000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

90*45に並べると、1が黒、0が白のQRコードになるので、1セル1文字になるよう調整し、qr.txtに保存する。

#!/usr/bin/env python3
with open('90,45.txt', 'r') as f:
    data = f.read()

size = data.split(',')[0]
data = data.split(',')[1]
w = int(size.split('*')[0])
h = int(size.split('*')[1])

rows = []
for i in range(0, len(data), w):
    rows.append(data[i:i+w])

for row in rows[4:-5]:
    r = ''
    for i in range(8, len(row) - 8, 2):
        r += row[i]
    print(r)
$ cat qr.txt
1111111010011001100011110110001111111
1000001001100000101101001100101000001
1011101000101001101011001101001011101
1011101000001000100100011001001011101
1011101001010011110001110000001011101
1000001000101001101010010000101000001
1111111010101010101010101010101111111
0000000010110101101100000101100000000
1101101001110100110101010011001000001
0001110000001100100100111001000110010
0010001101010101110010110101101001111
0011110100011100010110100011001000100
1000001010011100010010011010011101011
0000100110000111111101110101000011110
0110101101011101001110100111110000011
1001010111010001001100001010100110101
0110001110000011110110111100001101111
1100000111011111100110000011010101000
1010011101010001000110011001011110001
1101110111001010000100100101010011001
0100101000101111000100111001111010011
0001000000000011110100010101000111110
1001001101101011111001011011000110101
1010010100000011010110100010000101111
1111111010100110001000011101001000001
1011100010101000100100110101100011010
1111011010000011101100000011010010011
1001000110101110001000010000111101101
1001111000111001100111100101111110110
0000000010010001010111001000100011110
1111111000101111110110010000101010001
1000001001010100000100101101100010001
1011101011110101000001000111111111011
1011101010101101110100000101001001011
1011101001110101100000110010010111101
1000001011111101010100001001000101111
1111111011011101110100111000100100001
$ python sqrd.py qr.txt
https://www.youtube.com/watch?v=dQw4w9WgXcQ?flag=HCTF{w0w_W3ll_doNe_8RuH_Y0u_G0t_17}
HCTF{w0w_W3ll_doNe_8RuH_Y0u_G0t_17}

Aperol Spritz (Misc)

バイナリエディタでjpgの高さ442を1000に変える。具体的にはファイルのオフセット0xb0-0xb1の部分を 01 ba から 03 e8 に変える。画像の下に新しく画像が現れ、フラグが書かれていた。

HCTF{Ap3Rol_is_for_k1Dz_c4Mpar1_i5_f0r_Ch4d5}

Sanity rev (Reverse)

$ strings sanityrev | grep hctf{
hctf{It_h4s_b33N_345Y}
hctf{It_h4s_b33N_345Y}

eXclusive club (Reverse)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  int iVar1;
  undefined8 uVar2;
  size_t sVar3;
  long in_FS_OFFSET;
  char local_28 [24];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  printf("Welcome to our eXclusive club.\nType your password to join us.\n>");
  __isoc99_scanf(&DAT_00102048,local_28);
  uVar2 = obfuscation(local_28);
  sVar3 = strlen(local_28);
  iVar1 = check_access(uVar2,sVar3 & 0xffffffff);
  if (iVar1 == 0) {
    puts("You can\'t join us this time...");
  }
  else {
    puts("Access granted, bro!");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

void * obfuscation(char *param_1)

{
  size_t sVar1;
  void *pvVar2;
  int local_28;
  
  sVar1 = strlen(param_1);
  pvVar2 = malloc(sVar1 << 2);
  local_28 = 0;
  while( true ) {
    sVar1 = strlen(param_1);
    if (sVar1 <= (ulong)(long)local_28) break;
    *(uint *)((long)pvVar2 + (long)local_28 * 4) = (int)param_1[local_28] ^ 0x41;
    local_28 = local_28 + 1;
  }
  return pvVar2;
}

int check_access(long param_1,int param_2)

{
  int iVar1;
  long in_FS_OFFSET;
  int local_7c;
  int local_78 [26];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  iVar1 = 0;
  local_78[0] = 0x29;
  local_78[1] = 0x22;
  local_78[2] = 0x35;
  local_78[3] = 0x27;
  local_78[4] = 0x3a;
  local_78[5] = 0x24;
  local_78[6] = 0x19;
  local_78[7] = 0x22;
  local_78[8] = 0x2d;
  local_78[9] = 0x14;
  local_78[10] = 0x74;
  local_78[11] = 0x70;
  local_78[12] = 0x37;
  local_78[13] = 0x72;
  local_78[14] = 0x1e;
  local_78[15] = 0x71;
  local_78[16] = 0x33;
  local_78[17] = 0x1f;
  local_78[18] = 0xf;
  local_78[19] = 0x71;
  local_78[20] = 0x35;
  local_78[21] = 0x7e;
  local_78[22] = 0x3c;
  if (param_2 == 0x17) {
    for (local_7c = 0; local_7c < 0x17; local_7c = local_7c + 1) {
      iVar1 = local_78[local_7c];
      if (*(int *)(param_1 + (long)local_7c * 4) != iVar1) {
        iVar1 = 0;
        break;
      }
      if (local_7c == 0x16) {
        iVar1 = 1;
        break;
      }
    }
  }
  else {
    iVar1 = 0;
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return iVar1;
}

0x41とのXORがlocal_78[i]と一致すればよい。

#!/usr/bin/env python3
enc = [0x29, 0x22, 0x35, 0x27, 0x3a, 0x24, 0x19, 0x22, 0x2d, 0x14, 0x74, 0x70,
    0x37, 0x72, 0x1e, 0x71, 0x33, 0x1f, 0xf, 0x71, 0x35, 0x7e, 0x3c]

flag = ''
for c in enc:
    flag += chr(c ^ 0x41)
print(flag)
hctf{eXclU51v3_0r^N0t?}

Hackappa_rev (Reverse)

Ghidraでデコンパイルする。
重要そうなコードは以下の部分。

int decrypt(EVP_PKEY_CTX *ctx,uchar *out,size_t *outlen,uchar *in,size_t inlen)

{
  undefined8 local_28;
  undefined8 local_20;
  undefined local_18;
  int local_c;
  
  local_28 = 0x627d367e4957464b;
  local_20 = 0x3655626e71787547;
  local_18 = 0x79;
  printf("%s",&local_28);
  for (local_c = 0; (local_c < 100 && (*(char *)((long)&local_28 + (long)local_c) != '\0'));
      local_c = local_c + 1) {
    *(char *)((long)&local_28 + (long)local_c) = *(char *)((long)&local_28 + (long)local_c) + -3;
  }
  printf("%s}\n",&local_28);
  return 0;
}

local_28以降の各バイトで-3すればよい。

#!/usr/bin/env python3
c0 = 0x627d367e4957464b
c1 = 0x3655626e71787547
c2 = 0x79

flag = ''
c0 = c0.to_bytes(8, 'little')
for c in c0:
    flag += chr(c - 3)
c1 = c1.to_bytes(8, 'little')
for c in c1:
    flag += chr(c - 3)
c2 = c2.to_bytes(1, 'little')
for c in c2:
    flag += chr(c - 3)
flag += '}'
print(flag)
HCTF{3z_Drunk_R3v}

Welcome To Web(ere) (Web)

HTMLソースを見ると、コメントにフラグの断片がある。

<!-- hctf{th3_good_0l_ -->

またリンクされている、main.cssを見ると、コメントに別のフラグの断片がある。

/* t1mes_wh3n_si7es*/

最後にリンクされている、main.jsを見ると、コメントに別のフラグの断片がある。

// _wer3_st4tic}

見つけたフラグの断片を結合すると、フラグになる。

hctf{th3_good_0l_t1mes_wh3n_si7es_wer3_st4tic}

Hidden cocktails (Forensic)

rarファイルを解凍すると、BooksやDocuments、imagesフォルダがあり、それぞれファイルが複数格納されている。rarファイルということで、代替データストリームが含まれていないか確認する。

D:\CTF\work>cd Stuff

D:\CTF\work\Stuff>dir /r
 ドライブ D のボリューム ラベルは DATA です
 ボリューム シリアル番号は CC27-65B0 です

 D:\CTF\work\Stuff のディレクトリ

2022/12/11  19:37    <DIR>          .
2022/12/11  19:37    <DIR>          ..
2022/11/08  22:33    <DIR>          Books
                                 40 Books:spritz_4_life.txt:$DATA
2022/11/08  20:20    <DIR>          Documents
2022/11/08  20:16    <DIR>          images
               0 個のファイル                   0 バイト
               5 個のディレクトリ  164,108,300,288 バイトの空き領域

D:\CTF\work\Stuff>more < Books:spritz_4_life.txt:$DATA
hctf{4lt3rn4t3_D4t4_Str34m_G0n3_W1ld}
hctf{4lt3rn4t3_D4t4_Str34m_G0n3_W1ld}

Hackappatoi CTF '22 Feedback form (SPECIAL)

アンケートに答えたら、フラグが表示された。

HCTF{Hackappatoi_l0v3s_y0u_4ll_<3}