SECCON 2023 Capsule CTF

SECCON 2023 Finalsおよび電脳会議の併設イベントとしてCapsule CTFを実施しました。結構盛況で嬉しかったです。

参加者同士で問題を交換しあって増やしていくトレーディングシステムが結構機能していたのも非常に良い。

Writeup

ここでは自分が作問した以下の問題のWriteupを書きます

とにかく簡単な問題を大量に作る必要があったので、結構簡単だと思います。

Pwn

int

-1

src.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

char buf[31] = {0};

int main() {
    char *flag = buf;
    char *text[4] = {
        "Life is but a fleeting dream, Slippery as a mountain stream.",
        "Time ticks away, silent and stern, Teaching us we must learn.",
        "Wisdom's voice is often low, But in its echo, truths will grow.",
        "A single act of kindness throws Out roots in all directions, and the roots spring up and make new trees."
    };
    int selection = 0;

    puts("Welcome to the fortune teller!");
    printf("Index(0~3): ");
    scanf("%d", &selection);
    if (selection > 3) {
        puts("Invalid index!");
        return 1;
    }
    puts("Here is your fortune:");
    puts(text[selection]);
}

__attribute__((constructor))
void init() {
    FILE *f = fopen("flag.txt", "r");
    if (!f) {
        puts("Missing flag.txt. Contact an admin if you see this on remote.");
        exit(1);
    }
    fgets(buf, sizeof(buf), f);
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    alarm(60);
}

見ての通りtextflagが連続しているので、いい感じにselectionを合わせればいいだけです。-1で行けます。

SECCON{L0ng_D5t4nc3_Run4r0und}

Yes

Reversing

just_read

簡単です。読むだけなので

mainを見てみると

 2987: int main (int argc, char **argv, char **envp);
           ; var signed int var_4h @ rbp-0x4
           ; var uint32_t var_5h @ rbp-0x5
           ; var char *s @ rbp-0x70
           0x00001179      55             push rbp
           0x0000117a      4889e5         mov rbp, rsp
           0x0000117d      4883ec70       sub rsp, 0x70
           0x00001181      488d057c0e00.  lea rax, str.Enter_the_FLAG:_ ; 0x2004 ; "Enter the FLAG: "
           0x00001188      4889c7         mov rdi, rax                ; const char *format
           0x0000118b      b800000000     mov eax, 0
           0x00001190      e8bbfeffff     call sym.imp.printf         ; int printf(const char *format)
           0x00001195      488d4590       lea rax, [s]
           0x00001199      4889c6         mov rsi, rax
           0x0000119c      488d05720e00.  lea rax, str._99s___n_      ; 0x2015 ; "%99s%*[^\n]"
           0x000011a3      4889c7         mov rdi, rax                ; const char *format
           0x000011a6      b800000000     mov eax, 0
           0x000011ab      e8b0feffff     call sym.imp.__isoc99_scanf ; int scanf(const char *format)
           0x000011b0      488d4590       lea rax, [s]
           0x000011b4      4889c7         mov rdi, rax                ; const char *s
           0x000011b7      e884feffff     call sym.imp.strlen         ; size_t strlen(const char *s)
           0x000011bc      4883f843       cmp rax, 0x43               ; 'C'
       ┌─< 0x000011c0      7419           je 0x11db
          0x000011c2      488d05570e00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
          0x000011c9      4889c7         mov rdi, rax                ; const char *s
          0x000011cc      e85ffeffff     call sym.imp.puts           ; int puts(const char *s)
          0x000011d1      b801000000     mov eax, 1
      ┌──< 0x000011d6      e9470b0000     jmp 0x1d22
      ││   ; CODE XREF from main @ 0x11c0(x)
      │└─> 0x000011db      c745fc000000.  mov dword [var_4h], 0
      │┌─< 0x000011e2      e91d0b0000     jmp 0x1d04
      ││   ; CODE XREF from main @ 0x1d08(x)
     ┌───> 0x000011e7      8b45fc         mov eax, dword [var_4h]
     ╎││   0x000011ea      4898           cdqe
     ╎││   0x000011ec      0fb6440590     movzx eax, byte [rbp + rax - 0x70]
     ╎││   0x000011f1      3c60           cmp al, 0x60                ; '`'
    ┌────< 0x000011f3      7e47           jle 0x123c
    │╎││   0x000011f5      8b45fc         mov eax, dword [var_4h]
    │╎││   0x000011f8      4898           cdqe
    │╎││   0x000011fa      0fb6440590     movzx eax, byte [rbp + rax - 0x70]
    │╎││   0x000011ff      3c7a           cmp al, 0x7a                ; 'z'
   ┌─────< 0x00001201      7f39           jg 0x123c
   ││╎││   0x00001203      8b45fc         mov eax, dword [var_4h]
   ││╎││   0x00001206      4898           cdqe
   ││╎││   0x00001208      0fb6440590     movzx eax, byte [rbp + rax - 0x70]
   ││╎││   0x0000120d      0fbec0         movsx eax, al
   ││╎││   0x00001210      83e854         sub eax, 0x54
   ││╎││   0x00001213      4863d0         movsxd rdx, eax
   ││╎││   0x00001216      4869d24fecc4.  imul rdx, rdx, 0x4ec4ec4f
   ││╎││   0x0000121d      48c1ea20       shr rdx, 0x20
   ││╎││   0x00001221      c1fa03         sar edx, 3
   ││╎││   0x00001224      89c1           mov ecx, eax
   ││╎││   0x00001226      c1f91f         sar ecx, 0x1f
   ││╎││   0x00001229      29ca           sub edx, ecx
   ││╎││   0x0000122b      6bca1a         imul ecx, edx, 0x1a
   ││╎││   0x0000122e      29c8           sub eax, ecx
   ││╎││   0x00001230      89c2           mov edx, eax
   ││╎││   0x00001232      89d0           mov eax, edx
   ││╎││   0x00001234      83c061         add eax, 0x61
   ││╎││   0x00001237      8845fb         mov byte [var_5h], al
  ┌──────< 0x0000123a      eb62           jmp 0x129e
  │││╎││   ; CODE XREFS from main @ 0x11f3(x), 0x1201(x)
  │└└────> 0x0000123c      8b45fc         mov eax, dword [var_4h]
    ╎││   0x0000123f      4898           cdqe
    ╎││   0x00001241      0fb6440590     movzx eax, byte [rbp + rax - 0x70]
    ╎││   0x00001246      3c40           cmp al, 0x40                ; elf_phdr
   ┌────< 0x00001248      7e47           jle 0x1291
   │╎││   0x0000124a      8b45fc         mov eax, dword [var_4h]
   │╎││   0x0000124d      4898           cdqe
   │╎││   0x0000124f      0fb6440590     movzx eax, byte [rbp + rax - 0x70]
   │╎││   0x00001254      3c5a           cmp al, 0x5a                ; 'Z'
  │┌─────< 0x00001256      7f39           jg 0x1291
  │││╎││   0x00001258      8b45fc         mov eax, dword [var_4h]
  │││╎││   0x0000125b      4898           cdqe
  │││╎││   0x0000125d      0fb6440590     movzx eax, byte [rbp + rax - 0x70]
  │││╎││   0x00001262      0fbec0         movsx eax, al
  │││╎││   0x00001265      83e834         sub eax, 0x34
  │││╎││   0x00001268      4863d0         movsxd rdx, eax
  │││╎││   0x0000126b      4869d24fecc4.  imul rdx, rdx, 0x4ec4ec4f
  │││╎││   0x00001272      48c1ea20       shr rdx, 0x20
  │││╎││   0x00001276      c1fa03         sar edx, 3
  │││╎││   0x00001279      89c1           mov ecx, eax
  │││╎││   0x0000127b      c1f91f         sar ecx, 0x1f
  │││╎││   0x0000127e      29ca           sub edx, ecx
  │││╎││   0x00001280      6bca1a         imul ecx, edx, 0x1a
  │││╎││   0x00001283      29c8           sub eax, ecx
  │││╎││   0x00001285      89c2           mov edx, eax
  │││╎││   0x00001287      89d0           mov eax, edx
  │││╎││   0x00001289      83c041         add eax, 0x41
  │││╎││   0x0000128c      8845fb         mov byte [var_5h], al
 ┌───────< 0x0000128f      eb0d           jmp 0x129e
 ││││╎││   ; CODE XREFS from main @ 0x1248(x), 0x1256(x)
 ││└└────> 0x00001291      8b45fc         mov eax, dword [var_4h]
 ││  ╎││   0x00001294      4898           cdqe
 ││  ╎││   0x00001296      0fb6440590     movzx eax, byte [rbp + rax - 0x70]
 ││  ╎││   0x0000129b      8845fb         mov byte [var_5h], al
 ││  ╎││   ; CODE XREFS from main @ 0x123a(x), 0x128f(x)
 └└──────> 0x0000129e      837dfc42       cmp dword [var_4h], 0x42    ; 'B'
    ┌────< 0x000012a2      0f87580a0000   ja case.default.0x12c9
    │╎││   0x000012a8      8b45fc         mov eax, dword [var_4h]
    │╎││   0x000012ab      488d14850000.  lea rdx, [rax*4]
    │╎││   0x000012b3      488d057a0d00.  lea rax, [0x00002034]
    │╎││   0x000012ba      8b0402         mov eax, dword [rdx + rax]
    │╎││   0x000012bd      4898           cdqe
    │╎││   0x000012bf      488d156e0d00.  lea rdx, [0x00002034]
    │╎││   0x000012c6      4801d0         add rax, rdx
    │╎││   ;-- switch
    │╎││   0x000012c9      ffe0           jmp rax                     ; switch table (67 cases) at 0x2034
    │╎││   ;-- case 0:                                                ; from 0x000012c9
    │╎││   ; CODE XREF from main @ 0x12c9(x)
    │╎││   0x000012cb      807dfb46       cmp byte [var_5h], 0x46     ; 'F'
   ┌─────< 0x000012cf      0f841f090000   je 0x1bf4
   ││╎││   0x000012d5      488d05440d00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
   ││╎││   0x000012dc      4889c7         mov rdi, rax                ; const char *s
   ││╎││   0x000012df      e84cfdffff     call sym.imp.puts           ; int puts(const char *s)
   ││╎││   0x000012e4      bf01000000     mov edi, 1                  ; int status
   ││╎││   0x000012e9      e882fdffff     call sym.imp.exit           ; void exit(int status)
   ││╎││   ;-- case 1:                                                ; from 0x000012c9
   ││╎││   ; CODE XREF from main @ 0x12c9(x)
   ││╎││   0x000012ee      807dfb52       cmp byte [var_5h], 0x52     ; 'R'
  ┌──────< 0x000012f2      0f8402090000   je 0x1bfa
  │││╎││   0x000012f8      488d05210d00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
  │││╎││   0x000012ff      4889c7         mov rdi, rax                ; const char *s
  │││╎││   0x00001302      e829fdffff     call sym.imp.puts           ; int puts(const char *s)
  │││╎││   0x00001307      bf01000000     mov edi, 1                  ; int status
  │││╎││   0x0000130c      e85ffdffff     call sym.imp.exit           ; void exit(int status)
  │││╎││   ;-- case 2:                                                ; from 0x000012c9
  │││╎││   ; CODE XREF from main @ 0x12c9(x)
  │││╎││   0x00001311      807dfb50       cmp byte [var_5h], 0x50     ; 'P'
 ┌───────< 0x00001315      0f84e5080000   je 0x1c00
 ││││╎││   0x0000131b      488d05fe0c00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
 ││││╎││   0x00001322      4889c7         mov rdi, rax                ; const char *s
 ││││╎││   0x00001325      e806fdffff     call sym.imp.puts           ; int puts(const char *s)
 ││││╎││   0x0000132a      bf01000000     mov edi, 1                  ; int status
 ││││╎││   0x0000132f      e83cfdffff     call sym.imp.exit           ; void exit(int status)
 ││││╎││   ;-- case 3:                                                ; from 0x000012c9
 ││││╎││   ; CODE XREF from main @ 0x12c9(x)
 ││││╎││   0x00001334      807dfb50       cmp byte [var_5h], 0x50     ; 'P'
 ────────< 0x00001338      0f84c8080000   je 0x1c06
 ││││╎││   0x0000133e      488d05db0c00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
 ││││╎││   0x00001345      4889c7         mov rdi, rax                ; const char *s
 ││││╎││   0x00001348      e8e3fcffff     call sym.imp.puts           ; int puts(const char *s)
 ││││╎││   0x0000134d      bf01000000     mov edi, 1                  ; int status
 ││││╎││   0x00001352      e819fdffff     call sym.imp.exit           ; void exit(int status)
 ││││╎││   ;-- case 4:                                                ; from 0x000012c9
 ││││╎││   ; CODE XREF from main @ 0x12c9(x)
 ││││╎││   0x00001357      807dfb42       cmp byte [var_5h], 0x42     ; 'B'
 ────────< 0x0000135b      0f84ab080000   je 0x1c0c
 ││││╎││   0x00001361      488d05b80c00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
 ││││╎││   0x00001368      4889c7         mov rdi, rax                ; const char *s
 ││││╎││   0x0000136b      e8c0fcffff     call sym.imp.puts           ; int puts(const char *s)
 ││││╎││   0x00001370      bf01000000     mov edi, 1                  ; int status
 ││││╎││   0x00001375      e8f6fcffff     call sym.imp.exit           ; void exit(int status)
 ││││╎││   ;-- case 5:                                                ; from 0x000012c9
 ││││╎││   ; CODE XREF from main @ 0x12c9(x)
 ││││╎││   0x0000137a      807dfb41       cmp byte [var_5h], 0x41     ; 'A'
 ────────< 0x0000137e      0f848e080000   je 0x1c12
 ││││╎││   0x00001384      488d05950c00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
 ││││╎││   0x0000138b      4889c7         mov rdi, rax                ; const char *s
 ││││╎││   0x0000138e      e89dfcffff     call sym.imp.puts           ; int puts(const char *s)
 ││││╎││   0x00001393      bf01000000     mov edi, 1                  ; int status
 ││││╎││   0x00001398      e8d3fcffff     call sym.imp.exit           ; void exit(int status)
 ││││╎││   ;-- case 6:                                                ; from 0x000012c9
 ││││╎││   ; CODE XREF from main @ 0x12c9(x)
 ││││╎││   0x0000139d      807dfb7b       cmp byte [var_5h], 0x7b     ; '{'
 ────────< 0x000013a1      0f8471080000   je 0x1c18
 ││││╎││   0x000013a7      488d05720c00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
 ││││╎││   0x000013ae      4889c7         mov rdi, rax                ; const char *s
 ││││╎││   0x000013b1      e87afcffff     call sym.imp.puts           ; int puts(const char *s)
 ││││╎││   0x000013b6      bf01000000     mov edi, 1                  ; int status
 ││││╎││   0x000013bb      e8b0fcffff     call sym.imp.exit           ; void exit(int status)
 ││││╎││   ;-- case 7:                                                ; from 0x000012c9
 ││││╎││   ; CODE XREF from main @ 0x12c9(x)
 ││││╎││   0x000013c0      807dfb30       cmp byte [var_5h], 0x30     ; '0'
 ────────< 0x000013c4      0f8454080000   je 0x1c1e
 ││││╎││   0x000013ca      488d054f0c00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
 ││││╎││   0x000013d1      4889c7         mov rdi, rax                ; const char *s
 ││││╎││   0x000013d4      e857fcffff     call sym.imp.puts           ; int puts(const char *s)
 ││││╎││   0x000013d9      bf01000000     mov edi, 1                  ; int status
 ││││╎││   0x000013de      e88dfcffff     call sym.imp.exit           ; void exit(int status)
 ││││╎││   ;-- case 8:                                                ; from 0x000012c9
 ││││╎││   ; CODE XREF from main @ 0x12c9(x)
 ││││╎││   0x000013e3      807dfb61       cmp byte [var_5h], 0x61     ; 'a'
 ────────< 0x000013e7      0f8437080000   je 0x1c24
 ││││╎││   0x000013ed      488d052c0c00.  lea rax, str.Incorrect      ; 0x2020 ; "Incorrect"
 ││││╎││   0x000013f4      4889c7         mov rdi, rax                ; const char *s
 ││││╎││   0x000013f7      e834fcffff     call sym.imp.puts           ; int puts(const char *s)
 ││││╎││   0x000013fc      bf01000000     mov edi, 1                  ; int status
 ││││╎││   0x00001401      e86afcffff     call sym.imp.exit           ; void exit(int status)

~~ snip ~~

     ╎│└─> 0x00001d04      837dfc42       cmp dword [var_4h], 0x42    ; 'B'
     └───< 0x00001d08      0f8ed9f4ffff   jle 0x11e7
          0x00001d0e      488d05150300.  lea rax, str.Correct        ; 0x202a ; "Correct"
          0x00001d15      4889c7         mov rdi, rax                ; const char *s
          0x00001d18      e813f3ffff     call sym.imp.puts           ; int puts(const char *s)
          0x00001d1d      b800000000     mov eax, 0
          ; CODE XREF from main @ 0x11d6(x)
      └──> 0x00001d22      c9             leave
           0x00001d23      c3             ret

こんな感じで一文字ずつ比較しています。

気合で読んだり、ツールで抽出するとrot13っぽいことがわかります。

>>> import r2pipe
>>> pipe = r2pipe.open('just_read', flags=['-2'])
>>> _=pipe.cmd('aaa')
>>> disas = pipe.cmd('pdf @main')
>>> cmps = [x for x in disas.split('\n') if 'cmp byte' in x]
>>> print(''.join([c[-2] for c in cmps]))
FRPPBA{0a3_a33q_a0g_u4i3_o33a_Pnrfne_1a_0eq3e_g0_haq3e5g4aq_Pnrfne}

というわけで、全体のSolverはこう

#!/usr/bin/env python3
import r2pipe
import codecs

pipe = r2pipe.open("just_read", flags=["-2"])
_ = pipe.cmd("aaa")

disas = pipe.cmd("pdf @main")

cmps = [x for x in disas.split("\n") if "cmp byte" in x]

encoded_flag = ''.join([c[-2] for c in cmps])

print(codecs.decode(encoded_flag, 'rot_13'))

SECCON{0n3_n33d_n0t_h4v3_b33n_Caesar_1n_0rd3r_t0_und3r5t4nd_Caesar}

snake

pythonを読んで逆をする系の問題です。

#!/use/bin/env python3
# -*- coding: utf-8 -*-

flag = open('FLAG', 'r').read()
open('output', 'wb').write(bytes([(ord(c) ^ 0x42) + 10 for c in flag]))

output

00000000: 1b11 0b0b 1716 4310 8042 7b30 2780 3630  ......C..B{0'.60
00000010: 272b 7c36 2e41 817b 3049 52              '+|6.A.{0IR

やります

>>> output = open('output', 'rb').read()
>>> ''.join([chr((c-10)^0x42) for c in output])
'SECCON{D4z3d_4nd_c0nfu53d}\n'

Zeppelinですね

pl

Pythonはみんな読めるやろ。ということで今度はPerlにしました。

use MIME::Base64;eval(decode_base64('c3ViIHIgewogIG15KCRkLCAkaykgPSBAXzsKICBteSBAcyA9IDAuLjI1NTsKICBteSAoJGksICRqLCAkYykgPSAoMCwgMCwgJycpOwogIG15ICRsID0gQCRrOwogIGZvciAoJGkgPSAwOyAkaSA8IDI1NjsgJGkrKykgewogICAgJGogPSAoJGogKyAkc1skaV0gKyAkay0+WyRpJSRsXSkgJSAyNTY7CiAgICBAc1skaSwgJGpdID0gQHNbJGosICRpXTsKICB9CiAgJGkgPSAkaiA9IDA7CiAgZm9yZWFjaCBteSAkY2hhciAoc3BsaXQgLy8sICRkKSB7CiAgICAkaSA9ICgkaSArIDEpICUgMjU2OwogICAgJGogPSAoJGogKyAkc1skaV0pICUgMjU2OwogICAgQHNbJGksICRqXSA9IEBzWyRqLCAkaV07CiAgICAkYyAuPSBjaHIob3JkKCRjaGFyKSBeICRzWygkc1skaV0gKyAkc1skal0pICUgMjU2XSk7CiAgfQogIHJldHVybiAkYzsKfQpteSAkayA9IFs1NSwgNDksIDUwLCAxMDAsIDk5LCA5NywgMTAyLCA1NiwgMTAxLCA1NiwgNTAsIDUxLCA1NywgNTAsIDUyLCAxMDIsIDEwMCwgNTcsIDk3LCAxMDAsIDEwMiwgNTcsIDk3LCA1NSwgMTAxLCA5NywgOTksIDUzLCA5OSwgNTYsIDU2LCAxMDJdOwpteSAkZT0gJzg3ZDg1Y2Y1MDM3NWY3M2NhMDY2ZGEzNjQ1NjQwYWVmYjBkYzc4NTFjMzIzNGE2NDVkY2FjYjVmMjInOwpteSAkeCA9IHIoJGUsICRrKTsKcHJpbnQgImZsYWc6ICI7Cm15ICRwID0gPFNURElOPjsKY2hvbXAgJHA7Cm15ICRpID0gcigkcCwgJGspOwpwcmludCB1bnBhY2soJ0gqJywgJGkpIGVxICRlPyJDb3JyZWN0IVxuIjoiV3JvbmchXG4iOwo='));

まぁこういうのはevalprintとかにしましょう。というかbase64って書いてあるのでデコードしてみましょう。

sub r {
  my($d, $k) = @_;
  my @s = 0..255;
  my ($i, $j, $c) = (0, 0, '');
  my $l = @$k;
  for ($i = 0; $i < 256; $i++) {
    $j = ($j + $s[$i] + $k->[$i%$l]) % 256;
    @s[$i, $j] = @s[$j, $i];
  }
  $i = $j = 0;
  foreach my $char (split //, $d) {
    $i = ($i + 1) % 256;
    $j = ($j + $s[$i]) % 256;
    @s[$i, $j] = @s[$j, $i];
    $c .= chr(ord($char) ^ $s[($s[$i] + $s[$j]) % 256]);
  }
  return $c;
}
my $k = [55, 49, 50, 100, 99, 97, 102, 56, 101, 56, 50, 51, 57, 50, 52, 102, 100, 57, 97, 100, 102, 57, 97, 55, 101, 97, 99, 53, 99, 56, 56, 102];
my $e= '87d85cf50375f73ca066da3645640aefb0dc7851c3234a645dcacb5f22';
my $x = r($e, $k);
print "flag: ";
my $p = <STDIN>;
chomp $p;
my $i = r($p, $k);
print unpack('H*', $i) eq $e?"Correct!\n":"Wrong!\n";

なんだろうこのmy $x = r($e, $k)の行。正直自分でも覚えてないです。

まぁ見ての通りRC4ですね。ChatGPTもそう言っています。

$ fask '以下のPerlで書かれた暗号化処理を説明してください
∙ sub r {
  my($d, $k) = @_;
  my @s = 0..255;
  my ($i, $j, $c) = (0, 0, '');
  my $l = @$k;
  for ($i = 0; $i < 256; $i++) {
    $j = ($j + $s[$i] + $k->[$i%$l]) % 256;
    @s[$i, $j] = @s[$j, $i];
  }
  $i = $j = 0;
  foreach my $char (split //, $d) {
    $i = ($i + 1) % 256;
    $j = ($j + $s[$i]) % 256;
    @s[$i, $j] = @s[$j, $i];
    $c .= chr(ord($char) ^ $s[($s[$i] + $s[$j]) % 256]);
  }
  return $c;
}'
このPerlサブルーチン`r`は、RC4ストリーム暗号アルゴリズムに基づいた暗号化(および復号化)処理を実行するためのコードです。RC4は鍵ストリームを生成して平文(または暗号文)と排他的論理和(XOR)を取るアルゴリズムです。このコードはそのための初期化とデータ処理を行っています。

サブルーチンの引数:
- `$d`は暗号化または復号化するデータ(文字列)
- `$k`は暗号化(または復号化)の鍵を表す配列のリファレンス

手順の説明:

1. 配列`@s`を初期化し、0から255までの数値で埋めます。これは、RC4S-box(順列ボックス)です。

2. インデックス`$i``$j`0に初期化します。これらはアルゴリズム内で使用される変数です。

3. 鍵の長さ`$l`を取得します(スカラー配列リファレンスをデリファレンスして配列サイズを取得している)。

4. 鍵の初期化ステップ: 0から255の各値`$i`について、S-boxを鍵に基づいて初期化します。`$j`S-boxと鍵の値を使用して更新され、S-boxの位置`$i``$j`の値を交換します。

5. 変数`$i``$j`を再び0にリセットします。

6. 暗号化(または復号化)のメインループ: データ`$d`1文字ずつ処理します。

   a. S-boxを使用して鍵ストリームを生成します。`$i``$j`は更新され、S-boxの当該位置も交換されます。

   b. 生成した鍵ストリームの値(S-boxの値を使用)とデータ文字のASCII値のXORを取り、暗号化(または復号化)された文字を生成します。

   c. 処理された文字を結果文字列`$c`に追加します。

7. 処理が完了した後、暗号化(または復号化)されたデータを含む文字列`$c`を返します。

この処理により、平文と鍵を使用して暗号文を生成することができます。また、同じ鍵を使って暗号文に対してこのサブルーチンを実 行することで、元の平文を復号化することができます。これは、XOR操作が反転可能なためです(同じ鍵ストリームを使用して二度XOR を行うと、元のデータに戻ります)。

まずは$kがasciiっぽいのでいい感じにします

>>> ''.join([chr(c) for c in [55, 49, 50, 100, 99, 97, 102, 56, 101, 56, 50, 51, 57, 50, 52, 102, 100, 57, 97, 100, 102, 57, 97, 55, 101, 97, 99, 53, 99, 56, 56, 102]])
'712dcaf8e823924fd9adf9a7eac5c88f'

あとはCyberChefにでも投げればdecryptoできます

SECCON{R1d3_0n_5h00t1ng_5t4r}

flcl

Web

poem

Web問が最初なさすぎたので作ったんですが、pathと結構被ってます。

require 'sinatra'

get '/' do
  """
  <html>
    <body>
      <h1>My Poems</h1>
      <ul>
        <li><a href='/read?poem=poem1.html'>Poem 1</a></li>
        <li><a href='/read?poem=poem2.html'>Poem 2</a></li>
        <li><a href='/read?poem=poem3.html'>Poem 3</a></li>
      </ul>
    </body>
  </html>
  """
end

get '/read' do
  file = params[:poem]
  begin
    File.open(file, 'r') do |f|
      f.read
    end
  rescue
    "Can't read"
  end
end

get '/flag.txt' do
  "Do not look at me!"
end

ポエムはChatGPTに作らせました。こういうので便利。

/read?poem=flag.txtだけです。

SECCON{Und3r_Th3_Br1dg3}

Blood Sugar Sex Magik

総括

CTF会場の入り口で主にやっていたんですが、一般参加者が結構集まって交流もしてくれたので非常に嬉しかったです。

気合と機会があれば来年もやりたいですね。

おわりに

この記事はn01e0 Advent Calendar 2023の24日目の記事です。

明日でやっと解放されますが、明日のネタはありません。

また、IPFactory OB Advent Calendar 2023の24日目の記事も兼ねています。