driver_console_t *driver_console_create(select_group_t *group) /*, char *name, char *download, int first_chunk)*/ { driver_console_t *driver = (driver_console_t*) safe_malloc(sizeof(driver_console_t)); driver->group = group; driver->is_shutdown = FALSE; driver->outgoing_data = buffer_create(BO_LITTLE_ENDIAN); #ifdef WIN32 /* On Windows, the stdin_handle is quite complicated, and involves a sub-thread. */ HANDLE stdin_handle = get_stdin_handle(); select_group_add_pipe(group, -1, stdin_handle, driver); select_set_recv(group, -1, console_stdin_recv); select_set_closed(group, -1, console_stdin_closed); #else /* On Linux, the stdin_handle is easy. */ int stdin_handle = STDIN_FILENO; select_group_add_socket(group, stdin_handle, SOCKET_TYPE_STREAM, driver); select_set_recv(group, stdin_handle, console_stdin_recv); select_set_closed(group, stdin_handle, console_stdin_closed); #endif return driver; }
driver_console_t *driver_console_create(select_group_t *group, char *name, char *download, int first_chunk) { driver_console_t *driver = (driver_console_t*) safe_malloc(sizeof(driver_console_t)); message_options_t options[4]; #ifdef WIN32 /* On Windows, the stdin_handle is quite complicated, and involves a sub-thread. */ HANDLE stdin_handle = get_stdin_handle(); select_group_add_pipe(group, -1, stdin_handle, driver); select_set_recv(group, -1, console_stdin_recv); select_set_closed(group, -1, console_stdin_closed); #else /* On Linux, the stdin_handle is easy. */ int stdin_handle = STDIN_FILENO; select_group_add_socket(group, stdin_handle, SOCKET_TYPE_STREAM, driver); select_set_recv(group, stdin_handle, console_stdin_recv); select_set_closed(group, stdin_handle, console_stdin_closed); #endif driver->name = name ? name : "[unnamed console]"; driver->download = download; driver->first_chunk = first_chunk; /* Subscribe to the messages we care about. */ message_subscribe(MESSAGE_DATA_IN, handle_message, driver); options[0].name = "name"; options[0].value.s = driver->name; if(driver->download) { options[1].name = "download"; options[1].value.s = driver->download; options[2].name = "first_chunk"; options[2].value.i = driver->first_chunk; } else { options[1].name = NULL; } options[3].name = NULL; driver->session_id = message_post_create_session(options); return driver; }
static SELECT_RESPONSE_t listener_accept(void *group, int s, void *d) { driver_listener_t *driver = (driver_listener_t*) d; message_options_t options[2]; client_entry_t *client = safe_malloc(sizeof(client_entry_t)); client->s = tcp_accept(s, &client->address, &client->port); options[0].name = "name"; if(driver->name) options[0].value.s = driver->name; else options[0].value.s = "[unnamed listener]"; options[1].name = NULL; client->session_id = message_post_create_session(options); client->driver = driver; client->next = first_client; first_client = client; LOG_WARNING("Received a connection from %s:%d (created session %d)", client->address, client->port, client->session_id); select_group_add_socket(group, client->s, SOCKET_TYPE_STREAM, client); select_set_recv(group, client->s, client_recv); select_set_closed(group, client->s, client_closed); return SELECT_OK; }
driver_dns_t *driver_dns_create(select_group_t *group, char *domain, dns_type_t type) { driver_dns_t *driver_dns = (driver_dns_t*) safe_malloc(sizeof(driver_dns_t)); /* Create the actual DNS socket. */ LOG_INFO("Creating UDP (DNS) socket"); driver_dns->s = udp_create_socket(0, "0.0.0.0"); if(driver_dns->s == -1) { LOG_FATAL("Couldn't create UDP socket!"); exit(1); } /* Set the domain and stuff. */ driver_dns->domain = domain; driver_dns->type = type; /* If it succeeds, add it to the select_group */ select_group_add_socket(group, driver_dns->s, SOCKET_TYPE_STREAM, driver_dns); select_set_recv(group, driver_dns->s, recv_socket_callback); select_set_closed(group, driver_dns->s, dns_data_closed); /* Subscribe to the messages we care about. */ message_subscribe(MESSAGE_PACKET_OUT, handle_message, driver_dns); /* TODO: Do I still need this? */ message_post_config_int("max_packet_length", MAX_DNSCAT_LENGTH(driver_dns->domain)); return driver_dns; }
void sessions_attach_stdin(sessions_t *sessions) { #ifdef WIN32 /* On Windows, the stdin_handle is quire complicated, and involves a sub-thread. */ HANDLE stdin_handle = get_stdin_handle(); select_group_add_pipe(sessions->select_group, -1, stdin_handle, sessions); select_set_recv(sessions->select_group, -1, stdin_callback); select_set_closed(sessions->select_group, -1, stdin_closed_callback); #else /* On Linux, the stdin_handle is easy. */ int stdin_handle = STDIN_FILENO; select_group_add_socket(sessions->select_group, stdin_handle, SOCKET_TYPE_STREAM, sessions); select_set_recv(sessions->select_group, stdin_handle, stdin_callback); select_set_closed(sessions->select_group, stdin_handle, stdin_closed_callback); #endif }
SELECT_RESPONSE_t listener(void *group, int s, struct sockaddr_in addr, void *param) { int new_socket = tcp_accept(s, NULL); select_group_add_socket((select_group_t*)group, new_socket, SOCKET_TYPE_STREAM, NULL); select_set_recv((select_group_t*)group, new_socket, incoming); select_set_timeout((select_group_t*)group, new_socket, timeout); select_group_wait_for_bytes((select_group_t*)group, new_socket, 4); return SELECT_CLOSE_REMOVE; }
static void nb_poll(settings_t *settings) { settings->group = select_group_create(); select_group_add_socket(settings->group, settings->socket, SOCKET_TYPE_DATAGRAM, settings); select_set_recv(settings->group, settings->socket, nb_recv_callback); select_set_timeout(settings->group, settings->socket, nb_timeout); while(1) select_group_do_select(settings->group, settings->wait); select_group_destroy(settings->group); }
void tcpcat_send(uint8_t *data, size_t length, void *d) { options_t *options = (options_t*) d; buffer_t *buffer; uint8_t *encoded_data; size_t encoded_length; if(options->s == -1) { /* Attempt a TCP connection */ LOG_INFO("Connecting to %s:%d", options->host, options->port); options->s = tcp_connect(options->host, options->port); /* If it fails, just return (it will try again next send) */ if(options->s == -1) { LOG_FATAL("Connection failed!"); exit(1); } /* If it succeeds, add it to the select_group */ select_group_add_socket(options->group, options->s, SOCKET_TYPE_STREAM, options); select_set_recv(options->group, options->s, recv_callback); select_set_closed(options->group, options->s, closed_callback); } assert(options->s != -1); /* Make sure we have a valid socket. */ assert(data); /* Make sure they aren't trying to send NULL. */ assert(length > 0); /* Make sure they aren't trying to send 0 bytes. */ buffer = buffer_create(BO_BIG_ENDIAN); buffer_add_int16(buffer, length); buffer_add_bytes(buffer, data, length); encoded_data = buffer_create_string_and_destroy(buffer, &encoded_length); if(tcp_send(options->s, encoded_data, encoded_length) == -1) { LOG_ERROR("[[TCP]] send error, closing socket!"); tcpcat_close(options); } }
driver_exec_t *driver_exec_create(select_group_t *group, char *process, char *name) { driver_exec_t *driver_exec = (driver_exec_t*) safe_malloc(sizeof(driver_exec_t)); message_options_t options[2]; /* Declare some WIN32 variables needed for starting the sub-process. */ #ifdef WIN32 STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation; SECURITY_ATTRIBUTES sa; #endif driver_exec->process = process; driver_exec->group = group; driver_exec->name = name ? name : process; /* Subscribe to the messages we care about. */ message_subscribe(MESSAGE_DATA_IN, handle_message, driver_exec); /* Set up the session options and create the session. */ options[0].name = "name"; options[0].value.s = driver_exec->name; options[1].name = NULL; driver_exec->session_id = message_post_create_session(options); #ifdef WIN32 /* Create a security attributes structure. This is required to inherit handles. */ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the anonymous pipes. */ if(!CreatePipe(&driver_exec->exec_stdin[PIPE_READ], &driver_exec->exec_stdin[PIPE_WRITE], &sa, 0)) DIE("exec: Couldn't create pipe for stdin"); if(!CreatePipe(&driver_exec->exec_stdout[PIPE_READ], &driver_exec->exec_stdout[PIPE_WRITE], &sa, 0)) DIE("exec: Couldn't create pipe for stdout"); fprintf(stderr, "Attempting to load the program: %s\n", driver_exec->process); /* Initialize the STARTUPINFO structure. */ ZeroMemory(&startupInfo, sizeof(STARTUPINFO)); startupInfo.cb = sizeof(STARTUPINFO); startupInfo.dwFlags = STARTF_USESTDHANDLES; startupInfo.hStdInput = driver_exec->exec_stdin[PIPE_READ]; startupInfo.hStdOutput = driver_exec->exec_stdout[PIPE_WRITE]; startupInfo.hStdError = driver_exec->exec_stdout[PIPE_WRITE]; /* Initialize the PROCESS_INFORMATION structure. */ ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION)); /* Create the actual process with an overly-complicated CreateProcess function. */ if(!CreateProcessA(NULL, driver_exec->process, 0, &sa, TRUE, CREATE_NO_WINDOW, 0, NULL, &startupInfo, &processInformation)) { fprintf(stderr, "Failed to create the process"); exit(1); } /* Save the process id and the handle. */ driver_exec->pid = processInformation.dwProcessId; driver_exec->exec_handle = processInformation.hProcess; /* Close the duplicate pipes we created -- this lets us detect the proicess termination. */ CloseHandle(driver_exec->exec_stdin[PIPE_READ]); CloseHandle(driver_exec->exec_stdout[PIPE_WRITE]); CloseHandle(driver_exec->exec_stdout[PIPE_WRITE]); fprintf(stderr, "Successfully created the process!\n\n"); /* Create a socket_id value - this is a totally arbitrary value that's only used so we can find this entry later. */ driver_exec->socket_id = --driver_exec->socket_id; /* On Windows, add the sub-process's stdout as a pipe. */ select_group_add_pipe(driver_exec->group, driver_exec->socket_id, driver_exec->exec_stdout[PIPE_READ], driver_exec); select_set_recv(driver_exec->group, driver_exec->socket_id, exec_callback); select_set_closed(driver_exec->group, driver_exec->socket_id, exec_closed_callback); #else LOG_INFO("Attempting to start process '%s'...", driver_exec->process); /* Create communication channels. */ if(pipe(driver_exec->pipe_stdin) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } if(pipe(driver_exec->pipe_stdout) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } driver_exec->pid = fork(); if(driver_exec->pid == -1) { LOG_FATAL("exec: couldn't create process (%d)", errno); exit(1); } /* If we're in the child process... */ if(driver_exec->pid == 0) { /* Copy the pipes. */ if(dup2(driver_exec->pipe_stdin[PIPE_READ], STDIN_FILENO) == -1) nbdie("exec: couldn't duplicate STDIN handle"); if(dup2(driver_exec->pipe_stdout[PIPE_WRITE], STDOUT_FILENO) == -1) nbdie("exec: couldn't duplicate STDOUT handle"); if(dup2(driver_exec->pipe_stdout[PIPE_WRITE], STDERR_FILENO) == -1) nbdie("exec: couldn't duplicate STDERR handle"); /* Execute the new process. */ execlp("/bin/sh", "sh", "-c", driver_exec->process, (char*) NULL); /* If execlp returns, bad stuff happened. */ LOG_FATAL("exec: execlp failed (%d)", errno); exit(1); } LOG_WARNING("Started: %s (pid: %d)", driver_exec->process, driver_exec->pid); close(driver_exec->pipe_stdin[PIPE_READ]); close(driver_exec->pipe_stdout[PIPE_WRITE]); /* Add the sub-process's stdout as a socket. */ select_group_add_socket(driver_exec->group, driver_exec->pipe_stdout[PIPE_READ], SOCKET_TYPE_STREAM, driver_exec); select_set_recv(driver_exec->group, driver_exec->pipe_stdout[PIPE_READ], exec_callback); select_set_closed(driver_exec->group, driver_exec->pipe_stdout[PIPE_READ], exec_closed_callback); #endif return driver_exec; }
/* This is called after the drivers are created, to kick things off. */ static void handle_start(driver_exec_t *driver) { message_post_create_session(); /* Create the exec socket */ #ifdef WIN32 /* TODO */ #else LOG_INFO("Attempting to start process '%s'...", driver->process); /* Create communication channels. */ if(pipe(driver->pipe_stdin) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } if(pipe(driver->pipe_stdout) == -1) { LOG_FATAL("exec: couldn't create pipe (%d)", errno); exit(1); } driver->pid = fork(); if(driver->pid == -1) { LOG_FATAL("exec: couldn't create process (%d)", errno); exit(1); } /* If we're in the child process... */ if(driver->pid == 0) { /* Copy the pipes. */ if(dup2(driver->pipe_stdin[PIPE_READ], STDIN_FILENO) == -1) nbdie("exec: couldn't duplicate STDIN handle"); if(dup2(driver->pipe_stdout[PIPE_WRITE], STDOUT_FILENO) == -1) nbdie("exec: couldn't duplicate STDOUT handle"); if(dup2(driver->pipe_stdout[PIPE_WRITE], STDERR_FILENO) == -1) nbdie("exec: couldn't duplicate STDERR handle"); /* Execute the new process. */ execlp("/bin/sh", "sh", "-c", driver->process, (char*) NULL); /* If execlp returns, bad stuff happened. */ LOG_FATAL("exec: execlp failed (%d)", errno); exit(1); } LOG_WARNING("Started: %s (pid: %d)", driver->process, driver->pid); close(driver->pipe_stdin[PIPE_READ]); close(driver->pipe_stdout[PIPE_WRITE]); /* Add the sub-process's stdout as a socket. */ select_group_add_socket(driver->group, driver->pipe_stdout[PIPE_READ], SOCKET_TYPE_STREAM, driver); select_set_recv(driver->group, driver->pipe_stdout[PIPE_READ], exec_callback); select_set_closed(driver->group, driver->pipe_stdout[PIPE_READ], exec_closed_callback); #endif }
static NBBOOL session_attach_process(sessions_t *sessions, session_t *session, char *process) { #ifdef WIN32 STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation; SECURITY_ATTRIBUTES sa; session_group_t *session_group = (session_group_t*) safe_malloc(sizeof(session_group_t)); session_group->session = session; session_group->sessions = sessions; /* Create a security attributes structure. This is required to inherit handles. */ ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES)); sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; /* Create the anonymous pipes. */ if(!CreatePipe(&session->exec_stdin[PIPE_READ], &session->exec_stdin[PIPE_WRITE], &sa, 0)) nbdie("exec: Couldn't create pipe for stdin"); if(!CreatePipe(&session->exec_stdout[PIPE_READ], &session->exec_stdout[PIPE_WRITE], &sa, 0)) nbdie("exec: Couldn't create pipe for stdout"); fprintf(stderr, "Attempting to load the program: %s\n", process); /* Initialize the STARTUPINFO structure. */ ZeroMemory(&startupInfo, sizeof(STARTUPINFO)); startupInfo.cb = sizeof(STARTUPINFO); startupInfo.dwFlags = STARTF_USESTDHANDLES; startupInfo.hStdInput = session->exec_stdin[PIPE_READ]; startupInfo.hStdOutput = session->exec_stdout[PIPE_WRITE]; if(!sessions->exec_no_stderr) startupInfo.hStdError = session->exec_stdout[PIPE_WRITE]; /* Initialize the PROCESS_INFORMATION structure. */ ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION)); /* Create the actual process with an overly-complicated CreateProcess function. */ if(!CreateProcessA(NULL, process, 0, &sa, TRUE, CREATE_NO_WINDOW, 0, NULL, &startupInfo, &processInformation)) { fprintf(stderr, "Failed to create the process"); exit(1); } /* Save the process id and the handle. */ session->pid = processInformation.dwProcessId; session->exec_handle = processInformation.hProcess; session->socket_id = --sessions->current_socket_id; /* Close the duplicate pipes we created -- this lets us detect the proicess termination. */ CloseHandle(session->exec_stdin[PIPE_READ]); CloseHandle(session->exec_stdout[PIPE_WRITE]); if(!sessions->exec_no_stderr) CloseHandle(session->exec_stdout[PIPE_WRITE]); fprintf(stderr, "Successfully created the process!\n\n"); /* On Windows, add the sub-process's stdout as a pipe. */ select_group_add_pipe(sessions->select_group, session->socket_id, session->exec_stdout[PIPE_READ], session_group); select_set_recv(sessions->select_group, session->socket_id, exec_callback); select_set_closed(sessions->select_group, session->socket_id, exec_closed_callback); #else session_group_t *session_group = (session_group_t*) safe_malloc(sizeof(session_group_t)); session_group->session = session; session_group->sessions = sessions; fprintf(stderr, "Attempting to start process '%s' for session %s\n", process, session->name); /* Create communication channels. */ if(pipe(session->exec_stdin) == -1) nbdie("exec: couldn't create pipe for STDIN"); if(pipe(session->exec_stdout) == -1) nbdie("exec: couldn't create pipe for STDOUT"); session->pid = fork(); if(session->pid == -1) nbdie("exec: couldn't create process"); if(session->pid == 0) { /* Copy the pipes. */ if(dup2(session->exec_stdin[PIPE_READ], STDIN_FILENO) == -1) nbdie("exec: couldn't duplicate STDIN handle"); if(dup2(session->exec_stdout[PIPE_WRITE], STDOUT_FILENO) == -1) nbdie("exec: couldn't duplicate STDOUT handle"); if(sessions->exec_no_stderr) { session->exec_stdout[PIPE_WRITE] = 0; } else { if(dup2(session->exec_stdout[PIPE_WRITE], STDERR_FILENO) == -1) nbdie("exec: couldn't duplicate STDERR handle"); } /* Execute the new process. */ execlp("/bin/sh", "sh", "-c", process, (char*) NULL); /* If execlp returns, bad stuff happened. */ fprintf(stderr, "exec: execlp failed"); return FALSE; } fprintf(stderr, "Started: %s (pid: %d)\n", process, session->pid); close(session->exec_stdin[PIPE_READ]); close(session->exec_stdout[PIPE_WRITE]); /* On Linux, add the sub-process's stdout as a socket. */ select_group_add_socket(sessions->select_group, session->exec_stdout[PIPE_READ], SOCKET_TYPE_STREAM, session_group); select_set_recv(sessions->select_group, session->exec_stdout[PIPE_READ], exec_callback); select_set_closed(sessions->select_group, session->exec_stdout[PIPE_READ], exec_closed_callback); #endif return TRUE; }