winsock으로 rawsocket 보내기

simybh의 이미지

안녕하십니까 전에 winsock으로 rawsocket을 사용하여 tcp syn플래그를 보내는 것에 대해 문의 했었는데요
우선 답변을 주셔서 감사합니다.
알려주신대로 사이트(http://www.codeproject.com/KB/IP/rawsocket.aspx)에서 소스를 다운받아서 컴파일해서
실행해 보니 패킷보낼때 raw소켓 생성시나 send시에 에러는 없는데 이상하게 와이어샤크에서는 잡히지 않네요
windows2000 server이고 vc++6을 사용했습니다.
udp, icmp는 rawsocket으로 잘 갑니다. 와이어샤크에서도 패킷이 뜨구요
따라서 환경이 rawsocket이 발송안되는건 아닌거 같은데 tcp로 보낼때만 와이어샤크에 패킷이 잡히지 않네요
rawsocket이 아닌 SOCK_STREAM으로는 tcp도 잘 갑니다.
아래는 소스입니다. 물론 위 codeproject에서 다운받은 소스이구요

소스변형은 없었구요, 도대체 뭣때문에 tcp패킷이 rawsocket일때 안나가는지,, 알려주세요 ㅜ.ㅜ
이거 한 3주 잡고 있습니다.

//raw tcp packet crafter
 
#include "stdio.h"
#include "winsock2.h"
#include "ws2tcpip.h"  //IP_HDRINCL is here
#include "conio.h"
 
#pragma comment(lib,"ws2_32.lib")  //winsock 2.2 library
 
typedef struct ip_hdr
{
    unsigned char  ip_header_len:4;  // 4-bit header length (in 32-bit words) normally=5 (Means 20 Bytes may be 24 also)
    unsigned char  ip_version   :4;  // 4-bit IPv4 version
    unsigned char  ip_tos;           // IP type of service
    unsigned short ip_total_length;  // Total length
    unsigned short ip_id;            // Unique identifier 
 
	unsigned char  ip_frag_offset   :5;        // Fragment offset field
 
	unsigned char  ip_more_fragment :1;
	unsigned char  ip_dont_fragment :1;
	unsigned char  ip_reserved_zero :1;
 
    unsigned char  ip_frag_offset1;    //fragment offset
 
	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;      // Source address
}   IPV4_HDR, *PIPV4_HDR, FAR * LPIPV4_HDR;
 
 
// TCP header
typedef struct tcp_header 
{ 
	unsigned short source_port;  // source port 
	unsigned short dest_port;    // destination port 
	unsigned int   sequence;     // sequence number - 32 bits 
	unsigned int   acknowledge;  // acknowledgement number - 32 bits 
 
	unsigned char  ns   :1;          //Nonce Sum Flag Added in RFC 3540.
	unsigned char  reserved_part1:3; //according to rfc
	unsigned char  data_offset:4;    /*The number of 32-bit words in the TCP header. 
									   This indicates where the data begins. 
									   The length of the TCP header is always a multiple 
									   of 32 bits.*/
 
	unsigned char  fin  :1;      //Finish Flag
	unsigned char  syn  :1;      //Synchronise Flag
	unsigned char  rst  :1;      //Reset Flag
	unsigned char  psh  :1;      //Push Flag 
	unsigned char  ack  :1;      //Acknowledgement Flag 
	unsigned char  urg  :1;      //Urgent Flag
 
	unsigned char  ecn  :1;      //ECN-Echo Flag
    unsigned char  cwr  :1;      //Congestion Window Reduced Flag
 
	////////////////////////////////
 
	unsigned short window;  // window 
	unsigned short checksum;  // checksum 
	unsigned short urgent_pointer;  // urgent pointer 
}   TCP_HDR , *PTCP_HDR , FAR * LPTCP_HDR , TCPHeader , TCP_HEADER;
 
int main()
{
	char host[100],buf[1000],*data=NULL,source_ip[20]; //buf is the complete packet
	SOCKET s;
	int k=1;
 
	IPV4_HDR *v4hdr=NULL;
	TCP_HDR  *tcphdr=NULL;
 
	int payload=512 , optval;
	SOCKADDR_IN dest;
	hostent *server;
 
	//Initialise Winsock
	WSADATA wsock;
	printf("\nInitialising Winsock...");
	if (WSAStartup(MAKEWORD(2,2),&wsock) != 0)
	{
		fprintf(stderr,"WSAStartup() failed");
        exit(EXIT_FAILURE); 
	} 
	printf("Initialised successfully.");
	////////////////////////////////////////////////
 
	//Create Raw TCP Packet
	printf("\nCreating Raw TCP Socket...");
	if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))==SOCKET_ERROR)
	{
		printf("Creation of raw socket failed.");
		return 0;
	}
	printf("Raw TCP Socket Created successfully.");
	////////////////////////////////////////////////
 
	//Put Socket in RAW Mode.
	printf("\nSetting the socket in RAW mode...");
	if(setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval))==SOCKET_ERROR)
	{
		printf("failed to set socket in raw mode.");
		return 0;
	}
	printf("Successful.");
	////////////////////////////////////////////////
 
 
	//Target Hostname
	printf("\nEnter hostname : ");
	gets(host);
	printf("\nResolving Hostname...");
	if((server=gethostbyname(host))==0)
	{
		printf("Unable to resolve.");
		return 0;
	}
	dest.sin_family = AF_INET;
	dest.sin_port   = htons(50000);  //your destination port
	memcpy(&dest.sin_addr.s_addr,server->h_addr,server->h_length);
	printf("Resolved.");
	/////////////////////////////////////////////////
 
	printf("\nEnter Source IP : ");
	gets(source_ip);
 
 
	v4hdr = (IPV4_HDR *)buf;  //lets point to the ip header portion
	v4hdr->ip_version=4;
	v4hdr->ip_header_len=5;
	v4hdr->ip_tos    = 0;
	v4hdr->ip_total_length = htons ( sizeof(IPV4_HDR) + sizeof(TCP_HDR) + payload );
	v4hdr->ip_id     = htons(2);
	v4hdr->ip_frag_offset = 0;
	v4hdr->ip_frag_offset1 = 0;
	v4hdr->ip_reserved_zero = 0;
	v4hdr->ip_dont_fragment = 1;
	v4hdr->ip_more_fragment = 0;
	v4hdr->ip_ttl    = 8;
	v4hdr->ip_protocol = IPPROTO_TCP;
	v4hdr->ip_srcaddr  = inet_addr(source_ip);
	v4hdr->ip_destaddr = inet_addr(inet_ntoa(dest.sin_addr));
	v4hdr->ip_checksum = 0;
 
	tcphdr = (TCP_HDR *)&buf[sizeof(IPV4_HDR)]; //get the pointer to the tcp header in the packet
 
	tcphdr->source_port = htons(1234);
	tcphdr->dest_port = htons(50000);
 
	tcphdr->cwr=0;
	tcphdr->ecn=1;
	tcphdr->urg=0;
	tcphdr->ack=0;
	tcphdr->psh=0;
	tcphdr->rst=1;
	tcphdr->syn=0;
	tcphdr->fin=0;
	tcphdr->ns=1;
 
	tcphdr->checksum = 0;
 
 
	// Initialize the TCP payload to some rubbish
	data = &buf[sizeof(IPV4_HDR) + sizeof(TCP_HDR)];
	memset(data, '^', payload);
 
 
	printf("\nSending packet...\n");
 
	while(!_kbhit())
	{
		printf("  %d  packets send\r",k++);
		if((sendto(s , buf , sizeof(IPV4_HDR)+sizeof(TCP_HDR) + payload, 0,
               (SOCKADDR *)&dest, sizeof(dest)))==SOCKET_ERROR)
		{
 
		printf("Error sending Packet : %d",WSAGetLastError());
		break;
		}
	}
 
 
	return 0;
}
brucewang의 이미지

전에 어떤 분도 유사한 문제를 가지고 고민 하셔서 답변을 드린 기억이 나는데요,

제가 알기로 MS-Windows의 rawsocket은 connectionless datagram으로 처리 됩니다.

즉, user level application에 생성한 raw socket이 TCP일 경우 network driver 에서 제대로 처리되지 못할 가능성이 있다고 생각되네요... 테스트를 해 본 것은 아닙니다.

하지만, 예를들어 Transport layer 하단에 존재하는 network driver에서는 그 상위 레벨 스택에서 보내는 패킷 구조를 보고 "어라? 이건 ip 이하 레벨에 바인드 한건데 tcp라니? 나를 건너 뛰고 직접 세션 관리를 하겠다는 것인가?, 내가 뭘 어쩌면 되는 것인지 프로그램되어 있지 않네... 무섭다 그냥 drop시키자" 할 수도 있다는 것이죠..

테스트 해보지 않고 답변 드려 죄송합니다. (_ _)

그리고 이와는 별도로 패킷캡쳐 프로그램 구조상 패킷 캡쳐가 안되는 경우도 있습니다. Windows에는 Intercept 할 수 있는 layer 가 많이 있습니다. LSP 라는 dll 기반의 서비스 프로바이더, TPI 레벨 드라이버, IP 레벨 intermediate 드라이버, 그리고 minport driver, 또 제가 모르는 어떤 프레임워크가 있을지도 모릅니다.

아무튼 WinShark 가 사용하는 WinPcap의 경우 IP 레벨 intermediate 드라이버가 사용될 것인데, 이 intermediate 드라이버도 여러 순서에 의해 layering을 할 수 가 있습니다. 아마도 최신버전의 winpcap은 스택상의 상위 레벨에 들어가게 되어, 예를 들어 VPN 등의 경우 암호화 처리가 이미 되어 버린 상태의 결과 밖에 못보게 됩니다.

즉, 제대로 패킷이 전송된다 하더라도, rawsocket이 winpcap이 모니터 가능한 아래 레벨에 바인딩 되서 전송되는 것이라면 보지 못할 가능성도 충분하다는 것이죠.

제대로 확인 해 보시려면, dummy hub 에 다른 컴퓨터를 연결해서 그 다른 컴퓨터에서 패킷을 잡아보시면 되겠습니다.

저도 결과가 궁금하니 꼭 후기를 올려주시면 고맙겠습니다.......

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

simybh의 이미지

확인해 보니 어뎀터를 잘못지정해서 나타난 현상이었습니다. codeproject 사이트 소스는 정상적으로 syn 패킷을 전달 하더군요
근데 한가지,,
win2k에서는 되는데 xp에서는 안되던데 xp(sp2) 부터는 tcp data는 rawsock이 안된다고 msdn에 나와 있는데 혹시 xp에서도
rawsocket을 사용할수 있는 방법이 있는지요?
예로 레지스터리를 수정한다던가 하는 방법으로,,

brucewang의 이미지

앗 그것은 제가 경험해보지 못한 것이네요.
저도 인터넷을 찾아 보는 수 밖에 없을 것 같습니다. 혹시 나중에 알게 되면 댓글 드리겠습니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

brucewang의 이미지

여러 솔루션이 있던것 같군요.
http://forums.techguy.org/networking/524127-solved-need-enable-raw-socket.html

이 외에도 다양한 방법이 있는것 같습니다. 한번 시간을 내보셔서 찾아보시면 더 좋을 듯 합니다.
어떤 프로그램을 배포하실 생각이 아니시라면 XP Home을 사용하시면 될 것 같네요.

이 SP2의 제약 사항에 대해 말들이 많았군요.
http://www.interact-sw.co.uk/iangblog/2004/08/12/norawsockets
http://silverstr.ufies.org/blog/archives/000666.html

MS Windows의 절대 다수 사용자층은 자신도 모르는 사이에 zombie가 될 수 있으니까요. 개발자들에게 욕을 먹더라도...사용자층이 많은 XP가 DDOS에 사용되는 (자의적이건 Zombie화 되건)것을 막기 위한 어쩔 수 없는 선택이었을지도 모르겠습니다.

-------------------------------------------------
$yes 4 8 15 16 23 42

-------------------------------------------------
$yes 4 8 15 16 23 42

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.