Skip to content

Instantly share code, notes, and snippets.

@gquere
Created August 19, 2019 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gquere/8dc40c5a6a900215102e6ac94716b33d to your computer and use it in GitHub Desktop.
Save gquere/8dc40c5a6a900215102e6ac94716b33d to your computer and use it in GitHub Desktop.
shiro1 Nexus hash cracking password breaking
/**
* gcc shiro1.c -lcrypto -lssl -fopenmp
*
* Crack salted iterated SHA512 hashes.
* Just wanted to check how much faster it was rather in C than in Java:
* https://gist.github.com/gquere/365cfcceef9ac8d145cc59bbf2c27648
*
* Here are the results I got using rockyou, 1024 iterations, so about 15 billion hashes:
* time ./a.out ../rockyou.txt
* 8130,86s user 1,05s system 787% cpu 17:12,07 total
*
* time java -classpath /usr/share/java/shiro-core.jar:: bla --arg rockyou.txt
* 9510,15s user 3,13s system 702% cpu 22:34,48 total
*
* Looks like it's a bit faster, notably because OpenMP threads are scheduled more efficiently
* than java's parallel filter.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
#define OUT
/**
* Found algorithm description in the shiro Java sources here:
* https://shiro.apache.org/static/1.3.2/shiro-core/jacoco/org.apache.shiro.crypto.hash/Sha512Hash.java.html
* https://shiro.apache.org/static/1.3.2/shiro-core/jacoco/org.apache.shiro.crypto.hash/SimpleHash.java.html
*/
void sha512_iterate_hash(const char *salt, const char *password,
const size_t password_len, const uint32_t iterations,
OUT uint8_t *md)
{
SHA512_CTX ctx;
SHA512_Init(&ctx);
SHA512_Update(&ctx, salt, strlen(salt));
SHA512_Update(&ctx, password, password_len);
SHA512_Final(md, &ctx);
uint32_t i;
for (i = 0; i < iterations - 1; i++) {
SHA512_Init(&ctx);
SHA512_Update(&ctx, md, SHA512_DIGEST_LENGTH);
SHA512_Final(md, &ctx);
}
}
int main(int argc, char *argv[])
{
/* Test value "Jenydoby6!" */
char *salt = "\x72\xd6\x0f\xe7\x66\xb6\x4a\x9d\xb2\x22\x3c\xf3\x94\x90\x2e\x3e";
uint32_t iterations = 500000;
char *check = "\x72\xd6\x78\x81\x0b\x4d\x77\xb6\xca\x23\x44\x96\xb6\x4b\x51\x02\x23\xf8\x5f\x38\x24\xeb\xab\x1a\x6e\x0d\xe9\x8f\x4a\x50\x06\x62\x99\x9a\x01\xbb\x28\x05\xd9\xa8\x08\x41\x24\x9d\xdc\x09\x3a\x9e\x9d\xfa\xa2\xe0\xb4\xe0\x79\x99\xe1\xe3\x06\x8b\xea\x83\x07\xfb";
FILE *password_file = fopen(argv[1], "r");
if (password_file == NULL) {
printf("Failed opening file\n");
return 1;
}
/* read all lines */
char **passwords = malloc(1000 * sizeof(char *));
char *line = NULL;
size_t line_len = 0;
ssize_t size_read;
uint32_t i = 0;
while ((size_read = getline(&line, &line_len, password_file)) != -1) {
line[strlen(line) - 1] = 0; //remove newline
passwords[i++] = strdup(line);
if (i && (i % 1000) == 0) {
passwords = realloc(passwords, (i + 1000) * sizeof(char *));
}
}
fclose(password_file);
uint32_t nb_lines = i;
printf("[+] Done buffering passwords\n");
/* check hashes */
#pragma omp parallel
#pragma omp for
for (i = 0; i < nb_lines; i++) {
uint8_t md[SHA512_DIGEST_LENGTH];
sha512_iterate_hash(salt, passwords[i], strlen(passwords[i]), iterations, (uint8_t *)&md);
if (memcmp(md, check, SHA512_DIGEST_LENGTH) == 0) {
printf("Found match for %s\n", passwords[i]);
exit(0);
}
free(passwords[i]);
}
free(passwords);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment