This commit is contained in:
Ada 2024-03-02 23:55:03 +01:00
commit c76f62f424
Signed by: ada
GPG key ID: 6A7F898157C6DE6E
20 changed files with 1095 additions and 0 deletions

66
.clang-format Normal file
View file

@ -0,0 +1,66 @@
# Generated from CLion C/C++ Code Style settings
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: None
AlignOperands: Align
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Always
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 0
CompactNamespaces: false
ContinuationIndentWidth: 8
IndentCaseLabels: true
IndentPPDirectives: None
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 2
NamespaceIndentation: All
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Right
ReflowComments: false
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 0
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
UseTab: Never

148
.clang-tidy Normal file
View file

@ -0,0 +1,148 @@
# Generated from CLion Inspection settings
---
Checks: '-*,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-fold-init-type,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase,
bugprone-incorrect-roundings,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-no-escape,
bugprone-not-null-terminated-result,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-reserved-identifier,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-enum-usage,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-realloc-usage,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-self-assignment,
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-use-after-move,
bugprone-virtual-near-miss,
cert-dcl21-cpp,
cert-dcl58-cpp,
cert-err34-c,
cert-err52-cpp,
cert-err60-cpp,
cert-flp30-c,
cert-msc50-cpp,
cert-msc51-cpp,
cert-str34-c,
cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-slicing,
google-default-arguments,
google-explicit-constructor,
google-runtime-operator,
hicpp-exception-baseclass,
hicpp-multiway-paths-covered,
misc-misplaced-const,
misc-new-delete-overloads,
misc-non-copyable-objects,
misc-throw-by-value-catch-by-reference,
misc-unconventional-assign-operator,
misc-uniqueptr-reset-release,
modernize-avoid-bind,
modernize-concat-nested-namespaces,
modernize-deprecated-headers,
modernize-deprecated-ios-base-aliases,
modernize-loop-convert,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-raw-string-literal,
modernize-redundant-void-arg,
modernize-replace-auto-ptr,
modernize-replace-disallow-copy-and-assign-macro,
modernize-replace-random-shuffle,
modernize-return-braced-init-list,
modernize-shrink-to-fit,
modernize-unary-static-assert,
modernize-use-auto,
modernize-use-bool-literals,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-transparent-functors,
modernize-use-uncaught-exceptions,
mpi-buffer-deref,
mpi-type-mismatch,
openmp-use-default-none,
performance-faster-string-find,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-string-concatenation,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-move-constructor-init,
performance-no-automatic-move,
performance-noexcept-move-constructor,
performance-trivially-destructible,
performance-type-promotion-in-math-fn,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
portability-simd-intrinsics,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-convert-member-functions-to-static,
readability-delete-null-pointer,
readability-deleted-default,
readability-inconsistent-declaration-parameter-name,
readability-make-member-function-const,
readability-misleading-indentation,
readability-misplaced-array-index,
readability-non-const-parameter,
readability-redundant-control-flow,
readability-redundant-declaration,
readability-redundant-function-ptr-dereference,
readability-redundant-smartptr-get,
readability-redundant-string-cstr,
readability-redundant-string-init,
readability-simplify-subscript-expr,
readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace,
readability-string-compare,
readability-uniqueptr-delete-release,
readability-use-anyofallof,
clang-analyzer-*,
google-*'

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
a.out
.idea/
build/
log

23
Makefile Normal file
View file

@ -0,0 +1,23 @@
CC = clang
CFLAGS = -Wall -Wextra -Wconversion -Wdeprecated -Wpedantic -Wshadow -Wuninitialized -Wunused -Wcast-qual -Wfloat-equal -Wformat=2 -Winit-self -Wstrict-prototypes -Wswitch-default -Wswitch-enum -Wundef -Wunused-macros -Wwrite-strings -Wmissing-prototypes --std=gnu17
all: clean build
dev: clean build-dbg
build:
mkdir build/
$(CC) $(CFLAGS) client/main.c client/config.c client/crack.c client/calculateHash.c shared.c -o build/client -lcrypto -lbsd
$(CC) $(CFLAGS) server/main.c server/config.c shared.c -o build/server -lbsd
build-dbg:
mkdir build/
$(CC) $(CFLAGS) -g client/main.c client/config.c client/log.c client/crack.c client/calculateHash.c shared.c -o build/client -lcrypto -lbsd
$(CC) $(CFLAGS) -g server/main.c server/config.c server/log.c shared.c -o build/server -lcrypto -lbsd
clean:
rm -rf build/
lint:
find . -type f -name '*.c' -exec clang-tidy {} \;

37
README.md Normal file
View file

@ -0,0 +1,37 @@
# Hash breaker
A school project (code is not clean, I know) for break md5 with a client server program. Support wordlist or basic bruteforce based on array of char.
## Configuration :
### Client :
- -a: Server IP
- -p: Server port
- -l: Maximum password length
- -e: Ascii generation end (default 127)
- -b: Ascii generation begin (default 32)
- -f: Output error to file
- -h: Help
### Serveur :
- -i: Listen IP
- -p: Listen port
- -s: Hash to break
- -f: Output log to file
- -h: Help
# Build
## Install Dependencies
### Debian :
`sudo apt install build-essential libbsd-dev libssl-dev clang`
## Compile
- `make build` output binary in `build/{server,client}`
- `make build-dbg` output binary in `build/{server,client}` with debug symbol
- `make lint` lint with `clang-tidy`
- `make clean` delete `build/`
- `make` ou `make all` clean+lint+build
- `make dev` clean+build-dbg

32
client/calculateHash.c Normal file
View file

@ -0,0 +1,32 @@
#include <openssl/evp.h>
#include <string.h>
#include <stdio.h>
#include "../default.h"
#include "../shared.h"
#include "calculateHash.h"
char *generateMD5(char *string_p) {
unsigned char mdValue[EVP_MAX_MD_SIZE];
unsigned int mdLength;
size_t i;
char *formattedHash_p = (char *) calloc(MD5_STR_SIZE, sizeof(char));
if (formattedHash_p == NULL) {
showError(NULL);
return NULL;
}
EVP_MD_CTX *MDctx_p = EVP_MD_CTX_new();
EVP_DigestInit_ex(MDctx_p, EVP_md5(), NULL);
EVP_DigestUpdate(MDctx_p, string_p, strlen(string_p));
EVP_DigestFinal_ex(MDctx_p, mdValue, &mdLength);
for (i = 0; i < mdLength; i++) {
snprintf(&formattedHash_p[i * 2], 3, "%02x", mdValue[i]); // Transform int to correct format
}
EVP_MD_CTX_free(MDctx_p);
return formattedHash_p;
}

9
client/calculateHash.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef CALCULATEHASH_H
#define CALCULATEHASH_H
#include "config.h"
char *generateMD5(
char *string_p); // Generate and store md5 hash into array of char pointer. Take string_p for source string, formattedHash for formatted result string.
#endif

148
client/config.c Normal file
View file

@ -0,0 +1,148 @@
#include <stdio.h>
#include <bsd/string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sysexits.h>
#include <linux/limits.h>
#include "../default.h"
#include "../shared.h"
#include "main.h"
#include "config.h"
int setConfig(int argc, char *argv[], config_t *currentConfig_p) {
int numberOptions;
while ((numberOptions = getopt(argc, argv, "a:p:l:b:e:f:w:h")) != -1) {
// a: Server address
// p: Server port
// l: Max password length (default 8)
// b: Ascii generation begin (default 32)
// e: Ascii generation end (default 127)
// f: Log file
// w: Wordlist
// h: Help
currentConfig_p->AsciiBegin = 32;
currentConfig_p->AsciiEnd = 127;
currentConfig_p->maxLength = 8;
currentConfig_p->logToFile = false;
currentConfig_p->wordlist = false;
switch (numberOptions) {
case 'a':
if (inet_addr(optarg) == INADDR_NONE) {
fprintf(stderr, "Adresse IP du serveur invalide.\n");
return EX_CONFIG;
}
currentConfig_p->serverIP = inet_addr(optarg);
break;
case 'f':
if (strncmp(optarg, "", PATH_MAX) == 0) { // Max size based on POSIX spec
break;
}
currentConfig_p->logToFile = true;
strlcpy(currentConfig_p->logFile, optarg, PATH_MAX);
break;
case 'w':
if (strncmp(optarg, "", PATH_MAX) == 0) { // Max size based on POSIX spec
break;
}
currentConfig_p->wordlist = true;
strlcpy(currentConfig_p->wordlistPath, optarg, PATH_MAX);
break;
case 'p':
errno = 0;
if (strtol(optarg, NULL, 10) > MIN_PORT && strtol(optarg, NULL, 10) <= MAX_PORT) {
currentConfig_p->serverPort = (unsigned short) strtol(optarg, NULL, 10);
} else {
fprintf(stderr, "Invalid port.\n");
printHelp();
return EX_CONFIG;
}
if (errno == ERANGE) {
showError(NULL);
printHelp();
return EX_CONFIG;
}
break;
case 'l':
errno = 0;
if (strtol(optarg, NULL, 10) < 0) {
fprintf(stderr, "length is invalid, must be >0.\n");
printHelp();
return EX_CONFIG;
}
currentConfig_p->maxLength = (unsigned short) strtol(optarg, NULL, 10);
if (errno == ERANGE) {
showError(NULL);
printHelp();
return EX_CONFIG;
}
break;
case 'b':
errno = 0;
if (strtol(optarg, NULL, 10) < 0) {
fprintf(stderr, "Invalid settings, must be >0.\n");
printHelp();
return EX_CONFIG;
}
if (strtol(optarg, NULL, 10) > 127) {
fprintf(stderr, "Invalid settings, must be =<127.\n");
printHelp();
return EX_CONFIG;
}
currentConfig_p->AsciiBegin = (unsigned short) strtol(optarg, NULL, 10);
if (errno == ERANGE) {
showError(NULL);
printHelp();
return EX_CONFIG;
}
break;
case 'e':
errno = 0;
if (strtol(optarg, NULL, 10) < 0) {
fprintf(stderr, "Invalid settings, must be >0.\n");
printHelp();
return EX_CONFIG;
}
if (strtol(optarg, NULL, 10) > 127) {
fprintf(stderr, "Invalid settings, must be =<127.\n");
printHelp();
return EX_CONFIG;
}
currentConfig_p->AsciiEnd = (unsigned short) strtol(optarg, NULL, 10);
if (errno == ERANGE) {
showError(NULL);
printHelp();
return EX_CONFIG;
}
break;
case 'h':
printHelp();
exit(EXIT_SUCCESS);
default:
printHelp();
return EX_CONFIG;
}
}
// Verify mandatory options.
if (currentConfig_p->maxLength == 0) {
printHelp();
return EX_CONFIG;
}
if (currentConfig_p->serverPort == 0) {
printHelp();
return EX_CONFIG;
}
return EXIT_SUCCESS;
}

22
client/config.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <stdbool.h>
#include <stdint.h>
#include <linux/limits.h>
typedef struct config_s { // store all config.
uint32_t serverIP;
unsigned short serverPort;
unsigned short maxLength;
unsigned short AsciiBegin; // Begin of ascii table for array generation
unsigned short AsciiEnd; // Begin of ascii table for array generation
bool logToFile; // bool for check if log to file is enabled
char logFile[PATH_MAX]; // Path for logfile
bool wordlist; // bool for check if wordlist mode is enabled
char wordlistPath[PATH_MAX]; // path to wordlist mode.
} config_t;
int setConfig(int argc, char *argv[], config_t *currentConfig_p); // set config from command line argument.
#endif

174
client/crack.c Normal file
View file

@ -0,0 +1,174 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#include "../default.h"
#include "../shared.h"
#include "calculateHash.h"
#include "crack.h"
void freeCharList_s(charList_t *s) {
safeFree((void **) &s->charList);
safeFree((void **) &s);
}
bruteforceResult_t *initBruteforceResult_s(void) {
bruteforceResult_t *s = (bruteforceResult_t *) calloc(1, sizeof(bruteforceResult_t));
if (s == NULL) {
showError(NULL);
return NULLPTR;
}
s->resultSize = (size_t) NULL;
s->result = (char *) NULL;
s->found = false;
return s;
}
void freeBruteforceResult_s(bruteforceResult_t *s) {
safeFree((void **) &s->result);
safeFree((void **) &s);
}
int bruteforce(char *prefix_p, unsigned short length, char *toCrackHash_p, bruteforceResult_t *bruteforceResult_p,
charList_t *charList_p) {
char *hash_p = NULLPTR;
if (length == 0) {
hash_p = generateMD5(prefix_p);
if (hash_p == NULL) {
showError(NULL);
return 1;
}
if (strncmp(toCrackHash_p, hash_p, MD5_STR_SIZE * sizeof(char)) == 0) {
safeFree((void **) &hash_p);
strlcpy(bruteforceResult_p->result, prefix_p, bruteforceResult_p->resultSize);
return 0;
}
safeFree((void **) &hash_p);
return 1;
}
char c;
for (unsigned int i = 0; i < length; i++) {
for (unsigned int j = 0; j < charList_p->arraySize; j++) {
c = charList_p->charList[j];
prefix_p[length - 1] = c;
if (bruteforce(prefix_p, length - 1, toCrackHash_p, bruteforceResult_p, charList_p) == 0) {
safeFree((void **) &hash_p);
return 0;
}
}
}
safeFree((void **) &hash_p);
return 1;
}
void incrementalBruteforce(unsigned short length, char *toCrackHash_p, bruteforceResult_t *bruteforceResult_p,
charList_t *charList_p) {
char *prefix_p = (char *) calloc((length + 1), sizeof(char));
if (prefix_p == NULL) {
showError(NULL);
return;
}
for (unsigned short i = 1; i <= length; i++) {
bruteforceResult_p->resultSize = (i + 1) * sizeof(char);
bruteforceResult_p->result = (char *) calloc(1, bruteforceResult_p->resultSize);
if (bruteforceResult_p == NULL) {
safeFree((void **) &prefix_p);
showError(NULL);
return;
}
if (bruteforce(prefix_p, i, toCrackHash_p, bruteforceResult_p, charList_p) == 0) {
safeFree((void **) &prefix_p);
bruteforceResult_p->found = true;
return;
}
safeFree((void **) &bruteforceResult_p->result);
bruteforceResult_p->resultSize = 0;
}
safeFree((void **) &prefix_p);
}
charList_t *generateAsciiRange(unsigned short begin, unsigned short end) {
charList_t *charList_p = (charList_t *) calloc(1, sizeof(charList_t));
if (charList_p == NULL) {
showError(NULL);
return NULL;
}
charList_p->arraySize = (size_t) end - begin;
charList_p->charList = (char *) calloc(charList_p->arraySize + 1, sizeof(char));
if (charList_p->charList == NULL) {
showError(NULL);
return NULLPTR;
}
for (unsigned short i = begin; i <= end; i++) {
charList_p->charList[i - begin] = (char) i;
}
return charList_p;
}
void bruteforceWordlist(const char *toCrackHash_p, const char *wordlist_p, bruteforceResult_t *bruteforceResult_p) {
errno = 0;
if (bruteforceResult_p == NULL) {
return;
}
FILE *f = fopen(wordlist_p, "r");
if (f == NULL) {
showError(NULL);
return;
}
char *line = NULLPTR;
size_t len = 0;
ssize_t currentRead;
char *hash_p = NULLPTR;
while ((currentRead = getline(&line, &len, f)) != -1) {
line[strcspn(line, "\r\n")] = 0;
hash_p = generateMD5(line);
if (hash_p == NULL) {
showError(NULL);
fclose(f);
safeFree((void **) &line);
return;
}
if (strncmp(toCrackHash_p, hash_p, MD5_STR_SIZE * sizeof(char)) == 0) {
bruteforceResult_p->resultSize = (unsigned long) currentRead + 1 * sizeof(char);
bruteforceResult_p->result = (char *) calloc(1, bruteforceResult_p->resultSize);
if (bruteforceResult_p->result == NULL) {
showError(NULL);
freeBruteforceResult_s(bruteforceResult_p);
safeFree((void **) &line);
safeFree((void **) &hash_p);
fclose(f);
return;
}
bruteforceResult_p->found = true;
strlcpy(bruteforceResult_p->result, line, bruteforceResult_p->resultSize);
safeFree((void **) &hash_p);
safeFree((void **) &line);
fclose(f);
return;
} else {
safeFree((void **) &hash_p);
}
}
fclose(f);
safeFree((void **) &hash_p);
safeFree((void **) &line);
}

36
client/crack.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef CRACK_H
#define CRACK_H
#include <stddef.h>
#include <stdbool.h>
typedef struct CharList_s { // List of char for bruteforce step
size_t arraySize;
char *charList;
} charList_t;
typedef struct bruteforceResult_s { // store result of bruteforce
bool found;
size_t resultSize;
char *result;
} bruteforceResult_t;
int bruteforce(char *prefix, unsigned short length, char *toCrackHash, bruteforceResult_t *bruteforceResult,
charList_t *charList); // bruteforce a specific length, with a specific array of char.
void incrementalBruteforce(unsigned short length, char *toCrackHash_p, bruteforceResult_t *bruteforceResult_p,
charList_t *charList_p); // bruteforce from 0 to max length with an array of char. Take (max) length, pointer for hash to crack, bruteForceResult_s structure, charList_s structure.
charList_t *generateAsciiRange(unsigned short begin,
unsigned short end); // Generate array of char with range of ASCII character, take begin of range, end of range. Return pointer to charList_s structure.
void freeCharList_s(charList_t *s); // free charList_s, take pointer to structure
bruteforceResult_t *initBruteforceResult_s(void); // Initialise bruteforceResult_s, return pointer to structure.
void freeBruteforceResult_s(bruteforceResult_t *s); // free bruteforceResult_s, take pointer to structure.
void bruteforceWordlist(const char *toCrackHash_p, const char *wordlist_p,
bruteforceResult_t *bruteforceResult_p); // Bruteforce with wordlist, pointer for hash to crack, a bruteforceResult_s structure and a pointer for currentConfig.
#endif

136
client/main.c Normal file
View file

@ -0,0 +1,136 @@
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include "../default.h"
#include "../shared.h"
#include "config.h"
#include "crack.h"
#include "main.h"
void printHelp(void) {
printf("Options are : \n -a: IPv4 address for server\n -p: Server port\n -l: Max length\n -h: This message\n -b: Ascii generation begin (default 32)\n -e: Ascii generation end (default 127)\n -f: Log file (default stderr)\n");
}
// Manage config (argv + getopt()), contact server and start cracking.
int main(int argc, char *argv[]) {
config_t currentConfig;
errno = 0;
int setConfigReturn = setConfig(argc, argv, &currentConfig);
if (setConfigReturn != 0) {
return setConfigReturn;
}
if (currentConfig.logToFile == true) {
showError((char *) &currentConfig.logFile);
}
int clientSockD = socket(AF_INET, SOCK_STREAM, 0);
if (clientSockD == -1) {
showError(NULL);
return errno;
}
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(currentConfig.serverPort);
serverAddress.sin_addr.s_addr = currentConfig.serverIP;
if (connect(clientSockD, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) == -1) {
showError(NULL);
close(clientSockD);
return errno;
}
char *hash_p = (char *) calloc(MD5_STR_SIZE, sizeof(char));
if (hash_p == NULL) {
showError(NULL);
close(clientSockD);
return errno;
}
if (send(clientSockD, "hash", sizeof("hash"), 0) == -1) {
showError(NULL);
close(clientSockD);
safeFree((void **) &hash_p);
return errno;
}
if (recv(clientSockD, hash_p, MD5_STR_SIZE * sizeof(char), 0) == -1) {
showError(NULL);
close(clientSockD);
safeFree((void **) &hash_p);
return errno;
}
printf("Hash : %s\n", hash_p);
bruteforceResult_t *bruteforceResult_p = initBruteforceResult_s();
if (bruteforceResult_p == NULLPTR) {
close(clientSockD);
safeFree((void **) &hash_p);
return errno;
}
if (currentConfig.wordlist == true) {
bruteforceWordlist(hash_p, currentConfig.wordlistPath, bruteforceResult_p);
} else {
charList_t *charList = generateAsciiRange(currentConfig.AsciiBegin, currentConfig.AsciiEnd);
if (charList == NULL) {
freeBruteforceResult_s(bruteforceResult_p);
close(clientSockD);
safeFree((void **) &hash_p);
return EXIT_FAILURE;
}
bruteforceResult_p->resultSize = (currentConfig.maxLength + 1) * sizeof(char);
bruteforceResult_p->result = NULLPTR;
incrementalBruteforce(currentConfig.maxLength, hash_p, bruteforceResult_p, charList);
freeCharList_s(charList);
}
if (bruteforceResult_p->found == true) {
printf("Answer : %s - %s\n", hash_p, bruteforceResult_p->result);
if (send(clientSockD, "found", sizeof("found"), 0) == -1) {
showError(NULL);
close(clientSockD);
safeFree((void **) &hash_p);
freeBruteforceResult_s(bruteforceResult_p);
return errno;
}
sleep(1);
if (send(clientSockD, bruteforceResult_p->result, bruteforceResult_p->resultSize, 0) == -1) {
showError(NULL);
close(clientSockD);
safeFree((void **) &hash_p);
freeBruteforceResult_s(bruteforceResult_p);
return errno;
}
} else {
if (send(clientSockD, "notfound", sizeof("notfound"), 0) == -1) {
showError(NULL);
close(clientSockD);
safeFree((void **) &hash_p);
freeBruteforceResult_s(bruteforceResult_p);
return errno;
}
printf("Response not found.\n");
}
close(clientSockD);
freeBruteforceResult_s(bruteforceResult_p);
safeFree((void **) &hash_p);
return EXIT_SUCCESS;
}

6
client/main.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef MAIN_H
#define MAIN_H
void printHelp(void); // Print help message
#endif

3
default.h Normal file
View file

@ -0,0 +1,3 @@
#define MIN_PORT 0
#define MAX_PORT 65535
#define MD5_STR_SIZE 33 // 32+1

76
server/config.c Normal file
View file

@ -0,0 +1,76 @@
#include <stdio.h>
#include <bsd/string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <getopt.h>
#include <string.h>
#include <stdlib.h>
#include <sysexits.h>
#include "../default.h"
#include "../shared.h"
#include "main.h"
#include "config.h"
int setConfig(int argc, char *argv[], config_t *currentConfig_p) {
// Set config
// - currentConfig_p : Actual config
// return : 0 if success, else if error
int numberOptions;
while ((numberOptions = getopt(argc, argv, "a:p:s:f:h")) != -1) {
currentConfig_p->logToFile = false;
switch (numberOptions) {
case 'f':
if (strncmp(optarg, "", 4096) == 0) { // Max size based on POSIX spec
break;
}
currentConfig_p->logToFile = true;
strlcpy(currentConfig_p->logFile, optarg, 4096);
break;
case 'a':
currentConfig_p->serverIP = inet_addr(optarg);
break;
case 'p':
errno = 0;
if (strtol(optarg, NULL, 10) > MIN_PORT && strtol(optarg, NULL, 10) <= MAX_PORT) {
currentConfig_p->serverPort = (unsigned short) strtol(optarg, NULL, 10);
} else {
fprintf(stderr, "Port invalide.\n");
printHelp();
return EX_CONFIG;
}
if (errno == ERANGE) {
showError(NULL);
printHelp();
return EX_CONFIG;
}
break;
case 's':
errno = 0;
strlcpy(currentConfig_p->hash, optarg, MD5_STR_SIZE * sizeof(char));
if (errno == ERANGE) {
showError(NULL);
printHelp();
return EX_CONFIG;
}
break;
case 'h':
printHelp();
exit(EXIT_SUCCESS);
default:
printHelp();
return EX_CONFIG;
}
}
// Verify mandatory options.
if (currentConfig_p->serverPort == 0) {
fprintf(stderr, "Port invalide ou manquant.\n");
printHelp();
return EX_CONFIG;
}
return 0;
}

20
server/config.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <stdbool.h>
#include <stdint.h>
#include <linux/limits.h>
#include "../default.h"
typedef struct config_s {
uint32_t serverIP;
char hash[MD5_STR_SIZE];
unsigned short serverPort;
bool logToFile; // bool for check if log to file is enabled
char logFile[PATH_MAX]; // Path for logfile
} config_t;
int setConfig(int argc, char *argv[], config_t *currentConfig_p);
#endif

102
server/main.c Normal file
View file

@ -0,0 +1,102 @@
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <errno.h>
#include "../default.h"
#include "../shared.h"
#include "config.h"
#include "main.h"
void printHelp(void) {
printf("Options are : \n -a: IPv4 address for socket\n -p: Port to listen\n -s: Hash to crack\n -h: This message\n");
}
int main(int argc, char *argv[]) {
config_t currentConfig; // Global config structure
int setConfigReturn = setConfig(argc, argv, &currentConfig);
if (setConfigReturn != 0) {
return setConfigReturn;
}
if (currentConfig.logToFile == true) {
showError((char *) &currentConfig.logFile);
}
int serverSockD = socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
if ((setsockopt(serverSockD, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) == -1) {
showError(NULL);
close(serverSockD);
return errno;
}
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(currentConfig.serverPort);
serverAddress.sin_addr.s_addr = currentConfig.serverIP;
if (bind(serverSockD, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) == -1) {
showError(NULL);
close(serverSockD);
return errno;
}
if (listen(serverSockD, 1) == -1) {
showError(NULL);
close(serverSockD);
return errno;
}
int clientSockD = accept(serverSockD, NULL, NULL);
if (clientSockD == -1) {
showError(NULL);
close(serverSockD);
return errno;
}
char clientResponseBuffer[8192];
for (;;) {
ssize_t recvResult;
recvResult = recv(clientSockD, clientResponseBuffer, sizeof(clientResponseBuffer) - 1, 0);
if (recvResult == -1) {
showError(NULL);
close(clientSockD);
close(serverSockD);
return errno;
}
clientResponseBuffer[recvResult] = 0;
if (strncmp(clientResponseBuffer, "hash", sizeof(clientResponseBuffer)) == 0) {
if (send(clientSockD, (char *) &currentConfig.hash, sizeof(currentConfig.hash) - 1, 0) == -1) {
showError(NULL);
close(clientSockD);
close(serverSockD);
return errno;
}
} else if (strncmp(clientResponseBuffer, "found", sizeof(clientResponseBuffer)) == 0) {
recvResult = recv(clientSockD, clientResponseBuffer, sizeof(clientResponseBuffer) - 1, 0);
if (recvResult == -1) {
showError(NULL);
close(serverSockD);
close(clientSockD);
return errno;
}
clientResponseBuffer[recvResult] = 0;
printf("Response is : %s - %s\n", currentConfig.hash, clientResponseBuffer);
break;
} else if (strncmp(clientResponseBuffer, "notfound", sizeof(clientResponseBuffer)) == 0) {
printf("Response not found.\n");
break;
}
}
close(serverSockD);
close(clientSockD);
return 0;
}

6
server/main.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef MAIN_H
#define MAIN_H
void printHelp(void);
#endif

35
shared.c Normal file
View file

@ -0,0 +1,35 @@
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <linux/limits.h>
#include "shared.h"
void safeFree(void **toFree) {
if (*toFree != NULL || *toFree != NULLPTR) {
free(*toFree);
*toFree = NULLPTR;
}
}
void showError(const char *logFilePath_p) {
static char staticLogFilePath[PATH_MAX];
if (logFilePath_p != NULL) {
strlcpy(staticLogFilePath, logFilePath_p, PATH_MAX);
return;
}
if (staticLogFilePath[0] != 0) {
FILE *f = fopen(staticLogFilePath, "a");
if (f == NULL) {
fprintf(stderr, "Impossible d'ouvrir le fichier de log. :\n%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(f, "%s\n", strerror(errno));
fclose(f);
return;
}
fprintf(stderr, "%s\n", strerror(errno));
}

12
shared.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef SHARED_H
#define SHARED_H
#define NULLPTR ((void*)0) // Point to 0x0, better than just NULL (0)
#include <stdbool.h>
void safeFree(void **toFree);
void showError(const char *logFilePath_p); // Show error, based on errno. Initialise it with logToFile et logFilePath.
#endif