Skip to content

Instantly share code, notes, and snippets.

@joshbode
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save joshbode/b8533079115b603b855a to your computer and use it in GitHub Desktop.

Select an option

Save joshbode/b8533079115b603b855a to your computer and use it in GitHub Desktop.
Super-Optimistic Disk Image Password-Guesser: ./unlock.py foo.dmg 6
#!/usr/bin/env python
import sys, time, string, logging, itertools, subprocess, multiprocessing
hdiutil_opts = [
'-quiet', '-readonly', '-stdinpass', '-nomount', '-noverify', '-noautofsck', '-noidme', '-noautoopen'
]
def mount(image, queue):
"""Worker to attempt to mount the image. Return if successful or poisoned."""
while True:
password = queue.get()
if password is None:
logging.info("Oh, I am slain!")
return
logging.info("Trying: {0}".format(password))
process = subprocess.Popen(
['hdiutil', 'mount', image] + hdiutil_opts,
stdin=subprocess.PIPE
)
process.communicate(password)
if not process.wait():
logging.info("Success: {0}".format(password))
queue.close()
return
logging.info("Failed: {0}".format(password))
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO, format='%(asctime)s: %(message)s')
image = sys.argv[1]
length = int(sys.argv[2])
processes = 20 # multiprocessing.cpu_count() * 4
queue = multiprocessing.Queue(processes * 2)
# start the workers
for _ in range(processes):
multiprocessing.Process(target=mount, args=(image, queue)).start()
# sequential iterator for passwords
passwords = (
''.join(p)
for p in itertools.chain.from_iterable(
itertools.permutations(string.lowercase, w)
for w in range(1, length + 1)
)
)
try:
for password in passwords:
# don't overload queue
while queue.full():
time.sleep(0.1)
queue.put(password)
except KeyboardInterrupt:
for _ in range(processes):
queue.put(None) # poison the workers. poison all of them!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment