Skip to content

Instantly share code, notes, and snippets.

@3ch01c
Created February 22, 2019 21:35
Show Gist options
  • Save 3ch01c/9902dc0d2c8b09faea5ee3da866aa5ab to your computer and use it in GitHub Desktop.
Save 3ch01c/9902dc0d2c8b09faea5ee3da866aa5ab to your computer and use it in GitHub Desktop.
bad hash
#! /usr/local/bin/python3
import random
from string import ascii_lowercase
import sys
import requests
def secure_hash(p):
l = len(p)
#print("Get the length of the plaintext: l = len('{:s}') = {:d}".format(p,l))
random.seed(ord(p[0]))
#print("Generate seed: ord(p[0]) = ord({:s}) = {:d}".format(p[0],ord(p[0])))
h = ""
for _ in range(16):
c = random.randint(0,l-1)
#print("Pick a random number c 0-len(p): c = random.randint(0,{:d}) = {:d}".format(l, c))
#print("Pick p[c], and asc2hex it: p[{:d}] = {:s}, ord({:s}) = {:d}, hex({:d})[2:].zfill(2) = {:s}".format(c,p[c],p[c],ord(p[c]),ord(p[c]),hex(ord(p[c]))[2:].zfill(2)))
h += hex(ord(p[c]))[2:].zfill(2)
#print("Append that hex to our hash: {:s}".format(h))
return h
# converts hex string to ASCII byte array
def h2ba(h):
n = 2
return [bytearray.fromhex(h[i:i+n]).decode() for i in range(0, len(h), n)]
# Gets index of first character in hash for first plaintext character c for length l
def get_first_index(l):
m = []
for c in ascii_lowercase:
random.seed(ord(c))
i = random.randint(0,l-1)
m.append(i)
return m
#print("Let's map some possible first indices (i.e., a-z)...")
#print("String length, index map (a-z)")
indices = []
for l in range(1,64):
indices.append([l,get_first_index(l)])
for l in indices:
print("{:d} {}".format(l[0], l[1]))
#print("Isn't that interesting?")
# Returns a valid plaintext p or False for first letter f, length l, hash hex string h
def hack_the_hash(f, l, h):
p = ['_'] * l # p is plaintext of length l.
p[0] = f # we only know the first letter so the rest is just blanks for now
random.seed(ord(p[0])) # seed is the first letter in p
ba = h2ba(h) # convert hash string to char array
for e in ba: # for character e in char array
c = random.randint(0,l-1) # e is cth letter in p
if (p[c] != "_" and p[c] != e): return False # solution must not alter any letters
else: p[c] = e # set p[c] to e
#if (all(str.__contains__(''.join(p), a) for a in set(ba))) return False # solution must contain the set of chars in ba (unnecessary check)
return ''.join(p) # solution must match the hash
h = "616563636377616174726174776f6561" # the known valid hash
ba = h2ba(h) # hash converted to char array
charset = set(ba) # set of characters in char array
print("Known hash found in the code: {:s}".format(h))
print("Converted solution from hex string to char array: {}".format(ba))
print("Rules:")
print("* Plaintext must be have at least {:d} characters because the hash has that many unique characters.".format(len(charset)))
print("* Password must start with the first letter we pick.")
n = int(sys.argv[1]) if (len(sys.argv) > 1) else 28
solutions = []
for l in range(len(charset),n): # try password lengths from len(charset) to n
for f in ascii_lowercase: # iterate first letter
solution = hack_the_hash(f, l, h)
if (solution): solutions.append(solution) # add solution to solution set if valid
def ericwaswrongify(s):
return s.replace("____________", "ericwaswrong")
# print out the valid solutions
for solution in solutions:
solution = ericwaswrongify(solution)
print("{:s}".format(solution))
r = requests.get('https://acmsigsec.mst.edu/ctf/badhash/?password={:s}'.format(solution))
print(r.text)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment