// Module Name: iphdrinc.c // #pragma pack(1)
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h> #include <ws2tcpip.h>
#include <stdio.h> #include <stdlib.h>
#define MAX_MESSAGE 4068 #define MAX_PACKET 4096 // // Set up some default values // #define DEFAULT_PORT 5150 #define DEFAULT_IP "10.0.0.1" #define DEFAULT_COUNT 5 #define DEFAULT_MESSAGE "This is a test"
//
// Define the IP header. Make the version and length fields one
// character since we can't declare two 4-bit fields without
// the compiler aligning them on at least a 1-byte boundary.
//
typedef struct ip_hdr
{
unsigned char ip_verlen; // IP version & length
unsigned char ip_tos; // IP type of service
unsigned short ip_totallength; // Total length
unsigned short ip_id; // Unique identifier
unsigned short ip_offset; // Fragment offset field
unsigned char ip_ttl; // Time to live
unsigned char ip_protocol; // Protocol(TCP, UDP, etc.)
unsigned short ip_checksum; // IP checksum
unsigned int ip_srcaddr; // Source address
unsigned int ip_destaddr; // Destination address
} IP_HDR, *PIP_HDR, FAR* LPIP_HDR;
//
// Define the UDP header
//
typedef struct udp_hdr
{
unsigned short src_portno; // Source port number
unsigned short dst_portno; // Destination port number
unsigned short udp_length; // UDP packet length
unsigned short udp_checksum; // UDP checksum (optional)
} UDP_HDR, *PUDP_HDR;
//
// Global variables
//
unsigned long dwToIP, // IP to send to
dwFromIP; // IP to send from (spoof)
unsigned short iToPort, // Port to send to
iFromPort; // Port to send from (spoof)
DWORD dwCount; // Number of times to send
char strMessage[MAX_MESSAGE]; // Message to send
//
// Description:
// Print usage information and exit
//
void usage(char *progname)
{
printf("usage: %s [-fp:int] [-fi:str] [-tp:int] [-ti:str]/
[-n:int] [-m:str]/n", progname);
printf(" -fp:int From (sender) port number/n");
printf(" -fi:IP From (sender) IP address/n");
printf(" -fp:int To (recipient) port number/n");
printf(" -fi:IP To (recipient) IP address/n");
printf(" -n:int Number of times to read message/n");
printf(" -m:str Size of buffer to read/n/n");
ExitProcess(1);
}
//
// Function: ValidateArgs
//
// Description:
// Parse the command line arguments, and set some global flags to
// indicate the actions to perform
//
void ValidateArgs(int argc, char **argv)
{
int i;
iToPort = DEFAULT_PORT; iFromPort = DEFAULT_PORT; dwToIP = inet_addr(DEFAULT_IP); dwFromIP = inet_addr(DEFAULT_IP); dwCount = DEFAULT_COUNT; strcpy(strMessage, DEFAULT_MESSAGE);
for(i = 1; i < argc; i++)
{
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
{
switch (tolower(argv[i][1]))
{
case 'f': // From address
switch (tolower(argv[i][2]))
{
case 'p':
if (strlen(argv[i]) > 4)
iFromPort = atoi(&argv[i][4]);
break;
case 'i':
if (strlen(argv[i]) > 4)
dwFromIP = inet_addr(&argv[i][4]);
break;
default:
usage(argv[0]);
break;
}
break;
case 't': // To address
switch (tolower(argv[i][2]))
{
case 'p':
if (strlen(argv[i]) > 4)
iToPort = atoi(&argv[i][4]);
break;
case 'i':
if (strlen(argv[i]) > 4)
dwToIP = inet_addr(&argv[i][4]);
break;
default:
usage(argv[0]);
break;
}
break;
case 'n': // Number of times to send message
if (strlen(argv[i]) > 3)
dwCount = atol(&argv[i][3]);
break;
case 'm':
if (strlen(argv[i]) > 3)
strcpy(strMessage, &argv[i][3]);
break;
default:
usage(argv[0]);
break;
}
}
}
return;
}
//
// Function: checksum
//
// Description:
// This function calculates the 16-bit one's complement sum
// for the supplied buffer
//
USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;
while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (USHORT)(~cksum); }
//
// Function: main
//
// Description:
// First parse command line arguments and load Winsock. Then
// create the raw socket and set the IP_HDRINCL option.
// Following this, assemble the IP and UDP packet headers by
// assigning the correct values and calculating the checksums.
// Then fill in the data and send to its destination.
//
int main(int argc, char **argv)
{
WSADATA wsd;
SOCKET s;
BOOL bOpt;
struct sockaddr_in remote; // IP addressing structures
IP_HDR ipHdr;
UDP_HDR udpHdr;
int ret;
DWORD i;
unsigned short iTotalSize, // Lots of sizes needed to fill
iUdpSize, // the various headers with
iUdpChecksumSize,
iIPVersion,
iIPSize,
cksum = 0;
char buf[MAX_PACKET],
*ptr = NULL;
IN_ADDR addr;
// Parse command line arguments, and print them out
//
ValidateArgs(argc, argv);
addr.S_un.S_addr = dwFromIP;
printf("From IP: <%s>/n Port: %d/n", inet_ntoa(addr),
iFromPort);
addr.S_un.S_addr = dwToIP;
printf("To IP: <%s>/n Port: %d/n", inet_ntoa(addr),
iToPort);
printf("Message: [%s]/n", strMessage);
printf("Count: %d/n", dwCount);
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d/n", GetLastError());
return -1;
}
// Creating a raw socket
//
s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,0);
if (s == INVALID_SOCKET)
{
printf("WSASocket() failed: %d/n", WSAGetLastError());
return -1;
}
// Enable the IP header include option
//
bOpt = TRUE;
ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt,
sizeof(bOpt));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(IP_HDRINCL) failed: %d/n", WSAGetLastError());
return -1;
}
// Initalize the IP header
//
iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + strlen(strMessage);
iIPVersion = 4; iIPSize = sizeof(ipHdr) / sizeof(unsigned long); // // IP version goes in the high-order 4 bits of ip_verlen. The // IP header length (in 32-bit words) goes in the lower 4 bits. // ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize; ipHdr.ip_tos = 0; // IP type of service ipHdr.ip_totallength = htons(iTotalSize); // Total packet len ipHdr.ip_id = 0; // Unique identifier: set to 0 ipHdr.ip_offset = 0; // Fragment offset field ipHdr.ip_ttl = 128; // Time to live ipHdr.ip_protocol = 0x11; // Protocol(UDP) ipHdr.ip_checksum = 0 ; // IP checksum ipHdr.ip_srcaddr = dwFromIP; // Source address ipHdr.ip_destaddr = dwToIP; // Destination address // // Initalize the UDP header // iUdpSize = sizeof(udpHdr) + strlen(strMessage);
udpHdr.src_portno = htons(iFromPort) ; udpHdr.dst_portno = htons(iToPort) ; udpHdr.udp_length = htons(iUdpSize) ; udpHdr.udp_checksum = 0 ; // // Build the UDP pseudo-header for calculating the UDP checksum. // The pseudo-header consists of the 32-bit source IP address, // the 32-bit destination IP address, a zero byte, the 8-bit // IP protocol field, the 16-bit UDP length, and the UDP // header itself along with its data (padded with a 0 if // the data is odd length). // iUdpChecksumSize = 0; ptr = buf; ZeroMemory(buf, MAX_PACKET);
memcpy(ptr, &ipHdr.ip_srcaddr, sizeof(ipHdr.ip_srcaddr)); ptr += sizeof(ipHdr.ip_srcaddr); iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);
memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr)); ptr += sizeof(ipHdr.ip_destaddr); iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);
ptr++; iUdpChecksumSize += 1;
memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol)); ptr += sizeof(ipHdr.ip_protocol); iUdpChecksumSize += sizeof(ipHdr.ip_protocol);
memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length)); ptr += sizeof(udpHdr.udp_length); iUdpChecksumSize += sizeof(udpHdr.udp_length);
memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr); iUdpChecksumSize += sizeof(udpHdr);
for(i = 0; i < strlen(strMessage); i++, ptr++)
*ptr = strMessage[i];
iUdpChecksumSize += strlen(strMessage);
cksum = checksum((USHORT *)buf, iUdpChecksumSize); udpHdr.udp_checksum = cksum; // // Now assemble the IP and UDP headers along with the data // so we can send it // ZeroMemory(buf, MAX_PACKET); ptr = buf;
memcpy(ptr, &ipHdr, sizeof(ipHdr)); ptr += sizeof(ipHdr); memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr); memcpy(ptr, strMessage, strlen(strMessage));
// Apparently, this SOCKADDR_IN structure makes no difference. // Whatever we put as the destination IP addr in the IP header // is what goes. Specifying a different destination in remote // will be ignored. // remote.sin_family = AF_INET; remote.sin_port = htons(iToPort); remote.sin_addr.s_addr = dwToIP;
for(i = 0; i < dwCount; i++)
{
ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote,
sizeof(remote));
if (ret == SOCKET_ERROR)
{
printf("sendto() failed: %d/n", WSAGetLastError());
break;
}
else
printf("sent %d bytes/n", ret);
}
closesocket(s) ;
WSACleanup() ;
return 0; }
本文介绍了一个使用C语言编写的程序,该程序能够手动构造IP和UDP数据包,并通过设置各种字段来实现自定义的数据包发送。文章详细解释了如何初始化IP和UDP头部信息、计算校验和以及如何通过套接字发送这些数据包。


被折叠的 条评论
为什么被折叠?



