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_!!}