1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
| #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <stdatomic.h> #include <pthread.h> #include <openssl/evp.h>
#define LEN 7 #define BYTES 16 #define TOTAL 8031810176LL
static uint8_t partial[BYTES]; static atomic_int found = 0; static char answer[LEN + 1]; static long nthreads = 1;
static void md5_digest(const unsigned char *msg, size_t len, unsigned char out[16]) { EVP_MD_CTX *ctx = EVP_MD_CTX_new(); EVP_DigestInit_ex(ctx, EVP_md5(), NULL); EVP_DigestUpdate(ctx, msg, len); EVP_DigestFinal_ex(ctx, out, NULL); EVP_MD_CTX_free(ctx); }
static inline int matches(const unsigned char *digest) { for (int i = 0; i < BYTES; i++) { uint8_t hi = digest[i] >> 4, lo = digest[i] & 0xF; if (partial[i] != hi && partial[i] != lo) return 0; } return 1; }
static void *worker(void *arg) { long tid = (long)arg;
long long per = TOTAL / nthreads; long long start = tid * per; long long end = (tid == nthreads - 1) ? TOTAL : start + per;
unsigned char cand[LEN], digest[BYTES]; for (long long k = start; k < end; k++) { if (atomic_load(&found)) break; if ((k - start) % 100000000 == 0) printf(" Thread %ld: %lld / %lld (%.1f%%)\n", tid, k - start, per, 100.0 * (k - start) / per);
long long v = k; for (int i = LEN - 1; i >= 0; i--) { cand[i] = 'a' + (v % 26); v /= 26; }
md5_digest(cand, LEN, digest); if (matches(digest)) { memcpy(answer, cand, LEN); answer[LEN] = '\0'; atomic_store(&found, 1); printf("FOUND: %s\n", answer); break; } } return NULL; }
int main(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "usage: %s <partial_hex> [threads]\n", argv[0]); return 1; } if (strlen(argv[1]) != BYTES) { fprintf(stderr, "partial must be %d hex chars\n", BYTES); return 1; } for (int i = 0; i < BYTES; i++) { char c = argv[1][i]; if (c >= '0' && c <= '9') partial[i] = c - '0'; else if (c >= 'a' && c <= 'f') partial[i] = c - 'a' + 10; else if (c >= 'A' && c <= 'F') partial[i] = c - 'A' + 10; else { fprintf(stderr, "invalid hex char: %c\n", c); return 1; } } nthreads = argc > 2 ? atol(argv[2]) : 16; if (nthreads < 1) nthreads = 1;
printf("Starting brute force: %lld combinations across %ld threads\n", TOTAL, nthreads); printf("Partial hash: %s\n", argv[1]);
pthread_t *th = malloc(sizeof(pthread_t) * nthreads); for (long t = 0; t < nthreads; t++) pthread_create(&th[t], NULL, worker, (void *)t); for (long t = 0; t < nthreads; t++) pthread_join(th[t], NULL);
if (atomic_load(&found)) printf("ANSWER: %s\n", answer); else printf("NOT FOUND in range\n"); return 0; }
|