3 月 8 日から 3 月 10 日にかけて開催された Pragyan CTF 2019 に、チーム Harekaze で参加しました。最終的にチームで 1325 点を獲得し、順位は得点 499 チーム中 74 位でした。うち、私は 10 問を解いて 1325 点を入れました。
以下、解いた問題の write-up です。
Can you cook the most delicious recipe?
nc 159.89.166.12 9800
添付ファイル: challenge1 (x86_64 の ELF ファイル)
逆アセンブルしてどのような処理を行っているか確認します。以下のように srand(time(NULL))
を行ったあと rand()
で 3 つの数値 (var_90
var_8c
var_88
) を生成し、
a58: bf 00 00 00 00 mov edi,0x0
a5d: e8 3e fe ff ff call 8a0 <time@plt>
a62: 89 c7 mov edi,eax
a64: e8 17 fe ff ff call 880 <srand@plt>
a69: e8 92 fe ff ff call 900 <rand@plt>
︙
a96: 89 85 70 ff ff ff mov DWORD PTR [rbp-0x90],eax
a9c: e8 5f fe ff ff call 900 <rand@plt>
︙
ac9: 89 85 74 ff ff ff mov DWORD PTR [rbp-0x8c],eax
acf: e8 2c fe ff ff call 900 <rand@plt>
︙
afc: 89 85 78 ff ff ff mov DWORD PTR [rbp-0x88],eax
それらの数値を出力、
b0e: 8b 8d 78 ff ff ff mov ecx,DWORD PTR [rbp-0x88]
b14: 8b 95 74 ff ff ff mov edx,DWORD PTR [rbp-0x8c]
b1a: 8b 85 70 ff ff ff mov eax,DWORD PTR [rbp-0x90]
b20: 89 c6 mov esi,eax
b22: 48 8d 3d a9 02 00 00 lea rdi,[rip+0x2a9] # "%d ; %d ; %d ;\n"
b29: b8 00 00 00 00 mov eax,0x0
b2e: e8 3d fd ff ff call 870 <printf@plt>
scanf("%s", var_6e)
で文字列の入力を行っています。
b33: 48 8d 45 92 lea rax,[rbp-0x6e]
b37: 48 89 c6 mov rsi,rax
b3a: 48 8d 3d a1 02 00 00 lea rdi,[rip+0x2a1] # "%s"
b41: b8 00 00 00 00 mov eax,0x0
b46: e8 85 fd ff ff call 8d0 <__isoc99_scanf@plt>
その後、ユーザ入力の文字数をチェックしてから、atoi(ユーザ入力)
atoi(ユーザ入力[10:])
atoi(ユーザ入力[20:])
をそれぞれ変数として var_84
var_80
var_7c
に保存し、
bc1: 48 8d 45 92 lea rax,[rbp-0x6e]
bc5: 48 89 c7 mov rdi,rax
bc8: e8 f3 fc ff ff call 8c0 <atoi@plt>
bcd: 89 85 7c ff ff ff mov DWORD PTR [rbp-0x84],eax
bd3: 48 8d 45 9c lea rax,[rbp-0x64]
bd7: 48 89 c7 mov rdi,rax
bda: e8 e1 fc ff ff call 8c0 <atoi@plt>
bdf: 89 45 80 mov DWORD PTR [rbp-0x80],eax
be2: 48 8d 45 a6 lea rax,[rbp-0x5a]
be6: 48 89 c7 mov rdi,rax
be9: e8 d2 fc ff ff call 8c0 <atoi@plt>
bee: 89 45 84 mov DWORD PTR [rbp-0x7c],eax
var_84 + var_80 == var_90
var_80 + var_7c == var_8c
var_7c + var_84 == var_88
であるか確認しています。
bf1: 8b 95 7c ff ff ff mov edx,DWORD PTR [rbp-0x84]
bf7: 8b 45 80 mov eax,DWORD PTR [rbp-0x80]
bfa: 01 d0 add eax,edx
bfc: 39 85 70 ff ff ff cmp DWORD PTR [rbp-0x90],eax
c02: 0f 85 b6 00 00 00 jne cbe <main+0x281>
c08: 8b 55 80 mov edx,DWORD PTR [rbp-0x80]
c0b: 8b 45 84 mov eax,DWORD PTR [rbp-0x7c]
c0e: 01 d0 add eax,edx
c10: 39 85 74 ff ff ff cmp DWORD PTR [rbp-0x8c],eax
c16: 0f 85 96 00 00 00 jne cb2 <main+0x275>
c1c: 8b 55 84 mov edx,DWORD PTR [rbp-0x7c]
c1f: 8b 85 7c ff ff ff mov eax,DWORD PTR [rbp-0x84]
c25: 01 d0 add eax,edx
c27: 39 85 78 ff ff ff cmp DWORD PTR [rbp-0x88],eax
c2d: 75 77 jne ca6 <main+0x269>
一度の入力で 3 つの数値を入力する必要があるのが少し厄介ですが、atoi
の数字以外の文字が出現すればその時点で処理を終了するという仕様を利用して、1---------2---------3
のように -
を padding にしてしまいましょう。また、var_84
var_80
var_7c
の探索については Z3Py に任せてしまいましょう。
import sys
from z3 import *
a, b, c = Ints('a b c')
x = [int(x) for x in sys.argv[1].split(' ; ')]
solver = Solver()
solver.add(b + a == x[0], c + b == x[1], a + c == x[2])
solver.check()
m = solver.model()
print('{:-<10}{:-<10}{:-<10}'.format(m[a], m[b], m[c]))
$ nc 159.89.166.12 9800
Can you cook my favourite food using these ingredients :)
-12220 ; -19820 ; -1566 ;
3017-------15237-----4583-----
That's yummy.... Here is your gift:
pctf{p1zz4_t0pp3d_w1th_p1n34ppl3_s4uc3}
フラグが得られました。
pctf{p1zz4_t0pp3d_w1th_p1n34ppl3_s4uc3}
My friend Alex needs your help very fast. He has been possessed by a ghost and the only way to save him is if you tell the flag to the ghost. Hurry up, time is running out!
添付ファイル: encoded.txt
以下のような内容のファイルが与えられました。
1
1
1
1
1
1
1
1
1
1
1
︙
0
もしくは 1
のみの行が 10000 行続いています。1
の場合には黒、0
の場合には白として、100 ピクセル * 100 ピクセルの画像にしてみましょう。
import binascii
from PIL import Image
w, h = 100, 100
im = Image.new('1', (w, h))
pix = im.load()
with open('encoded.txt', 'r') as f:
s = f.read().replace('\n', '')
for y in range(h):
for x in range(w):
pix[x, y] = int(s[y * w + x])
im.show()
im.save('res.png')
QR コードが出てきました。これを zbarimg
で読んでみましょう。
>zbarimg res.png
QR-Code:160f15011d1b095339595138535f135613595e1a
scanned 1 barcode symbols from 1 images
hex としてデコードし、フラグフォーマットの pctf{
と xor してみましょう。
$ python
>>> s = "160f15011d1b095339595138535f135613595e1a".decode('hex')
>>> xor(s, 'pctf{')
'flagfkj\'_"![\'9h&p-8a'
flag
と xor されているようです。
>>> xor(s, 'flag')
'pctf{wh4_50_53r1u5?}'
フラグが得られました。
pctf{wh4_50_53r1u5?}
Bran Stark, wants to convey an important information to the Sansa back at winterfell. He sends her a message. The message however, is encrypted though.
Can you find out what Bran is trying to convey??
添付ファイル: key.pdf
key.pdf
を開くと、3a2c3a35152538272c2d213e332e3c25383030373a15
と表示されました。
バイナリエディタで key.pdf
を開くと、以下のように %%EOF
(PDF の終端) 以降にも何かがあることが分かります。
︙
%%EOF0000006a0000006f0000006e000000730000006e0000006f000000770000006900000073000000640000007200000061000000670000006f0000006e00000062000000790000006200000069000000720000007400000068
これらを xor してみましょう。
$ python
>>> from pwn import *
>>> s = "3a2c3a35152538272c2d213e332e3c25383030373a15".decode('hex')
>>> t = """0000006a0000006f0000006e000000730000006e0000006f000000770000006900000073000000640000007200000061000000670000006f0000006e00000062000000790000006200000069000000720000007400000068""".replace('000000', '').decode('hex')
>>> xor(s, t).lower()
'pctf{jon_is_targaryen}'
フラグが得られました。
pctf{jon_is_targaryen}
Rahul, the geek boy of his class, doesn’t like doing things the conventional way. He’s just learned polynomials in class, and wants to prove a point to his friend Sandhya. But Sandhya is sitting in the first bench, so Ram decides to write what he wants to convey on a chit and pass it through the guys sitting in front of him. The guys in between try to read it, but do not understand. Sadly, nor does Sandhya. Can you help him out?
添付ファイル: polynomials.txt
polynomials.txt
は以下のような内容でした。
p = x^406 + x^405 + x^402 + x^399 + x^397 + x^391 + x^390 + x^387 + x^386 + x^378 + x^374 + x^372 + x^371 + x^369 + x^367 + x^364 + x^360 + x^358 + x^357 + x^352 + x^350 + x^345 + x^344 + x^341 + x^336 + x^335 + x^334 + x^333 + x^331 + x^330 + x^329 + x^328 + x^327 + x^324 + x^322 + x^320 + x^314 + x^311 + x^308 + x^307 + x^303 + x^300 + x^299 + x^296 + x^295 + x^290 + x^289 + x^287 + x^279 + x^271 + x^266 + x^264 + x^262 + x^260 + x^257 + x^256 + x^252 + x^249 + x^248 + x^246 + x^243 + x^239 + x^238 + x^236 + x^233 + x^230 + x^227 + x^225 + x^223 + x^222 + x^220 + x^218 + x^216 + x^215 + x^209 + x^208 + x^207 + x^204 + x^202 + x^199 + x^190 + x^189 + x^185 + x^184 + x^180 + x^177 + x^176 + x^175 + x^172 + x^167 + x^166 + x^162 + x^160 + x^159 + x^155 + x^154 + x^149 + x^147 + x^143 + x^137 + x^135 + x^131 + x^129 + x^126 + x^124 + x^122 + x^116 + x^110 + x^108 + x^105 + x^104 + x^100 + x^99 + x^97 + x^94 + x^93 + x^90 + x^88 + x^87 + x^86 + x^85 + x^83 + x^75 + x^73 + x^69 + x^63 + x^62 + x^57 + x^54 + x^51 + x^44 + x^41 + x^38 + x^37 + x^36 + x^34 + x^29 + x^28 + x^26 + x^25 + x^21 + x^20 + x^19 + x^16 + x^15 + x^14 + x^13 + x^6 + x^5 + x^2
q = x^399 + x^398 + x^396 + x^393 + x^392 + x^391 + x^388 + x^386 + x^384 + x^381 + x^377 + x^376 + x^368 + x^364 + x^360 + x^355 + x^354 + x^353 + x^352 + x^348 + x^346 + x^345 + x^344 + x^343 + x^335 + x^334 + x^329 + x^326 + x^325 + x^321 + x^318 + x^317 + x^315 + x^314 + x^311 + x^307 + x^306 + x^304 + x^300 + x^296 + x^293 + x^291 + x^282 + x^277 + x^270 + x^263 + x^261 + x^260 + x^256 + x^254 + x^253 + x^252 + x^251 + x^248 + x^245 + x^242 + x^241 + x^239 + x^238 + x^236 + x^232 + x^226 + x^225 + x^222 + x^220 + x^219 + x^214 + x^209 + x^208 + x^207 + x^206 + x^202 + x^200 + x^196 + x^191 + x^190 + x^186 + x^181 + x^180 + x^178 + x^177 + x^169 + x^168 + x^165 + x^164 + x^163 + x^162 + x^161 + x^159 + x^157 + x^156 + x^151 + x^149 + x^148 + x^147 + x^146 + x^144 + x^141 + x^140 + x^138 + x^137 + x^136 + x^134 + x^133 + x^132 + x^130 + x^129 + x^128 + x^126 + x^123 + x^121 + x^113 + x^109 + x^103 + x^101 + x^100 + x^95 + x^93 + x^91 + x^85 + x^84 + x^81 + x^74 + x^73 + x^71 + x^68 + x^67 + x^54 + x^52 + x^51 + x^50 + x^48 + x^46 + x^45 + x^43 + x^39 + x^35 + x^32 + x^31 + x^30 + x^29 + x^21 + x^15 + x^14 + x^9 + x^8 + x^5 + x^4 + x^2 + 1
r = x^404 + x^402 + x^396 + x^389 + x^387 + x^386 + x^384 + x^382 + x^376 + x^373 + x^367 + x^366 + x^365 + x^362 + x^361 + x^358 + x^356 + x^355 + x^354 + x^353 + x^352 + x^349 + x^348 + x^347 + x^345 + x^343 + x^340 + x^334 + x^332 + x^331 + x^328 + x^327 + x^326 + x^322 + x^317 + x^316 + x^314 + x^313 + x^312 + x^310 + x^309 + x^308 + x^305 + x^304 + x^303 + x^301 + x^300 + x^299 + x^296 + x^295 + x^292 + x^291 + x^290 + x^288 + x^287 + x^286 + x^285 + x^283 + x^279 + x^278 + x^274 + x^271 + x^269 + x^268 + x^266 + x^265 + x^263 + x^261 + x^260 + x^259 + x^258 + x^256 + x^254 + x^252 + x^251 + x^250 + x^249 + x^244 + x^243 + x^242 + x^237 + x^236 + x^228 + x^225 + x^224 + x^223 + x^222 + x^221 + x^215 + x^214 + x^213 + x^212 + x^205 + x^201 + x^200 + x^199 + x^197 + x^193 + x^192 + x^191 + x^190 + x^189 + x^188 + x^187 + x^182 + x^180 + x^175 + x^174 + x^173 + x^167 + x^166 + x^163 + x^158 + x^156 + x^155 + x^153 + x^151 + x^150 + x^149 + x^143 + x^142 + x^140 + x^139 + x^136 + x^135 + x^133 + x^129 + x^126 + x^125 + x^123 + x^121 + x^118 + x^117 + x^116 + x^115 + x^113 + x^110 + x^106 + x^105 + x^104 + x^103 + x^102 + x^98 + x^95 + x^92 + x^89 + x^87 + x^85 + x^81 + x^80 + x^77 + x^76 + x^75 + x^74 + x^71 + x^70 + x^67 + x^66 + x^64 + x^63 + x^60 + x^59 + x^58 + x^56 + x^54 + x^53 + x^48 + x^44 + x^41 + x^39 + x^38 + x^35 + x^34 + x^31 + x^29 + x^28 + x^27 + x^22 + x^21 + x^20 + x^17 + x^14 + x^12 + x^11 + x^10 + x^9 + x^6 + x^4 + x^3 + x + 1
それぞれビット列で表してみましょう。
import re
s = '''x^406 + x^405 + x^402 + x^399 + x^397 + x^391 + x^390 + x^387 + x^386 + x^378 + x^374 + x^372 + x^371 + x^369 + x^367 + x^364 + x^360 + x^358 + x^357 + x^352 + x^350 + x^345 + x^344 + x^341 + x^336 + x^335 + x^334 + x^333 + x^331 + x^330 + x^329 + x^328 + x^327 + x^324 + x^322 + x^320 + x^314 + x^311 + x^308 + x^307 + x^303 + x^300 + x^299 + x^296 + x^295 + x^290 + x^289 + x^287 + x^279 + x^271 + x^266 + x^264 + x^262 + x^260 + x^257 + x^256 + x^252 + x^249 + x^248 + x^246 + x^243 + x^239 + x^238 + x^236 + x^233 + x^230 + x^227 + x^225 + x^223 + x^222 + x^220 + x^218 + x^216 + x^215 + x^209 + x^208 + x^207 + x^204 + x^202 + x^199 + x^190 + x^189 + x^185 + x^184 + x^180 + x^177 + x^176 + x^175 + x^172 + x^167 + x^166 + x^162 + x^160 + x^159 + x^155 + x^154 + x^149 + x^147 + x^143 + x^137 + x^135 + x^131 + x^129 + x^126 + x^124 + x^122 + x^116 + x^110 + x^108 + x^105 + x^104 + x^100 + x^99 + x^97 + x^94 + x^93 + x^90 + x^88 + x^87 + x^86 + x^85 + x^83 + x^75 + x^73 + x^69 + x^63 + x^62 + x^57 + x^54 + x^51 + x^44 + x^41 + x^38 + x^37 + x^36 + x^34 + x^29 + x^28 + x^26 + x^25 + x^21 + x^20 + x^19 + x^16 + x^15 + x^14 + x^13 + x^6 + x^5 + x^2
x^399 + x^398 + x^396 + x^393 + x^392 + x^391 + x^388 + x^386 + x^384 + x^381 + x^377 + x^376 + x^368 + x^364 + x^360 + x^355 + x^354 + x^353 + x^352 + x^348 + x^346 + x^345 + x^344 + x^343 + x^335 + x^334 + x^329 + x^326 + x^325 + x^321 + x^318 + x^317 + x^315 + x^314 + x^311 + x^307 + x^306 + x^304 + x^300 + x^296 + x^293 + x^291 + x^282 + x^277 + x^270 + x^263 + x^261 + x^260 + x^256 + x^254 + x^253 + x^252 + x^251 + x^248 + x^245 + x^242 + x^241 + x^239 + x^238 + x^236 + x^232 + x^226 + x^225 + x^222 + x^220 + x^219 + x^214 + x^209 + x^208 + x^207 + x^206 + x^202 + x^200 + x^196 + x^191 + x^190 + x^186 + x^181 + x^180 + x^178 + x^177 + x^169 + x^168 + x^165 + x^164 + x^163 + x^162 + x^161 + x^159 + x^157 + x^156 + x^151 + x^149 + x^148 + x^147 + x^146 + x^144 + x^141 + x^140 + x^138 + x^137 + x^136 + x^134 + x^133 + x^132 + x^130 + x^129 + x^128 + x^126 + x^123 + x^121 + x^113 + x^109 + x^103 + x^101 + x^100 + x^95 + x^93 + x^91 + x^85 + x^84 + x^81 + x^74 + x^73 + x^71 + x^68 + x^67 + x^54 + x^52 + x^51 + x^50 + x^48 + x^46 + x^45 + x^43 + x^39 + x^35 + x^32 + x^31 + x^30 + x^29 + x^21 + x^15 + x^14 + x^9 + x^8 + x^5 + x^4 + x^2 + x^0
x^404 + x^402 + x^396 + x^389 + x^387 + x^386 + x^384 + x^382 + x^376 + x^373 + x^367 + x^366 + x^365 + x^362 + x^361 + x^358 + x^356 + x^355 + x^354 + x^353 + x^352 + x^349 + x^348 + x^347 + x^345 + x^343 + x^340 + x^334 + x^332 + x^331 + x^328 + x^327 + x^326 + x^322 + x^317 + x^316 + x^314 + x^313 + x^312 + x^310 + x^309 + x^308 + x^305 + x^304 + x^303 + x^301 + x^300 + x^299 + x^296 + x^295 + x^292 + x^291 + x^290 + x^288 + x^287 + x^286 + x^285 + x^283 + x^279 + x^278 + x^274 + x^271 + x^269 + x^268 + x^266 + x^265 + x^263 + x^261 + x^260 + x^259 + x^258 + x^256 + x^254 + x^252 + x^251 + x^250 + x^249 + x^244 + x^243 + x^242 + x^237 + x^236 + x^228 + x^225 + x^224 + x^223 + x^222 + x^221 + x^215 + x^214 + x^213 + x^212 + x^205 + x^201 + x^200 + x^199 + x^197 + x^193 + x^192 + x^191 + x^190 + x^189 + x^188 + x^187 + x^182 + x^180 + x^175 + x^174 + x^173 + x^167 + x^166 + x^163 + x^158 + x^156 + x^155 + x^153 + x^151 + x^150 + x^149 + x^143 + x^142 + x^140 + x^139 + x^136 + x^135 + x^133 + x^129 + x^126 + x^125 + x^123 + x^121 + x^118 + x^117 + x^116 + x^115 + x^113 + x^110 + x^106 + x^105 + x^104 + x^103 + x^102 + x^98 + x^95 + x^92 + x^89 + x^87 + x^85 + x^81 + x^80 + x^77 + x^76 + x^75 + x^74 + x^71 + x^70 + x^67 + x^66 + x^64 + x^63 + x^60 + x^59 + x^58 + x^56 + x^54 + x^53 + x^48 + x^44 + x^41 + x^39 + x^38 + x^35 + x^34 + x^31 + x^29 + x^28 + x^27 + x^22 + x^21 + x^20 + x^17 + x^14 + x^12 + x^11 + x^10 + x^9 + x^6 + x^4 + x^3 + x^1 + x^0'''
res = 0
for line in s.splitlines():
tmp = [0 for _ in range(408)]
for x in re.findall(r'\d+', line):
tmp[int(x)] = 1
tmp = tmp[::-1]
print(''.join(str(x) for x in tmp))
$ python test.py
011001001010000011001100000001000101101010010001011000010100001100100001111011111001010100000100100110001001100110000110100000001000000010000101010100110001001101001000110100100100101011010101100000111001010010000000011000110001001110010000110001011000110000101000100000101000101001010100000100000101001100011010011001011110100000001010001000001100001001001000000100100111010000110110001110011110000001100100
000000001101001110010101001000110000000100010001000011110001011110000000110000100110001001101100100011010001000100101000000001000010000001000000101100010111100100100110110100010000011001011000010000111100010100010000110001000011011000000011001111101011000010111101001101110111011101001010000000100010000010110000101010000011001000000110100110000000000001011101011010001000100111100000001000001100001100110101
000101000001000000101101010000010010000011100110010111110011101010010000010110011100010000110111011100111011100110011101111010001100010010110110101111010101111000011100001100000001001111100000111100000010001110100011111110000101000011100000110010000101101011100000110110011010001001101010011110100100011111000100100100101010001100111100110011011001110101100001000100101100110010111000011100100101111001011011
XOR is your best friend
というヒントが与えられているので、xor するように修正してみましょう。
import binascii
import re
s = '''x^406 + x^405 + x^402 + x^399 + x^397 + x^391 + x^390 + x^387 + x^386 + x^378 + x^374 + x^372 + x^371 + x^369 + x^367 + x^364 + x^360 + x^358 + x^357 + x^352 + x^350 + x^345 + x^344 + x^341 + x^336 + x^335 + x^334 + x^333 + x^331 + x^330 + x^329 + x^328 + x^327 + x^324 + x^322 + x^320 + x^314 + x^311 + x^308 + x^307 + x^303 + x^300 + x^299 + x^296 + x^295 + x^290 + x^289 + x^287 + x^279 + x^271 + x^266 + x^264 + x^262 + x^260 + x^257 + x^256 + x^252 + x^249 + x^248 + x^246 + x^243 + x^239 + x^238 + x^236 + x^233 + x^230 + x^227 + x^225 + x^223 + x^222 + x^220 + x^218 + x^216 + x^215 + x^209 + x^208 + x^207 + x^204 + x^202 + x^199 + x^190 + x^189 + x^185 + x^184 + x^180 + x^177 + x^176 + x^175 + x^172 + x^167 + x^166 + x^162 + x^160 + x^159 + x^155 + x^154 + x^149 + x^147 + x^143 + x^137 + x^135 + x^131 + x^129 + x^126 + x^124 + x^122 + x^116 + x^110 + x^108 + x^105 + x^104 + x^100 + x^99 + x^97 + x^94 + x^93 + x^90 + x^88 + x^87 + x^86 + x^85 + x^83 + x^75 + x^73 + x^69 + x^63 + x^62 + x^57 + x^54 + x^51 + x^44 + x^41 + x^38 + x^37 + x^36 + x^34 + x^29 + x^28 + x^26 + x^25 + x^21 + x^20 + x^19 + x^16 + x^15 + x^14 + x^13 + x^6 + x^5 + x^2
x^399 + x^398 + x^396 + x^393 + x^392 + x^391 + x^388 + x^386 + x^384 + x^381 + x^377 + x^376 + x^368 + x^364 + x^360 + x^355 + x^354 + x^353 + x^352 + x^348 + x^346 + x^345 + x^344 + x^343 + x^335 + x^334 + x^329 + x^326 + x^325 + x^321 + x^318 + x^317 + x^315 + x^314 + x^311 + x^307 + x^306 + x^304 + x^300 + x^296 + x^293 + x^291 + x^282 + x^277 + x^270 + x^263 + x^261 + x^260 + x^256 + x^254 + x^253 + x^252 + x^251 + x^248 + x^245 + x^242 + x^241 + x^239 + x^238 + x^236 + x^232 + x^226 + x^225 + x^222 + x^220 + x^219 + x^214 + x^209 + x^208 + x^207 + x^206 + x^202 + x^200 + x^196 + x^191 + x^190 + x^186 + x^181 + x^180 + x^178 + x^177 + x^169 + x^168 + x^165 + x^164 + x^163 + x^162 + x^161 + x^159 + x^157 + x^156 + x^151 + x^149 + x^148 + x^147 + x^146 + x^144 + x^141 + x^140 + x^138 + x^137 + x^136 + x^134 + x^133 + x^132 + x^130 + x^129 + x^128 + x^126 + x^123 + x^121 + x^113 + x^109 + x^103 + x^101 + x^100 + x^95 + x^93 + x^91 + x^85 + x^84 + x^81 + x^74 + x^73 + x^71 + x^68 + x^67 + x^54 + x^52 + x^51 + x^50 + x^48 + x^46 + x^45 + x^43 + x^39 + x^35 + x^32 + x^31 + x^30 + x^29 + x^21 + x^15 + x^14 + x^9 + x^8 + x^5 + x^4 + x^2 + x^0
x^404 + x^402 + x^396 + x^389 + x^387 + x^386 + x^384 + x^382 + x^376 + x^373 + x^367 + x^366 + x^365 + x^362 + x^361 + x^358 + x^356 + x^355 + x^354 + x^353 + x^352 + x^349 + x^348 + x^347 + x^345 + x^343 + x^340 + x^334 + x^332 + x^331 + x^328 + x^327 + x^326 + x^322 + x^317 + x^316 + x^314 + x^313 + x^312 + x^310 + x^309 + x^308 + x^305 + x^304 + x^303 + x^301 + x^300 + x^299 + x^296 + x^295 + x^292 + x^291 + x^290 + x^288 + x^287 + x^286 + x^285 + x^283 + x^279 + x^278 + x^274 + x^271 + x^269 + x^268 + x^266 + x^265 + x^263 + x^261 + x^260 + x^259 + x^258 + x^256 + x^254 + x^252 + x^251 + x^250 + x^249 + x^244 + x^243 + x^242 + x^237 + x^236 + x^228 + x^225 + x^224 + x^223 + x^222 + x^221 + x^215 + x^214 + x^213 + x^212 + x^205 + x^201 + x^200 + x^199 + x^197 + x^193 + x^192 + x^191 + x^190 + x^189 + x^188 + x^187 + x^182 + x^180 + x^175 + x^174 + x^173 + x^167 + x^166 + x^163 + x^158 + x^156 + x^155 + x^153 + x^151 + x^150 + x^149 + x^143 + x^142 + x^140 + x^139 + x^136 + x^135 + x^133 + x^129 + x^126 + x^125 + x^123 + x^121 + x^118 + x^117 + x^116 + x^115 + x^113 + x^110 + x^106 + x^105 + x^104 + x^103 + x^102 + x^98 + x^95 + x^92 + x^89 + x^87 + x^85 + x^81 + x^80 + x^77 + x^76 + x^75 + x^74 + x^71 + x^70 + x^67 + x^66 + x^64 + x^63 + x^60 + x^59 + x^58 + x^56 + x^54 + x^53 + x^48 + x^44 + x^41 + x^39 + x^38 + x^35 + x^34 + x^31 + x^29 + x^28 + x^27 + x^22 + x^21 + x^20 + x^17 + x^14 + x^12 + x^11 + x^10 + x^9 + x^6 + x^4 + x^3 + x^1 + x^0'''
res = 0
for line in s.splitlines():
tmp = [0 for _ in range(408)]
for x in re.findall(r'\d+', line):
tmp[int(x)] = 1
tmp = tmp[::-1]
res ^= int(''.join(str(x) for x in tmp),2)
print(binascii.unhexlify(hex(res)[2:]).decode())
$ python solve.py
pctf{f1n1t3_f13lds_4r3_m0r3_us3ful_th4n_y0u_th1nk}
フラグが得られました。
pctf{f1n1t3_f13lds_4r3_m0r3_us3ful_th4n_y0u_th1nk}
Magic PNGs:
Can you help me open this zip file? I seem to have forgotten its password. I think the image file has something to do with it.
添付ファイル: tryme.zip, you_cant_see_me.png
tryme.zip
はパスワード付きの ZIP ファイル、you_cant_see_me.png
はそのままでは開けない PNG ファイルのようです。
バイナリエディタで you_cant_see_me.png
を眺めていると、tEXt
チャンクに md5_MEf89jf4h9
という文字列があり、また IDAT
チャンクの Chunk Type が idat
と小文字になっていることが分かりました。
IDAT
チャンクの Chunk Type を IDAT
と大文字に修正すると、画像として開くことができるようになりました。内容は h4CK3RM4n
という文字列でした。
tEXt
チャンクの md5 me
というヒントと組み合わせて、2c919f82ee2ed6985d5c5e275d67e4f8
(md5('h4CK3RM4n')
) をパスワードとして tryme.zip
を展開することができました。
pctf{y0u_s33_m33_n0w!}
Do prepare to see cookies lurking everywhere. http://159.89.166.12:13500/
与えられた URL にアクセスすると、flag=bc54f4d60f1cec0f9a6cb70e13f2127a
という Cookie が発行されました。Cookie を保持して更新すると今度は flag=114d6a415b3d04db792ca7c0da0c7a55
という Cookie が発行されました。
bc54f4d60f1cec0f9a6cb70e13f2127a
と 114d6a415b3d04db792ca7c0da0c7a55
でググると、それぞれ pc
と tf
の MD5 ハッシュであることが分かります。
自動で Cookie の取得と元の文字列の探索をしてくれるスクリプトを書きましょう。
import hashlib
import requests
URL = 'http://159.89.166.12:13500/'
table = {}
for a in range(256):
for b in range(256):
tmp = chr(a) + chr(b)
table[hashlib.md5(tmp).hexdigest()] = tmp
sess = requests.Session()
res = ''
while True:
sess.get(URL)
res += table[sess.cookies.get('flag')]
print res
if '}' in res:
break
>python2 solve.py
pc
pctf
pctf{c
pctf{c0o
pctf{c0oki
pctf{c0oki3s
pctf{c0oki3s_@
pctf{c0oki3s_@re
pctf{c0oki3s_@re_y
pctf{c0oki3s_@re_yUm
pctf{c0oki3s_@re_yUm_b
pctf{c0oki3s_@re_yUm_bUt
pctf{c0oki3s_@re_yUm_bUt_t
pctf{c0oki3s_@re_yUm_bUt_tHE
pctf{c0oki3s_@re_yUm_bUt_tHEy_
pctf{c0oki3s_@re_yUm_bUt_tHEy_@l
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r3v
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r3vEa
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r3vEaL_
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r3vEaL_@_
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r3vEaL_@_l0
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r3vEaL_@_l0t}
フラグが得られました。
pctf{c0oki3s_@re_yUm_bUt_tHEy_@ls0_r3vEaL_@_l0t}
The Game of Faces, welcomes you. In this era, where AIs generate a lot of faces, we would like you to contribute to the same by uploading your image. Thank you for contributing, to continue.
http://159.89.166.12:15000/
与えられた URL にアクセスすると、以下のようなフォームが含まれるページが表示されました。
<form action='#' method = "GET" target="resultFrame">
Upload Your Profile Picture : <input type="file" name="profile_pic" >
<input type="submit" value="Upload Image" name="submit">
</form>
適当なファイルをアップロードすると /?profile_pic=favicon.png&submit=Upload+Image#
に遷移し、以下のような文字列が表示されました。
<div class="row">
<div class="col-lg-12" >
<h1>VGhlX3Njcm9sbF9zYXlzPXRoZV9uaWdodF9raW5nVlN2YWx5cmlhbi50eHQ==</h1> </div>
VGhlX3Njcm9sbF9zYXlzPXRoZV9uaWdodF9raW5nVlN2YWx5cmlhbi50eHQ==
を Base64 デコードすると The_scroll_says=the_night_kingVSvalyrian.txt
になります。/the_night_kingVSvalyrian.txt
にアクセスするとフラグが得られました。
pctf{You_L00K_Wi3Rd_IN_H3R3}
PHP, PHP everywhere get the flag and earn your points there.
http://159.89.166.12:14000/
与えられた URL にアクセスすると、以下のようなソースコードが表示されました。
<?php
include 'flag.php';
highlight_file('index.php');
$a = $_GET["val1"];
$b = $_GET["val2"];
$c = $_GET["val3"];
$d = $_GET["val4"];
if(preg_match('/[^A-Za-z]/', $a))
die('oh my gawd...');
$a=hash("sha256",$a);
$a=(log10($a**(0.5)))**2;
if($c>0&&$d>0&&$d>$c&&$a==$c*$c+$d*$d)
$s1="true";
else
die("Bye...");
if($s1==="true")
echo $flag1;
for($i=1;$i<=10;$i++){
if($b==urldecode($b))
die('duck');
else
$b=urldecode($b);
}
if($b==="WoAHh!")
$s2="true";
else
die('oops..');
if($s2==="true")
echo $flag2;
die('end...');
?>
まず $a
$c
$d
について考えていきましょう。1e309 === INF
かつ INF == '1e309aaaa'
であることを利用して、SHA256 のハッシュ値が /^1e309[abcde]/
に当てはまるような文字列を探索してみましょう。
import hashlib
import itertools
import re
for x in itertools.product('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', repeat=8):
s = ''.join(x)
hash = hashlib.sha256(s.encode()).hexdigest()
if re.match('^1e309[abcdf]', hash):
print(s)
break
実行すると AAAAFGWQ
が見つかりました。$c
と $d
については、$c
が 1
、$d
が INF
になるようにすればよいでしょう。
$b
について考えてみましょう。10 回 urldecode
した結果が WoAHh!
になればよいようなので、urlencode
でその逆の操作をすればよいでしょう。
<?php
$b = "WoAHh!";
for ($i = 0; $i < 11; $i++) {
$b = urlencode($b);
}
var_dump($b);
これらを組み合わせて /?val1=AAAAFGWQ&val2=WoAHh%2525252525252525252521&val3=1&val4=1e309
でフラグが得られました。
pctf{b3_c4r3fu1_w1th_pHp_f31145}