首页 > 用户发贴区 > 编程问题提问区 > 缓存溢出问题求救
2007
12-17

缓存溢出问题求救

以下代码有缓存溢出, 请帮忙指出, 多谢~


#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <strings.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/uio.h>
#include <stdarg.h>
#include <errno.h>


#ifndef USE_MMAP
#define USE_MMAP
#endif


#ifdef USE_MMAP
#include <sys/mman.h>
#define START_ADDR (void *) 0x55385C00
#endif


#ifdef __CYGWIN__
#include “getopt.h”
#endif



/* Binary code for HLT (halt) instruction */
#define HALT_INSTR 0xF4


#define NORMAL_CNT 1
#define NORMAL_BUFFER_SIZE 32


uint32_t cookie = 0xDEADBEEF;


/*——————————————————————–*/
//global variable declaration


struct aconnexion {
  int nfd;
  char bufcon[1000];
  int buflen;
  long starttime;
} con[32];


int listen_port = 9010, fdc;
struct timeval tv;
struct tm *ptm;
fd_set origfds;
struct sockaddr_in srv;


/***************************************************************************
function : reverse_string
Description : reverse a string
Parameters : dest (destination buffer)
             src (source buffer)
Local : string_leng, j
Returned value : none
***************************************************************************/


void reverse_string ( char *dest, char *src) {
  int string_leng = strlen (src);
  int j;
  for (j=(string_leng -1);j>=0; j–) {
    *(dest++) = src[j]; }
}



/***************************************************************************
function : close_connec
Description : close a connection
Parameters : aconnec (the connection to close)
Globals : origfds
Local : none
Returned value : none
***************************************************************************/


void close_connec(struct aconnexion *connec) {
  FD_CLR((*connec).nfd, &origfds);
  close((*connec).nfd);
  (*connec).nfd =-1;
}



/***************************************************************************
function : check_error
Description : check if an error occured
Parameters : errorbuf (buffer to store a string reporting the error)
             nb (number to check)
             lw (if no error, nb = lw)
Globals : none
Local : none
Returned value : 0 if error else 1
***************************************************************************/


int check_error (char *errorbuf, int nb, int lw) {
  if (nb == -1) {
    sprintf (errorbuf, “Error while writing the response, check your connection, err# : %d\n”, errno);
    return 1;
  } else if (nb < lw) {
    strcpy (errorbuf, “Response partially sent !!\n”);
    return 1;
  } else {
    return 0;
  }

    



/***************************************************************************
function : processbuf
Description : treate the received data and send a response back
Parameters : fdnb (decriptor of a connection)
             buf (received data)
             paramlen (number of string to reverse)
             pstart (position of the first string)
Globals : none
Local : errorbuf, err, bufrep_pos, i, nbytew, revstring, bufrep
Returned value : 0 if an error occurred, 1 else
***************************************************************************/


int processbuf(int fdnb, char *buf, int paramlen, char *pstart) {
  int nbytew,err;
  char errorbuf[200];
  char revstring[21], *bufrep_pos;
  char bufrep[2000];
  int i;


  pstart++;
  for (i=0;i<2000;i++) bufrep[i]=0;
  for (i=0;i<21;i++) revstring[i]=0;
  //store the beginning of the response in bufrep
  snprintf(bufrep, 2000, buf);
  // change to REP
  bufrep[2] = ‘P’;
  bufrep[3] = ‘|’;


  bufrep_pos= bufrep + 4; 
  i= 4;
  while (*(buf+i)!= 0) { *(revstring+i- 4) = *(buf+i); i++;}
  strncpy(bufrep_pos, revstring, 2);


  //reverse string and fill bufrep with the result
  bufrep_pos += strlen(bufrep_pos);
  for (i=0;i<paramlen; i++) {
    *bufrep_pos  = ‘|’;
    bufrep_pos++;
    reverse_string (revstring, pstart);
    pstart += 21;
    snprintf(bufrep_pos, 21, revstring);
    bufrep_pos += 20;
  }


  //send the response and check for errors
  nbytew = write(fdnb, bufrep, strlen(bufrep));
  err = check_error(errorbuf, nbytew, strlen(bufrep));
  if (err == 1) printf (errorbuf);
  
  return (err);
}



/***************************************************************************
function : server
Description : listen to a socket and treate REV request 
Parameters : argc, argv
Globals : all
Local : check below ;-)
Returned value : 0 if an error occured
***************************************************************************/


int server() {
  int fd, paramlen, i, freepos, chkpass;
  const int optval =1;
  fd_set readfds;
  int maxfds, next, count, nbyte, int_pos;
  struct sockaddr_in cli;
  struct timeval s_timeout;
  int cli_len;
  char *start_param_pos, *paramlen_pos;
  int paramlen_offset;
 
  //create a socket
  fd = socket(AF_INET, SOCK_STREAM, 0);
  if (fd == -1) {printf(“error while creating the socket\n”);return(0);}
 
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1){
    printf(“Error while setting socket option, errno: %d\n”, errno);
  }
 
  srv.sin_family = AF_INET;
  srv.sin_port = htons(listen_port);
  srv.sin_addr.s_addr = htonl(INADDR_ANY);
  //bind the socket
  if (bind (fd, (struct sockaddr*) &srv, sizeof(srv)) == -1) {
    printf(“error while binding %d\n”, errno);return(0);}
  //listen
  if (listen (fd, 10)<0) {
    printf(“error while trying to listen\n”);return(0);}


  maxfds = fd;
  FD_ZERO(&origfds);
  FD_SET(fd, &origfds);
  next=0;
  s_timeout.tv_sec = 1;
  s_timeout.tv_usec = 0;
  printf(“server on\n”);
  //check for request
  while (1) {
    bcopy (&origfds, &readfds, sizeof (origfds));
    select (maxfds +1, &readfds, 0, 0, &s_timeout);
    if (FD_ISSET(fd, &readfds)) {
      if (next < 31) {
         printf(“new connexion\n”);
         cli_len = sizeof(cli);
         con[next++].nfd = accept (fd, (struct sockaddr*) &cli, &cli_len);
         if (con[next-1].nfd<0) {
             printf(“error while accepting %d\n”, errno);return(0);
         }
         if (con[next-1].nfd > maxfds) maxfds = con[next-1].nfd;
         gettimeofday(&tv, NULL);
         con[next-1].starttime = tv.tv_sec;
         bzero(con[next-1].bufcon, 1000);
         con[next-1].buflen = 0;
         FD_SET(con[next-1].nfd, &origfds);
      } else { 
 return (0);
      }
    }


    //check existing connection
    for (count=0;count<next;count++) {
    
      if (con[count].nfd <0) continue;
      if (FD_ISSET(con[count].nfd, &readfds)) {
        nbyte = 0;
        nbyte = read(con[count].nfd, &((con[count].bufcon)[con[count].buflen]), 999 – con[count].buflen );
      
        con[count].buflen += nbyte;
         
        if (nbyte == 0) {
          // client has closed the connection
          close_connec(&(con[count]));
        }else{
          //replace | by 0
          for (i=0;i<con[count].buflen; i++)
            if ((con[count].bufcon)[i] == ‘|’) (con[count].bufcon)[i]=0;
          chkpass = 0; int_pos = 0;
          //check if the request has a valid format
          if (strncmp(con[count].bufcon, “REV”, 3) ==0) {
              paramlen_pos = con[count].bufcon;
              while(*paramlen_pos++ != 0);
              paramlen_offset =(int) (paramlen_pos – con[count].bufcon);            
             
              paramlen = atoi( &((con[count].bufcon)[paramlen_offset]));
            start_param_pos  =  &((con[count].bufcon)[paramlen_offset]);
            while(*start_param_pos != 0) start_param_pos++;
            int_pos = (int)( start_param_pos – (con[count].bufcon));
            if (paramlen > 47) { // 47*21 + 4 = 993
              bzero(con[count].bufcon, 1000);
              con[count].buflen = 0;
            }
            if ((paramlen != 0)&&
                ((con[count].buflen – int_pos) == paramlen*21)) {
              chkpass = 1;
              for (i=1; i<paramlen; i++)
                if (*(start_param_pos + 21*i) != ‘\0′) chkpass = 0;
            }
   }else {
            bzero(con[count].bufcon, 1000);
            con[count].buflen = 0;
          }
          if ((con[count].buflen -  int_pos) > paramlen*21) {
     bzero(con[count].bufcon, 1000);
          }
          if ((con[count].buflen -  int_pos) >= paramlen*21) {
            con[count].buflen = 0;
          }
         
          if (chkpass) {
            //process the request
            processbuf(con[count].nfd,con[count].bufcon, paramlen, start_param_pos);
            bzero(con[count].bufcon, 1000);
   }
          gettimeofday(&tv, NULL);
          con[count].starttime = tv.tv_sec;
        }
     
      }
    }
    //check if some connections have been idling for more than 5 seconds
    gettimeofday(&tv, NULL);
    for (count=0;count<next;count++) {
      if (con[count].nfd <0) continue;
      if ( (tv.tv_sec – con[count].starttime) > 5) {
        close_connec(&(con[count]));
      }
    }
    //sort the array “con”
    if (next == 10 % 11) {
      freepos = 0;
      for (i=0; i<next; i++) {
        if (con[i].nfd >= 0) {
          if (freepos == i) {freepos++;}
          else {
            con[freepos++] = con[i];
            con[i].nfd = -1;
          }
        }
      }
      next = freepos;
    }
  }
  close (fd);
  return 1;
}


/* New version of launching code.
   Optionally uses MMAP to generate stable stack position */


/* Must put context information in global variables,
   since stack will get messed up */
int global_nitro = 0;
int global_offset = 0;
volatile    void *stack_top;
volatile  void *global_save_stack = NULL;


/* This function makes it possible to shift stack to mapped region */
void launcher(int nitro, int offset)
{
#ifdef USE_MMAP
  void *new_stack;
#endif
  global_nitro = nitro;
  global_offset = offset;



#ifdef USE_MMAP
#define STACK_SIZE 0×100000
  new_stack = mmap(START_ADDR, STACK_SIZE, PROT_EXEC|PROT_READ|PROT_WRITE,
     MAP_PRIVATE | MAP_GROWSDOWN | MAP_ANONYMOUS,
     0, 0);
  if (new_stack == MAP_FAILED) {
    fprintf(stderr, “Internal error.  Couldn’t use mmap\n”);
    exit(1);
  }
  stack_top = new_stack + STACK_SIZE – 8;
  asm(“movl %%esp,%%eax ; movl %1,%%esp ; movl %%eax,%0″
      : “=r” (global_save_stack)
      : “r”  (stack_top)
      : “%eax”
      );
#endif
  server();
  //  launch(global_nitro, global_offset);
#ifdef USE_MMAP
  asm(“movl %0,%%esp”
      :
      : “r” (global_save_stack)
      );
  munmap(new_stack, STACK_SIZE);
#endif
}
 
int main(int argc, char** argv) {
  int cookie_tweak = 0;
  int nitro = 0; /* Run in unstable mode? */
  int i;
  int *offsets;
  int cnt = NORMAL_CNT;
  char c;


  // set up random stack offsets for nitro mode
  srandom(cookie);
  cookie_tweak =  random() & 0xFF8;


  offsets = (int *) calloc(cnt, sizeof(int));
  for (i = 0; i < cnt-2; i++)
    offsets[i] = random() & 0×38;
  if  (cnt >= 2)
    offsets[cnt-2] = 0×38;
  offsets[cnt-1] = 0;


  for (i = 0; i < cnt; i++)
    launcher(nitro, offsets[i]+cookie_tweak); 


  return 0;
}


留下一个回复