Implicitly linked C Program is not connecting to localhost

80 views Asked by At

Where am I going wrong with my experimentation:

I am trying to experimentally deduce the details of creating a simple shellcode. My first impression was I probably would not be able to use imports, as my shellcode is not linked by the compiler of the target program. I then began wondering how small I can make a simple shell command interface over a socket without using imports, so I wrote up some code; and started ignoring implicit call warnings:

// socket_family
#define AF_INET 2
#define AF_PACKET 17
// socket_type
#define SOCK_STREAM 1

typedef unsigned short sa_family_t;

struct sockaddr {
    sa_family_t sa_family;
    char        sa_data[14];
};

struct in_addr {
    unsigned long s_addr;          // load with inet_pton()
};

struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, above
    char             sin_zero[8];  // zero this if you want to
};

int main(void) {
    int sfd;
    const short family = AF_INET;
    const char host[] = "127.0.0.1";
    struct sockaddr addr;
    struct sockaddr_in *addr_full = (struct sockaddr_in*)&addr;

    if (sfd = socket(family, SOCK_STREAM, 0) < 0) return 1;
    memset(&addr, 0, sizeof(struct sockaddr));
    addr_full->sin_family = family;
    addr_full->sin_port = htons(8000);
    inet_pton(family, host, &(addr_full->sin_addr.s_addr));
    if (connect(sfd, &addr, sizeof(struct sockaddr)) < 0) return 2;
    close(sfd);
    return 0;
}

Somewhere along the line I am not connecting to my python -m SimpleHTTPServer properly; which reports Serving HTTP on 0.0.0.0 port 8000.

$ gcc my_program.c -o my_program
$ ./my_program
$ echo $?
2

I am taking a Coursera course on software security; and a lot of this topic is new to me.

EDIT:

After removing redefinitions and adding includes:

#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>

int main(void) {
    int sfd;
    const short family = AF_INET;
    const char host[] = "127.0.0.1";
    struct sockaddr_in addr_full; // = (struct sockaddr_in*)&addr;

    if (sfd = socket(family, SOCK_STREAM, 0) < 0) return 1;
    memset(&addr_full, 0, sizeof(struct sockaddr));
    addr_full.sin_family = family;
    addr_full.sin_port = htons(8000);
    inet_pton(family, host, &(addr_full.sin_addr.s_addr));
    if (connect(sfd, (struct sockaddr*)&addr_full, sizeof(struct sockaddr)) < 0) return 2;
    close(sfd);
    return 0;
}

The program still exits with 2.

3

There are 3 answers

2
Roman Nikitchenko On BEST ANSWER

Motoko, please grab C language book and check operations priority. And do it regulary, even experienced developers make errors here. And don't write this crazy style, please learn how to write for humans:

if (sfd = socket(family, SOCK_STREAM, 0) < 0) return 1;

You should instead do something like this:

sfd = socket(family, SOCK_STREAM, 0);
if (sfd < 0)
{
    /* perror() is pretty old style but some good check is recommended. */
    perror("socket");
    return 1;
}

SPOILER: < just has higher priority here so sfd is always 0 in your code.

4
lkamp On

Your assumption about the include files is wrong. The include files only contain the function declarations, not the code itself. They don't determine how your program will get linked to shared libraries.

Include files only tell the compiler that the functions you call inside your program exist somewhere, in some external library or in another source file you wrote. After compilation the linker tries to find all the functions that your program needs, and if they are not found, linking fails.

Try compiling your code with the necessary files included (socket.h etc.). This will give you useful warnings, for example when you pass an argument of the wrong type.

2
motoku On

The socket file descriptor was not being assigned properly. Adding parenthesis, I should be assigning the descriptor, then checking its value:

if ((sfd = socket(family, SOCK_STREAM, 0)) < 0) return 1;