import time from timeit import timeit import random import hashlib import re import sys import signal
from secret import * sys.setrecursionlimit(10010)
defget_evidence(data: str): r = str(random.randint(0, 2**32 - 1)) h = hashlib.sha256(f'{r}||{data}||{secretkey}'.encode()).hexdigest() returnf'{r}||{data}||{h}'
defhandler(signum, frame): raise TimeoutError
signal.signal(signal.SIGALRM, handler)
deftest_slow(func, *args, flag): try: measure = timeit(lambda: hashlib.md5(str(random.randint(0, 2**24)).encode()), number=10000) wait = measure * 80 signal.alarm(int(wait)) ret = func(*args) time.sleep(wait % 1) signal.alarm(0) except TimeoutError: print(f'Good for you! The flag is {flag}') exit()
return ret
defproof_of_work(): r = random.randint(0, 2**24 - 1) h = hashlib.md5(f'{r}'.encode()).hexdigest()[0:8] print(f'give me `i` such that md5(i)[0:8] == "{h}" : ', end='') i = input() if hashlib.md5(f'{i}'.encode()).hexdigest()[0:8] != h: print('nope') exit()
defmenu(): print('-------------------------------------------------') print('| Welcome to my service! I am Sophia. Working |') print('| is my favorite things to do. You should work |') print('| hard to catch up with me. I mean, work very, |') print('| very hard. |') print("| Hurry up! I don't have any time to waste on |") print('| you! |') print('| |') print('| 1) the funniest and quickest sorting service |') print('| 2) send your love letter to me |') print('| 3) doing work is my favorite pasttime <3 |') print('-------------------------------------------------')
defhappy_qsort(): defqsort(arr: list): n = len(arr) if n == 0: return arr pivot = arr[n // 2] l = [ i for i in arr if i < pivot ] g = [ i for i in arr if i > pivot ] cnt = arr.count(pivot) return qsort(l) + [pivot] * cnt + qsort(g)
print('Give me the array to be sorted (blank separated) : ', end='') s = input() try: assertlen(s) < 35000# need tuning arr = [ int(i) for i in s.split() ] except: print('bad') exit() ret = test_slow(qsort, arr, flag=flag) print(f'Here is the sorted array: {ret}')
defmarvelous_regex(): print('What do you want to tell Sophia?') print('format: "Dear Sophia, `blahblahblah`. Best wishes, `yourname`."') print(': ', end='') s = input() iflen(s) > 1000: print('Sophia has no time to read such long letter!') exit() pattern = re.compile(r'^Dear Sophia, (.*柴魚){10,15}.*\. Best wishes, ([a-zA-Z0-9]+ ?)+\.$') if test_slow(pattern.match, s, flag=flag): print('Okay, got your message. But Sophia fed her 柴魚 with your letter QQ') else: print('You don\'t even know how to write a letter!')
defwant_more_POW(): n = 10 rate = n / timeit(proof_of_work, number=n) rate_str = str(rate) print(f'Wow! You can finish {rate_str} POWs per second!') print(f'Here is the certificate: {get_evidence(rate_str)}') if rate > 150: print(f'Good for you! The flag is {flag}')
defmain(): try: proof_of_work() menu() op = input('your choice: ') if op == '1': happy_qsort() elif op == '2': marvelous_regex() elif op == '3': want_more_POW() else: print('bye~') except EOFError: pass
if __name__ == '__main__': main()
分析上述程式碼,如果先不看 proof_of_work 的話,我是有看到幾個可能可以拿到 flag 的路徑:
# Specify your GDB script here for debugging gdbscript = ''' starti '''.format(**locals())
# Set up pwntools for the correct architecture # exe = "BIN_FILE_PATH" # This will automatically get context arch, bits, os etc # elf = context.binary = ELF(exe, checksec=True) # Change logging level to help with debugging (error/warning/info/debug) context.log_level = 'error'
# NEED TO GO INTO TMUX FIRST! # print("NEED TO GO INTO TMUX FIRST!") # context.terminal = ['tmux', 'splitw', '-h']
# ========== Exploit ( start ) ==========
counter = 0 counter_real = 0
real_start_time = time.time()
whileTrue:
counter = counter + 1
try: io = start() md5_8 = str(io.recvuntil(b": ").replace(b"give me `i` such that md5(i)[0:8] == \"", b"").replace(b"\" : ", b""))[2:-1] # print("origin md5:", md5_8)
ans = "" for i inrange(0,9999999999999999): md5=hashlib.md5(str(i).encode("utf-8")).hexdigest() if md5[0:8]==md5_8[0:8]: # print(i) ans=str(i) break