原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM、SOCK_DGRAM的套接字,它实现于系统核心。然而,原始套接字能做什么呢?首
先来说,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利
用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。总体来说,SOCK_RAW可以处理普通的网络报文之外,还可以处理
一些特殊协议报文以及操作IP层及其以上的数据。
既然SOCK_RAW有以上特性,所以在某些处理流程上它区别于普通套接字。
·  若设置IP_HDRINCL选项,SOCK_RAW可以操作IP头数据(也就是用户需用填充IP头及其以上的payload);否则SOCK_RAW无法操
作IP头数据
·  端口对于SOCK_RAW而言没有任何意义
·  如果使用bind函数绑定本地IP,那么如果IP_HDRINCL未设置,则用此IP填充源IP地址;若不调用bind则将源IP地址设置为外
出接口的主IP地址
·  如果使用connect函数设置目标IP,则可以使用send或者write函数发送报文,而不需要使用sendto函数
·  内核处理流程:
·  接收到的TCP、UDP分组不会传递给任何SOCK_RAW
·  ICMP、IGMP报文分组传递给SOCK_RAW
·  内核不识别的IP报文传递给SOCK_RAW
·  SOCK_RAW是否接收报文:
·  Protocol指定类型需要匹配,否则不传递给该SOCK_RAW
·  如果使用bind函数绑定了源IP,则报文目的IP必须和绑定的IP匹配,否则不传递给该SOCK_RAW
·  如果使用connect函数绑定了目的IP,则报文源IP必须和指定的IP匹配,否则不传递给该SOCK_RAW 
综上所述,原始套接字处理的只是IP层及其以上的数据,比如实现SYN FLOOD攻击、处理PING报文等。当需要操作更底层的数据的
时候,就需要采用其他的方式。其中 SOCK_STREAM、SOCK_DGRAM 工作在传输层,SOCK_RAW 工作在网络层。SOCK_RAW 可以 处理
ICMP、IGMP等网络报文、特殊的IPv4报文、可以通过IP_HDRINCL套接字选项由用户构造IP头。

Windows2000在TCP/IP协议组件上做了很多改进,功能也有增强。比如在协议栈上的调整,增大了默认窗口大小,以及高延迟链接新算法。同时在安全性上,可应用IPSec加强安全性,比NT下有不少的改进。

Microsoft TCP/IP 组件包含 “核心协议 ”、 “服务 ”及两者之间的 “接口 ”。传输驱动程序接口 (TDI) 与网络设备接口规范 (NDIS) 是公用的。此外,还有许多用户模型应用程序的更高级接口。最常用的接口是 Windows Sockets、远程过程调用 (RPC)和 NetBIOS。
  Windows Sockets 是一个编程接口,它是在加州大学伯克利分校开发的套接字接口的基础上定义的。它包括了一组扩展件,以充分利用 Microsoft Windows消息驱动的特点。规范的 1.1版是在 1993年 1月发行的, 2.2.0版在 1996年 5月发行。 Windows 2000支持 Winsock 2.2版。在 Winsock2中,支持多个传输协议的原始套接字,重叠 I/O模型、服务质量控制等。
  这里介绍 Windows Sockets的一些关于原始套接字 (Raw Socket)的编程。同 Winsock1相比,最明显的就是支持了 Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制 Windows下的多种协议,而且能够对网络底层的传输机制进行控制。
1、创建一个原始套接字,并设置 IP头选项。
SOCKET sock;
sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
或者:
s = WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);
  这里,我们设置了 SOCK_RAW标志,表示我们声明的是一个原始套接字类型。创建原始套接字后, IP头就会包含在接收的数据中,如果我们设定 IP_HDRINCL选项,那么,就需要自己来构造 IP头。注意,如果设置 IP_HDRINCL选项,那么必须具有 administrator权限,要不就必须修改注册表:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Afd\Parameter\
修改键: DisableRawSecurity(类型为 DWORD),把值修改为 1。如果没有,就添加。
BOOL blnFlag=TRUE;
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&blnFlag, sizeof(blnFlag);
  对于原始套接字在接收数据报的时候,要注意这么几点:
1、如果接收的数据报中协议类型和定义的原始套接字匹配,那么,接收的所有数据就拷贝到套接字中。
2、如果绑定了本地地址,那么只有接收数据 IP头中对应的远端地址匹配,接收的数据就拷贝到套接字中。
3、如果定义的是外部地址,比如使用 connect(),那么,只有接收数据 IP头中对应的源地址匹配,接收的数据就拷贝到套接字中。

// tt2.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Windows.h>#pragma comment(lib,"WS2_32")//定义IP首部
typedef struct ip_hdr
{ unsigned char h_verlen;           //4位首部长度,4位IP版本号 unsigned char tos;             //8位服务类型TOS unsigned short total_len;       //16位总长度(字节) unsigned short ident;            //16位标识 unsigned short frag_and_flags;  //3位标志位 unsigned char ttl;              //8位生存时间 TTL unsigned char proto;           //8位协议 (TCP, UDP 或其他) unsigned short checksum;      //16位IP首部校验和 unsigned int sourceIP;         //32位源IP地址 unsigned int destIP;         //32位目的IP地址
}IPHEADER; //定义TCP伪首部
typedef struct tsd_hdr
{ unsigned long saddr;          //源地址 unsigned long daddr;          //目的地址 char mbz; char ptcl;                     //协议类型 unsigned short tcpl;         //TCP长度
}PSDHEADER; //定义TCP首部
typedef struct tcp_hdr
{ USHORT th_sport;              //16位源端口 USHORT th_dport;               //16位目的端口 unsigned int th_seq;          //32位序列号 unsigned int th_ack;           //32位确认号 unsigned char th_lenres;       //4位首部长度/6位保留字 unsigned char th_flag;           //6位标志位 USHORT th_win;                  //16位窗口大小 USHORT th_sum;                    //16位校验和 USHORT th_urp;                 //16位紧急数据偏移量
}TCPHEADER; //CheckSum:计算校验和的子函数
USHORT checksum(USHORT *buffer, int size)
{ unsigned long cksum=0; while(size >1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size ) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum);
} int _tmain(int argc, _TCHAR* argv[])
{WSADATA WSAData; SOCKET sock; SOCKADDR_IN addr_in; IPHEADER ipHeader; TCPHEADER tcpHeader; PSDHEADER psdHeader; char szSendBuf[60]={0}; BOOL flag; int rect,nTimeOver; if (WSAStartup(MAKEWORD(2,0), &WSAData)!=0) { printf("WSAStartup Error!\n"); return false; } if ((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET){ printf("Socket Setup Error!\n"); return false; } flag=true; if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR) { printf("setsockopt IP_HDRINCL error!\n"); return false; } nTimeOver=1000; if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR) { printf("setsockopt SO_SNDTIMEO error!\n"); return false; } addr_in.sin_family=AF_INET; addr_in.sin_port=htons(4000); addr_in.sin_addr.S_un.S_addr=inet_addr("192.168.0.20"); //填充IP首部 ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long)); // ipHeader.tos=0; ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader)); ipHeader.ident=1; ipHeader.frag_and_flags=0; ipHeader.ttl=128; ipHeader.proto=IPPROTO_TCP; ipHeader.checksum=0; ipHeader.sourceIP=inet_addr("192.168.0.222"); ipHeader.destIP=inet_addr("192.168.0.20"); //填充TCP首部 tcpHeader.th_dport=htons(4000); tcpHeader.th_sport=htons(7234); //源端口号 tcpHeader.th_seq=htonl(0x12345678); tcpHeader.th_ack=0; tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0); tcpHeader.th_flag=2; //修改这里来实现不同的标志位探测,2是SYN,1是FIN,16是ACK探测等等 tcpHeader.th_win=htons(512); tcpHeader.th_urp=0; tcpHeader.th_sum=0; psdHeader.saddr=ipHeader.sourceIP; psdHeader.daddr=ipHeader.destIP; psdHeader.mbz=0; psdHeader.ptcl=IPPROTO_TCP; psdHeader.tcpl=htons(sizeof(tcpHeader)); //计算校验和 memcpy(szSendBuf, &psdHeader, sizeof(psdHeader)); memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader)); tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader)); memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4); ipHeader.checksum=checksum((USHORT *)szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader)); memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader), 0, (struct sockaddr*)&addr_in, sizeof(addr_in)); if (rect==SOCKET_ERROR) { printf("send error!:%d\n",WSAGetLastError()); return false; } else {printf("send ok!\n"); }closesocket(sock); WSACleanup(); Sleep(110000);return 0;
}

4、接收数据
  和发送原始套接字数据相比,接收就比较麻烦了。因为在 WIN我们不能用 recv()来接收 raw socket上的数据,这是因为,所有的 IP包都是先递交给系统核心,然后再传输到用户程序,当发送一个 raws socket包的时候(比如 syn),核心并不知道,也没有这个数据被发送或者连接建立的记录,因此,当远端主机回应的时候,系统核心就把这些包都全部丢掉,从而到不了应用程序上。所以,就不能简单地使用接收函数来接收这些数据报。要达到接收数据的目的,就必须采用嗅探,接收所有通过的数据包,然后进行筛选,留下符合我们需要的。可以再定义一个原始套接字,用来完成接收数据的任务,需要设置 SIO_RCVALL,表示接收所有的数据。
SOCKET sniffersock;
sniffsock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
DWORD lpvBuffer = 1;
DWORD lpcbBytesReturned = 0 ;
WSAIoctl(sniffersock, SIO_RCVALL, &lpvBuffer, sizeof(lpvBuffer), NULL, 0, & lpcbBytesReturned, NULL, NULL);
  创建一个用于接收数据的原始套接字,我们可以用接收函数来接收数据包了。然后在使用一个过滤函数达到筛选的目的,接收我们需要的数据包。
在 http://www.xici.net/board/doc.asp?id=5891453&sub=15提供了一个完整的发送和接收的程序,可以参考。

Raw Socket编程相关推荐

  1. linux raw socket 例子,raw socket编程例子

    raw socket编程例子内容安排: 1.原始套接字介绍 1.1 原始套接字工作原理与规则 1.2 简单应用 2 FTP密码窃取器实现(简单的rootkit) 2.1 设计思路 2.2 实现 2.3 ...

  2. C#下的Raw Socket编程实现网络封包监视

    谈起socket编程,大家也许会想起QQ和IE,没错.还有许多网络工具如P2P.NetMeeting等在应用层实现的应用程序,也是用socket来实现的.Socket是一个网络编程接口,实现于网络应用 ...

  3. 用C#下的Raw Socket编程实现网络封包监视(摘录)

    谈起socket编程,大家也许会想起QQ和IE,没错.还有许多网络工具如P2P.NetMeeting等在应用层实现的应用程序,也是用 socket来实现的.Socket是一个网络编程接口,实现于网络应 ...

  4. raw socket java_记一次蛋疼的Raw socket发送经历。附:Raw socket编程总结

    最近在做信息安全导论的实验,实验很简单,就是实现一个ping程序,能够扫描主机是否打开的情况,但是,我也就纳了闷了,每次有个不易发现的bug(可能由于自己知识有限造成的),都得让我碰上,并且还得为这个 ...

  5. 基于原始套接字(raw socket)的网络抓包工具

    基于raw socket的网络抓包工具 1. 原始套接字(raw socket)简介 原始套接字可以接收本机网卡上的数据帧或者数据包,利用raw socket可以编写基于IP协议的程序.一般的TCP/ ...

  6. Raw Socket和Socket编程

    1.原始套接字(raw socket) 1.1 原始套接字工作原理与规则          原始套接字是一个特殊的套接字类型,它的创建方式跟TCP/UDP创建方法几乎是 一摸一样,例如,通过 CODE ...

  7. socket 编程(四) Linux raw socket

    Linux raw socket demo 抓包: #include <stdio.h> #include <stdlib.h> #include <string.h&g ...

  8. 用C#的Raw Socket实现网络封包监视

    <script language="javascript" src="/ad/js/edu_left_300-300.js" type="tex ...

  9. python 图形化socket编程_Python黑帽编程2.8 套接字编程

    Python黑帽编程2.8 套接字编程 套接字编程在本系列教程中地位并不是很突出,但是我们观察网络应用,绝大多数都是基于Socket来做的,哪怕是绝大多数的木马程序也是如此.官方关于socket编程的 ...

最新文章

  1. pta 插入排序还是堆排序
  2. linux重做引导分区,linuxgrub 0.97三重引导,基本无解,除非重做硬盘
  3. 我国有线电视信源编码现有体制和对高清的制约
  4. Power Strings_JAVA
  5. 一个关于VOFM的文章
  6. loadrunner脚本运行时设置:Run Logic设置运行次数
  7. 【详解】C语言:编写一个函数itob(int n,char s[], int b),将整数n转换为以b进制的数。保存到s中。...
  8. 文件管理器android开源,寻找优秀的安卓文件管理器 五款文件管理器大评比
  9. Luogu P5008 逛庭院
  10. (16)python_random学习笔记
  11. RTI_DDS自定义插件开发 7 资源
  12. Python编程:pycharm开发工具汉化步骤
  13. 百度搜索跳过验证码_百度搜索是死是活?网友吵翻了天,你觉得呢
  14. Java实例(1)BMI计算
  15. 小米路由器R3G救砖TTL教程
  16. 深入浅出Java Object Layout (JOL)
  17. RabbitTMQ实战 高效部署分布式消息队列笔记
  18. matlab雷达处理工具箱,GitHub - feng-zx/radar_tools: 雷达信号处理工具箱
  19. 免费2022车载导航。
  20. 使用NPOI创建行折叠效果的Excel文件

热门文章

  1. MybatisPlus入门之介绍
  2. System类的常用方法
  3. Spring Schedule定时关单快速入门
  4. 设计模式之_Strategy_02
  5. 学计算机的男孩子怎么追女孩子,男孩子追女孩子的套路,原来有这么多,快来学一学...
  6. linux防火墙阻断目的,基于Linux防火墙的内部邮件监控与阻断系统
  7. mycat配置访问oracle_教程 | MySql都会了,确定不学习一下MyCat分片?
  8. free: seconds argument `1‘ failed
  9. git遇到的问题-- Another git process seems to be running in this repository
  10. 中国香港地区 DDoS- botnet 态势分析