[RFC] Carmageddon cheat retrieval
#1
Hello,



Recently we've begun looking into reverse engineering the old venerable Carmageddon game.

As part of this, we found hashes of cheat codes in the binary.



The game engine applies a hash function on the recent keys and looks into a table for matches.

This avoids putting the cheat codes as strings into the binary.



I've created a hashcat module to find matches, at https://github.com/madebr/hashcat/tree/carmageddon.

I'm interested in feedback about ways to speed it up.


The c equivalent of the hashing algorithm can be found below.
It only accepts lower case letters [a-z].


Code:
#include <ctype.h>

#include <stdint.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>



typedef struct {

  uint32_t sum;

  uint32_t code1;

  uint32_t code2;

} state_t;



typedef struct {

  uint32_t code1;

  uint32_t code2;

} hash_t;



void

hash_reset(state_t *state) {

  memset(state, 0, sizeof(state_t));

}



void

hash_update(state_t *state, const char *txt) {

  while (*txt != '\0') {

    uint8_t letterCode = tolower(*txt) - 'a' + 22;

    state->sum += letterCode;

    state->code1 += letterCode << 11;

    state->code1 = (state->code1 >> 17) + (state->code1 << 4);

    state->code2 = (state->code2 >> 29) + (state->code2 << 3) + letterCode * letterCode;

    txt += 1;

  }

}



void

hash_digest(const state_t *state, hash_t *hash) {

hash->code1 = (state->code1 >> 11) + (state->sum << 21);

hash->code2 = state->code2;

}



int main(int argc, char *argv[]) {

  if (argc == 1) {

#ifdef _WIN32

    fprintf(stderr, "Need at least one argument\n");

    return 1;

#else

    char *line = NULL;

    size_t lineSize = 0;

    while (!feof(stdin)) {

      ssize_t nb = getline(&line, &lineSize, stdin);

      line[nb - 1] = '\0';

      printf("got '%s'\n", line);

    }

    free(line);

    return 0;

#endif

  }

  state_t state;

  hash_t hash;

  for (int i = 1; i < argc; i += 1) {

    hash_reset(&state);

    hash_update(&state, argv[i]);

    hash_digest(&state, &hash);

    printf("%08x:%08x %s\n", hash.code1, hash.code2, argv[i]);

  }

  return 0;

}
Reply