Winja CTF | Nullcon Berlin 2022 Writeup

この大会は2022/4/9 7:00(JST)~2022/4/9 23:00(JST)に開催されました。
今回もチームで参戦。結果は627点で93チーム中40位でした。
自分で解けた問題をWriteupとして書いておきます。

Suárez (Miscellaneous)

pythonアセンブリからコードを起こし、実行する。

$ cat solve.py
new_flag = list(range(0, 54))

new_flag[34] = chr(57)
new_flag[50] = chr(120)
new_flag[47] = chr(53)
new_flag[5] = chr(53)
new_flag[9] = chr(98)
new_flag[26] = chr(49)
new_flag[20] = chr(57)
new_flag[0] = chr(102)
new_flag[53] = chr(125)
new_flag[49] = chr(95)
new_flag[33] = chr(57)
new_flag[2] = chr(97)
new_flag[27] = chr(55)
new_flag[7] = chr(50)
new_flag[24] = chr(97)
new_flag[15] = chr(49)
new_flag[6] = chr(52)
new_flag[36] = chr(57)
new_flag[28] = chr(100)
new_flag[12] = chr(97)
new_flag[35] = chr(98)
new_flag[25] = chr(97)
new_flag[8] = chr(52)
new_flag[19] = chr(49)
new_flag[40] = chr(36)
new_flag[30] = chr(53)
new_flag[1] = chr(108)
new_flag[3] = chr(103)
new_flag[17] = chr(57)
new_flag[14] = chr(101)
new_flag[21] = chr(56)
new_flag[32] = chr(53)
new_flag[4] = chr(123)
new_flag[22] = chr(99)
new_flag[31] = chr(97)
new_flag[41] = chr(95)
new_flag[23] = chr(53)
new_flag[10] = chr(48)
new_flag[44] = chr(95)
new_flag[42] = chr(73)
new_flag[18] = chr(52)
new_flag[16] = chr(97)
new_flag[46] = chr(64)
new_flag[48] = chr(121)
new_flag[37] = chr(95)
new_flag[13] = chr(48)
new_flag[52] = chr(82)
new_flag[11] = chr(49)
new_flag[38] = chr(119)
new_flag[39] = chr(65)
new_flag[45] = chr(101)
new_flag[29] = chr(101)
new_flag[43] = chr(55)
new_flag[51] = chr(48)

print(''.join(new_flag))
$ python3 solve.py
flag{5424b01a0e1a94198c5aa17de5a599b9_wA$_I7_e@5y_x0R}
flag{5424b01a0e1a94198c5aa17de5a599b9_wA$_I7_e@5y_x0R}

Mercedes Colmenar (Reverse Engineering 350)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  basic_ostream *pbVar1;
  char local_1d8 [65];
  undefined8 local_197;
  undefined local_18f;
  undefined4 local_18e;
  undefined2 local_18a;
  undefined local_188;
  undefined4 local_187;
  undefined2 local_183;
  undefined local_181;
  undefined8 local_180;
  char local_178 [38];
  undefined4 local_152;
  undefined2 local_14e;
  undefined4 local_14c;
  undefined2 local_148;
  undefined4 local_146;
  undefined2 local_142;
  undefined8 local_140;
  undefined4 local_138;
  undefined2 local_134;
  undefined8 local_132;
  undefined4 local_12a;
  undefined2 local_126;
  undefined local_124;
  undefined4 local_123;
  undefined2 local_11f;
  undefined4 local_11d;
  undefined local_119;
  char local_118 [268];
  int local_c;
  
  local_11d = 0x4548745f;
  local_119 = 0;
  local_123 = 0x345f5369;
  local_11f = 0x5f;
  local_12a = 0x63303939;
  local_126 = 0x6661;
  local_124 = 0;
  local_132 = 0x62376631643634;
  local_138 = 0x5f656854;
  local_134 = 0x33;
  local_140 = 0x31653062306261;
  local_146 = 0x664c4553;
  local_142 = 0x31;
  local_14c = 0x344f725f;
  local_148 = 0x44;
  local_152 = 0x305f646e;
  local_14e = 0x66;
  strcpy(local_178,(char *)&local_138);
  strcat(local_178,(char *)&local_152);
  std::operator<<((basic_ostream *)std::cout,"password: ");
  std::operator>>((basic_istream *)std::cin,local_118);
  strcat(local_178,(char *)&local_11d);
  strcat(local_178,(char *)&local_14c);
  local_c = strcmp(local_118,local_178);
  if (local_c == 0) {
    local_180 = 0x63636631386133;
    local_187 = 0x405f6835;
    local_183 = 0x7463;
    local_181 = 0;
    local_18e = 0x676e4576;
    local_18a = 0x5f65;
    local_188 = 0;
    local_197 = 0x45525f6563313063;
    local_18f = 0;
    strcpy(local_1d8,(char *)&local_180);
    strcat(local_1d8,(char *)&local_132);
    strcat(local_1d8,(char *)&local_12a);
    strcat(local_1d8,(char *)&local_140);
    strcat(local_1d8,(char *)&local_197);
    strcat(local_1d8,(char *)&local_18e);
    strcat(local_1d8,(char *)&local_123);
    strcat(local_1d8,(char *)&local_146);
    strcat(local_1d8,(char *)&local_187);
    banner();
    pbVar1 = std::operator<<((basic_ostream *)std::cout,"flag{");
    pbVar1 = std::operator<<(pbVar1,local_1d8);
    pbVar1 = std::operator<<(pbVar1,"} ");
    std::basic_ostream<char,std::char_traits<char>>::operator<<
              ((basic_ostream<char,std::char_traits<char>> *)pbVar1,
               std::endl<char,std::char_traits<char>>);
  }
  else {
    pbVar1 = (basic_ostream *)
             std::basic_ostream<char,std::char_traits<char>>::operator<<
                       ((basic_ostream<char,std::char_traits<char>> *)std::cout,
                        std::endl<char,std::char_traits<char>>);
    pbVar1 = std::operator<<(pbVar1,"Incorrect :( ");
    std::basic_ostream<char,std::char_traits<char>>::operator<<
              ((basic_ostream<char,std::char_traits<char>> *)pbVar1,
               std::endl<char,std::char_traits<char>>);
  }
  return 0;
}

passwordはlocal_178に連結した文字列と比較している。

>>> bytes.fromhex('5f656854')[::-1]
b'The_'
>>> bytes.fromhex('33')[::-1]
b'3'
>>> bytes.fromhex('305f646e')[::-1]
b'nd_0'
>>> bytes.fromhex('66')[::-1]
b'f'
>>> bytes.fromhex('4548745f')[::-1]
b'_tHE'
>>> bytes.fromhex('344f725f')[::-1]
b'_rO4'
>>> bytes.fromhex('44')[::-1]
b'D'
The_3nd_0f_tHE_rO4D
$ ./Mercedes_Colmenar 
password: The_3nd_0f_tHE_rO4D



░▒█▀▀▄░▒█▀▀▀░▒█░░░░▒█░░░░█▀▀▄░░░▒█▀▀▄░▀█▀░█▀▀▄░▒█▀▀▀█░░
░▒█▀▀▄░▒█▀▀▀░▒█░░░░▒█░░░▒█▄▄█░░░▒█░░░░▒█░▒█▄▄█░▒█░░▒█░░
░▒█▄▄█░▒█▄▄▄░▒█▄▄█░▒█▄▄█▒█░▒█░░░▒█▄▄▀░▄█▄▒█░▒█░▒█▄▄▄█░░


flag{3a81fcc46d1f7b990cafab0b0e1c01ce_REvEnge_iS_4_SELf15h_@ct}
flag{3a81fcc46d1f7b990cafab0b0e1c01ce_REvEnge_iS_4_SELf15h_@ct}

Manila (Forensics)

バイナリエディタで見ると、pngフォーマットが逆順で含まれているので、逆順にして抽出する。

#!/usr/bin/env python3
with open('Manila.pdf', 'rb') as f:
    data = f.read()

png = data[0x7c85:0xc502][::-1]

with open('flag.png', 'wb') as f:
    f.write(png)

抽出した画像にフラグが書いてあった。
f:id:satou-y:20220413130402p:plain

flag{f497dfa4fe524bdaa6d973453859df9a_You_f0UNd_7H3_undERCover_r0bber}