[[질문]winsock을 사용하여 rawsocket으로 syn 패킷 보내기
글쓴이: simybh / 작성시간: 월, 2008/08/04 - 12:22오후
고수님들 알려주세요,,
winsock을 사용하여 rawsocket으로 syn패킷을 보낼려고 합니다
linux 소캣프로그래밍을 초보수준으로 해본터라 winsock도 linux와 약간차이가 있지만 별어려움 없이 구현하겠는데
rawsocket은 해더정의부터 햇깔립니다. ㅡ.ㅡ
linux는 각 해더들이 정의되어 있어 값만 잘 채우면 됬었는데 winsock은 일일이 해더를 정의해 주어야 하더군요,,
또 tcp, ip, icmp등 각 해더들이 winsock과 linux와약간씩 다른거 같습니다. 잘 몰라서 그런지;;
arp 해더는 winsock은 못찾겠더군요
rawsock으로 udp, icmp는 인터넷에서 자료를 구해서 구현을 했는데 이상하게 tcp로 구현한 rawsocket은 못찾겠네요
rawsocket으로 구현한 udp와 비슷한 로직에 tcp해더를 구현해주고 체크섬만 정확하게 해주면 될거 같은데
자료가 없어서 안됩니다.
아래 코드대로 해 봤는데 windows 2000 ad server에서 vc++6.0입니다.
아마 해더정의가 잘못되었거나 체크섬을 잘못계산하거나 그중 하나일거 같은데,,
혹시 winsock쪽에 rawsocket에 관한 책이 있으면 추천 부탁드립니다
#include <winsock2.h> #include <stdio.h> #include "ws2tcpip.h" //IP_HDRINCL is here struct ip_hdr { unsigned char ip_ver; //4bit ipv4 version //4bit ip header length unsigned char ip_tos; //ip tos unsigned short ip_totallength; //total length unsigned short ip_id; //id unsigned short ip_off; //offset unsigned char ip_ttl; //ttl unsigned char ip_protocol; //protocol unsigned short sum; //checksum unsigned int ip_srcaddr; //source unsigned int ip_destaddr; //dest }; struct tcp_hdr { unsigned short th_sport; //src port unsigned short th_dport; //dest port unsigned long seq; //sequence number unsigned long ack; //acknowledgement number unsigned char data; //offset unsigned char flag; //flag unsigned short win; //window unsigned short sum; //checksum unsigned short urgptr; //urgent pointer }; struct pseudohdr { unsigned int saddr; unsigned int daddr; unsigned char useless; unsigned char protocol; unsigned short tcplength; }; unsigned short in_chksum(unsigned short *addr, int len) { int sum = 0; int nleft = len; u_short *w=addr; u_short answer = 0; while(nleft >1) { sum +=*w++; nleft -= 2; } if(nleft == 1) { *(u_char *)(&answer) = *(u_char *)w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return (answer); } int main() { struct sockaddr_in target_addr; struct sockaddr_in your_addr; ip_hdr *iphdr; tcp_hdr *tcphdr; pseudohdr * pe; SOCKET s; WSADATA wsaData; WORD wVersionRequested = MAKEWORD(2,2); char buf[1500], *data; int optval, nRet; int payload; payload = 1500; // Init WinSock nRet = WSAStartup(wVersionRequested, &wsaData); if (nRet) { fprintf(stderr,"\nError initializing WinSock\n"); return 0; } // Check version if (wsaData.wVersion != wVersionRequested) { fprintf(stderr,"\nWinSock version not supported\n"); return 0; } target_addr.sin_family = AF_INET; target_addr.sin_addr.s_addr = inet_addr("192.168.10.102"); target_addr.sin_port = htons(1500); your_addr.sin_addr.s_addr = inet_addr("192.168.10.101"); your_addr.sin_port = htons(1500); iphdr = (struct ip_hdr *)buf; tcphdr = (struct tcp_hdr *)&buf[sizeof(struct ip_hdr)]; pe = (struct pseudohdr *)((char*)tcphdr-sizeof(struct pseudohdr)); pe->saddr = your_addr.sin_addr.s_addr; pe->daddr = target_addr.sin_addr.s_addr; pe->protocol = IPPROTO_TCP; pe->tcplength = htons(sizeof(struct tcp_hdr)); iphdr->ip_ver = (4<<4) | (sizeof(ip_hdr) /sizeof(ULONG)); iphdr->ip_tos = 0; iphdr->ip_totallength = htons(sizeof(ip_hdr) + sizeof(tcp_hdr) + payload); iphdr->ip_id = rand()%0xffff; iphdr->ip_off = 0; iphdr->ip_ttl = 8; iphdr->ip_protocol = IPPROTO_TCP; iphdr->sum = 0; iphdr->ip_srcaddr = inet_addr("192.168.10.101"); iphdr->ip_destaddr = inet_addr("192.168.10.102"); iphdr->sum = in_chksum((u_short *)&iphdr, sizeof(ip_hdr)); tcphdr->th_sport = htons(1500); tcphdr->th_dport = htons(80); tcphdr->flag = 0x02; //syn패킷 tcphdr->data = 0; tcphdr->seq = htonl(100); tcphdr->ack = htonl(0); tcphdr->win = htons(512); tcphdr->urgptr = 0; tcphdr->sum = in_chksum((u_short *)pe,(sizeof(struct pseudohdr)+sizeof(struct tcp_hdr))); data = &buf[sizeof(ip_hdr) + sizeof(tcp_hdr)]; memset(data,'@',payload); s = socket(AF_INET,SOCK_RAW,IPPROTO_RAW); optval = 1; setsockopt(s,IPPROTO_IP,IP_HDRINCL, (char *) &optval, sizeof(optval)); sendto(s,buf,sizeof(ip_hdr) + sizeof(tcp_hdr)+payload, 0, (SOCKADDR *)&target_addr, sizeof(target_addr)); // Free WinSock WSACleanup(); return 0; }
Forums:
Linux에서는 어떤지
Linux에서는 어떤지 모르겠는데, MS-Windows에서는 raw socket은 모두 connectionless datagram으로 처리됩니다. MS Windows Network programming에 여러 책이 있겠지만, MSDN을 참고하시는 것 만으로도 많은 정보를 얻으실 수 있을것 같습니다.
http://msdn.microsoft.com/en-us/library/ms740548.aspx
Windows에서 모든 TCP connection은 kernel driver에서 처리되어 user level의 winsock 레이어에 그 결과가 전달되는데, 따라서 raw socket으로 syn을 보내시더라도 모든 reply/send는 알아서 처리하셔야 할 것 같네요. 즉 보내신 syn과 windows의 network driver는 전혀 관계 없이 진행될것 같습니다.
codeproject.com 이라는 곳이 있는데, Windows programmer들에겐 잘 알려진 사이트가 있어서 소개를 해드립니다.
http://www.codeproject.com/KB/IP/rawsocket.aspx
그리고, 구성하려는 packet헤더 정보 특히 arp 같은것들은 아마 rfc내용이나 linux 소스코드에 있는것들을 복사해서 쓰시면 될 것 같습니다.
-------------------------------------------------
$yes 4 8 15 16 23 42
댓글 달기