aboutsummaryrefslogtreecommitdiff
path: root/examples/linux_kernel_ip
diff options
context:
space:
mode:
authorRobert Swiecki <robert@swiecki.net>2017-03-30 16:13:56 +0200
committerRobert Swiecki <robert@swiecki.net>2017-03-30 16:13:56 +0200
commite2588d4bb6288706ebf395da7a2fdbbb4208f744 (patch)
tree30f0396e8b38feb299487effddfd759b1ca93969 /examples/linux_kernel_ip
parent37d27ca07b6d74b0fe43e8c4f0d835eefc23196e (diff)
Linux kernel IP fuzzing with Intel PT/BTS
Diffstat (limited to 'examples/linux_kernel_ip')
-rw-r--r--examples/linux_kernel_ip/Makefile24
-rw-r--r--examples/linux_kernel_ip/tun.c183
2 files changed, 207 insertions, 0 deletions
diff --git a/examples/linux_kernel_ip/Makefile b/examples/linux_kernel_ip/Makefile
new file mode 100644
index 00000000..7a9530cd
--- /dev/null
+++ b/examples/linux_kernel_ip/Makefile
@@ -0,0 +1,24 @@
+CC ?= gcc
+LD = $(CC)
+BIN := tun
+SRCS := tun.c
+CFLAGS := -std=c11
+LDFLAGS := ~/src/honggfuzz/libhfuzz/libhfuzz.a
+
+OBJS := $(SRCS:.c=.o)
+
+all: $(BIN)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+$(BIN): $(OBJS)
+ $(LD) -o $(BIN) $(OBJS) $(LDFLAGS)
+
+.PHONY: clean
+clean:
+ $(RM) -r core $(OBJS) $(BIN) *~ */*~
+
+.PHONY: indent
+indent:
+ clang-format-4.0 -style=WebKit -i --sort-includes $(SRCS)
diff --git a/examples/linux_kernel_ip/tun.c b/examples/linux_kernel_ip/tun.c
new file mode 100644
index 00000000..7c8a54af
--- /dev/null
+++ b/examples/linux_kernel_ip/tun.c
@@ -0,0 +1,183 @@
+#define _GNU_SOURCE
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/if_tun.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <sched.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+void HF_ITER(uint8_t**, size_t*);
+
+void fatal(const char* fmt, ...)
+{
+ fprintf(stdout, "[-] ");
+
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+
+ fprintf(stdout, "\n");
+
+ exit(1);
+}
+
+void pfatal(const char* fmt, ...)
+{
+ fprintf(stdout, "[-] ");
+
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+
+ fprintf(stdout, ": %s\n", strerror(errno));
+
+ exit(1);
+}
+
+void mlog(const char* fmt, ...)
+{
+ fprintf(stdout, "[+] ");
+
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+
+ fprintf(stdout, "\n");
+}
+
+int main(void)
+{
+ if (unshare(CLONE_NEWUSER | CLONE_NEWNET) == -1) {
+ pfatal("unshare()");
+ }
+
+ struct ifreq ifr;
+ memset(&ifr, '\0', sizeof(ifr));
+ ifr.ifr_flags = IFF_TUN | IFF_NO_PI | IFF_NOFILTER;
+ strcpy(ifr.ifr_name, "FUZZ0");
+
+ int fd = open("/dev/net/tun", O_RDWR);
+ if (fd == -1) {
+ pfatal("open('/dev/net/tun')");
+ }
+ if (ioctl(fd, TUNSETIFF, (void*)&ifr) != 0) {
+ pfatal("ioctl(TUNSETIFF)");
+ }
+ if (ioctl(fd, TUNSETNOCSUM, 1) != 0) {
+ pfatal("ioctl(TUNSETNOCSUM)");
+ }
+
+ int udp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if (udp_sock == -1) {
+ pfatal("socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)");
+ }
+ int tcp_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
+ if (tcp_sock == -1) {
+ pfatal("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)");
+ }
+
+ struct sockaddr_in* sa = (struct sockaddr_in*)(&ifr.ifr_addr);
+ sa->sin_family = AF_INET;
+ sa->sin_addr.s_addr = inet_addr("192.168.255.1");
+ if (ioctl(tcp_sock, SIOCSIFADDR, &ifr) == -1) {
+ pfatal("ioctl(tcp_sock, SIOCSIFADDR, &ifr)");
+ }
+ sa->sin_addr.s_addr = inet_addr("192.168.255.2");
+ if (ioctl(tcp_sock, SIOCSIFDSTADDR, &ifr) == -1) {
+ pfatal("ioctl(tcp_sock, SIOCSIFDSTADDR, &ifr)");
+ }
+
+ if (ioctl(tcp_sock, SIOCGIFFLAGS, &ifr) == -1) {
+ pfatal("ioctl(tcp_sock, SIOCGIFFLAGS, &ifr)");
+ }
+ ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
+ if (ioctl(tcp_sock, SIOCSIFFLAGS, &ifr) == -1) {
+ pfatal("ioctl(tcp_sock, SIOCSIFFLAGS, &ifr)");
+ }
+
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = htons(1337),
+ .sin_addr.s_addr = INADDR_ANY,
+ };
+
+ if (bind(tcp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ pfatal("bind(tcp)");
+ }
+ if (bind(udp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+ pfatal("bind(udp)");
+ }
+ if (fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR) == -1) {
+ pfatal("fcntl(fd, F_SETFL, O_NONBLOCK|O_RDWR)");
+ }
+ if (fcntl(tcp_sock, F_SETFL, O_NONBLOCK | O_RDWR) == -1) {
+ pfatal("fcntl(tcp_sock, F_SETFL, O_NONBLOCK|O_RDWR)");
+ }
+ if (fcntl(udp_sock, F_SETFL, O_NONBLOCK | O_RDWR) == -1) {
+ pfatal("fcntl(sock, F_SETFL, O_NONBLOCK|O_RDWR)");
+ }
+
+ if (listen(tcp_sock, SOMAXCONN) == -1) {
+ pfatal("listen(tcp_sock)");
+ }
+
+ int tcp_acc_sock = -1;
+
+ for (;;) {
+ uint8_t* buf;
+ size_t len;
+
+ HF_ITER(&buf, &len);
+
+ while (len > 0) {
+ size_t tlen = (len > 1500) ? 1500 : len;
+ write(fd, buf, tlen);
+ len -= tlen;
+ }
+
+ for (;;) {
+ char b[1024 * 128];
+ if (read(fd, b, sizeof(b)) <= 0) {
+ break;
+ }
+ }
+
+ if (tcp_acc_sock == -1) {
+ struct sockaddr_in nsock;
+ socklen_t slen = sizeof(nsock);
+ tcp_acc_sock = accept4(tcp_sock, (struct sockaddr*)&nsock, &slen, SOCK_NONBLOCK);
+ }
+ if (tcp_acc_sock != -1) {
+ char b[1024 * 128];
+ if (recv(tcp_acc_sock, b, sizeof(b), MSG_DONTWAIT) == 0) {
+ close(tcp_acc_sock);
+ tcp_acc_sock = -1;
+ }
+ send(tcp_acc_sock, b, 1, MSG_NOSIGNAL | MSG_DONTWAIT);
+ }
+
+ char b[1024 * 128];
+
+ struct sockaddr_in addr;
+ socklen_t slen = sizeof(addr);
+ if (recvfrom(udp_sock, b, sizeof(b), MSG_DONTWAIT, (struct sockaddr*)&addr, &slen) > 0) {
+ sendto(udp_sock, b, 1, MSG_NOSIGNAL | MSG_DONTWAIT, (struct sockaddr*)&addr, slen);
+ }
+ }
+}