houndsniff

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 2f3a4d284cf20a3d2dab94525e2dd5679fec55ed
parent 7773019ee4570f4410a3162691e652cfbc732f58
Author: Christopher Wellons <wellons@nullprogram.com>
Date:   Sat,  2 Jan 2021 16:00:45 -0500

Remove external databases, including SQLite

Baking the data into the binary means there's no need for external data
files. These files could be missing because they weren't installed
correctly. They're also redundant (and were inconsistent) with each
other.

This is also smaller and faster than SQLite since it doesn't involve
opening a database, then analyzing and compiling a dynamically
constructed (!) SQL expression. This is especially true since the
database contained no relevant indexes, and so SQLite was doing the same
linear table scan and sort. (Though the table is so small that this
hardly matters.)

With some cleverer database organization, even the sort could be
skipped, but it's probably more important to be readable.

Diffstat:
MREADME.md | 4++--
Dhashes-db.txt | 92-------------------------------------------------------------------------------
Msrc/Makefile | 2+-
Dsrc/hashes | 0
Dsrc/list.txt | 62--------------------------------------------------------------
Msrc/main.c | 25+------------------------
Msrc/select.c | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/select.h | 1+
8 files changed, 109 insertions(+), 212 deletions(-)

diff --git a/README.md b/README.md @@ -1,5 +1,5 @@ # houndsniff -Houndsniff is a minimal hash identification and recognition tool written in C that uses an SQLite database to compare a hash's features to characteristics of other common hashing algorithm results. Email hashes that I missed at houndsniff@protonmail.com +Houndsniff is a minimal hash identification and recognition tool written in C that uses a database to compare a hash's features to characteristics of other common hashing algorithm results. Email hashes that I missed at houndsniff@protonmail.com By Michael Constantine Dimopoulos @@ -21,7 +21,7 @@ make or manually ``` -gcc main.c select.c -lsqlite3 -std=c89 -o hound +gcc main.c select.c -std=c89 -o hound ``` diff --git a/hashes-db.txt b/hashes-db.txt @@ -1,92 +0,0 @@ -# Houndsniff (GNU GPL) -# by Michael Constantine Dimopoulos -# -# SQLite database dump in plaintext -# suggested by kurahaupo - -# Notes: -# 0. The rows are split into chunks of 3 for readability -# 1. The popularity integer determines how the results are sorted -# 2. It is determined by the number web search results compared -# to other hashing algorithms with the same characteristics. - -# charsets: -# a = String is made only of numbers & lowercase letters -# b = string includes a '$' -# c = string includes a '/' -# d = string begins with '$0$' -# e = string includes uppercase letters - - -TABLE: hashes - -name (TEXT) length (INT) charset (TEXT) popularity (INT) - -MD5 32 a 100 -SHA1 40 a 85 -SHA256 64 a 87 - -SHA224 56 a 79 -SHA384 96 a 58 -SHA512 128 a 70 - -RIPEMD160 40 a 38 -MD4 32 a 40 -MD2 32 a 35 - -CRC32b 8 a 10 -ADLER32 8 a 8 -CRYPT16 24 c 10 - -LanManager Hash 32 a 25 -Windows NT-Hash 32 a 20 -MSSQL 2000 94 d 20 - -MSSQL 2005 54 d 20 -MySQL 3.2.3 16 a 20 -DES Crypt 13 e 20 - -FreeBSD nthash 36 b 20 -CRC32 8 a 19 -HAVAL128,5 32 a 28 - -HAVAL128,4 32 a 26 -HAVAL128,3 32 a 27 -HAVAL256,5 64 a 20 - -HAVAL224,5 56 a 21 -HAVAL192,5 48 a 27 -HAVAL160,5 40 a 22 - -HAVAL224,4 56 a 25 -HAVAL192,4 48 a 26 -HAVAL160,4 40 a 21 - -HAVAL256,3 64 a 18 -HAVAL224,3 56 a 20 -HAVAL192,3 48 a 25 - -HAVAL160,3 40 a 22 -Whirpool 128 a 50 -GOST Hash 64 a 10 - -Snefru-128 64 a 5 -RIPEMD128 32 a 9 -RIPEMD256 64 a 9 - -RIPEMD320 80 a 8 -Tiger128,3 32 a 5 -Tiger160,3 40 a 5 - -Tiger192,3 48 a 6 -Tiger128,4 32 a 7 -Tiger160,4 40 a 7 - -Tiger192,4 48 a 5 -CRC16 4 a 50 -DCC 32 a 10 - -MD5 (half) 16 a 10 -MD4 HMAC 32 a 7 -MD5 HMAC 32 a 12 - diff --git a/src/Makefile b/src/Makefile @@ -1,5 +1,5 @@ output: main.o select.o - gcc main.o select.o -o hound -lsqlite3 + gcc main.o select.o -o hound main.o: main.c gcc -c main.c diff --git a/src/hashes b/src/hashes Binary files differ. diff --git a/src/list.txt b/src/list.txt @@ -1,62 +0,0 @@ -MD5 - -SHA1 -SHA256 -SHA224 -SHA384 -SHA512 -RIPEMD160 -MD4 -MD2 -CRC32b -ADLER32 -CRYPT16 -LanManager Hash -Windows NT-Hash -MSSQL 2000 -MSSQL 2005 -MySQL 3.2.3 -DES Crypt -FreeBSD nthash -CRC32 -HAVAL128,5 -HAVAL128,4 -HAVAL128,3 -HAVAL256,5 -HAVAL224,5 -HAVAL192,5 -HAVAL160,5 -HAVAL224,4 -HAVAL192,4 -HAVAL160,4 -HAVAL256,3 -HAVAL224,3 -HAVAL192,3 -HAVAL160,3 -Whirpool -GOST Hash -Snefru-128 -RIPEMD128 -RIPEMD256 -RIPEMD320 -Tiger128,3 -Tiger160,3 -Tiger192,3 -Tiger128,4 -Tiger160,4 -Tiger192,4 -MD5 (half) -CRC16 -DomainCachedCredentials -MD5 (half) -MD4 HMAC -MD5 HMAC -Wordpress hash -MD5 crypt(3) -SHA256 crypt(3) -SHA512 crypt(3) -Base64 (I know it's not a hash) -APR1 -phpBB -SHA1 Django -MD5 Joomla (pass:salt) diff --git a/src/main.c b/src/main.c @@ -40,29 +40,6 @@ banner() printf("Houndsniff - Hash Identification Program - Version %s\nBy Michael Constantine Dimopoulos Sep 2020\n\n",version); } -/* This function prints out the supported hashes - * The reason I used a text file is because - * 1. it's easier - * 2. it's simpler and - * 3. I can add comments etc. - */ - -void -list_(void) -{ - printf("\nHoundsniff supports:\n\n"); - int c; - FILE *file; - file = fopen("list.txt", "r"); - - if (file) { - while ((c = getc(file)) != EOF) - putchar(c); - fclose(file); - } - -} - /* This is the first test; * here we identify the hash * based on *definite* characteristics @@ -143,7 +120,7 @@ main(int argc, char* argv[]) if(strcmp(argv[1],"-h")==0 || strcmp(argv[1],"--help")==0){ help(); } else if(strcmp(argv[1], "-l")==0) { - list_(); + list(); } else { int len = strlen(argv[1]); printf("Hash: %s\n", argv[1]); diff --git a/src/select.c b/src/select.c @@ -1,4 +1,3 @@ -#include <sqlite3.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -8,45 +7,119 @@ indexes through the database and picks out the rows with desired values */ -int counter = 0; -int callback(void *, int, char **, char **); +void list(void); +int matchcmp(const void *, const void *); int sel(int length, const char *charset); +/* Notes: + 0. The rows are split into chunks of 3 for readability + 1. The popularity integer determines how the results are sorted + 2. It is determined by the number web search results compared + to other hashing algorithms with the same characteristics. + + charsets: + a = String is made only of numbers & lowercase letters + b = string includes a '$' + c = string includes a '/' + d = string begins with '$0$' + e = string includes uppercase letters */ + +#define NHASHES (int)(sizeof(hashes) / sizeof(hashes[0])) +static const struct { + char *name; + short length; + char charset; + char popularity; +} hashes[] = { + {"MD5", 32, 'a', 100}, + {"SHA1", 40, 'a', 85}, + {"SHA256", 64, 'a', 87}, + {"SHA224", 56, 'a', 79}, + {"SHA384", 96, 'a', 58}, + {"SHA512", 128, 'a', 70}, + {"RIPEMD160 ", 40, 'a', 38}, + {"MD4", 32, 'a', 40}, + {"MD2", 32, 'a', 35}, + {"CRC32b", 8, 'a', 10}, + {"ADLER32", 8, 'a', 8}, + {"CRYPT16", 24, 'c', 10}, + {"LanManager Hash", 32, 'a', 25}, + {"Windows NT-Hash", 32, 'a', 20}, + {"MSSQL 2000", 94, 'd', 20}, + {"MSSQL 2005", 54, 'd', 20}, + {"MySQL 3.2.3", 16, 'a', 20}, + {"DES Crypt", 13, 'e', 20}, + {"FreeBSD nthash", 36, 'b', 20}, + {"CRC32", 8, 'a', 19}, + {"HAVAL128,5", 32, 'a', 28}, + {"HAVAL128,4", 32, 'a', 26}, + {"HAVAL128,3", 32, 'a', 27}, + {"HAVAL256,5", 64, 'a', 20}, + {"HAVAL224,5", 56, 'a', 21}, + {"HAVAL192,5", 48, 'a', 27}, + {"HAVAL160,5", 40, 'a', 22}, + {"HAVAL224,4", 56, 'a', 25}, + {"HAVAL192,4", 48, 'a', 26}, + {"HAVAL160,4", 40, 'a', 21}, + {"HAVAL256,3", 64, 'a', 18}, + {"HAVAL224,3", 56, 'a', 20}, + {"HAVAL192,3", 48, 'a', 25}, + {"HAVAL160,3", 40, 'a', 22}, + {"Whirpool", 128, 'a', 50}, + {"GOST Hash", 64, 'a', 10}, + {"Snefru-128", 64, 'a', 5}, + {"RIPEMD128", 32, 'a', 9}, + {"RIPEMD256", 64, 'a', 9}, + {"RIPEMD320", 80, 'a', 8}, + {"Tiger128,3", 32, 'a', 5}, + {"Tiger160,3", 40, 'a', 5}, + {"Tiger192,3", 48, 'a', 6}, + {"Tiger128,4", 32, 'a', 7}, + {"Tiger160,4", 40, 'a', 7}, + {"Tiger192,4", 48, 'a', 5}, + {"CRC16", 4, 'a', 50}, + {"DomainCachedCredentials", 32, 'a', 10}, + {"MD5 (half)", 16, 'a', 10}, + {"MD4 HMAC", 32, 'a', 7}, + {"MD5 HMAC", 32, 'a', 12}, +}; + int sel(int length, const char *charset) { - sqlite3 *db; - char *err_msg = 0; - - int rc = sqlite3_open("hashes", &db); - char sql[1150], len[5], pt2[30], pt3[40]; - - strcpy(sql, "SELECT name FROM hashes WHERE length="); - sprintf(len, "%d", length); - strcpy(pt2, " AND charset='"); - strcpy(pt3, "' ORDER BY popularity DESC;"); - - strcat(sql, len); - strcat(sql, pt2); - strcat(sql, charset); - strcat(sql, pt3); - rc = sqlite3_exec(db, sql, callback, 0, &err_msg); - sqlite3_close(db); - + int i; + int nmatch = 0; + int matches[NHASHES]; + + for (i = 0; i < NHASHES; i++) { + if (hashes[i].length == length && hashes[i].charset == *charset) { + matches[nmatch++] = i; + } + } + + qsort(matches, nmatch, sizeof(*matches), matchcmp); + + printf("Possible results:\n\n"); + for (i = 0; i < nmatch; i++) { + printf("[%d] %s\n", i + 1, hashes[matches[i]].name); + } return 0; } int -callback(void *unused, int argc, char **argv, char **azColName) +matchcmp(const void *p0, const void *p1) { - counter++; - int i; + int m0 = *(int *)p0; + int m1 = *(int *)p1; + return hashes[m1].popularity - hashes[m0].popularity; +} - for (i = 0; i < argc; i++) { - if (counter == 1) - printf("Possible results:\n\n[%d] %s", counter, argv[i] ? argv[i] : "NULL"); - else - printf("[%d] %s", counter, argv[i] ? argv[i] : "NULL"); - } printf("\n"); - return 0; +void +list(void) +{ + int i; + printf("\nHoundsniff supports:\n\n"); + for (i = 0; i < NHASHES; i++) { + puts(hashes[i].name); + } } diff --git a/src/select.h b/src/select.h @@ -8,6 +8,7 @@ #ifndef SELECT_H #define SELECT_H +void list(void); int sel(int length, const char *charset); #endif