0

As an assignment of a lab , I want first to find the vulnaribility of the following code , then run in as a sample timeserver and then attack it using buffer overflow . But the first problem is not knowing where exactly to start . I know that there are some functions that could be harmfull in that C program ( such as " strftime " , or " memcoy " , or "strcpy" ) but I can not select which one is the most proper one to start with .

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <time.h>


#define CANBUFSIZE 106
#define MSGBUFSIZE 256
#define TIMEBUFSIZE 128

char msgbuf[MSGBUFSIZE];
char canarybuf[CANBUFSIZE];

void get_time(char* format, char* retstr, unsigned received)
{
  // memory for our local copy of the timestring
  char timebuf[TIMEBUFSIZE];
  time_t curtime;

  // if the format string esceeds our local buffer ...
  if(strlen(format) > TIMEBUFSIZE)
  {
    strcpy(retstr,"Process Error.");
    return;
  }

  // otherwise create a local working copy
  memcpy(timebuf,format,received);

  // Get the current time.
  curtime = time (NULL);

  // Convert it to local time representation.
  // and convert the format string to the real timestring
  struct tm *loctime = localtime (&curtime);
  strftime(retstr,TIMEBUFSIZE,timebuf,loctime);

  return;
}


int main(int argc, char** argv)
{
  int port;                     // the portnumber of our service
  struct in_addr bind_addr;     // bind address of the server
  int sd;                       // the socketdescriptor
  struct sockaddr_in addr;      // address of our service
  struct sockaddr_in addr_from; //address of the client
  int addrlen = sizeof(addr_from);
  int pid;                      // our process id
  int sid;                      // our session id
  unsigned received;            // number of bytes received from network


  // resolve command line arguments
  if(argc != 3)
  {
    printf("Usage: timeservice <bind address> <portnum>\n");
    return 1;
  }
  
  if (inet_aton(argv[1], &bind_addr) == 0)
  {
       fprintf(stderr, "Invalid bind address\n");
       exit(EXIT_FAILURE);
  }
  
  port = atoi(argv[2]); 
  if ((port < 1024) || (port > 65535))
  {
    printf("Portrange has to be between 1024 and 65535.\n");
    exit(EXIT_FAILURE);
  }


  // forking to background
  pid = fork();
  if(pid < 0)
  {
    printf("fork() failed\n");
    exit(EXIT_FAILURE);
  }
  // we are parent
  else if(pid > 0)
  {
    return 0;
  }

  /*
   * we are the child process
   * because of the termination of our parent, we need a new session id,
   * else we are zombie
   */
  sid = setsid();
  if (sid < 0) {
    return 1;
  }

  /*
   * since we are a system service we have to close all standard file 
   * descriptors
   */
  close(STDIN_FILENO);
  close(STDOUT_FILENO);
  close(STDERR_FILENO);

  // create an udp socket
  if((sd = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
  {
    return 1;
  }

  // clear the memory of our addr struct
  memset(&addr,0,sizeof(addr));

  // Protocol Family = IPv4
  addr.sin_family = PF_INET; 
  
  // Listen on bindAddr and bindPort only
  addr.sin_addr.s_addr = bind_addr.s_addr;
  addr.sin_port = htons(port);

  // bind to the udp socket
  if(bind(sd,(struct sockaddr*)&addr,sizeof(addr)) != 0)
  {
    return 1;
  }

  for(;;)
  {
    // prepare memory
    memset(&msgbuf, 0, sizeof(msgbuf));

    received = recvfrom(sd,msgbuf,MSGBUFSIZE,MSG_WAITALL,
      (struct sockaddr*)&addr_from,(socklen_t*) &addrlen);

    // fork a new child
    pid = fork();

    // we are parent
    if (pid > 0)
    {
      // wait for the child to finish
      waitpid(pid,NULL,0);
    }
    else
    {
      /*
       * we are inside the child process
       */

      // reserve some memory for our response
      char * returnstr = (char*) malloc(TIMEBUFSIZE);

      // analyse the client request and format the time string
      get_time(msgbuf, returnstr, received);

      // send our response to the client
      sendto(sd,returnstr,strlen(returnstr)+1,MSG_DONTWAIT,
        (struct sockaddr *) &addr_from, addrlen);

      free(returnstr);
      return EXIT_SUCCESS;
    }
  }

  close(sd);

  return 0;
}

I compiled the file using gcc and run the localserver with ./timeserver 127.0.0.1 2222 and then connects to that with nc -u 127.0.0.1 2222 . Then I'm now able to input some strings of format strings to the server and take some results back . For example if I use %d in the command line it will show me a date/time in a special format . I know that this is the place that I should force some strings and crash the program but I can not find exact string of that .

1
  • The type of received is wrong. Commented Jan 1, 2021 at 11:53

1 Answer 1

0

The return value of recvfrom is not checked, which is a mistake. If recvfrom gets an error, then the return value is -1. Since the type of received is unsigned, a second mistake, this will appear to be a large positive value. The memcpy call will cause the program to fail.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.