Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Hacking a Test Sever code

Options
  • 22-04-2011 11:08pm
    #1
    Closed Accounts Posts: 6


    Hi guys, I came across this code below recently and have being trying to hack it...
    I am not having much luck with it and was wondering if anyone has any experience with hacking code that could lend a hand or give me some tips... This is a genuine request and I can give the url of the site when I found the challenge, just wasn't sure if it was o.k to post the url....

    The TEST :
    ``````````
    A remote, multi threaded server sits listening on port 8001. The server runs on an x86 machine running Linux . The server was built with gcc 3.3.5 (i.e. the older gcc version available off the lab machines under /usr/local/bin).

    When we connect to it, the server prompts us to enter our name. After receiving our name the server welcomes us and asks us to enter a message. After receiving our message the server exits. the server has been built as follows:

    $/usr/local/bin/gcc -mpreferred-stack-boundary=2 -o server server.c -lpthread


    THE MISSION :
    `````````````
    Exploit the vulnerable server in order to gain remote control of the host on which the server resides.
    1. Study the server to understand what it does, how it does it and identify any flaws
    2. Determine what your payload needs to do, write the payload in C and test it
    3. Translate the payload into assembly
    4. Convert the assembly into hexadecimal opcodes
    5. Write and test the exploit



    THE SERVER:
    ``````````

    /*
    * Our vulnerable server. It simply reads a name and a message from a client
    * before exiting.
    */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <pthread.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    #include <netdb.h>
    #include <time.h>

    #define PORTNUM 8001
    #define BLENGTH 256
    #define MLENGTH 128

    /* Read the name of a client */
    static void
    read_name(int s, char *buffer, char *greeting)
    {
    char *p;

    /* Construct a prompt */
    (void) snprintf(buffer, BLENGTH, "Please enter your name:\n");

    /* Send the prompt to the client */
    (void) send(s, (void *)buffer, BLENGTH, 0);

    /* Receive a response from the client */
    (void) recv(s, (void *)buffer, BLENGTH, MSG_WAITALL);

    /* Remove trailing '\n' from the response */
    p = buffer + strlen(buffer) - 1;
    *p = '\0';

    /* Transfer response to greeting */
    (void) snprintf(greeting, BLENGTH, buffer);

    /* Construct greeting */
    (void) strncat(greeting, ", you are most welcome!\n", BLENGTH);

    /* Send greeting to client */
    (void) send(s, greeting, BLENGTH, 0);
    }


    /* Read a message from a client */
    static void
    read_message(int s, char *buffer, char *message)
    {
    /* Construct a prompt */
    (void) snprintf(buffer, BLENGTH, "Please enter your message:\n");

    /* Send the prompt to the client */
    (void) send(s, (void *)buffer, BLENGTH, 0);

    /* Receive a response from the client */
    (void) recv(s, (void *)buffer, BLENGTH, MSG_WAITALL);

    /* Copy the response to a local buffer */
    (void) strcpy(message, buffer);
    }

    /* Make an introduction */
    static void
    do_first_bit(int s)
    {
    char greeting[BLENGTH];
    char buffer[BLENGTH];

    read_name(s, buffer, greeting);
    }

    /* Do the work */
    static void
    do_second_bit(int s)
    {
    char message[MLENGTH];
    char buffer[BLENGTH];

    read_message(s, buffer, message);
    }

    /* One thread per connection */
    void *
    handler(void *n)
    {
    int s;

    /* Detach */
    (void) pthread_detach(pthread_self());

    /* Cast parameter */
    s = *((int *)n);

    /* Make an introduction */
    do_first_bit(s);

    /* Do the work */
    do_second_bit(s);

    /* Close the socket */
    (void) close(s);

    /* Free memory */
    free(n);

    return ((void *)NULL);
    }


    /* Connect and talk to a client */
    int
    main(void)
    {
    struct sockaddr_in socketname, client;
    struct hostent *host;
    socklen_t clientlen = sizeof (client);
    pthread_t tid;
    int s, n, *c, optval = 1;

    /* We will always be localhost */
    if ((host = gethostbyname("localhost")) == NULL) {
    perror("gethostbyname()");
    exit(EXIT_FAILURE);
    }

    /* Fill in the socket address structure */
    (void) memset((char *)&socketname, '\0', sizeof (socketname));
    socketname.sin_family = AF_INET;
    socketname.sin_port = htons(PORTNUM);
    (void) memcpy((char *)&socketname.sin_addr, host->h_addr_list[0],
    host->h_length);

    /* Create an Internet family, stream socket */
    s = socket(AF_INET, SOCK_STREAM, 0);

    /* Did that work? */
    if (s < 0) {
    perror("socket()");
    exit(EXIT_FAILURE);
    }

    /* Allow binding if waiting on kernel to clean up */
    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
    (char *)&optval, sizeof (optval)) < 0) {
    perror("setsockopt()");
    exit(EXIT_FAILURE);
    }

    /* Now bind the address to our socket so it becomes visible */
    if (bind(s, (struct sockaddr *)&socketname,
    sizeof (socketname)) < 0) {
    perror("bind()");
    exit(EXIT_FAILURE);
    }

    /* Make our now visible socket available for connections */
    if (listen(s, 5)) {
    perror("listen()");
    exit(EXIT_FAILURE);
    }

    /* Loop forever */
    while (1) {

    /* Accept a connection */
    n = accept(s, (struct sockaddr *)&client, &clientlen);

    /* Did that work? */
    if (n < 0) {
    perror("accept()");
    exit(EXIT_FAILURE);
    }

    /* Allocate room for socket for this thread */
    c = malloc(sizeof (*c));

    /* Check we got some memory */
    if (!c) {
    perror("malloc()");
    exit(EXIT_FAILURE);
    }

    /* Initialise */
    *c = n;

    /* Have a conversation */
    (void) pthread_create(&tid, NULL, handler, (void *)c);
    }

    /* Close socket */
    (void) close(s);

    return (0);
    }


    CLIENT:
    ```````


    /*
    * Simple demonstration of talking to our vulnerable server
    */
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <errno.h>
    #include <netdb.h>
    #include <time.h>

    #define PORTNUM 8001
    #define BLENGTH 256

    /* Send our name to the server */
    static void
    send_name(int s)
    {
    char buffer[BLENGTH];

    /* Receive a prompt from the server */
    (void) recv(s, (void *)buffer, BLENGTH, MSG_WAITALL);

    /* Display the prompt to the user */
    (void) fputs(buffer, stdout);

    /* Read a response from the user */
    (void) fgets(buffer, BLENGTH, stdin);

    /* Send the response to the server */
    (void) send(s, (void *)buffer, BLENGTH, 0);

    /* Receive a reply from the server */
    (void) recv(s, (void *)buffer, BLENGTH, MSG_WAITALL);

    /* Display the reply to the user */
    (void) fputs(buffer, stdout);
    }

    /* Send our message to the server */
    static void
    send_message(int s)
    {
    char buffer[BLENGTH];

    /* Receive a prompt from the server */
    (void) recv(s, (void *)buffer, BLENGTH, MSG_WAITALL);

    /* Display the prompt to the user */
    (void) fputs(buffer, stdout);

    /* Read a response from the user */
    (void) fgets(buffer, BLENGTH, stdin);

    /* Send the response to the server */
    (void) send(s, (void *)buffer, BLENGTH, 0);
    }
    /* Connect and talk to the server */
    int
    main(void)
    {
    struct sockaddr_in server;
    struct hostent *host;
    int s;

    /* Create an Internet family, stream socket */
    s = socket(AF_INET, SOCK_STREAM, 0);

    /* Did that work? */
    if (s < 0) {
    perror("socket()");
    exit(EXIT_FAILURE);
    }

    /* We are running the server on localhost for the minute */
    if ((host = gethostbyname("localhost")) == NULL) {
    perror("gethostbyname()");
    exit(EXIT_FAILURE);
    }

    /* Fill in the socket address structure */
    (void) memset((char *)&server, '\0', sizeof (server));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORTNUM);
    (void) memcpy((char *)&server.sin_addr, host->h_addr_list[0],
    host->h_length);

    /* Connect to the server */
    if (connect(s, (struct sockaddr *)&server, sizeof (server)) < 0) {
    perror("connect()");
    exit(EXIT_FAILURE);
    }

    /* Send our name first */
    send_name(s);

    /* Now send a message */
    send_message(s);

    /* Close the socket */
    (void) close(s);

    return (0);
    }


Comments

  • Registered Users Posts: 1,064 ✭✭✭Snowbat




  • Closed Accounts Posts: 6 mreilly2008


    Hi snowbat... that is where I originally found the discussion. but while there is some info there about it... they do not go into any detail on how you go about actually doing it and just kinda gloss over the general issues... I understand the format string and buffer overflow issues, but unfortunately I don't seem tech savvy enough to actually make it work... was hoping maybe some one else had maybe tried or could give me a push in right direction code wise....

    thanks a million for your reply..
    all the best.


  • Registered Users Posts: 6,215 ✭✭✭bonzodog2


    Basically you have to find a buffer-overflow-susceptible input from the client, identify where in the server code this is located, and generate some input from a client that injects suitable executable bytes such that they are executed when the input from the client has finished. A map or assembler listing of the server code as compiled by the specified compiler & options may help identify this.

    I'm not going to spend any time poring over the server code, or compiling & running it, to help you though; either you're that way inclined or you ain't. Good luck though !


  • Closed Accounts Posts: 6 mreilly2008


    Hi bonzodog2,
    I have already spotted a format string vulnerability here :

    /* Transfer response to greeting */
    (void) snprintf(greeting, BLENGTH, buffer);

    which I am hoping will help with the mapping out of address to use in the buffer over flow you talk about... and hopefully ti will help me become that way inclined...
    "that way inclined", wait... doesn't that have a different connotation :)...

    thanks a mill, bonzodog2... take care.


  • Registered Users Posts: 6,215 ✭✭✭bonzodog2


    I'm sure there are many ways of being "that way inclined" ....


  • Advertisement
  • Moderators, Recreation & Hobbies Moderators, Science, Health & Environment Moderators, Technology & Internet Moderators Posts: 91,219 Mod ✭✭✭✭Capt'n Midnight


    There is a security forum http://www.boards.ie/vbulletin/forumdisplay.php?f=24 <--- Edit wrong link :o

    But don't no one's going to do it for you unless you have shown that you have done a lot already - this sort of stuff is self authenticating knowledge


  • Closed Accounts Posts: 6 mreilly2008


    Thanks Capt'n Midnight,
    I will have a look at that forum and maybe add all the stuff I have done so far... I am a nice bit of the way into it... including getting my shellcode sent back to the server... still getting seg faults at the moment... so hopefully its just trial and error from here on it...

    all the best


  • Moderators, Recreation & Hobbies Moderators, Science, Health & Environment Moderators, Technology & Internet Moderators Posts: 91,219 Mod ✭✭✭✭Capt'n Midnight




  • Closed Accounts Posts: 6 mreilly2008


    Please close this thread I have reposted in Security forum.

    Thanks.


Advertisement