Ugra CTF Quals 2021 Writeup

この大会は2021/2/27 16:00(JST)~2021/3/1 4:00(JST)に開催されました。
今回もチームで参戦。結果は450点で139チーム中53位でした。
自分で解けた問題をWriteupとして書いておきます。

nothingtosee (WEB 100)

証明書が無効になっているので、証明書を見てみる。
Netscape コメントにフラグがあった。
f:id:satou-y:20210316064844p:plain

ugra_v1_p0sm0tr3l1_5b566c0581c4

developers (FORENSICS 200)

$ cat .git/ORIG_HEAD 
86d7e5988f56123960fe5755a4f22a91acd00b56

$ python -c 'import zlib; print zlib.decompress(open(".git/objects/86/d7e5988f56123960fe5755a4f22a91acd00b56").read())'
commit 230tree d36c2293f57eca1cfd8f147c243202bd34eb4e71
parent 7116f28ab8d9b017e237f8529cfa074c0a5f2501
author Validian <validian@validian.name> 1576012530 +0845
committer Validian <validian@validian.name> 1576012530 +0845

added info.txt.

$ python -c 'import zlib; print zlib.decompress(open(".git/objects/d3/6c2293f57eca1cfd8f147c243202bd34eb4e71").read())' | xxd -g 1
00000000: 74 72 65 65 20 36 33 33 00 31 30 30 36 34 34 20  tree 633.100644 
00000010: 2e 64 69 72 2d 6c 6f 63 61 6c 73 2e 65 6c 00 49  .dir-locals.el.I
00000020: 02 7d ab 5d 0d d4 82 66 83 a6 f8 28 6e 5f 9e 39  .}.]...f...(n_.9
00000030: 55 fa c2 31 30 30 36 34 34 20 2e 67 69 74 69 67  U..100644 .gitig
00000040: 6e 6f 72 65 00 be 8a 43 4d c1 f1 3e 94 52 19 3e  nore...CM..>.R.>
00000050: 64 47 2e e3 16 47 fa 3c 60 31 30 30 36 34 34 20  dG...G.<`100644 
00000060: 2e 74 72 61 76 69 73 2e 79 6d 6c 00 19 de 5d ff  .travis.yml...].
00000070: a7 45 f1 12 2d 65 7d 9c c1 71 b9 6e 63 fc de 14  .E..-e}..q.nc...
00000080: 31 30 30 36 34 34 20 4c 49 43 45 4e 53 45 00 ba  100644 LICENSE..
00000090: 78 cc 23 7c ff 9e 7d 0a e0 94 e9 78 c0 aa 27 d6  x.#|..}....x..'.
000000a0: 20 1f 2c 31 30 30 37 35 35 20 4d 61 6b 65 66 69   .,100755 Makefi
000000b0: 6c 65 00 56 74 91 f4 b1 89 b6 d9 9e 46 5d 84 a8  le.Vt.......F]..
000000c0: 8e 73 a4 c7 73 ff c8 31 30 30 36 34 34 20 52 45  .s..s..100644 RE
000000d0: 41 44 4d 45 2e 6d 64 00 a0 3c 4e 2f 7e 86 45 fa  ADME.md..<N/~.E.
000000e0: 82 b0 32 98 d6 6d 7a 92 6b e3 51 f1 31 30 30 37  ..2..mz.k.Q.1007
000000f0: 35 35 20 62 6f 6f 74 73 74 72 61 70 2e 73 68 00  55 bootstrap.sh.
00000100: 50 6b 16 0f 7b 02 07 33 b5 35 c7 cd ac 31 9f 2c  Pk..{..3.5...1.,
00000110: 1e 64 60 25 31 30 30 37 35 35 20 63 6f 6e 66 69  .d`%100755 confi
00000120: 67 75 72 65 00 db 1a 12 8d f7 d8 7f cd a8 66 54  gure..........fT
00000130: 32 57 1c 36 59 50 f0 fa 3f 31 30 30 36 34 34 20  2W.6YP..?100644 
00000140: 63 6f 6e 66 69 67 75 72 65 2e 6b 61 66 6b 61 63  configure.kafkac
00000150: 61 74 00 05 d2 bb 5a 4c 67 eb 69 09 13 a8 1d 5b  at....ZLg.i....[
00000160: ee fc 5b 80 4c af 43 31 30 30 36 34 34 20 66 6f  ..[.L.C100644 fo
00000170: 72 6d 61 74 2e 63 00 25 ba 84 47 6a 5b f3 39 cc  rmat.c.%..Gj[.9.
00000180: db d4 1e 25 e6 1a 41 e6 13 f3 eb 31 30 30 36 34  ...%..A....10064
00000190: 34 20 69 6e 66 6f 2e 74 78 74 00 f0 80 0f f8 40  4 info.txt.....@
000001a0: 7d 8b ce 0b 30 87 97 2a 4e 8e ec 52 c0 28 66 31  }...0..*N..R.(f1
000001b0: 30 30 36 34 34 20 6a 73 6f 6e 2e 63 00 41 64 8d  00644 json.c.Ad.
000001c0: b3 b9 af 07 f7 87 83 3b 0e f3 b7 6f c4 48 fb 15  .......;...o.H..
000001d0: 6f 31 30 30 36 34 34 20 6b 61 66 6b 61 63 61 74  o100644 kafkacat
000001e0: 2e 31 00 ea 7c e5 40 3a 9a c1 64 fe 59 6b ac 2a  .1..|.@:..d.Yk.*
000001f0: b6 3d 5d 9f 3d 86 d2 31 30 30 36 34 34 20 6b 61  .=].=..100644 ka
00000200: 66 6b 61 63 61 74 2e 63 00 36 c6 98 4b 33 ee 7e  fkacat.c.6..K3.~
00000210: 68 5d 6c 68 a0 ad 2b 75 f6 33 89 f6 b3 31 30 30  h]lh..+u.3...100
00000220: 36 34 34 20 6b 61 66 6b 61 63 61 74 2e 68 00 3d  644 kafkacat.h.=
00000230: 35 4e e5 33 27 c2 4a 41 49 8c 05 d2 68 9a 4f e7  5N.3'.JAI...h.O.
00000240: 86 cf 2b 34 30 30 30 30 20 6d 6b 6c 6f 76 65 00  ..+40000 mklove.
00000250: 96 2c 50 5e 77 ce 27 89 0e a6 13 40 1e 43 9f 23  .,P^w.'....@.C.#
00000260: 3c 72 21 b2 34 30 30 30 30 20 72 70 6d 00 db 39  <r!.40000 rpm..9
00000270: f1 0d 69 16 dd 4c da e3 34 24 64 16 8f ae c7 80  ..i..L..4$d.....
00000280: 0d 11 0a                                         ...

info.txtの情報を見てみる。

$ python -c 'import zlib; print zlib.decompress(open(".git/objects/f0/800ff8407d8bce0b3087972a4e8eec52c02866").read())'
blob 282If you are reading this, I am definitely dead by now.

I also know that by reaching this file, you have demonstrated
the best of your ability and courage. Here is the key to my
lifetime secret: ugra_the_yellow_purse_c79f005f1610f86a

You will understand what to do next. Good luck!

info.txtにフラグが書いてあった。

ugra_the_yellow_purse_c79f005f1610f86a

apl (CRYPTO 150)

APL言語。https://en.wikipedia.org/wiki/APL_syntax_and_symbolsを参考に読み解く。

A ← 'abcdefghijklmnopqrstuvwxy_1234567890'

I ← (6 6 ⍴ 1 + ⍳6)+⍉(10 × 6 6 ⍴ 1 + ⍳6)

11 12 13 14 15 16
21 22 23 24 25 26
31 32 33 34 35 36
41 42 43 44 45 46
51 52 53 54 55 56
61 62 63 64 65 66

S ← 6 6 ⍴ A
abcdef
ghijkl
mnopqr
stuvwx
y_1234
567890

E ← {⌈/⌈/ (~⍵ ⍳ S) × I}
E¨flag

以下のように暗号化している数字で対応する文字に置き換えて復号する。

11 -> a
12 -> b
   :
61 -> 5
   :
66 -> 0
def get_index(code):
    c1 = int(code[0]) - 1
    c2 = int(code[1]) - 1
    return c1 * 6 + c2

A = 'abcdefghijklmnopqrstuvwxy_1234567890'
enc = '43 21 36 11 52 42 22 15 52 32 15 46 42 52 41 42 11 42 23 33 32 52 23 41 52 15 41 33 42 15 36 23 13 52 34 36 33 21 36 11 31 31 23 32 21 52 54 12 53 64 65 66 55 63 66 62 65 65 56 11 63 13 13 54 12 62 63 12 14 53 62 13 54 53 64 56 13 11 62 62 62 62 63 64 13 16 15 54 65 54 62 15 63 15 12 54 13 15 63 62 13 63 54 11'
codes = enc.split(' ')

flag = ''
for c in codes:
    index = get_index(c)
    flag += A[index]
print flag
ugra_the_next_station_is_esoteric_programming_2b18903706994a7cc2b67bd16c2184ca666678cfe2926e7eb2ce76c72a