MeePwn CTF 2017: |\/|/-\T|-| (100)
We are given a file, hack.py
, which looks as follows.
from Crypto.Util.number import *
from hashlib import md5
flag = "XXX"
assert len(flag) == 4
pad = bytes_to_long(md5(flag).digest())
hack = 0
for char in flag:
hack+= pad
hack*= ord(char)
print hack
print pad
print hack % pad
#hack = 64364485357060434848865708402537097493512746702748009007197338675
#flag_to_submit = "MeePwnCTF{" + flag + "}"
Looking at the loop, hack
will be like \(abcdx + bcdx + cdx + dx\), with \(x\) is the value of
pad
. The value of hack
is not quite long. Factoring hack
leads to 13 prime factors (11
distincts prime factors). We can search which one is \(x\) by brute-force, and then try to solve
the remaining equation.
After dividing hack
with \(x\), the remaining value will be in a form like \(abcd + bcd + cd +
d\). We can find a proper factor of the remaining equation, and then substract it with 1, and the
remaining value will in a form like \(abc + bc + c\). This means we can recursively do this and it
will be the correct sequence if we can make it 0 and MD5(flag)
is the same as our candidate
padding. We will use DFS to recursively
find the candidate.
Here is the Python script to find the value of flag:
import string
from Crypto.Util.number import *
from hashlib import md5
primes = [3,3,5,5,7,107,487,607,28429,29287,420577267963,3680317203978923,1002528655290265069]
hack = 64364485357060434848865708402537097493512746702748009007197338675
flen = 14
total = 1
for p in primes:
total = total * p
assert(hack == total)
mask = 2 ** len(primes)
cand = []
for i in range(mask):
q = 1
for j in range(len(primes)):
if ((i & (1<<j)) != 0):
q = q * primes[j]
if (2 ** 120 <= q and q <= 2 ** 128):
cand.append(q)
def check(d, t, a, h):
if d == 0 and t == 0:
flag = "".join([chr(c) for c in a])
if (bytes_to_long(md5(flag).digest()) == h):
print(flag)
return
if t == 0:
return
if (d,t) in vis:
return
vis.add((d,t))
for c in string.printable:
x = ord(c)
if t % x == 0:
check(d-1, (t // x) - 1, [x] + a, h)
for pad in cand:
t = hack // pad
vis = set()
check(flen, t, [], pad)
Flag is: MeePwnCTF{d0y0ul1keM@TH?}