SYN (synchronize)

SYN是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN-ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。 TCP连接的第一个包,非常小的一种数据包。SYN 攻击包括大量此类的包,由于这些包看上去来自实际不存在的站点,因此无法有效进行处理。每个机器的欺骗包都要花几秒钟进行尝试方可放弃提供正常响应。

SYN攻击属于DoS攻击的一种,它利用TCP协议缺陷,通过发送大量的半连接请求,耗费CPU和内存资源。SYN攻击除了能影响主机外,还可以危害路由器、防火墙等网络系统,事实上SYN攻击并不管目标是什么系统,只要这些系统打开TCP服务就可以实施。服务器接收到连接请求(syn= j),将此信息加入未连接队列,并发送请求包给客户(syn=k,ack=j+1),此时进入SYN_RECV状态。当服务器未收到客户端的确认包时,重发请求包,一直到超时,才将此条目从未连接队列删除。配合IP欺骗,SYN攻击能达到很好的效果,通常,客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。

下面我们来亲自体验SYN编程,实现安全隐患监测

先实现检测主机信息

#include <winsock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32.lib")
int main()
{// 初始化 Windows sockets API.//WORD wVersionRequested = MAKEWORD(2, 2);WSADATA wsaData;if (WSAStartup(wVersionRequested, &wsaData)) {printf("WSAStartup failed %s\n", WSAGetLastError());return 0;}//// 获得主机名.//char hostname[256];int res = gethostname(hostname, sizeof(hostname));if (res != 0) {printf("Error: %u\n", WSAGetLastError());return 0;}printf("hostname=%s\n", hostname);// 根据主机名获取主机信息. //hostent* pHostent = gethostbyname(hostname);if (pHostent==NULL) {printf("Error: %u\n", WSAGetLastError());return 0;}//// 解析返回的hostent信息.//hostent& he = *pHostent;printf("name=%s\naliases=%s\naddrtype=%d\nlength=%d\n",he.h_name, he.h_aliases, he.h_addrtype, he.h_length);sockaddr_in sa;//根据 he.h_addr_list[nAdapter]是否为空来获取所有IP地址for (int nAdapter=0; he.h_addr_list[nAdapter]; nAdapter++) {memcpy ( &sa.sin_addr.s_addr, he.h_addr_list[nAdapter],he.h_length);// 输出机器的IP地址.printf("Address [%d%]: %s\n",nAdapter, inet_ntoa(sa.sin_addr)); // 显示地址串}//// 终止 Windows sockets API//WSACleanup();return 0;
}

下面开始SYN 扫描

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>#include <time.h>
#include "mstcpip.h"
#pragma comment(lib,"ws2_32.lib")
#define SEQ 0x28376839SOCKET sockRaw = INVALID_SOCKET,
sockListen = INVALID_SOCKET;
struct sockaddr_in dest;BOOL ScanOK=FALSE;
char *DEST_HOST;
int DEST_PORT;
int DEST_PORTEND;
int play=0;
clock_t start,end;//程序运行的起始和结束时间
float costtime;//程序耗时typedef struct _iphdr
{
unsigned char h_lenver; //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地址
}IP_HEADER;typedef struct _tcphdr //定义TCP首部
{
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位紧急数据偏移量
}TCP_HEADER; struct //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}psd_header;//SOCK错误处理程序
void CheckSockError(int iErrorCode, char *pErrorMsg)
{
if(iErrorCode==SOCKET_ERROR)
{
printf("%s Error:%d\n", pErrorMsg, GetLastError());
closesocket(sockRaw);
ExitProcess(-1);
}}//计算检验和
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);
}//IP解包程序
bool DecodeIPHeader(char *buf, int bytes)
{
IP_HEADER *iphdr;
TCP_HEADER *tcphdr;
unsigned short iphdrlen;
iphdr = (IP_HEADER *)buf;
iphdrlen = sizeof(unsigned long) * (iphdr->h_lenver & 0xf);
tcphdr = (TCP_HEADER*)(buf + iphdrlen);
//是否来自目标IP
if(iphdr->sourceIP != dest.sin_addr.s_addr) return false;//序列号是否正确
if((ntohl(tcphdr->th_ack) != (SEQ+1)) && (ntohl(tcphdr->th_ack) != SEQ)) return false;
//if(tcphdr->th_flag == 20)return true;
//SYN/ACK - 扫描到一个端口
if(tcphdr ->th_flag == 18)
{
printf("\t%d\t open \n",ntohs(tcphdr->th_sport));
return true;
}return true;
}void usage(void)
{
printf("\t===================SYN portscaner======================\n");
printf("\t============gxisone@hotmail.com     2004/7/6===========\n");
printf("\tusage: synscan DomainName[IP] StartPort-EndPort\n");
printf("\tExample: synscan www.163.com 1-139\n");
printf("\tExample: synscan 192.168.1.1 8000-9000\n");
}DWORD WINAPI RecvThread(LPVOID para)//接收数据线程函数
{
int iErrorCode;
struct hostent *hp;
char RecvBuf[65535]={0};
sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockListen, "socket");//设置IP头操作选项
BOOL bOpt = true;
iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&bOpt,sizeof(bOpt));
CheckSockError(iErrorCode, "setsockopt()"); //获得本地IP
SOCKADDR_IN sa;
unsigned char LocalName[256];iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
CheckSockError(iErrorCode, "gethostname()");
if((hp = gethostbyname((char*)LocalName)) == NULL)
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
memcpy(&sa.sin_addr.S_un.S_addr,hp->h_addr_list[1],hp->h_length);
sa.sin_family = AF_INET;
sa.sin_port = htons(7000);
iErrorCode = bind(sockListen, (PSOCKADDR)&sa, sizeof(sa));
CheckSockError(iErrorCode, "bind");//设置SOCK_RAW为SIO_RCVALL,以便接收所有的IP包
DWORD dwBufferLen[10] ;
DWORD dwBufferInLen = 1 ;
DWORD dwBytesReturned = 0 ;
iErrorCode=WSAIoctl(sockListen, SIO_RCVALL,&dwBufferInLen, sizeof(dwBufferInLen),&dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL );
CheckSockError(iErrorCode, "Ioctl");
memset(RecvBuf, 0, sizeof(RecvBuf));
//接收数据
for(;;)
{iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
//CheckSockError(iErrorCode, "recv");
DecodeIPHeader(RecvBuf,iErrorCode) ;
}
if(ScanOK)
{closesocket(sockListen);return 0;
}
}void playx(void)  // 定义状态提示函数
{
// 进度条
char *plays[12]=
{ " | ", " / ", " - ", " \\ ", " | ", " / ", " - ", " \\ ", " | ", " / ", " - ", " \\ ",
};
printf(" =%s=\r", plays[play]);
play=(play==11)?0:play+1;
Sleep(2);
} //主函数
int main(int argc,char **argv)
{
char *p;
if(argc!=3)
{
usage();
return 0;
}p=argv[2];//处理端口参数if(strstr(argv[2],"-")){    DEST_PORT=atoi(argv[2]);for(;*p;)if(*(p++)=='-')break;DEST_PORTEND=atoi(p);if(DEST_PORT<1 || DEST_PORTEND>65535){    printf("Port Error!\n");return 0;}}DEST_HOST=argv[1];usage();int iErrorCode;
int datasize;
struct hostent *hp;
IP_HEADER ip_header;
TCP_HEADER tcp_header;
char SendBuf[128]={0};//初始化SOCKET
WSADATA wsaData;
iErrorCode = WSAStartup(MAKEWORD(2,2),&wsaData);
CheckSockError(iErrorCode, "WSAStartup()");
sockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockRaw, "socket()");
sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
CheckSockError(sockListen, "socket");//设置IP头操作选项
BOOL bOpt = true;
iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&bOpt,sizeof(bOpt));
CheckSockError(iErrorCode, "setsockopt()"); //获得本地IP
SOCKADDR_IN sa;
unsigned char LocalName[256];iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
CheckSockError(iErrorCode, "gethostname()");
if((hp = gethostbyname((char*)LocalName)) == NULL)
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}memcpy(&sa.sin_addr.S_un.S_addr,hp->h_addr_list[1],hp->h_length);
sa.sin_family = AF_INET;
sa.sin_port = htons(7000);
iErrorCode = bind(sockListen, (PSOCKADDR)&sa, sizeof(sa));
CheckSockError(iErrorCode, "bind");//获得目标主机IP
memset(&dest,0,sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(DEST_PORT);
if((dest.sin_addr.s_addr = inet_addr(DEST_HOST)) == INADDR_NONE)
{
if((hp = gethostbyname(DEST_HOST)) != NULL)
{
memcpy(&(dest.sin_addr),hp->h_addr_list[1],hp->h_length);
dest.sin_family = hp->h_addrtype;
printf("dest.sin_addr = %s\n",inet_ntoa(dest.sin_addr));
}
else
{
CheckSockError(SOCKET_ERROR, "gethostbyname()");
}
}//开启监听线程
HANDLE Thread=CreateThread(NULL,0,RecvThread,0,0,0);//填充IP首部
ip_header.h_lenver=(4<<4 | sizeof(ip_header)/sizeof(unsigned long));
//高四位IP版本号,低四位首部长度
ip_header.total_len=htons(sizeof(IP_HEADER)+sizeof(TCP_HEADER)); //16位总长度(字节)
ip_header.ident=1; //16位标识
ip_header.frag_and_flags=0; //3位标志位
ip_header.ttl=128; //8位生存时间TTL
ip_header.proto=IPPROTO_TCP; //8位协议(TCP,UDP…)
ip_header.checksum=0; //16位IP首部校验和
ip_header.sourceIP=sa.sin_addr.s_addr; //32位源IP地址
ip_header.destIP=dest.sin_addr.s_addr; //32位目的IP地址//填充TCP首部
tcp_header.th_sport=htons(7000); //源端口号
tcp_header.th_lenres=(sizeof(TCP_HEADER)/4<<4|0); //TCP长度和保留位
tcp_header.th_win=htons(16384); //填充TCP伪首部(用于计算校验和,并不真正发送)
psd_header.saddr=ip_header.sourceIP;
psd_header.daddr=ip_header.destIP;
psd_header.mbz=0;
psd_header.ptcl=IPPROTO_TCP;
psd_header.tcpl=htons(sizeof(tcp_header));Sleep(500);
printf("\n");
printf("Scaning %s\n",DEST_HOST);
start=clock();//开始计时for(;DEST_PORT<DEST_PORTEND;DEST_PORT++)
{playx();
tcp_header.th_dport=htons(DEST_PORT); //目的端口号
tcp_header.th_ack=0; //ACK序列号置为0
tcp_header.th_flag=2; //SYN 标志
tcp_header.th_seq=htonl(SEQ); //SYN序列号
tcp_header.th_urp=0; //偏移
tcp_header.th_sum=0; //校验和
//计算TCP校验和,计算校验和时需要包括TCP pseudo header
memcpy(SendBuf,&psd_header,sizeof(psd_header));
memcpy(SendBuf+sizeof(psd_header),&tcp_header,sizeof(tcp_header));
tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header)+sizeof(tcp_header));//计算IP校验和
memcpy(SendBuf,&ip_header,sizeof(ip_header));
memcpy(SendBuf+sizeof(ip_header),&tcp_header,sizeof(tcp_header));
memset(SendBuf+sizeof(ip_header)+sizeof(tcp_header),0,4);
datasize=sizeof(ip_header)+sizeof(tcp_header);
ip_header.checksum=checksum((USHORT *)SendBuf,datasize);//填充发送缓冲区
memcpy(SendBuf,&ip_header,sizeof(ip_header));//发送TCP报文
iErrorCode=sendto(sockRaw,SendBuf,datasize,0,(struct sockaddr*) &dest,
sizeof(dest));
CheckSockError(iErrorCode, "sendto()");
}
end=clock();//计时结束
ScanOK=TRUE;
printf("Closeing Thread.....\n");
WaitForSingleObject(Thread,5000);
CloseHandle(Thread);costtime= (float)(end - start) / CLOCKS_PER_SEC;  //转换时间格式
printf("Cost time:%f Sec",costtime);//显示耗时//退出前清理
if(sockRaw != INVALID_SOCKET) closesocket(sockRaw);
WSACleanup();
return 0;
}

原文链接: http://blog.csdn.net/yincheng01/article/details/7214036

转载于:https://my.oschina.net/junwong/blog/47920

基于visual c++之windows核心编程代码分析(36)实践SYN安全隐患监测相关推荐

  1. 基于visual c++之windows核心编程代码分析(64)现有的exe文件中添加自己的代码

    我们进行信息安全编程的时候,经常需要向exe文件插入自己的源代码, 我们如何在代码中实现呢.请见代码与注释讲解 #include <iostream.h> #include <win ...

  2. 基于visual c++之windows核心编程代码分析(24)IO控制、内核通信

    我们在进行Windows编程的时候,经常需要进行IO控制与内核通信,我们来实现IO控制与内核通信.请见代码实现与注释讲解 驱动代码实现与分析 /* 头文件 */ #include <ntddk. ...

  3. 基于visual c++之windows核心编程代码分析(31)SNMP协议编程

    SNMP(Simple Network Management Protocol,简单网络管理协议)的前身是简单网关监控协议(SGMP),用来对通信线路进行管理.随后,人们对SGMP进行了很大的修改,特 ...

  4. 基于visual c++之windows核心编程代码分析(42)windows下进程的身份切换

    进程是操作系统结构的基础:是一个正在执行的程序:计算机中正在运行的程序实例:可以分配给处理器并由处理器执行的一个实体: 由单一顺序的执行显示,一个当前状态和一组相关的系统资源所描述的活动单元. 对应用 ...

  5. 基于visual c++之windows核心编程代码分析(30)Telnet协议编程

    Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户提供了在本地计算机上完成远程主机工作的能力.在终端使用者的电脑上使用telnet程序,用它连接 ...

  6. 基于visual c++之windows核心编程代码分析(47)实现交换网络的QQ号嗅探

    当我们在一个交换网络里面,不知道别人的QQ号码是个很痛苦的事情,假如一个PLMM在上网,你却不知道她得QQ也没有勇气去问,是个很可惜的事情, 至于我们搞编程的,可以通过交换机的数据交换,嗅探出QQ号, ...

  7. 基于visual c++之windows核心编程代码分析(61)打造自己的Windows输入法

    IMM(Input Method Manager)只在安装了亚洲语言包之后才能使用. 通过调用GetSystemMetrics(SM_IMMENABLED)知道IMM是否使能. 一共由三部分组成: s ...

  8. 线程基础知识——Windows核心编程学习手札系列之六

    线程基础知识 --Windows核心编程学习手札系列之六 线程与进程一样由两部分构成:一是线程的内核对象,操作系统用它来对线程实施管理,也是系统用来存放线程统计信息的地方:二是线程堆栈,用于维护线程在 ...

  9. 进程——Windows核心编程学习手札系列之四

    进程 --Windows核心编程学习手札系列之四 进程是一个正在运行的程序的实例,有两个部分组成:一个是操作系统用来管理进程的内核对象,内核对象是系统用来存放关于进程的统计信息的地方:另一个是地址空间 ...

最新文章

  1. 某程序员发现新来女同事简历造假!原来是培训机构出身!纠结怎么处理,网友评论亮了!...
  2. 解决Win7英文版显示中文乱码
  3. helm安装_Helm部署和体验jenkins
  4. zendstudio 默认网页打开your project的时候不显示本地主机localhost的解决方法
  5. Spring框架----Spring的bean的作用范围
  6. java 调用枚举种方法_Java中枚举类型的一种使用方式
  7. 线序及模式配置Linux,[CCNA图文笔记]-1-水晶头线序及设备互联法则
  8. 使用JMeter建立接口测试
  9. 《自己动手写操作系统》(一)
  10. 汉王手写板linux驱动下载,汉王笔手写板驱动程序
  11. 长沙云长计算机,【长沙记忆】原来关羽和长沙有这么多不解之缘
  12. Go语言在大数据时代应用前景
  13. beego框架出现的问题-----panic: ./ippanichandle.exe flag redefined: graceful
  14. springMvc中的校验框架@valid和@validated
  15. 15幅非常有创意的影子摄影作品欣赏
  16. imx6ull移植Linux系统第二篇——Linux内核的移植
  17. c++、python实现置换密码(栅栏技术,列置换)、替代密码(加法密码(Caesar密码),乘法密码)
  18. 小米网关一二三代的区别【转载】网关,mesh ,zigbee
  19. 人工智能书单|Deep Learning on Graphs
  20. 纵横内外·突破盲区|BF-TR8500​高功率全频段数字中继台

热门文章

  1. Docker 【Nginx集群部署】
  2. tftpd 安装和配置
  3. python中文分词介绍
  4. 基于vue实现word 在线预览
  5. MySQL每天定时备份
  6. 机器学习强基计划2-2:一文详解ID3、C4.5、CART决策树算法+ Python实现
  7. 产品经理和项目经理的区别,读这一篇就够了!(史上最全总结)
  8. 数据挖掘课程设计报告总结
  9. Android中圆形图的几种实现方式
  10. SCI论文写作神器集合 —— 超级实用