🔥

2023/05/03に公開

# 結果

チーム参加。147位/609チーム

# 解けた問題

## crypto

• Numbers :pensive: (121 solves)
• MD5 (114 solves)
• PRNG (78 solves)

# Numbers :pensive: (121 solves)

It wouldn't be a real CTF without some contrived RSA challenge, right?

chall.py
from Crypto.Util.number import getPrime
from Crypto.Random.random import getrandbits, randint
from pathlib import Path
from math import gcd

e = 65537

while True:
p = getPrime(1024)
q = getPrime(1024)
n = p * q
phi = (p - 1) * (q - 1)
if gcd(e, phi) == 1:
break

print(f"n = {n}")
print(f"e = {e}")

while True:
chosen_e = int(input("Give me an e, and I'll give you a d: "))
if chosen_e == e:
print("Nice try!")
break
try:
print(pow(chosen_e, -1, phi))
except:
print("That's not invertible :pensive:")
continue
m = getrandbits(1024)
c = pow(m, e, n)
print("If you can decrypt this, I'll give you a flag!")
print(c)
if ans == m:
print(flag)
break
else:
print("Numbers, am I right :pensive:")


gigem{h4h4_numb3rs_ar3_s0_qu1rky}

# MD5 (114 solves)

MD5 jail?!?!?!?!

chall.py
import hashlib
import subprocess

def md5sum(b: bytes):
return hashlib.md5(b).digest()[:3]

whitelisted_cmd = b'echo lmao'
whitelisted_hash = md5sum(whitelisted_cmd)

def main():
while True:
cmd = input('> ').encode()
if cmd == b'exit':
print('Goodbye')
exit()

if md5sum(cmd) != whitelisted_hash:
print(f'Invalid command, try "{whitelisted_cmd.decode()}"')
continue

try:
out = subprocess.check_output(['/bin/bash', '-c', cmd])
print(out.decode())
except subprocess.CalledProcessError as e:
print(f'Command returned non-zero exit status {e.returncode}')

if __name__ == "__main__":
main()


subprocess.check_out() の部分が明らかに怪しい。また、 echo (任意の文字列) | (本当に打ちたいコマンド) のような形を送信することによって、任意のハッシュ値のコマンドを送信できる。結果として、 echo tVJu3dCT016T2AvyS | cat ./flag.txt が有効なコマンドだということが分かった。

make_command.py
import hashlib
import random
import string

def randomname(n):
randlst = [random.choice(string.ascii_letters + string.digits) for i in range(n)]
return ''.join(randlst)

def md5sum(b: bytes):
return hashlib.md5(b).digest()[:3]

whitelisted_cmd = b'echo lmao'
whitelisted_hash = md5sum(whitelisted_cmd)

test = ""

while True:
s = 'echo ' + randomname(random.randint(1, 20)) + ' | cat ./flag.txt'

s = s.encode('utf-8')

if md5sum(s) == whitelisted_hash:
test = s
break

print(test)


# PRNG

I know they say don't roll your own crypto, but secure RNG should be easy. How hard could it be?

chall.py
import secrets
from flag import flag, m, a, c

class Rand:
def __init__(self, seed):
self.m = m
self.a = a
self.c = c
self.seed = seed
if seed % 2 == 0: # initial state must be odd
self.seed += 1

def rand(self):
self.seed = (self.a * self.seed + self.c) % self.m
return self.seed

def main():
seed = secrets.choice(range(0, 0x7fffffffffffffff))
rng = Rand(seed)

chall = []
for _ in range(10):
chall.append(rng.rand())

print(f"Authenticate. Provide the next 10 numbers following")
for c in chall:
print(c)

for _ in range(10):
x = int(input('> '))
if x != rng.rand():
exit()

print("Access granted.")
print(flag)

if __name__ == "__main__":
main()


gigem{D0nt_r0ll_y0uR_oWn_RnG}

• 今のところなし

# upsolve したい問題

• [crypto]Vigenot (15 solved)
• 頻度分析っぽい問題だったけどうまくいかず
• よさげなWriteupを見つけたのでしっかりと理解したい

# 感想

けっこう難しいセットだった気がしたけど、半分くらいのcryptoを通せたので満足。