> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-17/vulnerability-exploitation/trick-0451.md).

# MD5 Partial Collision Exploitation

***

Exploiting a vulnerability where a system only compares the initial portion (e.g., the first 6 bytes) of an MD5 hash. The technique involves generating numerous input strings, calculating their MD5 hashes, and checking if the beginning of the generated hash matches the target hash's prefix.

For MD5 and a relatively small number of bytes (like 6), finding an input string whose hash shares the same initial bytes as the hash of a known target (like a secret string) is feasible through scripting, leveraging a birthday-attack-like approach. A script rapidly generates inputs (e.g., `word1`, `word2`, ...), computes their MD5 hashes, and stops when the hash prefix matches the target prefix.

For example, if the system compares the first 6 bytes of an MD5 hash, and the target hash prefix is `4e4f59` (the start of the MD5 hash of the word 'Flag'), a script could find that the input `word1566914` produces an MD5 hash that also starts with `4e4f59`.

This approach can be implemented with a simple program that generates random strings, calculates their MD5 hash, and checks if the hash begins with the desired prefix.

Here is a Python script illustrating this process:

```python
import hashlib
import random
import string
import time

def random_string(length):
   letters = string.ascii_lowercase + string.digits
   return ''.join(random.choice(letters) for i in range(length))

def find_prefix_match(hash_function, target_prefix, length=10):
    start_time = time.time()
    count = 0
    while True:
        count += 1
        message = random_string(length)
        # Calculate hash and get the hexdigest
        hash_value = hash_function(message.encode()).hexdigest()

        # Check if the hash starts with the target prefix
        if hash_value.startswith(target_prefix):
            end_time = time.time()
            print(f"Found match after {count} attempts:")
            print(f"Input: {message}")
            print(f"Hash: {hash_value}")
            print(f"Time taken: {end_time - start_time:.4f} seconds")
            return message, hash_value

# Example usage:
# Find a string whose MD5 hash starts with '4e4f59' (first 6 hex chars of MD5('Flag'))
# md5_target_prefix = '4e4f59'
# find_prefix_match(hashlib.md5, md5_target_prefix)
```

Alternatively, the hashing can be performed using libraries in other languages, such as C with OpenSSL:

```c
#include <stdio.h>
#include <string.h>
#include <openssl/md5.h>

int main() {
    unsigned char digest[MD5_DIGEST_LENGTH];
    char string[] = "hello world";

    MD5((unsigned char*)&string, strlen(string), (unsigned char*)&digest);

    char mdString[33];
    for(int i = 0; i < 16; i++)
         sprintf(&mdString[i*2], "%02x", (unsigned int)digest[i]);

    printf("md5 digest: %s\n", mdString);

    return 0;
}
```

A program implementing the prefix search would repeatedly generate inputs, calculate their MD5 hash using a function like shown above, convert the digest to a hex string, and compare the initial bytes with the target prefix until a match is found. This brute-force approach is feasible for short prefixes due to the nature of the birthday paradox.
