| #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 <netinet/tcp.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 <sys/uio.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, TUNSETOFFLOAD, TUN_F_CSUM | TUN_F_TSO_ECN | TUN_F_TSO4 | TUN_F_TSO6 | TUN_F_UFO) == -1) { |
| pfatal("ioctl(fd, TUNSETOFFLOAD)"); |
| } |
| |
| int udp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
| if (udp_sock == -1) { |
| pfatal("socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)"); |
| } |
| int tcp_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| if (tcp_sock == -1) { |
| pfatal("socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)"); |
| } |
| int sctp_sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); |
| if (sctp_sock == -1) { |
| pfatal("socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)"); |
| } |
| int udp_lite_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDPLITE); |
| if (udp_lite_sock == -1) { |
| pfatal("socket(AF_INET, SOCK_DGRAM, IPPROTO_UDPLITE)"); |
| } |
| |
| int disable = 1; |
| if (setsockopt(udp_sock, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)) == -1) { |
| pfatal("setsockopt(udp_sock, SOL_SOCKET, SO_NO_CHECK)"); |
| } |
| if (setsockopt(tcp_sock, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)) == -1) { |
| pfatal("setsockopt(tcp_sock, SOL_SOCKET, SO_NO_CHECK)"); |
| } |
| const uint8_t md5s[TCP_MD5SIG_MAXKEYLEN] = { 0 }; |
| setsockopt(tcp_sock, SOL_TCP, TCP_MD5SIG, (void*)md5s, sizeof(md5s)); |
| if (setsockopt(sctp_sock, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)) == -1) { |
| pfatal("setsockopt(sctp_sock, SOL_SOCKET, SO_NO_CHECK)"); |
| } |
| if (setsockopt(udp_lite_sock, SOL_SOCKET, SO_NO_CHECK, (void*)&disable, sizeof(disable)) == -1) { |
| pfatal("setsockopt(udp_lite_sock, SOL_SOCKET, SO_NO_CHECK)"); |
| } |
| |
| 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 (bind(sctp_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { |
| pfatal("bind(sctp)"); |
| } |
| if (bind(udp_lite_sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) { |
| pfatal("bind(udp_lite)"); |
| } |
| 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(udp_sock, F_SETFL, O_NONBLOCK|O_RDWR)"); |
| } |
| if (fcntl(sctp_sock, F_SETFL, O_NONBLOCK | O_RDWR) == -1) { |
| pfatal("fcntl(sctp_sock, F_SETFL, O_NONBLOCK|O_RDWR)"); |
| } |
| if (fcntl(udp_lite_sock, F_SETFL, O_NONBLOCK | O_RDWR) == -1) { |
| pfatal("fcntl(udp_lite_sock, F_SETFL, O_NONBLOCK|O_RDWR)"); |
| } |
| |
| if (listen(tcp_sock, SOMAXCONN) == -1) { |
| pfatal("listen(tcp_sock)"); |
| } |
| if (listen(sctp_sock, SOMAXCONN) == -1) { |
| pfatal("listen(sctp_sock)"); |
| } |
| |
| int tcp_acc_sock = -1; |
| |
| for (;;) { |
| char b[1024 * 128]; |
| for (;;) { |
| if (read(fd, b, sizeof(b)) <= 0) { |
| break; |
| } |
| } |
| |
| uint8_t* buf; |
| size_t len; |
| |
| HF_ITER(&buf, &len); |
| |
| const size_t pkt_size = 1400UL; |
| size_t num_iov = 0; |
| if (len > 0) { |
| num_iov = ((len - 1) / pkt_size) + 1; |
| } |
| for (size_t i = 0; i < num_iov; i++) { |
| size_t off = pkt_size * i; |
| size_t sz = ((len - off) > pkt_size) ? pkt_size : (len - off); |
| write(fd, &buf[off], sz); |
| |
| char b[1024 * 128]; |
| for (;;) { |
| 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) { |
| 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); |
| } |
| |
| 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); |
| } |
| |
| slen = sizeof(addr); |
| if (recvfrom(sctp_sock, b, sizeof(b), MSG_DONTWAIT, (struct sockaddr*)&addr, &slen) > 0) { |
| sendto(sctp_sock, b, 1, MSG_NOSIGNAL | MSG_DONTWAIT, (struct sockaddr*)&addr, slen); |
| } |
| |
| slen = sizeof(addr); |
| if (recvfrom(udp_lite_sock, b, sizeof(b), MSG_DONTWAIT, (struct sockaddr*)&addr, &slen) > 0) { |
| sendto(udp_lite_sock, b, 1, MSG_NOSIGNAL | MSG_DONTWAIT, (struct sockaddr*)&addr, slen); |
| } |
| } |
| } |
| } |