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;
}