NO ESCAPE CTF 2022 Writeup

この大会は2022/11/25 13:30(JST)~2022/11/26 13:30(JST)に開催されました。
今回は個人で参戦。結果は330点で137チーム中72位でした。
解けた問題をWriteupとして書いておきます。

Santa's key (Misc)

Pythonコードの構文としては誤っているが、XORの暗号と、鍵がわかっているので、それを使って復号する。

#!/usr/bin/env python3
flag_enc = [0x1d, 0x24, 0x2d, 0x20, 0x27, 0x28, 0x32, 0x2e, 0x1a,
    0x35, 0x32, 0x46, 0x1d, 0x2b, 0xa, 0x60, 0x18, 0x31, 0x1c,
    0x52, 0x21, 0x52, 0x13]

key = b'Santa'
flag = ''
for i in range(len(flag_enc)):
    flag += chr(flag_enc[i] ^ key[i%len(key)])
print(flag)
NECTF{S@nTa's_k3y_h3r3}

Bad Cake (Misc)

$ file badcake.dat 
badcake.dat: PNG image data, 245 x 245, 8-bit grayscale, non-interlaced
$ mv badcake.dat badcake.png


画像にはQRコードが書かれているので、読み取る。

NGUgNDUgNDMgNTQgNDYgN2IgNTQgNDggMzEgMjQgNWYgMzEgMjQgNWYgNTkgMzAgNTUgNTIgNWYgNDcgNGYgMzAgNDQgNWYgNDMgNDAgNGIgMzMgN2Q=

base64文字列のようなので、デコードする。

$ echo NGUgNDUgNDMgNTQgNDYgN2IgNTQgNDggMzEgMjQgNWYgMzEgMjQgNWYgNTkgMzAgNTUgNTIgNWYgNDcgNGYgMzAgNDQgNWYgNDMgNDAgNGIgMzMgN2Q= | base64 -d
4e 45 43 54 46 7b 54 48 31 24 5f 31 24 5f 59 30 55 52 5f 47 4f 30 44 5f 43 40 4b 33 7d
$ echo NGUgNDUgNDMgNTQgNDYgN2IgNTQgNDggMzEgMjQgNWYgMzEgMjQgNWYgNTkgMzAgNTUgNTIgNWYgNDcgNGYgMzAgNDQgNWYgNDMgNDAgNGIgMzMgN2Q= | base64 -d | xxd -r -p
NECTF{TH1$_1$_Y0UR_GO0D_C@K3}
NECTF{TH1$_1$_Y0UR_GO0D_C@K3}

Welcome to NECTF (Misc)

ブラウザのデベロッパーツールで、この問題文のHTMLソースを見ると、コメントがあり、以下のように書いてある。

<!--  NECTF{w3LC0M3_t0_N3CTF} -->
NECTF{w3LC0M3_t0_N3CTF}

The Real Santa (pwn)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  long in_FS_OFFSET;
  undefined local_e8;
  undefined local_e7;
  undefined local_e6;
  undefined local_e5;
  undefined local_e4;
  undefined local_e3;
  undefined local_e2;
  undefined local_e1;
  undefined local_e0;
  undefined local_df;
  undefined local_de;
  undefined local_dd;
  undefined local_dc;
  char local_78;
  char local_77;
  char local_76;
  char local_75;
  char local_74;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_e8 = 0x4e;
  local_e7 = 0x45;
  local_e6 = 0x43;
  local_e5 = 0x54;
  local_e4 = 0x46;
  local_e3 = 0x7b;
  local_e2 = 0x45;
  local_e1 = 0x55;
  local_e0 = 0x52;
  local_df = 0x33;
  local_de = 0x4b;
  local_dd = 0x41;
  local_dc = 0x7d;
  printf("Enter your secret santa name: ");
  __isoc99_scanf(&DAT_00102027,&local_78);
  if ((((local_78 == '@') && (local_77 == 't')) && (local_76 == 'n')) &&
     ((local_75 == '!' && (local_74 == 's')))) {
    printf("You are the real santa! Here is your flag: %s",&local_e8);
  }
  else {
    printf("You are not the real santa!");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

入力文字列に"@tn!s"と指定すればよい。

$ ./realSanta 
Enter your secret santa name: @tn!s
You are the real santa! Here is your flag: NECTF{EUR3KA}
NECTF{EUR3KA}

Laugh and Sing (Web)

レスポンスヘッダのx-hashにbase64文字列らしきものがセットされる。

TkVDVEZ7TWFraU5nX3NwMXJpdHNfYlJpZ2h0fQo=

base64デコードする。

$ echo TkVDVEZ7TWFraU5nX3NwMXJpdHNfYlJpZ2h0fQo= | base64 -d
NECTF{MakiNg_sp1rits_bRight}
NECTF{MakiNg_sp1rits_bRight}

Unlock your Santa's gift (Web)

HTMLソースを見ると、スクリプトにこう書いてある。

    <script>
      const checkPassword=()=>{let e=document.getElementById("password").value,d=Array.from(e).map(e=>5*"NO ESCAPE CTF".split("").map(e=>e.charCodeAt(0)).reduce(function(e,d){return e+d})+e.charCodeAt(0));return 4446===d[13]&&4477===d[15]&&4447===d[0]&&4489===d[2]&&4492===d[10]&&4496===d[8]&&4476===d[1]&&4476===d[3]&&4485===d[19]&&4478===d[20]&&4421===d[17]&&4407===d[12]&&4486===d[9]&&4489===d[11]&&4491===d[16]&&4480===d[5]&&4407===d[7]&&4487===d[18]&&4407===d[4]&&4490===d[6]&&4480===d[14]&&e};window.addEventListener("DOMContentLoaded",()=>{document.getElementById("go").addEventListener("click",()=>{let e=checkPassword();e?window.location.href=e:alert("Wrong password")}),document.getElementById("password").addEventListener("keydown",e=>{if(13===e.keyCode){let d=checkPassword();d?window.location.href=d:(document.getElementById("password").classList.remove("valid"),alert("Wrong password!"))}}),document.getElementById("password").addEventListener("keyup",e=>{checkPassword()?document.getElementById("password").classList.add("valid"):document.getElementById("password").classList.remove("valid")})},!1);
    </script>

この条件を満たすパスワードを割り出す。

#!/usr/bin/env python3

d = [4447, 4476, 4489, 4476, 4407, 4480, 4490, 4407, 4496, 4486, 4492, 4489,
    4407, 4446, 4480, 4477, 4491, 4421, 4487, 4485, 4478]

KEY = b'NO ESCAPE CTF'

base = 0
for k in KEY:
    base += k * 5

password = ''
for i in d:
    password += chr(i - base)
print(password)

パスワードは以下であることがわかる。

Here is your Gift.png

このパスワードでログインすると、フラグが表示された。

NECTF{YOU_R_LEGEND}

X-mas Carol (Forensics)

$ binwalk x-mas.mp3 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
400031        0x61A9F         Zip archive data, at least v2.0 to extract, compressed size: 9130, uncompressed size: 20969, name: .carol.txt
409309        0x63EDD         End of Zip archive, footer length: 22

末尾にzipが付いているので、抽出する。

$ binwalk -e x-mas.mp3 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
400031        0x61A9F         Zip archive data, at least v2.0 to extract, compressed size: 9130, uncompressed size: 20969, name: .carol.txt
409309        0x63EDD         End of Zip archive, footer length: 22

$ cat _x-mas.mp3.extracted/.carol.txt | grep NECTF{
Other popular and widely sung Christmas carols are "HerbNECTF{J1ngl3s_@alL_th3_wAy}ei, o ihr Gläub’gen", a German version of "Adeste fideles" (English: "O Come, All Ye Faithful"), Alle Jahre wieder ("Every year again"), Es ist ein Ros entsprungen (lit: "A rose has sprung up"), "Leise rieselt der Schnee" "(Silently the snow is falling)", "Tochter Zion, freue dich" (Daughter Zion, rejoice) and "Es ist für uns eine Zeit angekommen" ("Unto us a time has come").
Main article: List of Filipino Christmas carolsNECTF{}
NECTF{J1ngl3s_@alL_th3_wAy}

X-mas Present (Crypto)

$ nc ctf.x-mas.biz 8080
                               _                 _             
| | |_  /_  _  _ _  _  _/__   /_`_  _ _/__/  _  /_`_  _  __ _/_
|/|//_'//_ /_// / //_' / /_/ ._//_|/ // /_|_\  ._//_'/_ //_'/  
                                                               
  _             
 /_`_  _  ._  _ 
._//_'/|///_ /_'
                

What do you want?
1. Get Your Flag
2. Get Your X-mas Present
3. No, Thanks i'm happy!
Enter your choice: 3
Ok, don't worry, i'll give you the secret key but you need to decode it
Printing secret key in encrypted format...
0漢4d字0漢33字0漢72字0漢52字0漢79字0漢5f字0漢21字0漢58字0漢6d字0漢40字0漢24字

漢の後ろのコードをデコードしていく。

>>> chr(0x4d)
'M'
>>> chr(0x33)
'3'
>>> chr(0x72)
'r'
>>> chr(0x52)
'R'
>>> chr(0x79)
'y'
>>> chr(0x5f)
'_'
>>> chr(0x21)
'!'
>>> chr(0x58)
'X'
>>> chr(0x6d)
'm'
>>> chr(0x40)
'@'
>>> chr(0x24)
'$'
$ nc ctf.x-mas.biz 8080
  ##  ##             ###                                       
  ##  ##              ##                                       
 ##   ##    ####     ##       ####     ####    ## ##     ####  
 ##  ##   ##   ##    ##     ##       ##   ##  #######  ##   ## 
## # ##  ########   ##     ##       ##    ##  ## # ## ######## 
######   ##         ##     ##       ##   ##  ##   ##  ##       
## ##     ####     ####     #####    ####    ##   ##   ####    
                                                               
    ##            
   ##             
#######     ####  
  ##      ##   ## 
 ##      ##    ## 
 ##      ##   ##  
  ###     ####    
                  
   ####                        ##                ##            
  ##  ##                      ##                ##             
  ##        #####  ## ###  #######     #####             ##### 
   ##     ##   ##  ###  ##   ##      ##   ##            ##     
    ##   ##    ##  ##   ##  ##      ##    ##             ##    
##  ##   ##  ###  ##   ##   ##      ##  ###               ##   
 ####     ### ##  ##   ##    ###     ### ##           #####    
                                                               
   ####                                          ##   
  ##  ##                                        ##    
  ##        ####     ####    ## ###    ####  #######  
   ##     ##   ##  ##       ####     ##   ##   ##     
    ##   ######## ##        ##      ########  ##      
##  ##   ##       ##       ##       ##        ##      
 ####     ####     #####   ##        ####      ###    
                                                      
   ####                                  ##                    
  ##  ##                                                       
  ##        ####    ## ### ###  ###   ####      ####     ####  
   ##     ##   ##  ####     ##  ##      ##    ##       ##   ## 
    ##   ########  ##       ## ##      ##    ##       ######## 
##  ##   ##       ##         ###       ##    ##       ##       
 ####     ####    ##         ##      ######   #####    ####    
                                                               

What do you want?
1. Get Your Flag
2. Get Your X-mas Present
3. No, Thanks i'm happy!
Enter your choice: 2
Enter your secret key:M3rRy_!Xm@$
Here is your present: 
Congrats! You got the flag: 
NECTF{S@Nta_1$_@_h@cKer}
NECTF{S@Nta_1$_@_h@cKer}

Hello Santa (Crypto)

暗号化文字列の各文字について、鍵の文字のASCIIコードの和を引けば、フラグになる。

#!/usr/bin/env python3
import io

with io.open('helloSanta.txt', 'r', encoding = 'utf-8') as f:
    enc = f.read()

key = 'merry_xmas'

flag = ''
for i in range(len(enc)):
    code = ord(enc[i])
    for k in key:
        code -= ord(k)
    flag += chr(code)
print(flag)

復号結果は以下の通り。

flag: NECTF{HoL@_S@Nt@}
NECTF{HoL@_S@Nt@}

Jingle Bells (Crypto)

.DS_Storeのファイルを見ると、こう書いてある。

00000000  34 31 20 35 32 20 35 30 20 34 37 20 35 33 20 37  |41 52 50 47 53 7|
00000010  62 20 35 31 20 34 30 20 36 36 20 35 35 20 33 31  |b 51 40 66 55 31|
00000020  20 36 31 20 37 34 20 35 66 20 36 37 20 37 35 20  | 61 74 5f 67 75 |
00000030  36 35 20 34 32 20 36 38 20 37 34 20 37 35 20 35  |65 42 68 74 75 5|
00000040  66 20 36 37 20 35 35 20 33 33 20 35 66 20 32 34  |f 67 55 33 5f 24|
00000050  20 36 31 20 33 30 20 36 61 20 37 64              | 61 30 6a 7d|

hexデコードする。

$ echo "41 52 50 47 53 7b 51 40 66 55 31 61 74 5f 67 75 65 42 68 74 75 5f 67 55 33 5f 24 61 30 6a 7d" | xxd -r -p
ARPGS{Q@fU1at_gueBhtu_gU3_$a0j}

https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherでROT13をするとフラグになった。

NECTF{D@sH1ng_thrOugh_tH3_$n0w}

Hello Santa II (Crypto)

keyをブルートフォースして復号する。

#!/usr/bin/env python3
import io

with io.open('helloSanta.txt', 'r', encoding = 'utf-8') as f:
    enc = f.read()

with open('random.txt', 'r') as f:
    keys = f.read().splitlines()

for key in keys:
    success = True
    flag = ''
    for i in range(len(enc)):
        code = ord(enc[i])
        for k in key:
            code -= ord(k)
        if code > 126 or code < 32:
            success = False
        else:
            flag += chr(code)
    if not success:
        continue
    if 'NECTF' in flag:
        print(flag)
        break

復号結果は以下の通り。

flag: NECTF{Bruteforce_1s_4w3s0m3}
NECTF{Bruteforce_1s_4w3s0m3}