Full Weak Engineer CTF 2025のWriteupです。
自分で解けた問題のみのWriteupです。
baby-crypto (Crypt, Beginner)
sjrpgs{ebg13rq_zrffntr!}
rot13で解ける
fwectf{rot13ed_message!}
base🚀 (Crypt, Easy)
🪛🔱🛜🫗🚞👞🍁🎩🚎🐒🌬🧨🖱🥚🫁🧶🪛🔱👀🔧🚞👛😄🎩🚊🌡🌬🧮🤮🥚🫐🛞🪛🔱👽🔧🚞🐻🔳🎩😥🪨🌬🩰🖖🥚🫐🪐🪛🔱👿🫗🚞🏵📚🎩🚊🎄🌬🧯🕺🥚🫁📑🪛🔰🐀🫗🚞💿🔳🎩🚲🚟🌬🧲🚯🥚🫁🚰🪛🔱💀🔧🚞🏓🛼🎩🚿🪻🌬🧪🙊🥚🫐🧢🪛🔱🛟🔧🚞🚋🫳🎩😆🏉🌬🧶🚓🥚🫅💛🪛🔱🔌🐃🚞🐋🥍🎩😱🤮🌬🩰🛳🥚🫀📍🪛🔰🐽🫗🚞💿🍁🎩🚊🌋🌬🧵🔷🚀🚀🚀
% unzip base.zip
Archive: base.zip
inflating: base🚀/emoji.txt
inflating: __MACOSX/base🚀/._emoji.txt
inflating: base🚀/chall.py
inflating: __MACOSX/base🚀/._chall.py
emoji.txt
とchall.py
の中身を見てみる
⭐⭕🀄🃏🌀🌁🌂🌃🌄🌅🌆🌇🌈🌉🌊🌋🌌🌍🌐🌑🌓🌕🌗🌙🌚🌛🌜🌝🌞🌟🌠🌡🌤🌥🌦🌧🌨🌩🌪🌬🌭🌮🌯🌰🌱🌲🌳🌴🌵🌶🌷🌸🌹🌺🌻🌼🌽🌾🌿🍀🍁🍂🍃🍄🍅🍆🍇🍈🍉🍊🍋🍌🍍🍎🍏🍐🍑🍒🍓🍔🍕🍖🍗🍘🍙🍚🍛🍜🍝🍞🍟🍠🍡🍢🍣🍤🍥🍦🍧🍨🍩🍪🍫🍬🍭🍮🍯🍰🍱🍲🍳🍴🍵🍶🍷🍸🍹🍺🍻🍼🍽🍾🍿🎀🎁🎂🎃🎄🎅🎆🎇🎈🎉🎊🎋🎌🎍🎎🎏🎐🎑🎒🎓🎖🎗🎙🎚🎛🎞🎟🎠🎡🎢🎣🎤🎥🎦🎧🎨🎩🎪🎫🎬🎭🎮🎯🎰🎱🎲🎳🎴🎵🎶🎷🎸🎹🎺🎻🎼🎽🎾🎿🏀🏁🏂🏃🏄🏅🏆🏇🏈🏉🏊🏋🏌🏍🏎🏏🏐🏑🏒🏓🏔🏕🏖🏗🏘🏙🏚🏛🏜🏝🏞🏟🏠🏡🏢🏣🏤🏥🏦🏧🏨🏪🏫🏬🏭🏮🏯🏰🏳🏴🏵🏷🏸🏹🏺🐀🐁🐂🐃🐄🐅🐆🐇🐈🐉🐊🐋🐌🐍🐎🐏🐐🐑🐒🐓🐔🐕🐖🐗🐘🐙🐚🐛🐜🐝🐞🐟🐠🐡🐢🐣🐤🐥🐦🐧🐨🐩🐪🐫🐬🐭🐮🐯🐰🐱🐲🐳🐴🐵🐶🐷🐸🐹🐺🐻🐼🐽🐾🐿👀👁👂👃👄👅👆👇👈👉👊👋👌👍👎👏👐👑👒👓👔👕👖👗👘👙👚👛👜👝👞👟👠👡👢👣👤👥👦👧👨👩👪👫👬👭👮👯👰👱👲👳👴👵👶👷👸👹👺👻👼👽👾👿💀💁💂💃💄💅💆💇💈💉💊💋💌💍💎💏💐💑💒💔💕💖💘💙💚💛💜💝💞💟💠💡💢💣💤💥💦💧💨💩💪💫💬💭💮💯💰💳💴💵💶💷💸💹💺💻💼💽💾💿📀📅📆📇📈📉📊📋📌📍📎📏📐📑📒📓📔📕📖📚📛📜📝📞📟📠📡📢📣📦📧📨📪📮📯📰📱📲📵📶📷📸📹📺📻📼📽📿🔅🔆🔇🔈🔉🔊🔋🔌🔍🔎🔏🔐🔑🔒🔓🔔🔕🔖🔗🔘🔞🔥🔦🔧🔨🔩🔪🔫🔬🔭🔮🔯🔰🔱🔲🔳🔴🔵🔶🔷🔸🔹🔺🔻🔼🔽🕉🕊🕋🕌🕍🕎🕐🕯🕰🕳🕴🕵🕶🕷🕸🕹🕺🖇🖊🖋🖌🖍🖐🖕🖖🖤🖥🖨🖱🖲🖼🗂🗃🗄🗑🗒🗓🗜🗝🗞🗡🗣🗨🗯🗳🗺🗻🗼🗽🗾🗿😂😃😄😅😆😇😈😊😍😎😐😓😘😜😡😢😥😨😪😫😬😭😮😰😱😳😵🙄🙅🙆🙇🙈🙉🙊🙋🙌🙍🙎🙏🚁🚂🚃🚄🚅🚆🚇🚈🚉🚊🚋🚌🚍🚎🚏🚐🚑🚒🚓🚔🚕🚖🚗🚘🚙🚚🚛🚜🚝🚞🚟🚠🚡🚢🚣🚤🚥🚦🚧🚨🚩🚪🚫🚬🚭🚮🚯🚰🚱🚲🚳🚴🚵🚶🚷🚸🚽🚿🛀🛁🛌🛍🛎🛏🛐🛑🛒🛕🛖🛜🛝🛞🛟🛠🛡🛣🛤🛥🛩🛫🛬🛰🛳🛴🛵🛶🛷🛸🛹🛺🛻🛼🟠🟡🟢🟣🟤🟥🟦🟧🟨🤌🤏🤐🤑🤒🤔🤕🤖🤗🤘🤙🤚🤛🤝🤞🤟🤠🤡🤢🤣🤦🤧🤩🤪🤬🤮🤯🤰🤱🤲🤳🤴🤵🤶🤷🤸🤹🤺🤼🤽🤾🤿🥀🥁🥂🥃🥄🥅🥇🥈🥉🥊🥋🥌🥍🥎🥏🥐🥑🥒🥓🥔🥕🥖🥗🥘🥙🥚🥛🥜🥝🥞🥟🥠🥡🥢🥣🥤🥥🥦🥧🥨🥩🥪🥫🥬🥭🥮🥯🥰🥲🥳🥴🥵🥶🥷🥸🥹🥺🥻🥼🥽🥾🥿🦀🦁🦂🦃🦄🦅🦆🦇🦈🦉🦊🦋🦌🦍🦎🦏🦐🦑🦒🦓🦔🦕🦖🦗🦘🦙🦚🦛🦜🦝🦞🦟🦠🦡🦢🦣🦤🦥🦦🦧🦨🦩🦪🦫🦬🦭🦮🦯🦰🦱🦲🦳🦴🦵🦶🦷🦸🦹🦺🦻🦼🦽🦾🦿🧀🧁🧂🧃🧄🧅🧆🧇🧈🧉🧊🧋🧕🧖🧗🧘🧙🧚🧛🧜🧝🧞🧟🧠🧡🧢🧣🧤🧥🧦🧧🧨🧩🧪🧫🧬🧭🧮🧯🧰🧱🧲🧳🧴🧵🧶🧷🧸🧹🧺🧻🧼🧽🧾🧿🩰🩱🩲🩳🩴🩹🩺🩻🩼🪀🪁🪂🪃🪄🪅🪆🪇🪈🪐🪑🪒🪓🪔🪕🪖🪗🪘🪙🪚🪛🪜🪝🪞🪟🪠🪡🪢🪣🪤🪥🪦🪧🪨🪩🪪🪫🪬🪭🪮🪯🪱🪴🪵🪶🪷🪸🪹🪺🪻🪼🪽🪿🫀🫁🫂🫅🫎🫏🫐🫑🫒🫓🫔🫕🫖🫗🫘🫙🫚🫛🫠🫡🫦🫧🫰🫱🫲🫳🫵🫶🫷
#!/usr/bin/env python🚀
with open('emoji.txt', 'r', encoding='utf-8') as f:
emoji = list(f.read().strip())
table = {i: ch for i, ch in enumerate(emoji)}
def encode(data):
bits = ''.join(f'{b:08b}' for b in data)
pad = (-len(bits)) % 10
bits += '0' * pad
out = [table[int(bits[i:i+10], 2)] for i in range(0, len(bits), 10)]
r = (-len(out)) % 4
if r:
out.extend('🚀' * r)
return ''.join(out)
if __name__ == '__main__':
# msg = 'Hello!'
msg = 'hello'
enc = encode(msg.encode())
print('msg:', msg)
print('enc:', enc)
暗号化と逆の順番で処理させて復号する。
#!/usr/bin/env python🚀
import sys
try:
with open('emoji.txt', 'r', encoding='utf-8') as f:
emoji = list(f.read().strip())
except FileNotFoundError:
print("エラー: 'emoji.txt' が見つかりません。スクリプトと同じディレクトリに配置してください。", file=sys.stderr)
sys.exit(1)
# エンコード用テーブル {0: '😀', 1: '😁', ...}
table = {i: ch for i, ch in enumerate(emoji)}
# デコード用の逆引きテーブル {'😀': 0, '😁': 1, ...}
inv_table = {ch: i for i, ch in table.items()}
def encode(data: bytes) -> str:
# 1. バイトデータを8ビットの2進数文字列に変換
bits = ''.join(f'{b:08b}' for b in data)
# 2. 長さが10の倍数になるように '0' でパディング
pad = (-len(bits)) % 10
bits += '0' * pad
# 3. 10ビットずつに区切り、対応する絵文字に変換
out = [table[int(bits[i:i+10], 2)] for i in range(0, len(bits), 10)]
# 4. 絵文字リストの長さが4の倍数になるように '🚀' でパディング
r = (-len(out)) % 4
if r:
out.extend('🚀' * r)
return ''.join(out)
def decode(encoded_data: str) -> bytes:
"""絵文字でエンコードされた文字列を元のバイトデータにデコードします。"""
# 1. 末尾の '🚀' パディングを除去
s = encoded_data.rstrip('🚀')
# 2. 各絵文字を10ビットの2進数文字列に戻し、結合してビット文字列を再構築
bits = "".join(f'{inv_table[char]:010b}' for char in s)
# 3. 元のデータは8ビット(1バイト)単位なので、全体の長さを8の倍数に切り詰める
# これにより、エンコード時に追加された '0' のパディングが除去される
num_bytes = len(bits) // 8
bits = bits[:num_bytes * 8]
# 4. 8ビットずつに区切り、整数に変換してからバイトオブジェクトに戻す
original_bytes = bytes(int(bits[i:i+8], 2) for i in range(0, len(bits), 8))
return original_bytes
if __name__ == '__main__':
msg = 'Hello, world! こんにちは、世界!'
# エンコード
encoded = encode(msg.encode('utf-8'))
print('Original:', msg)
print('Encoded: ', encoded)
print("-" * 30)
# デコード
decoded_bytes = decode(encoded)
flag = decode('🪛🔱🛜🫗🚞👞🍁🎩🚎🐒🌬🧨🖱🥚🫁🧶🪛🔱👀🔧🚞👛😄🎩🚊🌡🌬🧮🤮🥚🫐🛞🪛🔱👽🔧🚞🐻🔳🎩😥🪨🌬🩰🖖🥚🫐🪐🪛🔱👿🫗🚞🏵📚🎩🚊🎄🌬🧯🕺🥚🫁📑🪛🔰🐀🫗🚞💿🔳🎩🚲🚟🌬🧲🚯🥚🫁🚰🪛🔱💀🔧🚞🏓🛼🎩🚿🪻🌬🧪🙊🥚🫐🧢🪛🔱🛟🔧🚞🚋🫳🎩😆🏉🌬🧶🚓🥚🫅💛🪛🔱🔌🐃🚞🐋🥍🎩😱🤮🌬🩰🛳🥚🫀📍🪛🔰🐽🫗🚞💿🍁🎩🚊🌋🌬🧵🔷🚀🚀🚀')
decoded_msg = decoded_bytes.decode('utf-8')
print('Decoded: ', decoded_msg)
print("flag? ", flag.decode('utf-8'))
print("flag_1 ", decode(flag.decode('utf-8')).decode('utf-8'))
# 検証
print("\n✅ Success:", msg == decoded_msg)
実行する
% python decode.py
Original: Hello, world! こんにちは、世界!
Encoded: 🐴🙅🥬🍴🎺🕉🔇🧄📌😍🍍🏮🔽👑🏫🚳🧩🌜🥉🧜🚧🗾🍰🫀🔹🌠👁🎠🧹👫🦍🪕🔻🚀🚀🚀
------------------------------
Decoded: Hello, world! こんにちは、世界!
flag? 🪛🔰🛏🍈📛🤵🔈🚁📷🦨🥩💇💼🥇🧷🥳🎆🚇🔅👶📷🚇🤧🗣💐🥵🌚🦽🏖🧇🪥🦿🏋🛜🙆🧀🏋🔭🥬🍲🔫🚀🚀🚀
flag_1 🚀Congratulations! fwectf{n0_r0ck37_3m0ji_n0_llm}
✅ Success: True
二回デコードする必要があったけどフラグゲット!
fwectf{n0_r0ck37_3m0ji_n0_llm}
unixor (Crypt, Easy)
I wanna be a novelist
% unzip unixor.zip
Archive: unixor.zip
creating: dist/
inflating: dist/encrypted.txt
inflating: dist/generate.py
����Ș���⪼�ؼ�߹������������Љ�����μı>���������ރ����ʧ������ڗ������������ҧ����Ւ���Ќƀ��ą����ޢ����ȑ�ב�ȃ���͎����������������ò������������ؔ�Ó�ۇ��������ԧ������Ȓ�ʇ¿��ހ����̧��������އ�������鱗���Ɣ���܁̽����������������~l����������������҂���Ŝ���ż��Ӻ���œ�����ŀ������������ɼŝ��م�������ƹ��Ӹ�йҪ��ƅ�ŀ��������ҹ���Ķ��������������������߹ʡ������������ͼ�ś�����������Ŝ��ӹ�ػ����օ�̀�Ř���Ӗ��꼰������ց���Г���Œ����Ŭ��́�̀�Ș���ŵ����Ŭ���l����ā����Ӄ����ާ�������͑���ּ�������秲����EUS��̍ļ��ׅ������������ɑ���¯��������觳���Δ�����ò��������������͔�̗������������ެ���������Ձ᳧�ͅ����Ƨ��������Ќ����ׅ����Ч�������˗���²��ԅ����ۧ��������އ���������ԧ����Ȕ�̑�ڌ妬������ɡ����ߔ�͓������ȅ����������֔�������lX��ӼŮ��Ӏ����������������ŝ��ߎ���Ȝ���î���������օ�������É��ͼ�ѹ����Ӏ����������Ҷ���ـ�DŽ�Ý���ŝ��ݼ�Ƽř�����������ŷ��ټ�¼IJ������������̊�����иѿ����������ƹ��켰�ٖ��ۅ����������ἰ����������������ŝ��ȼ���IJ�������ȝ���Ř�����ƼƱ�������̘���ı��ͼ��IJ��Dž�ͅ�ј���́����Ţ�����������ѿ����������Յ���̘���Ÿ�����ۼŵ��փ�������ŕ��ּ�ؼı>n�����܅�נ����ջ�����֑���������姍����ˉ���֗Ԟ�ن����⠱���ı܍���зؔ�Ć�����������߳���ж�������̠�����փ���ۼݙ������Ơ�����ޒ���Իڞ������櫸����ޚ���ԡԘ�ʆ�ڀ�����Դ���е˚������Š����ױ���ж������l��������ۼ���������������ŝ��뼳��������������Ƹ�����иѿ����π�Ϙ���ŷ��ټ���ƻ�����Ί�Ԙ���Ŕ��ּ��Ŭ�����������̿������ơ��υ�ڋ�ژ���IJ��ͼ��̊��̅��������Ő��ͼ�ѹġ������������������Һ���ׁ�ߋ������ſ��꼰��������ƀ������������ŝ�����ˀ������ř��ּ���Ř������������ŷ�����Ҡ�����������ſ��ͼ��ƿ�����ˀ�Ƙ��:N��������д��؆�߀�ߠ����α߰���՝��܀���堲����ޮ���ے��Ά��������ʹ�����еǞ�ц���������ñ���֧Ş����������ֱݣ���е���������礥�����࠰��Մ����Ѕ��������ޙ���е������ׅ���������ޟ���еʘ�҆�߅�ˠ����ñߴ���е��߆�˃�젱���ȵɃ���е��׆���蠱����ޮ���9>�������������ԅ����ߠ�������ԑ�ȇ����܅����������۔������ʅ����ӧ��������ò������𡨉��ȑ�ٗ���¯��Ņ����ݧ������������������������Ռ⼢������ħ�������ė���²���������Nд�������������ޖ���е������܅�媷���ɷӦ���ո�������������ݺ���ՁӞ�܂���ˠ�����߳���ж��ن�ۅ�奍���ȴ갰��е̔�߆�ڃ�栱����ެ���е�͌���觍���űޮ���ԡ��׆���Ġ��9��ҹ�ػ����҅�Ѐ�Θ���Ù��Լ�߹؟����Ά�����Ŭ��ּ���Ŝ�����ȝ���ľ�������Ÿ������������Ʊ��ͼ��Ŀ����������Ʋ������ľ��ׅ�ˀ�����İ��ڼ�̼ı������ɘ���œ��輰��ŷ��������Ƙ���ܽ�����ѹ����փ�߀�����ƾ��Լ�Ѻ�����ˆ������ŵ�������IJ���������������ź�ɼż��ӏ��������ŷ�����Ƹ�����������Ÿ��ۼ��
FLAG = b"fwectf{**REDACTED**}"
assert len(FLAG) < 30
"""
novel.txtはChatGPT 5 Autoによって生成された、UTF-8(BOMなし、改行LF)で書かれた小説です。
プロンプト(一部修正):
「**REDACTED**」という単語から連想される、1500字程度の小説を書いてください。
"""
novel = open("novel.txt", "rb").read()
encrypted = bytes([a ^ FLAG[i % len(FLAG)] for i, a in enumerate(novel)])
open("encrypted.txt", "wb").write(encrypted)
復号スクリプトを書く(Geminiが)
#!/usr/bin/env python3
import sys
from pathlib import Path
from collections import Counter, defaultdict
def try_build_key(ct: bytes, L: int):
# seed known prefix "fwectf{"
seed = b"fwectf{"
key = [None] * L
for i, b in enumerate(seed):
key[i % L] = b
# voting using frequent Japanese punctuation
triples = [
(0xE3, 0x80, 0x82), # "。"
(0xE3, 0x80, 0x81), # "、"
]
votes = [Counter() for _ in range(L)]
n = len(ct)
for i in range(n - 2):
for t in triples:
k0 = ct[i] ^ t[0]
k1 = ct[i+1] ^ t[1]
k2 = ct[i+2] ^ t[2]
votes[(i ) % L][k0] += 1
votes[(i + 1) % L][k1] += 1
votes[(i + 2) % L][k2] += 1
# also vote for newline 0x0A (line feeds common)
for i in range(n):
k = ct[i] ^ 0x0A
votes[i % L][k] += 1
# apply highest votes where key not fixed by seed
for pos in range(L):
if key[pos] is None and votes[pos]:
key[pos] = votes[pos].most_common(1)[0][0]
# if still some Nones, fill with 0 as placeholder (will likely fail and be discarded)
for pos in range(L):
if key[pos] is None:
key[pos] = 0
return bytes(key), votes
def score_utf8(decoded_bytes: bytes) -> float:
# returns fraction of bytes that are part of a successfully decoded UTF-8 string
# We attempt to decode; if fails, we do a tolerant pass counting valid sequences.
total = len(decoded_bytes)
i = 0
good = 0
while i < total:
b = decoded_bytes[i]
if b < 0x80:
good += 1
i += 1
elif 0xC2 <= b <= 0xDF:
if i + 1 < total and 0x80 <= decoded_bytes[i+1] <= 0xBF:
good += 2; i += 2
else:
i += 1
elif 0xE0 <= b <= 0xEF:
if (i + 2 < total and
0x80 <= decoded_bytes[i+1] <= 0xBF and
0x80 <= decoded_bytes[i+2] <= 0xBF):
good += 3; i += 3
else:
i += 1
elif 0xF0 <= b <= 0xF4:
if (i + 3 < total and
0x80 <= decoded_bytes[i+1] <= 0xBF and
0x80 <= decoded_bytes[i+2] <= 0xBF and
0x80 <= decoded_bytes[i+3] <= 0xBF):
good += 4; i += 4
else:
i += 1
else:
i += 1
return good / max(1, total)
def decrypt_with_key(ct: bytes, key: bytes) -> bytes:
L = len(key)
return bytes([ct[i] ^ key[i % L] for i in range(len(ct))])
def main():
enc_path = Path("encrypted.txt")
if not enc_path.exists():
print("[-] encrypted.txt not found in current directory.")
print(" Put encrypted.txt next to this script and run again.")
sys.exit(1)
ct = enc_path.read_bytes()
best = None
# flags are shorter than 30, try reasonable lengths
for L in range(8, 30):
key, votes = try_build_key(ct, L)
# enforce known prefix
if key[:7] != b"fwectf{":
# if voting overwrote the prefix, fix it
key = b"fwectf{" + key[7:]
pt = decrypt_with_key(ct, key)
score = score_utf8(pt)
# simple heuristic: decoded text should be largely valid UTF-8 (>0.85)
if best is None or score > best[0]:
best = (score, L, key, pt)
score, L, key, pt = best
print(f"[+] Best key length = {L} with UTF-8 score = {score:.3f}")
# Try to refine trailing key bytes by searching for '}' in key (flags end with })
# We'll read off the ASCII flag characters from key directly if it looks plausible.
try:
flag_text = key.decode("ascii", errors="strict")
except Exception:
# make a more robust extraction by assuming it starts with fwectf{ and ends with }
flag_text = ''.join(chr(b) if 32 <= b <= 126 else '?' for b in key)
# Extract fwectf{...} substring
import re
m = re.search(r"fwectf\{[ -~]{0,50}\}", flag_text)
if m:
print(f"[+] FLAG (from key): {m.group(0)}")
else:
print("[!] Could not confidently parse FLAG as ASCII from key bytes.")
print(" Key guess:", flag_text)
# Write decrypted novel for sanity check
out = Path("decrypted_novel.txt")
out.write_bytes(pt)
print(f"[+] Wrote decrypted novel to {out.resolve()}")
if __name__ == "__main__":
main()
実行する
% python solve_unixor.py
[+] Best key length = 24 with UTF-8 score = 1.000
[+] FLAG (from key): fwectf{dC0D3_fR_1S_D34d}
[+] Wrote decrypted novel to /home/saku0512/Desktop/CTF/Full_Weak_Engineer_CTF/Crypt/unixor/dist/decrypted_novel.txt
一応flagゲット
fwectf{dC0D3_fR_1S_D34d}
Adversarial Login (Misc, Medium)
The strange mascot seems to be trying to impersonate its way out of the venue. Your mission is to intentionally confuse an AI. Take the provided image and, with the utmost subtlety, modify it just enough to make the classifier believe it's looking at a gibbon.
英語分からんから日本語翻訳する
その奇妙なマスコットは、なりすましで会場を出ようとしているようだ。あなたのミッションは、AIを意図的に混乱させることです。提供された画像を、細心の注意を払いながら、分類機にテナガザルを見ていると思わせるのに十分な程度に修正してください。
AIの敵対的サンプルを作る問題っぽい
% unzip adversarial_login.zip
Archive: adversarial_login.zip
creating: adversarial_login/
creating: adversarial_login/templates/
inflating: adversarial_login/templates/login.html
inflating: adversarial_login/templates/index.html
inflating: adversarial_login/Dockerfile
inflating: adversarial_login/image.jpg
inflating: adversarial_login/requirements.txt
inflating: adversarial_login/app.py
inflating: adversarial_login/compose.yml
image.jpgはミャクミャクの画像
import os
from flask import Flask, flash, redirect, request, render_template, session, url_for
from PIL import Image
import numpy as np
import tensorflow as tf
FLAG = os.environ.get("FLAG", "fwectf{fake_flag}")
IMG_HEIGHT, IMG_WIDTH = 224, 224
ORIGINAL_IMAGE_PATH = 'image.jpg'
TARGET_CLASS_ID = 101
MSE_THRESHOLD = 0.05
app = Flask(__name__)
app.secret_key = os.urandom(16).hex()
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 # 100KB
def preprocess_image(img):
img = img.convert('RGB').resize((IMG_HEIGHT, IMG_WIDTH))
img_array = np.array(img)
preprocessed_img = tf.keras.applications.mobilenet_v2.preprocess_input(img_array)
return tf.convert_to_tensor(preprocessed_img, dtype=tf.float32)
original_image = Image.open(ORIGINAL_IMAGE_PATH)
original_image_tensor = preprocess_image(original_image)
model = tf.keras.applications.MobileNetV2(weights="imagenet")
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
try:
file = request.files['file']
image = Image.open(file.stream)
image_tensor = preprocess_image(image)
if image_tensor is None:
return render_template("login.html")
mse = tf.reduce_mean(tf.square(original_image_tensor - image_tensor))
if mse.numpy() > MSE_THRESHOLD:
flash(
f"[-] AUTH FAILED (Stage 1): Image is too different from the original.\n"
f" MSE: {mse.numpy():.4f} > Threshold: {MSE_THRESHOLD}\n"
)
return render_template("login.html")
prediction = model.predict(np.expand_dims(image_tensor, axis=0), verbose=0)
predicted_class_id = np.argmax(prediction[0])
if predicted_class_id == TARGET_CLASS_ID:
session["is_admin"] = True
return redirect(url_for("index"))
decoded_preds = tf.keras.applications.mobilenet_v2.decode_predictions(prediction, top=1)[0]
predicted_class_name = decoded_preds[0][1]
flash(
f"[-] AUTH FAILED (Stage 2): Image was not classified as the target class.\n"
f" Predicted as: '{predicted_class_name}' (ID: {predicted_class_id})\n"
)
except Exception as e:
flash(f"Error occured: {e}")
return render_template("login.html")
@app.route("/")
def index():
if not session.get("is_admin"):
return redirect(url_for("login"))
return render_template("index.html", flag=FLAG)
やはり敵対的サンプルを作成し、アップロードすればいいっぽい
import numpy as np
import tensorflow as tf
from PIL import Image
IMG_HEIGHT, IMG_WIDTH = 224, 224
ORIGINAL_IMAGE_PATH = 'image.jpg'
TARGET_CLASS_ID = 101
MSE_THRESHOLD = 0.05
OUTPUT_IMAGE_PATH = 'adversarial.png'
def preprocess_image(img):
img = img.convert('RGB').resize((IMG_HEIGHT, IMG_WIDTH))
img_array = np.array(img)
preprocessed_img = tf.keras.applications.mobilenet_v2.preprocess_input(img_array)
return tf.convert_to_tensor(preprocessed_img, dtype=tf.float32)
def deprocess_image(tensor):
tensor = tensor.numpy()
tensor = (tensor + 1.0) * 127.5
tensor = np.clip(tensor, 0, 255)
return Image.fromarray(tensor.astype('uint8'))
def main():
original_image = Image.open(ORIGINAL_IMAGE_PATH)
original_image_tensor = preprocess_image(original_image)
model = tf.keras.applications.MobileNetV2(weights="imagenet")
# 元の画像の分類結果を確認
initial_prediction = model.predict(np.expand_dims(original_image_tensor, axis=0))
initial_class_id = np.argmax(initial_prediction[0])
decoded_preds = tf.keras.applications.mobilenet_v2.decode_predictions(initial_prediction, top=1)[0]
print(f"[*] Original image is classified as: '{decoded_preds[0][1]}' (ID: {initial_class_id})")
adversarial_image_tensor = tf.Variable(original_image_tensor)
optimizer = tf.keras.optimizers.Adam(learning_rate=0.1)
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy()
print("[*] Generating adversarial image...")
for i in range(200):
with tf.GradientTape() as tape:
tape.watch(adversarial_image_tensor)
prediction = model(tf.expand_dims(adversarial_image_tensor, axis=0))
# ターゲットクラスに対する損失を計算
loss = loss_fn(tf.constant([TARGET_CLASS_ID]), prediction)
grads = tape.gradient(loss, adversarial_image_tensor)
optimizer.apply_gradients([(grads, adversarial_image_tensor)])
# 元画像との差分が大きくなりすぎないように制約をかける
perturbation = adversarial_image_tensor - original_image_tensor
perturbation = tf.clip_by_value(perturbation, -MSE_THRESHOLD, MSE_THRESHOLD)
adversarial_image_tensor.assign(original_image_tensor + perturbation)
# 前処理されたテンソルが[-1, 1]の範囲に収まるようにクリップ
adversarial_image_tensor.assign(tf.clip_by_value(adversarial_image_tensor, -1.0, 1.0))
if (i + 1) % 20 == 0:
final_prediction = model.predict(np.expand_dims(adversarial_image_tensor, axis=0), verbose=0)
final_class_id = np.argmax(final_prediction[0])
mse = tf.reduce_mean(tf.square(original_image_tensor - adversarial_image_tensor)).numpy()
print(f" Step {i+1:3d}: MSE = {mse:.4f}, Predicted Class ID = {final_class_id}")
if final_class_id == TARGET_CLASS_ID and mse <= MSE_THRESHOLD:
print("[+] Adversarial image generated successfully!")
break
final_prediction = model.predict(np.expand_dims(adversarial_image_tensor, axis=0))
final_class_id = np.argmax(final_prediction[0])
decoded_final_preds = tf.keras.applications.mobilenet_v2.decode_predictions(final_prediction, top=1)[0]
mse = tf.reduce_mean(tf.square(original_image_tensor - adversarial_image_tensor))
print(f"[*] Final prediction: '{decoded_final_preds[0][1]}' (ID: {final_class_id})")
print(f"[*] MSE with original image: {mse.numpy():.4f}")
if final_class_id == TARGET_CLASS_ID and mse.numpy() <= MSE_THRESHOLD:
print(f"[+] Conditions met. Saving image to '{OUTPUT_IMAGE_PATH}'")
adversarial_image = deprocess_image(adversarial_image_tensor)
adversarial_image.save(OUTPUT_IMAGE_PATH)
else:
print("[-] Failed to generate an adversarial image that meets the conditions.")
if __name__ == '__main__':
main()
実行して生成された画像をアップロードすればフラグゲット!
fwectf{1s_y0ur_br41n_d33p_l34rn1ng?}
Osaka Expo Pavilion Quiz! (OSINT, Easy)
大阪万博…だけど様子がちょっと変? この映像が放送された館を答えよ
Flag形式:fwectf{館名(日本語可)}
画像だけが配布される
perplexityで調べる
この画像が大阪万博(1970年開催)の会場で放送された館は「みどり館」です。
みどり館について
「みどり館」はドーム形の球体施設で、内部全体が巨大なスクリーンとなっていたため、広角映像や天井への投影が特徴的でした。
ドームの内装全体に映像が映し出される構造で、大変印象的な内部空間が創出されていました。
当時の技術を駆使して360度・上下210度に映像を投影できた点が特徴とされています。
ドーム天井装飾との関係
画像にも見られるような天井全体の映像や装飾は、みどり館ならではの大規模映像空間によるものです。
みどり館は多くの来場者に強い印象を残したパビリオンです。
したがって、画像のドーム天井およびその放送元は「みどり館」と特定できます。
フラグゲット!
fwectf{みどり館}
QR (Forensic, Beginner)
RGB RGB RGB
RGB RGB RGB
RGB RGB RGB
よみとってみる
367 294 815
おそらく各ブロックに対応している。
3 6 7
2 9 4
8 1 5
各ブロックの色をアイビスペイントのスポイト機能で調べる。
#7b5152 #6f6c6f #75725F
#637466 #36657D #5F616E
#393837 #667765 #645F63
各ブロックを読み取った順番で並べ替える。
復号スクリプトを書く。
def decrypt_from_hex(hex_codes):
"""
ヘックスコードのリストをデコードしてフラグ文字列を生成する関数
"""
decrypted_chars = []
# リスト内の各ヘックスコードを処理
for hex_code in hex_codes:
# '#' を取り除く
clean_hex = hex_code.lstrip('#')
# 2文字ずつ(RR, GG, BB)に分割して処理
for i in range(0, len(clean_hex), 2):
# 2文字の16進数文字列を取得 (例: "66")
hex_byte = clean_hex[i:i+2]
# 16進数文字列を10進数の整数に変換
decimal_value = int(hex_byte, 16)
# 整数をASCII文字に変換してリストに追加
decrypted_chars.append(chr(decimal_value))
# 文字リストを一つの文字列に結合して返す
return "".join(decrypted_chars)
# ユーザーが提供した、並べ替え後のヘックスコードのリスト
reordered_hex_codes = [
"#667765",
"#637466",
"#7b5152",
"#5F616E",
"#645F63",
"#6f6c6f",
"#75725F",
"#393837",
"#36657D",
]
# 関数を実行してフラグを復号
final_flag = decrypt_from_hex(reordered_hex_codes)
# 結果を出力
print("復号結果:")
print(final_flag)
% python solve.py
復号結果:
fwectf{QR_and_colour_9876e}
フラグゲット!
fwectf{QR_and_colour_9876e}
No need Logical Thinking (Rev, Easy)
論理的思考はどんな物事にも必要。
% unzip No_need_Logical_Thinking.zip
Archive: No_need_Logical_Thinking.zip
extracting: output.txt
inflating: Challenge.pl
各ファイルをみる
process_flag(FileName) :-
open(FileName, read, Stream),
read_string(Stream, _, Content),
close(Stream),
string_codes(Content, Codes),
transform_codes(Codes, 1, Transformed),
string_codes(NewString, Transformed),
writeln(NewString).
transform_codes([], _, []).
transform_codes([H|T], Index, [NewH|NewT]) :-
NewH is H + Index,
NextIndex is Index + 1,
transform_codes(T, NextIndex, NewT).
%EXECUTE
%?- process_flag('flag.txt').
gyhgyl|qoj\>@@xqDD|zyJyg}UD¡
output.txtをデコードする。
import sys
def solve(input_filename, output_filename):
"""
Reads the encrypted content from input_filename, reverses the
transformation from Challenge.pl, and writes the result to
output_filename.
"""
try:
# Open the input file and read the encrypted string
with open(input_filename, 'r', encoding='utf-8') as f:
encrypted_str = f.read().strip()
decrypted_flag = ""
# Loop through each character with its index
for i, char in enumerate(encrypted_str):
# Get the character code (ASCII/Unicode value)
encrypted_code = ord(char)
# The original script added the index (starting from 1),
# so we subtract it to reverse the process.
index_to_subtract = i + 1
original_code = encrypted_code - index_to_subtract
# Convert the code back to a character and append it
decrypted_flag += chr(original_code)
# Write the final decrypted string to the output file
with open(output_filename, 'w', encoding='utf-8') as f:
f.write(decrypted_flag)
print(f"Successfully decoded '{input_filename}' to '{output_filename}'.")
print(f"Decoded content: {decrypted_flag}")
except FileNotFoundError:
print(f"Error: The file '{input_filename}' was not found.")
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == '__main__':
# Check if a filename was provided as a command-line argument
if len(sys.argv) > 1:
input_file = sys.argv[1]
solve(input_file, 'flag.txt')
else:
# Default to 'output.txt' if no argument is given
solve('output.txt', 'flag.txt')
% python solve.py output.txt
Successfully decoded 'output.txt' to 'flag.txt'.
Decoded content: fwectf{the_Pr010g_10gica1_Languag3!}
フラグゲット!
fwectf{the_Pr010g_10gica1_Languag3!}
Mystery Zone (Rev, Medium)
よぉ~みんな! HelloWorld だぜ!!!
flag を探してたら変な所に迷い込んじまったみてぇだ……。
俺を操作して flag を見つけてくれ~!!
お前たち最高だぜ!
% unzip Mystery_Zone.zip
Archive: Mystery_Zone.zip
inflating: chall/Challenge.exe
creating: chall/Challenge_Data/
extracting: chall/Challenge_Data/app.info
inflating: chall/Challenge_Data/boot.config
inflating: chall/Challenge_Data/globalgamemanagers
inflating: chall/Challenge_Data/globalgamemanagers.assets
inflating: chall/Challenge_Data/globalgamemanagers.assets.resS
inflating: chall/Challenge_Data/level0
inflating: chall/Challenge_Data/level1
inflating: chall/Challenge_Data/level2
creating: chall/Challenge_Data/Managed/
inflating: chall/Challenge_Data/Managed/Assembly-CSharp.dll
inflating: chall/Challenge_Data/Managed/Mono.Security.dll
inflating: chall/Challenge_Data/Managed/mscorlib.dll
inflating: chall/Challenge_Data/Managed/netstandard.dll
inflating: chall/Challenge_Data/Managed/System.ComponentModel.Composition.dll
inflating: chall/Challenge_Data/Managed/System.Configuration.dll
inflating: chall/Challenge_Data/Managed/System.Core.dll
inflating: chall/Challenge_Data/Managed/System.Data.DataSetExtensions.dll
inflating: chall/Challenge_Data/Managed/System.Data.dll
inflating: chall/Challenge_Data/Managed/System.dll
inflating: chall/Challenge_Data/Managed/System.Drawing.dll
inflating: chall/Challenge_Data/Managed/System.EnterpriseServices.dll
inflating: chall/Challenge_Data/Managed/System.IO.Compression.dll
inflating: chall/Challenge_Data/Managed/System.IO.Compression.FileSystem.dll
inflating: chall/Challenge_Data/Managed/System.Net.Http.dll
inflating: chall/Challenge_Data/Managed/System.Numerics.dll
inflating: chall/Challenge_Data/Managed/System.Runtime.dll
inflating: chall/Challenge_Data/Managed/System.Runtime.Serialization.dll
inflating: chall/Challenge_Data/Managed/System.Security.dll
inflating: chall/Challenge_Data/Managed/System.ServiceModel.Internals.dll
inflating: chall/Challenge_Data/Managed/System.Transactions.dll
inflating: chall/Challenge_Data/Managed/System.Xml.dll
inflating: chall/Challenge_Data/Managed/System.Xml.Linq.dll
inflating: chall/Challenge_Data/Managed/Unity.2D.Animation.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.2D.Common.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.2D.IK.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.2D.PixelPerfect.dll
inflating: chall/Challenge_Data/Managed/Unity.2D.SpriteShape.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.2D.Tilemap.Extras.dll
inflating: chall/Challenge_Data/Managed/Unity.Burst.dll
inflating: chall/Challenge_Data/Managed/Unity.Burst.Unsafe.dll
inflating: chall/Challenge_Data/Managed/Unity.Collections.dll
inflating: chall/Challenge_Data/Managed/Unity.Collections.LowLevel.ILSupport.dll
inflating: chall/Challenge_Data/Managed/Unity.InputSystem.dll
inflating: chall/Challenge_Data/Managed/Unity.InputSystem.ForUI.dll
inflating: chall/Challenge_Data/Managed/Unity.InternalAPIEngineBridge.001.dll
inflating: chall/Challenge_Data/Managed/Unity.Mathematics.dll
inflating: chall/Challenge_Data/Managed/Unity.Multiplayer.Center.Common.dll
inflating: chall/Challenge_Data/Managed/Unity.Rendering.LightTransport.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipeline.Universal.ShaderLibrary.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.Core.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.Core.Runtime.Shared.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.Core.ShaderLibrary.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.GPUDriven.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.Universal.2D.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.Universal.Config.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.Universal.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.RenderPipelines.Universal.Shaders.dll
inflating: chall/Challenge_Data/Managed/Unity.TextMeshPro.dll
inflating: chall/Challenge_Data/Managed/Unity.Timeline.dll
inflating: chall/Challenge_Data/Managed/Unity.VisualScripting.Antlr3.Runtime.dll
inflating: chall/Challenge_Data/Managed/Unity.VisualScripting.Core.dll
inflating: chall/Challenge_Data/Managed/Unity.VisualScripting.Flow.dll
inflating: chall/Challenge_Data/Managed/Unity.VisualScripting.State.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.AccessibilityModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.AIModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.AMDModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.AndroidJNIModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.AnimationModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ARModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.AssetBundleModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.AudioModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ClothModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ClusterInputModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ClusterRendererModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ContentLoadModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.CoreModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.CrashReportingModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.DirectorModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.DSPGraphModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.GameCenterModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.GIModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.GraphicsStateCollectionSerializerModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.GridModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.HierarchyCoreModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.HotReloadModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ImageConversionModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.IMGUIModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.InputForUIModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.InputLegacyModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.InputModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.JSONSerializeModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.LocalizationModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.MarshallingModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.MultiplayerModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.NVIDIAModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ParticleSystemModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.PerformanceReportingModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.Physics2DModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.PhysicsModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.PropertiesModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.RuntimeInitializeOnLoadManagerInitializerModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ScreenCaptureModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.ShaderVariantAnalyticsModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.SharedInternalsModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.SpriteMaskModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.SpriteShapeModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.StreamingModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.SubstanceModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.SubsystemsModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.TerrainModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.TerrainPhysicsModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.TextCoreFontEngineModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.TextCoreTextEngineModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.TextRenderingModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.TilemapModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.TLSModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UI.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UIElementsModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UIModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UmbraModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityAnalyticsCommonModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityAnalyticsModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityConnectModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityCurlModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityTestProtocolModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityWebRequestAssetBundleModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityWebRequestAudioModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityWebRequestModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityWebRequestTextureModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.UnityWebRequestWWWModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.VehiclesModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.VFXModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.VideoModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.VirtualTexturingModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.VRModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.WindModule.dll
inflating: chall/Challenge_Data/Managed/UnityEngine.XRModule.dll
creating: chall/Challenge_Data/Plugins/
creating: chall/Challenge_Data/Plugins/x86_64/
inflating: chall/Challenge_Data/Plugins/x86_64/lib_burst_generated.dll
inflating: chall/Challenge_Data/resources.assets
inflating: chall/Challenge_Data/resources.assets.resS
creating: chall/Challenge_Data/Resources/
inflating: chall/Challenge_Data/Resources/unity default resources
inflating: chall/Challenge_Data/Resources/unity_builtin_extra
inflating: chall/Challenge_Data/RuntimeInitializeOnLoads.json
inflating: chall/Challenge_Data/ScriptingAssemblies.json
inflating: chall/Challenge_Data/sharedassets0.assets
inflating: chall/Challenge_Data/sharedassets0.assets.resS
inflating: chall/Challenge_Data/sharedassets0.resource
inflating: chall/Challenge_Data/sharedassets1.assets
inflating: chall/Challenge_Data/sharedassets1.assets.resS
inflating: chall/Challenge_Data/sharedassets1.resource
inflating: chall/Challenge_Data/sharedassets2.assets
inflating: chall/Challenge_Data/sharedassets2.assets.resS
inflating: chall/Challenge_Data/sharedassets2.resource
creating: chall/D3D12/
inflating: chall/D3D12/D3D12Core.dll
creating: chall/MonoBleedingEdge/
creating: chall/MonoBleedingEdge/EmbedRuntime/
inflating: chall/MonoBleedingEdge/EmbedRuntime/mono-2.0-bdwgc.dll
inflating: chall/MonoBleedingEdge/EmbedRuntime/MonoPosixHelper.dll
creating: chall/MonoBleedingEdge/etc/
creating: chall/MonoBleedingEdge/etc/mono/
creating: chall/MonoBleedingEdge/etc/mono/2.0/
creating: chall/MonoBleedingEdge/etc/mono/2.0/Browsers/
inflating: chall/MonoBleedingEdge/etc/mono/2.0/Browsers/Compat.browser
inflating: chall/MonoBleedingEdge/etc/mono/2.0/DefaultWsdlHelpGenerator.aspx
inflating: chall/MonoBleedingEdge/etc/mono/2.0/machine.config
inflating: chall/MonoBleedingEdge/etc/mono/2.0/settings.map
inflating: chall/MonoBleedingEdge/etc/mono/2.0/web.config
creating: chall/MonoBleedingEdge/etc/mono/4.0/
creating: chall/MonoBleedingEdge/etc/mono/4.0/Browsers/
inflating: chall/MonoBleedingEdge/etc/mono/4.0/Browsers/Compat.browser
inflating: chall/MonoBleedingEdge/etc/mono/4.0/DefaultWsdlHelpGenerator.aspx
inflating: chall/MonoBleedingEdge/etc/mono/4.0/machine.config
inflating: chall/MonoBleedingEdge/etc/mono/4.0/settings.map
inflating: chall/MonoBleedingEdge/etc/mono/4.0/web.config
creating: chall/MonoBleedingEdge/etc/mono/4.5/
creating: chall/MonoBleedingEdge/etc/mono/4.5/Browsers/
inflating: chall/MonoBleedingEdge/etc/mono/4.5/Browsers/Compat.browser
inflating: chall/MonoBleedingEdge/etc/mono/4.5/DefaultWsdlHelpGenerator.aspx
inflating: chall/MonoBleedingEdge/etc/mono/4.5/machine.config
inflating: chall/MonoBleedingEdge/etc/mono/4.5/settings.map
inflating: chall/MonoBleedingEdge/etc/mono/4.5/web.config
inflating: chall/MonoBleedingEdge/etc/mono/browscap.ini
inflating: chall/MonoBleedingEdge/etc/mono/config
creating: chall/MonoBleedingEdge/etc/mono/mconfig/
inflating: chall/MonoBleedingEdge/etc/mono/mconfig/config.xml
inflating: chall/UnityCrashHandler64.exe
inflating: chall/UnityPlayer.dll
chall/Challenge_Data/Managed/Assembly-CSharp.dll
が怪しい
Unityのゲームだと分かるのでdnSpyで解析する。
Shellmove
というスクリプトを見つけた
UPdate
関数にゲームオーバー条件と勝利条件がかかれている。
public class Shellmove : MonoBehaviour
{
// Token: 0x06000004 RID: 4 RVA: 0x00002074 File Offset: 0x00000274
private void Update()
{
Vector3 position = base.gameObject.transform.position;
if (Input.GetKey(KeyCode.Delete))
{
SceneManager.LoadScene("Main");
}
if (this.Len(position) >= 50.0)
{
this.TransError();
}
if (position == new Vector3(65535f, 65535f))
{
this.TransFlag();
}
if (!this.ismoving && this.canmove)
{
Vector3 zero = Vector3.zero;
if (Input.GetKeyDown(KeyCode.W))
{
zero = new Vector3(0f, this.grid);
this.walksound.Play();
}
if (Input.GetKeyDown(KeyCode.S))
{
zero = new Vector3(0f, -this.grid);
this.walksound.Play();
}
if (Input.GetKeyDown(KeyCode.D))
{
zero = new Vector3(this.grid, 0f);
this.walksound.Play();
}
if (Input.GetKeyDown(KeyCode.A))
{
zero = new Vector3(-this.grid, 0f);
this.walksound.Play();
}
if (zero != Vector3.zero)
{
base.StartCoroutine(this.MoveSmooth(zero));
}
}
}
最初にスポーンする原点(0,0)から距離が50以上離れるとゲームオーバー。
(65535f, 65535f)に到達するとthis.TransFlag();が呼び出され、ゲームクリア。
if (Input.GetKeyUp(KeyCode.W))
{
zero = new Vector3(0f, this.grid);
this.walksound.Play();
this.TransFlag();
}
w(前進)を押したら、クリア画面を表示するように変更。
QRコードを書いてを読み取ってフラグゲット!
fwectf{K494ku_no_Ch1k4r4_t7e_5u63h!}
所感
全体的に難易度が高い気がした(多分自分の実力不足)
PWN問題を一問も解けなかったのが悔しい