12-16-2021, 04:28 PM 
		
	
	
		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].
	
	
	
	
	
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;
} 
 

 
