From 456df57ba8680ea36c7b5b516d58fde232ef0b3f Mon Sep 17 00:00:00 2001 From: Maxime Vorwerk Date: Mon, 12 Aug 2024 13:35:05 +0200 Subject: [PATCH] It's Not My Fault 1 --- its_not_my_fault_1/flag.txt | 1 + its_not_my_fault_1/not_my_fault.py | 61 ++++++++++++++++++++++++++++++ its_not_my_fault_1/sol.py | 57 ++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 its_not_my_fault_1/flag.txt create mode 100755 its_not_my_fault_1/not_my_fault.py create mode 100755 its_not_my_fault_1/sol.py diff --git a/its_not_my_fault_1/flag.txt b/its_not_my_fault_1/flag.txt new file mode 100644 index 0000000..6c32239 --- /dev/null +++ b/its_not_my_fault_1/flag.txt @@ -0,0 +1 @@ +picoCTF{flagFLAG} diff --git a/its_not_my_fault_1/not_my_fault.py b/its_not_my_fault_1/not_my_fault.py new file mode 100755 index 0000000..9d728ab --- /dev/null +++ b/its_not_my_fault_1/not_my_fault.py @@ -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) + diff --git a/its_not_my_fault_1/sol.py b/its_not_my_fault_1/sol.py new file mode 100755 index 0000000..199e30f --- /dev/null +++ b/its_not_my_fault_1/sol.py @@ -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())) + +