网络编程-原始套接字实现SYN扫描,但用wireshark时始终没有发现发出去的包

问题描述

原始套接字实现SYN扫描,但用wireshark时始终没有发现发出去的包

#include
#include
#include
#include
#include
#include "WS2TCPIP.H"

#pragma comment(lib,"Ws2_32.lib")

using namespace std;

//SOCKADDR_IN target, source;
//sockaddr_in target, source;
//int sock;

typedef struct _iphdr
{
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 psd_hdr //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSDHEADER;

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位紧急数据偏移量
}TCPHEADER;

#define FINISH 100
#define RUN 200
#define SIO_WSAIOW(IOC_VENDOR,l)
#define SEQ 0x28376839

USHORT CheckSum(USHORT buffer, int size) //CRC校验通用代码
{
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解包******************
/*
int DecodeIPHeader(char recvbuf, int bytes)
{
IPHEADER *iphdr;
TCPHEADER *tcphdr;
unsigned short iphdrlen;
iphdr = (IPHEADER *)recvbuf;
iphdrlen = sizeof(unsigned long) * (iphdr->h_verlen & 0xf);
iphdrlen = sizeof(IPHEADER);
tcphdr = (TCPHEADER
)(recvbuf + iphdrlen);

//是否来自目标IP
if (iphdr->sourceIP != target.sin_addr.s_addr) {
printf("不来自目标IPn");
return 0;
}

//序列号是否正确
if (ntohl(tcphdr->th_ack) != (SEQ + 1)) {
printf("序列号错误n");
return 0;
}

//RST/ACK - 无服务
if (tcphdr->th_flag == 20) {
printf("RST+ACK 无服务.n");
return 1;
}

//SYN/ACK - 扫描到一个端口
if (tcphdr->th_flag == 18) {
printf("%dn", ntohs(tcphdr->th_sport));
return 2;
}
printf("未知n");
return 1;
}
*/

////////////////////////////////////////////////////////////////////////

void SynScan(string uIP, u_short uPortBegin, u_short uPortEnd)
{
int datasize;
IPHEADER ipHeader;//IP包头
TCPHEADER tcpHeader;//TCP包头
PSDHEADER psdHeader;//伪TCP包头

//**********************扫描顺序***********************
for (u_short port = uPortBegin;port<uPortEnd;port++)   //端口顺序
{
    //SOCKET sock = INVALID_SOCKET;
    //SOCKET sock;
    int sock;
    SOCKADDR_IN target, source;
    WSADATA data;
    WORD w = MAKEWORD(2, 2);
    WSAStartup(w, &data);

    if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET)
    {
        cout << "发送原始套接字Socket创建出错" << endl << GetLastError() << endl;
        return;
    }

    //**********************扫描顺序***********************

    BOOL flag = true;
    if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)) == SOCKET_ERROR)
    {
        cout << "套接字选项IP_HDRINCL出错!n" << endl;
        return;
    }

    //SIO_RCVALL函数是可以读取所有IP数据包的必要设置
    DWORD dwBufferLen[10];
    DWORD dwBufferInLen = 1;
    DWORD dwBytesReturned = 0;

    WSAIoctl(sock, _WSAIOW(IOC_VENDOR, 1), &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL);
    setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag));

    source.sin_family = AF_INET;
    source.sin_port = htons(53638);
    source.sin_addr.s_addr = inet_addr("10.15.57.28");//本机IP地址
    if (bind(sock, (PSOCKADDR)&source, sizeof(source)) == SOCKET_ERROR)
        cout << "绑定本地IP接收出错。" << endl;

    target.sin_family = AF_INET;

    target.sin_addr.s_addr = inet_addr(uIP.c_str());   //对方IP
    target.sin_port = htons(port);   //对方端口
    cout << uIP.c_str() << endl;

    //分别自己填充IP头、TCP头、伪IP头,并计算其中的校验和
    char SendBuf[1024] = { 0 };

    //设置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 = source.sin_addr.s_addr;
    ipHeader.destIP = target.sin_addr.s_addr;

    //设置TCP头
    tcpHeader.th_sport = source.sin_port;   //本地端口
    tcpHeader.th_dport = target.sin_port;   //目标端口

    tcpHeader.th_seq = htonl(SEQ);
    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(16384);
    tcpHeader.th_urp = 0;
    tcpHeader.th_sum = 0;

    //伪TCP头
    psdHeader.saddr = ipHeader.sourceIP;
    psdHeader.daddr = ipHeader.destIP;
    psdHeader.mbz = 0;
    psdHeader.ptcl = IPPROTO_TCP;
    psdHeader.tcpl = htons(sizeof(tcpHeader));

    //计算校验和
    memcpy(SendBuf, &psdHeader, sizeof(psdHeader));
    memcpy(SendBuf + sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));
    tcpHeader.th_sum = CheckSum((USHORT *)SendBuf, sizeof(psdHeader) + sizeof(tcpHeader));

    memcpy(SendBuf, &ipHeader, sizeof(ipHeader));
    memcpy(SendBuf + sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));
    memset(SendBuf + sizeof(ipHeader) + sizeof(tcpHeader), 0, 4);
    ipHeader.checksum = CheckSum((USHORT*)SendBuf, sizeof(ipHeader) + sizeof(tcpHeader));

    //复制IP包+TCP包,进行发送
    memcpy(SendBuf, &ipHeader, sizeof(ipHeader));
    if ((sendto(sock, SendBuf, sizeof(ipHeader) + sizeof(tcpHeader), 0, (struct sockaddr *)&target, sizeof(struct sockaddr))) < 0)
    {
        cout << "sendto error" << endl << GetLastError() << endl;
    }
    int buflen = sizeof(target);
    memset(RecvBuf, 0, sizeof(RecvBuf));
    cout << "端口 " << port << endl;

    shutdown(sock, 2);
    closesocket(sock);
    WSACleanup();
}

}

int main()
{
string ip = "10.15.57.1";
SynScan(ip, 1, 500);
system("pause");
return 0;
}


解决方案

http://bbs.csdn.net/topics/390659636

时间: 2025-01-07 14:22:18

网络编程-原始套接字实现SYN扫描,但用wireshark时始终没有发现发出去的包的相关文章

C# 网络编程之套接字编程基础知识

      最近阅读了周存杰编写的<C#网络编程实例教程>并阅读了很多相关方面的资料,同时自己也做了一些套接字编程方面的C#程序,所以根据它的知识总结了最近的套接字编程的一些知识点,方便自己的理解与他人的学习,同时也有一些自己以前学习的计算机网络.操作系统等相关知识. 一.   套接字编程的概念       套接字(Winsock)是一种独立于协议的网络编程接口,在OSI中集中在会话层和传输层.(补充知识)简单回归网络知识,计算机网络中的"五层协议的体系结构"和"

[python] 专题七.网络编程之套接字Socket、TCP和UDP通信实例

        很早以前研究过C#和C++的网络通信,参考我的文章:                  C#网络编程之Tcp实现客户端和服务器聊天                 C#网络编程之套接字编程基础知识                 C#网络编程之使用Socket类Send.Receive方法的同步通讯        Python网络编程也类似.同时最近找工作笔试面试考察Socket套接字.TCP\UDP区别比较多,所以这篇文章主要精简了<Python核心编程(第二版)>第16章内

Windows Socket网络编程(二) 套接字编程原理

一.客户机/服务器模式 在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model).该模式的建立基于以下两点:1.非对等作用:2.通信完全是异步的.客户机/服务器模式在操作过程中采取的是主动请示方式: 首先服务器方要先启动,并根据请示提供相应服务:(过程如下) 1.打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求. 2.等待客户请求到达该端口. 3.接收到重复服务请求,处理该请求并发送应答信号. 4.返回第二步,等待另一客户

UNIX网络编程:套接字选项(SOL_SOCKET级别)

#include <sys/socket.h> int setsockopt( int socket, int level, int option_name,const void *option_value, size_t option_len); 第一个参数socket是套接字描述符. 第二个参数level是被设置的选项的级别,如果想要在套接字级别上设置选项,就必须把level设置为SOL_SOCKET. 第三个参数 option_name指定准备设置的选项,option_name可以有哪些

UNIX网络编程:套接字选项(心跳检测、绑定地址复用)

01./* 设置套接字选项周期性消息检测连通性 心跳包. 心博.主要用于长连接. 02. * 参数:套接字, 1或0开启, 首次间隔时间, 两次间隔时间, 断开次数 03. */ 04.void setKeepAlive( int iSockfd , int iSockAttrOn, socklen_t iIdleTime , socklen_t iInterval , socklen_t iCount ){ 05. setsockopt( iSockfd , SOL_SOCKET , SO_K

UNIX网络编程:套接字选项(SO_RCVBUF和SO_SNDBUF)

有时候我们需要控制套接字的行为(如修改缓冲区的大小),这个时候我们就要学习套接字选项. int getsockopt(int sockfd,int level,int optname,void *optval,socklen_t *optlen) int setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t *optlen) level指定控制套接字的层次.可以取三种值: SOL_SOCKET:通用套接字

UNIX网络编程:套接字选项(SO_REUSEADDR)

1.一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用. SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用.server程序总是应该在调用bind()之前设置SO_REUSEADDR套接字选项.TCP,先调用close()的一方会进入TIME_WAIT状态 2.SO_REUSEADDR和SO_REUSEPORT SO_REUSEADDR提供如下四个功能: 当有一个有相同本地地址和

UNIX网络编程:套接字选项(setsockopt)

setsockopt的一些用法: close socket(一般不会立即关闭而经历TIME_WAIT的过程)后想继续重用该socket: BOOL bReuseaddr=TRUE; setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 如果要已经处于连接状态的soket在调用close socket后强制关闭,不经历TIME_WAIT的过程: BOOL bDontLinger = FALSE;

Python中利用原始套接字进行网络编程的示例

  这篇文章主要介绍了Python中利用原始套接字进行网络编程的示例,使用sock_raw接受和发送数据包可以避开网络协议的诸多限制,需要的朋友可以参考下 在实验中需要自己构造单独的HTTP数据报文,而使用SOCK_STREAM进行发送数据包,需要进行完整的TCP交互. 因此想使用原始套接字进行编程,直接构造数据包,并在IP层进行发送,即采用SOCK_RAW进行数据发送. 使用SOCK_RAW的优势是,可以对数据包进行完整的修改,可以处理IP层上的所有数据包,对各字段进行修改,而不受UDP和TC