Search code examples
csegmentation-faultport-scanning

Segmentation Fault is given, why? (C)


I've been studying C for a about 2 weeks now and decided to try my hand at a simple port scanner. I can compile the code with no errors but whenever I try to execute it I get a segmentation fault.

#include<stdio.h>
#include<sys/socket.h>
#include<errno.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>

int scanPort(char hostaddr[], int port) {
    struct hostent *host;
    int err, i, sock;
    struct sockaddr_in sa;

    strncpy((char*)&sa , "" , sizeof sa);
    sa.sin_family = AF_INET;

    if (isdigit(hostaddr[0])) {
        sa.sin_addr.s_addr = inet_addr(hostaddr);
    } else if ((host = gethostbyname(hostaddr)) != 0) {
        strncpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);
    } else {
        printf("\n[!] Failed to resolve host!\n");
        exit(1);
    }

    sa.sin_port = htons(port);
    sock = socket(AF_INET, SOCK_STREAM, 0);

    if (sock < 0) {
        printf("\n[!] Failed to create socket!\n");
        exit(1);
    }

    err = connect(sock,  (struct sockaddr*)&sa , sizeof sa);

    close(sock);

    if (err < 0) {
        return 0;
    } else {
        return 1;
    }
}

int main(int argc, char *argv[]) {
    if (argc != 4) {
        printf("usage: ./portscan [TARGET] [START PORT] [STOP PORT]\n");
        exit(0);
    }

    char host[20];
    strcpy(host, argv[1]);
    int beginport;
    int endport;

    if (isdigit(argv[2]) && isdigit(argv[3])) {
        beginport = atoi(argv[2]);
        endport = atoi(argv[3]);
    } else {
        printf("[!] Invalid port range given\n");
    }

    printf("[*] Beginning Scan...\n\n");

    int i = beginport;

    for (i; i<=endport; i++) {
        if (scanPort(host, i)) {
            printf("Port %d: Open\n", i);
        }
    }

    printf("\n[*] Scan complete!");
    return 0;
}

I understand that there is some improper/insecure function usage within the code, but I'm just trying to get this program functioning. This is only a test, not an actual program for use.

Here is a screenshot of compiling and executing, I don't think it'll be of much help though: enter image description here

UPDATE: I passed arguments to it, still get segmentation fault: enter image description here

UPDATE 2: I've added a few lines to evaluate argc

Thank you for your time.

-Defalt


Solution

  • The crash is happening here:

    if (isdigit(argv[2]) && isdigit(argv[3])) {
    

    The isdigit function expects an int (actually a char converted to an int), but you pass in a char *. This invokes undefined behavior, which in this case (luckily for you) manifests as a crash.

    You probably want to check the first character of each string, so pass in argv[2][0] and argv[3][0] to this function.

    Also, this is incorrect:

    strncpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);
    

    The strncpy function is for copying strings, not arbitrary bytes. If there is a null byte among the bytes being copied, no others bytes after that one will be copied. Use memcpy instead, which copies an exact number of bytes:

    memcpy((char*)&sa.sin_addr , (char*)host->h_addr , sizeof sa.sin_addr);