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;
}