It's Not My Fault 1
This commit is contained in:
1
its_not_my_fault_1/flag.txt
Normal file
1
its_not_my_fault_1/flag.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
picoCTF{flagFLAG}
|
||||||
61
its_not_my_fault_1/not_my_fault.py
Executable file
61
its_not_my_fault_1/not_my_fault.py
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!python3
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import hashlib
|
||||||
|
import time
|
||||||
|
|
||||||
|
from Crypto.Util.number import inverse, getPrime, bytes_to_long, GCD
|
||||||
|
from sympy.ntheory.modular import solve_congruence
|
||||||
|
|
||||||
|
FLAG = open('flag.txt', 'r').read()
|
||||||
|
|
||||||
|
def CRT(a, m, b, n):
|
||||||
|
val, mod = solve_congruence((a, m), (b, n))
|
||||||
|
return val
|
||||||
|
|
||||||
|
def gen_key():
|
||||||
|
while True:
|
||||||
|
p = getPrime(512)
|
||||||
|
q = getPrime(512)
|
||||||
|
if GCD(p-1, q-1) == 2:
|
||||||
|
return p, q
|
||||||
|
|
||||||
|
def get_clue(p, q, BITS):
|
||||||
|
while True:
|
||||||
|
d_p = random.randint(1, 1 << BITS)
|
||||||
|
d_q = random.randint(1, q - 1)
|
||||||
|
if d_p % 2 == d_q % 2:
|
||||||
|
d = CRT(d_p, p - 1, d_q, q - 1)
|
||||||
|
e = inverse(d, (p - 1) * (q - 1))
|
||||||
|
print("Clue : ", e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_flag(p, q):
|
||||||
|
start = time.time()
|
||||||
|
ans = int(input())
|
||||||
|
if (time.time() - start) > (15 * 60):
|
||||||
|
print("Too long!")
|
||||||
|
exit()
|
||||||
|
else:
|
||||||
|
if ans == p + q:
|
||||||
|
print(FLAG)
|
||||||
|
else:
|
||||||
|
print("oops...")
|
||||||
|
|
||||||
|
|
||||||
|
#PoW
|
||||||
|
|
||||||
|
vals1 = "".join([random.choice(string.digits) for _ in range(5)])
|
||||||
|
vals2 = "".join([random.choice(string.hexdigits.lower()) for _ in range(6)])
|
||||||
|
vals1 = "63494"
|
||||||
|
vals2 = "c8ecb7"
|
||||||
|
user_input = input("Enter a string that starts with \"{}\" (no quotes) which creates an md5 hash that ends in these six hex digits: {}\n".format(vals1, vals2))
|
||||||
|
user_hash = hashlib.md5(user_input.encode()).hexdigest()
|
||||||
|
|
||||||
|
if user_input[:5] == vals1 and user_hash[-6:] == vals2:
|
||||||
|
p, q = gen_key()
|
||||||
|
n = p * q
|
||||||
|
print("Public Modulus : ", n)
|
||||||
|
get_clue(p, q, 20)
|
||||||
|
get_flag(p, q)
|
||||||
|
|
||||||
57
its_not_my_fault_1/sol.py
Executable file
57
its_not_my_fault_1/sol.py
Executable file
@@ -0,0 +1,57 @@
|
|||||||
|
#!python3
|
||||||
|
from sage.all import Integer, IntegerRange, GCD
|
||||||
|
from pwn import *
|
||||||
|
from Crypto.Hash import MD5
|
||||||
|
|
||||||
|
#conn = process(['python3', 'not_my_fault.py'])
|
||||||
|
conn = remote("mercury.picoctf.net", 48006)
|
||||||
|
conn.recvuntil(b"\"")
|
||||||
|
str_start = conn.recvuntil(b"\"")[:-1]
|
||||||
|
log.info("string start: {}".format(str_start.decode()))
|
||||||
|
conn.recvuntil(b": ")
|
||||||
|
hash_end = conn.recvline().strip().decode()
|
||||||
|
log.info("hash end: {}".format(hash_end))
|
||||||
|
|
||||||
|
P = log.progress("bruteforcing hash")
|
||||||
|
hash = "0"*32
|
||||||
|
i = 0
|
||||||
|
while hash[-6:] != hash_end:
|
||||||
|
md5 = MD5.new()
|
||||||
|
str_to_hash = str_start + str(i).encode()
|
||||||
|
md5.update(str_to_hash)
|
||||||
|
hash = md5.hexdigest()
|
||||||
|
if i%100000 == 0:
|
||||||
|
P.status("msg: {} {}| hash end: {}".format(str_start.decode(), str(i).ljust(12), hash[-6:]))
|
||||||
|
i += 1
|
||||||
|
P.success("msg: {} {}| hash end: {}".format(str_start.decode(), str(i).ljust(16), hash[-6:]))
|
||||||
|
conn.sendline(str_to_hash)
|
||||||
|
|
||||||
|
conn.recvuntil(b" : ")
|
||||||
|
n = Integer(conn.recvline())
|
||||||
|
log.info("modulus: {}".format(hex(n)))
|
||||||
|
|
||||||
|
conn.recvuntil(b" : ")
|
||||||
|
ce = Integer(conn.recvline())
|
||||||
|
log.info("clue: {}".format(hex(ce)))
|
||||||
|
|
||||||
|
P = log.progress("bruteforcing p by guessing d_p: ")
|
||||||
|
n_bits = 20
|
||||||
|
limit = 1 << n_bits
|
||||||
|
m = Integer(3)
|
||||||
|
for _d_p in IntegerRange(1, limit):
|
||||||
|
if _d_p%2000 == 0:
|
||||||
|
P.status("{} ({:.1%})".format(_d_p, float(_d_p/limit)))
|
||||||
|
gcd = GCD(m-pow(m, ce*_d_p, n), n)
|
||||||
|
if gcd != 1 and gcd != n:
|
||||||
|
p = gcd.lift()
|
||||||
|
P.success("{} ({:.1%})".format(_d_p, float(_d_p/limit)))
|
||||||
|
assert n%p == 0
|
||||||
|
log.success("found p: {}".format(p))
|
||||||
|
|
||||||
|
q = n//p
|
||||||
|
assert p*q == n
|
||||||
|
conn.sendline(str(p+q).encode())
|
||||||
|
flag = conn.recvline()
|
||||||
|
log.success("flag: {}".format(flag.decode()))
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user