Skip to content

Instantly share code, notes, and snippets.

@mokhdzanifaeq
Last active November 26, 2018 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mokhdzanifaeq/2c1e4f7987100dc049e0dfc6e42d50d4 to your computer and use it in GitHub Desktop.
Save mokhdzanifaeq/2c1e4f7987100dc049e0dfc6e42d50d4 to your computer and use it in GitHub Desktop.
multithreaded hidden tear bruteforcer. start from the defined tick and decrease from there
# pip install pycryptodome
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Cipher import AES
from hashlib import sha256
from datetime import datetime
from ctypes import *
import multiprocessing as mp
# http://referencesource.microsoft.com/#mscorlib/system/random.cs
class Random(object):
def __init__(self, seed):
self.seed = c_int(seed).value
self.MBIG = 2147483647
self.MMIN = -2147483648
self.MZ = 0
self.MSEED = 161803398
self.SeedArray = [0] * 56
if seed == self.MMIN:
subtraction = self.MBIG
else:
subtraction = abs(seed)
mj = c_int(self.MSEED - subtraction).value
self.SeedArray[55] = mj
mk = 1
for i in range(1, 55):
ii = (21 * i) % 55
self.SeedArray[ii] = mk
mk = mj - mk
if mk < 0:
mk += self.MBIG
mj = self.SeedArray[ii]
for k in range(1, 5):
for i in range(1, 56):
self.SeedArray[i] -= self.SeedArray[1 + (i + 30) % 55]
if self.SeedArray[i] < 0:
self.SeedArray[i] = c_int(self.SeedArray[i] + self.MBIG).value
self.inext = 0
self.inextp = 21
self.seed = 1
def InternalSample(self):
locINext = self.inext + 1
locINextp = self.inextp + 1
if locINext >= 56:
locINext = 1
if locINextp >= 56:
locINextp = 1
retVal = c_int(self.SeedArray[locINext] - self.SeedArray[locINextp]).value
if retVal == self.MBIG:
retVal -= 1
if retVal < 0:
retVal = c_int(retVal + self.MBIG).value
self.SeedArray[locINext] = retVal
self.inext = locINext
self.inextp = locINextp
return retVal
def Next(self, maxValue=None):
return int(c_float(self.Sample() * maxValue).value)
def Sample(self):
s = self.InternalSample()
ret = c_double(s * c_double(1.0/self.MBIG).value).value
return ret
def gen_pwd(n, seed):
charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890*!=&?&/'
pwd = ''
r = Random(seed)
for i in range(n):
pwd += charset[r.Next(len(charset))]
return pwd
def worker(inc):
tick = ms - inc
while tick > 0:
pwd = gen_pwd(15, tick)
print '[+] trying:', pwd, 'tick:', tick
hashed = sha256(pwd).digest()
tmp = PBKDF2(hashed, salt, 48)
key, iv = tmp[:32], tmp[32:]
cipher_aes = AES.new(key, AES.MODE_CBC, iv)
dec = cipher_aes.decrypt(data)
if dec[:len(magic)] == magic:
return dec, tick
tick -= threads
return None, False
def callback(result):
if result[1] != False:
pool.terminate()
print ''
print '[!] found password', gen_pwd(15, result[1]), 'at tick', result[1]
saved = filename.replace('.locked', '')
open(saved, 'wb').write(result[0])
print '[!] decrypted file saved as', saved
print '[!] elapsed time:', datetime.now() - start
if __name__ == "__main__":
filename = 'important.docx.locked' # encrypted file name/path
magic = '\x50\x4B\x03\x04' # magic bytes of original file
ms = 3600000 # start tick (in millisecond)
threads = 10 # no of thread/process to use
# init data
data = open(filename, 'r').read()
salt = ''.join(map(chr, range(1, 9)))
start = datetime.now()
# init workers
pool = mp.Pool(threads)
for i in range(threads):
pool.apply_async(func=worker, args=(i,), callback=callback)
pool.close()
pool.join()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment