Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
470 views
in Technique[技术] by (71.8m points)

c - How to find the vulnerability of a program to exploit using buffer overflow attack

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>
");
    return 1;
  }
  
  if (inet_aton(argv[1], &bind_addr) == 0)
  {
       fprintf(stderr, "Invalid bind address
");
       exit(EXIT_FAILURE);
  }
  
  port = atoi(argv[2]); 
  if ((port < 1024) || (port > 65535))
  {
    printf("Portrange has to be between 1024 and 65535.
");
    exit(EXIT_FAILURE);
  }


  // forking to background
  pid = fork();
  if(pid < 0)
  {
    printf("fork() failed
");
    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 .


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...