icmp简单实现

Linux下,从raw socket 角度实现ICMP扫描,实现了ICMP扫描器的基本原理。参考《SCAN网络扫描技术揭密》。

类似代码可以参考hunt-1.5代码中net.c文件(http://packetstormsecurity.com/sniffers/hunt)。实现类似功能


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/ip.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>


char sBuf[8192] = {0};
char rBuf[8192] = {0};


typedef struct {
        char i_type;
        char i_code;
        unsigned short int i_chksum;
        unsigned short int i_id;
        unsigned short int i_seq;
        unsigned char buf[32];
} icmphdr, *p_icmphdr;
typedef struct{
        char ver;
        char tos;
        unsigned short int total_len;
        unsigned short int id;
        unsigned short int frag;
        unsigned char ttl;
        unsigned char proto;
        unsigned short int checksum;
        unsigned int sourceIp;
        unsigned int destIp;
} iphdr, *p_iphdr;


unsigned short CheckSum(unsigned short *ptr, int nbytes)
{
        register long sum=0;        /* assumes long == 32 bits */
        u_short oddbyte;


        while(nbytes>1){
                sum+=*ptr++;
                nbytes-=2;
        }
        if(nbytes==1){              /* mop up an odd byte, if necessary */
                oddbyte=0;              /* make sure top half is zero */
                *(u_char *)(&oddbyte)=*(u_char *)ptr;   /* one byte only */
                sum+=oddbyte;
        }
        sum = (sum >> 16) + (sum & 0xFFFF);
        return ~(sum  + (sum >> 16)) & 0xFFFF;
}


int main(int argc, char** argv)
{
        int fd = 0;
        struct sockaddr_in addr_inr, addr_inl;
        int val  = 1;
        p_iphdr ipHeader = (p_iphdr)sBuf;
        p_icmphdr icmpHeader = (p_icmphdr)&sBuf[sizeof(iphdr)];
        char* dataBody = "012345678901234567890123456789A";
        char* dataHeader = (char*)icmpHeader->buf;
        int cnt = 0;
printf("sizeof ip header: %d\n", sizeof(iphdr));
printf("sizeof icmp header: %d\n", sizeof(icmphdr));


        fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
        if( fd <= 0){
                perror("socket:");
                return 1;
        }
        addr_inl.sin_family = AF_INET;
        addr_inl.sin_port   = htons(11111);
        addr_inl.sin_addr.s_addr = inet_addr("192.168.31.133");


        addr_inr.sin_family = AF_INET;
        addr_inr.sin_port   = htons(11111);
        addr_inr.sin_addr.s_addr = inet_addr(argv[1]);
        if(setsockopt(fd, IPPROTO_IP, IP_HDRINCL, (char*)&val, sizeof(val))){
                perror("setsockopt:");
                return 1;
        }


        strcpy(dataHeader, dataBody);
        ipHeader->ver = 0x45;
        ipHeader->tos = 0;
        ipHeader->total_len = htons(sizeof(iphdr) + sizeof(icmphdr));
        ipHeader->id = 0x50BD;
        ipHeader->frag = 0;
        ipHeader->ttl = 128;
        ipHeader->proto = IPPROTO_ICMP;
        ipHeader->sourceIp = addr_inl.sin_addr.s_addr;
        ipHeader->checksum = CheckSum((unsigned short int*)sBuf, sizeof(ipHeader));


        icmpHeader->i_type = 8;
        icmpHeader->i_code = 0;
        icmpHeader->i_id = 0;
        icmpHeader->i_seq = 0;
        icmpHeader->i_chksum = CheckSum((unsigned short int*)icmpHeader, 60-sizeof(ipHeader));




        while(cnt < 10){
                printf("This is %d times.\n", cnt++);
                sendto(fd, sBuf, 60, 0, (struct sockaddr*)&addr_inr, sizeof(addr_inr));
        }
        return 0;
}

你可能感兴趣的:(icmp简单实现)