Search code examples
clinuxsocketsshellcode

Implicitly linked C Program is not connecting to localhost


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.


Solution

  • 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.