# Challenge DescriptionBaby MD5Your mission is to find weird hash collision!
nc 66.172.10.203 2570
# SolutionThe challenge is split into two parts, the first is a proof-of-worth (PoW) and the second is the actual challengeBooth parts are about getting partial hash collisions and by that I mean (4-6) hex digits of the hash are the same
## PoWYou are asked to provide a printable string with a defined length that when hashed with a hash function (that is defined in the question); will have the requested 6 hex digits at the end of the hash
Example: Please submit a printable string X, such that sha1(X)[-6:] = 5f4774 and len(X) = 32
options for hash functions are SHA1, SHA224, SHA256, SHA384, SHA512, MD5 and may be others that I didn't see
### How to solve?Generating random strings(or a padded counter string) with the requested length and testing if thier hash matches the required digits is actually possible since the search space is only 6 hex digitsSomething like this in a loop could work```python   new_str = ''.join(random.choice(string.ascii_letters) for _ in range(length)) # f'{counter}'.rjust(length, '0')   new_hash_seg = f(new_str) # f is your hash function```
Another faster solution is to use existing rainbow tables for hash functions that are pre-computed to get a string that matches the request but we didn't end up going for this solution
You get something like this (using a counter and padding it with zeros as this turned out faster than random strings):string = 00000000000000000000000000350390hash = 1807a375245bada596041dea0851b0260d5f4774
## Actual challengeYou are asked to provide a pair of strings that will result True in a given function (babymd5) which just checks the two strings to make sure they meet certain conditions.The conditions are that they have a pre-defined prefixes (one of them is the word 'dead'), and also that after repeatedly hashing them using MD5 they will provide the same hash
```pythondef babymd5(m, n, x_head, y_head, x, y):  if x.startswith(x_head) and y.startswith(y_head):    for _ in range(m):      xhash = md5(x.encode('utf-8')).hexdigest()      x = xhash    for _ in range(n):      yhash = md5(y.encode('utf-8')).hexdigest()      y = yhash    if xhash == yhash:      return Truereturn False```Where you are given m, n, x_head and y_head = 'dead' and you are asked to produce x and yExample: (m, n, x_head, y_head) = (195, 5, 'HLX', 'dead')
### How to solve? (We actually didn't solve this part during the competition)The solution depends on the fact that the word 'dead' is a valid start of a hex digest and m > n, and since the babymd5 function repetadly performs the hash on x;then all what we need is a string x that starts with the given x_head and that hashes to a hash that starts with the digits 'dead' after the right amount of times and then we use the resulting hash as our string y
Something like this in a loop will work:
```python   possible_x = x_head + ''.join(random.choice(string.ascii_letters) for _ in range(length)) # f'{x_head}{counter}'.ljust(length, '0')   x_hash = possible_x   for _ in range(m-n):       x_hash = md5(x_hash.encode('utf-8')).hexdigest()   if x_hash.startswith('dead')    y = x_hash    x = possible_x    break```the length should be a valid length for md5 hash for the y string, but isn't restricted for the x string but a good strategy since it isn't restricted is to just use the same length
You actually need to be lucky for the PoW since the server can disconnect and you will need to start over(or you can get a slow hashing function like sha512), but for the actual challenge you can hold the connection by periodically asking for the conditions
x = HLX52570000000000000000000000000 , y = dead8ff641a3d0853e9753ca3f98fb55
Flag: ASIS{MD5_c0L1iD!N9_iZ_4pProX1mA73lY_1.47*10^-29}
For a sample of the actual exploit code: check the original writeup