標籤:des style class http tar color
由於使用Raw Socket的時候,IP前序可完全由程式員自訂,所以我們可以任意地修改本地發送包的IP地址,使得接收方錯誤的認為IP報文是由欺騙地址發出的。
下面的程式示範了向某目標發送IP地址偽裝的UDP報文的過程:
void sendPesuoIpUDP(void) { WSADATA wsd; if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) { printf("WSAStartup() failed: %d ", GetLastError()); return; } SOCKET s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,WSA_FLAG_OVERLAPPED); // Create a raw socket if (s == INVALID_SOCKET) { printf("WSASocket() failed: %d ", WSAGetLastError()); return - 1; }
BOOL bOpt = TRUE; int ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char*) &bOpt, sizeof(bOpt)); // 使用IP_HDRINCL if (ret == SOCKET_ERROR) { printf("setsockopt(IP_HDRINCL) failed: %d ", WSAGetLastError()); return - 1; }
const int BUFFER_SIZE = 80; char buffer[BUFFER_SIZE];
const char *strMessage = "treat demo"; // Message to send
// Set IP header IP_HDR ipHdr; UDP_HDR udpHdr;
const unsigned short iIPSize = sizeof(ipHdr) / sizeof(unsigned long); const unsigned short iIPVersion = 4; ipHdr.ip_verlen = (iIPVersion << 4) | iIPSize; ipHdr.ip_tos = 0; // IP type of service const unsigned short iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + strlen(strMessage); 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 const char *target_ip_address = "192.168.0.102"; const char *treat_ip_address = "1.0.5.7"; ipHdr.ip_destaddr = inet_addr(target_ip_address); // 接收方IP地址 ipHdr.ip_srcaddr = inet_addr(treat_ip_address); // 發送方偽造的IP地址
// Set UDP header const u_short uToPort = 8000; udpHdr.dst_portno = htons(uToPort); // 接收方連接埠
const u_short uFromPort = 1000; udpHdr.src_portno = htons(uFromPort); // 發送偽造的連接埠
const unsigned short iUdpSize = sizeof(udpHdr) + strlen(strMessage); udpHdr.udp_length = htons(iUdpSize); udpHdr.udp_checksum = 0;
// 組建待發送的UDP報文 ZeroMemory(buffer, BUFFER_SIZE); char *ptr = buffer;
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.
sockaddr_in remote; remote.sin_family = AF_INET; remote.sin_port = htons(8000); remote.sin_addr.s_addr = inet_addr("192.168.0.102");
printf("TO %s:%d ", target_ip_address, uToPort);
ret = sendto(s, buffer, iTotalSize, 0, (SOCKADDR*) &remote, sizeof(remote)); // 發送偽造的報文 if (ret == SOCKET_ERROR) { printf("sendto() failed: %d ", WSAGetLastError()); } else printf("sent %d bytes ", ret);
closesocket(s); WSACleanup(); return; } |
如果我們在第4節描述的ICMP FLOOD攻擊中偽造IP地址,則對方將無法檢測出究竟是誰在對其進行攻擊,實際上,這也是一種非常常用的駭客攻擊中隱藏自身的途徑。