Skip to content

Commit

Permalink
Output log format are now customizable (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
matricali committed Apr 1, 2024
1 parent 72f016a commit 1013e53
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Hostname can be used as a username or password dynamically ($TARGET) (#28)
- Output log format are now customizable (#30)

### Fixed
- Added missing wrapper for FD_SET in static build
Expand Down
44 changes: 40 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Penetration tests on SSH servers using dictionary attacks. Written in _C_.
> _brute krag_ means "brute force" in afrikáans
## Disclaimer
>This tool is for ethical testing purpose only.
>cbrutekrag and its owners can't be held responsible for misuse by users.
>This tool is for ethical testing purpose only.
>cbrutekrag and its owners can't be held responsible for misuse by users.
>Users have to act as permitted by local law rules.
## Requirements
Expand Down Expand Up @@ -59,8 +59,8 @@ $ cbrutekrag -h
(c) Copyright 2014-2022 Jorge Matricali |___/
usage: ./cbrutekrag [-h] [-v] [-aA] [-D] [-P] [-T TARGETS.lst] [-C combinations.lst]
[-t THREADS] [-o OUTPUT.txt] [TARGETS...]
usage: ./cbrutekrag [-h] [-v] [-aA] [-D] [-P] [-T TARGETS.lst] [-C credentials.lst]
[-t THREADS] [-F OUTPUT FORMAT] [-o OUTPUT.txt] [TARGETS...]
-h This help
-v Verbose mode
Expand All @@ -72,6 +72,10 @@ usage: ./cbrutekrag [-h] [-v] [-aA] [-D] [-P] [-T TARGETS.lst] [-C combinations.
-C <combinations> Username and password file
-t <threads> Max threads
-o <output> Output log file
-F <format> Output log format
Available placeholders:
%DATETIME%, %HOSTNAME%
%PORT%, %USERNAME%, %PASSWORD%
-a Accepts non OpenSSH servers
-A Allow servers detected as honeypots.
```
Expand Down Expand Up @@ -104,3 +108,35 @@ root $TARGET
|------------|------|-----------|------------|
|$BLANKPASS|Blank password|✔️|-|
|$TARGET|Use hostname or IP as a password|✔️|✔️|
### Customizable output format
Output format can be easily customizable using the command line option `-F`
Example: `./cbrutekrag -F "%HOSTNAME%:%PORT%|%USERNAME%|%PASSWORD%\n"`, which
produces an output like:
```
192.168.0.100:22|root|toor
192.168.0.105:22|ubnt|ubnt
```
#### Default value
`%DATETIME%\t%HOSTNAME%:%PORT%\t%USERNAME%\t%PASSWORD%\n`
```
2024/04/01 13:05:13 192.168.0.100:22 root admin
```
#### Placeholders
|Placeholder|Description |Example |
|-----------|----------------------------------|-------------------|
|%DATETIME% |Replaced by `Y/m/d HH:ii:ss` date |2024/04/01 12:46:27|
|%HOSTNAME% |Replaced by hostname or IPv4 |192.168.0.100 |
|%PORT% |Replaced by connection port |22 |
|%USERNAME% |Replaced by username used |root |
|%PASSWORD% |Replaced by password used |admin |
|\n |Replaced by LF | |
|\t |Replaced by TAB | |
3 changes: 3 additions & 0 deletions include/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,7 @@ void print_output(int level, const char *file, int line, const char *head,

void log_output(FILE *stream, const char *format, ...);

void btkg_log_successfull_login(FILE *stream, const char *hostname, int port,
const char *username, const char *password);

#endif /* LOGGER_H */
4 changes: 4 additions & 0 deletions include/str.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@ SOFTWARE.

char **str_split(char *a_str, const char a_delim);
const char *str_repeat(char *str, size_t times);
char *str_replace(char *orig, char *rep, char *with);
char *btkg_str_replace_placeholder(char *input, const char *search,
const char *replace);
void btkg_str_replace_escape_sequences(char *str);

#endif /* STR_H */
4 changes: 2 additions & 2 deletions src/bruteforce_ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ int bruteforce_ssh_try_login(btkg_context_t *context, const char *hostname,
log_info("\033[32m[+]\033[0m %s:%d %s %s", hostname, port,
_username, _password);
if (output != NULL) {
log_output(output, "\t%s:%d\t%s\t%s\n", hostname, port,
_username, _password);
btkg_log_successfull_login(output, hostname, port,
_username, _password);
}
} else {
log_debug("\033[38m[-]\033[0m %s:%d %s %s", hostname, port,
Expand Down
20 changes: 18 additions & 2 deletions src/cbrutekrag.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ SOFTWARE.
#define NANO_PER_SEC 1000000000.0

int g_verbose = 0;
char *g_output_format = NULL;

void print_banner()
{
Expand All @@ -60,7 +61,7 @@ void print_banner()
void usage(const char *p)
{
printf("\nusage: %s [-h] [-v] [-aA] [-D] [-P] [-T TARGETS.lst] [-C credentials.lst]\n"
"\t\t[-t THREADS] [-o OUTPUT.txt] [TARGETS...]\n\n",
"\t\t[-t THREADS] [-F OUTPUT FORMAT] [-o OUTPUT.txt] [TARGETS...]\n\n",
p);
}

Expand Down Expand Up @@ -105,7 +106,7 @@ int main(int argc, char **argv)
context.max_threads =
(limit.rlim_cur > 1024) ? 1024 : limit.rlim_cur - 8;

while ((opt = getopt(argc, argv, "aAT:C:t:o:DsvVPh")) != -1) {
while ((opt = getopt(argc, argv, "aAT:C:t:o:F:DsvVPh")) != -1) {
switch (opt) {
case 'a':
context.non_openssh = 1;
Expand Down Expand Up @@ -135,6 +136,11 @@ int main(int argc, char **argv)
}
context.max_threads = (size_t)tempint;
break;
case 'F':
g_output_format = strdup(optarg);
btkg_str_replace_escape_sequences(
g_output_format);
break;
case 'o':
output_filename = strdup(optarg);
break;
Expand All @@ -160,6 +166,10 @@ int main(int argc, char **argv)
" -C <credentials> Username and password file\n"
" -t <threads> Max threads\n"
" -o <output> Output log file\n"
" -F <format> Output log format\n"
" Available placeholders:\n"
" %%DATETIME%%, %%HOSTNAME%%\n"
" %%PORT%%, %%USERNAME%%, %%PASSWORD%%\n"
" -a Accepts non OpenSSH servers\n"
" -A Allow servers detected as honeypots.\n");
exit(EXIT_SUCCESS);
Expand Down Expand Up @@ -225,6 +235,12 @@ int main(int argc, char **argv)
context.max_threads = target_list.length;
}

/* Output Format */
if (g_output_format == NULL) {
g_output_format = strdup(
"%DATETIME%\t%HOSTNAME%:%PORT%\t%USERNAME%\t%PASSWORD%\n");
}

/* Output file */
if (output_filename != NULL) {
output = fopen(output_filename, "a");
Expand Down
35 changes: 35 additions & 0 deletions src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ SOFTWARE.

#include <stdarg.h> /* va_list, va_start, va_end */
#include <stdio.h> /* fprintf, vfprintf, stderr */
#include <string.h> /* strlen, malloc, strncpy */
#include <time.h> /* time_t, time, tm, localtime, strftime */

#include "cbrutekrag.h" /* CBRUTEKRAG_VERBOSE_MODE */
#include "log.h"
#include "str.h" /* replace_placeholder */

extern int g_verbose;
extern char *g_output_format;

void print_output(int level, const char *file, int line, const char *head,
const char *tail, FILE *stream, const char *format, ...)
Expand Down Expand Up @@ -72,3 +75,35 @@ void log_output(FILE *stream, const char *format, ...)
va_end(arg);
fflush(stream);
}

void btkg_log_successfull_login(FILE *stream, const char *hostname, int port,
const char *username, const char *password)
{
int port_len = snprintf(NULL, 0, "%d", port);
char strport[port_len];

sprintf(strport, "%d", port);

// Allocation
size_t output_len = sizeof(char) * (strlen(g_output_format) + 1);
char *output = malloc(output_len);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
strncpy(output, g_output_format, output_len);
#pragma GCC diagnostic pop
// Timestamp
time_t t = time(NULL);
struct tm *tm = localtime(&t);
char s[20];

s[strftime(s, sizeof(s), "%Y/%m/%d %H:%M:%S", tm)] = '\0';

output = btkg_str_replace_placeholder(output, "%DATETIME%", s);
output = btkg_str_replace_placeholder(output, "%HOSTNAME%", hostname);
output = btkg_str_replace_placeholder(output, "%USERNAME%", username);
output = btkg_str_replace_placeholder(output, "%PASSWORD%", password);
output = btkg_str_replace_placeholder(output, "%PORT%", strport);

fprintf(stream, "%s", output);
free(output);
}
89 changes: 89 additions & 0 deletions src/str.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ char **str_split(char *a_str, const char a_delim)
return result;
}

// You must free the result if result is non-NULL.
const char *str_repeat(char *str, size_t times)
{
if (times < 1)
Expand All @@ -84,3 +85,91 @@ const char *str_repeat(char *str, size_t times)
}
return ret;
}

// You must free the result if result is non-NULL.
char *str_replace(char *orig, char *rep, char *with)
{
char *result;
char *ins;
char *tmp;
size_t len_rep;
size_t len_with;
size_t len_front;
size_t count;

// sanity checks and initialization
if (!orig || !rep)
return NULL;
len_rep = strlen(rep);
if (len_rep == 0)
return NULL; // empty rep causes infinite loop during count
if (!with)
with = "";
len_with = strlen(with);

// count the number of replacements needed
ins = orig;
for (count = 0; (tmp = strstr(ins, rep)); ++count) {
ins = tmp + len_rep;
}

tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);

if (!result)
return NULL;

// first time through the loop, all the variable are set correctly
// from here on,
// tmp points to the end of the result string
// ins points to the next occurrence of rep in orig
// orig points to the remainder of orig after "end of rep"
while (count--) {
ins = strstr(orig, rep);
len_front = (size_t)(ins - orig);
tmp = strncpy(tmp, orig, len_front) + len_front;
tmp = strcpy(tmp, with) + len_with;
orig += len_front + len_rep; // move to next "end of rep"
}
strcpy(tmp, orig);
return result;
}

char *btkg_str_replace_placeholder(char *input, const char *search,
const char *replace)
{
char *tmp = NULL;
tmp = str_replace(input, (char *)search, (char *)replace);
if (tmp) {
if (input)
free(input);
return tmp;
}
return input;
}

void btkg_str_replace_escape_sequences(char *str)
{
char *read = str;
char *write = str;
while (*read) {
if (*read == '\\' && *(read + 1)) {
read++;
switch (*read) {
case 'n':
*write++ = '\n';
break;
case 't':
*write++ = '\t';
break;
// --
default:
*write++ = '\\';
*write++ = *read;
}
} else {
*write++ = *read;
}
read++;
}
*write = '\0';
}

0 comments on commit 1013e53

Please sign in to comment.