免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2285 | 回复: 1
打印 上一主题 下一主题

在网上找了一个TCP半连接扫描端口的程序,sendto的时候老是失败 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-10-25 14:11 |只看该作者 |倒序浏览
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include "mstcpip.h"

#pragma comment(lib,"ws2_32"

#define DEFAULT_DEST_PORT 12000
#define DEST_HOST "192.168.2.195"
#define SEQ 0x28376839



typedef struct _iphdr
{
        unsigned char h_lenver;                         /*位首部长度+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首部校验和*/
        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;
        unsigned int th_ack;
        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;

SOCKET sockRaw = INVALID_SOCKET;
SOCKET sockListen = INVALID_SOCKET;
struct sockaddr_in dest;

/*SOCK错误处理程序*/
void CheckSockError(int iErrorCode, char *pErrorMsg, char *pFileName, int line)
{
        if(iErrorCode==SOCKET_ERROR || NULL == pFileName)
        {
                printf("%s Error:%d\t[%s\t%d]\n", pErrorMsg, GetLastError(), pFileName, line);
                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;

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

        /*SYN/ACK - 扫描到一个端口*/
        if(tcphdr ->th_flag == 1
        {
                printf("%d\n",ntohs(tcphdr->th_sport));
                return true;
        }

        return true;
}

/*主函数*/
int main(int argc,char **argv)
{
        int iErrorCode;
        int datasize;
        struct hostent *hp;
        IP_HEADER ip_header;
        TCP_HEADER tcp_header;
        char SendBuf[128]={0};
        char RecvBuf[65535]={0};

        /*初始化SOCKET*/
        WSADATA wsaData;
        iErrorCode = WSAStartup(MAKEWORD(2,2),&wsaData);
        CheckSockError(iErrorCode, "WSAStartup()", __FILE__, __LINE__ );
#if 0
        sockRaw = socket( AF_INET, SOCK_DGRAM, 0 );
#else
        sockRaw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
#endif
        CheckSockError(sockRaw, "socket()", __FILE__, __LINE__ );
       
        sockListen = socket(AF_INET , SOCK_RAW , IPPROTO_IP);
        CheckSockError(sockListen, "socket()", __FILE__, __LINE__ );

        /*设置IP头操作选项*/
        int bOpt = true;
        iErrorCode = setsockopt(sockRaw,IPPROTO_IP,IP_HDRINCL,(char *)&bOpt,sizeof(bOpt));
        CheckSockError(iErrorCode, "setsockopt()", __FILE__, __LINE__ );

        /*获得本地IP*/
        SOCKADDR_IN sa;
        unsigned char LocalName[256];
        iErrorCode = gethostname((char*)LocalName,sizeof(LocalName)-1);
        CheckSockError(iErrorCode, "gethostname()", __FILE__, __LINE__ );
        printf( "LocalName is %s", LocalName );
        if((hp = gethostbyname((char*)LocalName)) == NULL)
        {
                CheckSockError(SOCKET_ERROR, "gethostbyname()", __FILE__, __LINE__ );
        }

        memcpy(&sa.sin_addr.S_un.S_addr,hp->h_addr_list[0],hp->h_length);
        sa.sin_family = AF_INET;
        sa.sin_port = htons(50000);
        printf( "\tip :%s\r\n", inet_ntoa( sa.sin_addr ) );
        iErrorCode = bind(sockListen, (PSOCKADDR)&sa, sizeof(sa));
        CheckSockError(iErrorCode, "bind", __FILE__, __LINE__ );


        /*设置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", __FILE__, __LINE__ );

        /*获得目标主机IP*/
        memset(&dest,0,sizeof(dest));
        dest.sin_family = AF_INET;
        dest.sin_port = htons(DEFAULT_DEST_PORT);
        if((dest.sin_addr.S_un.S_addr = inet_addr(DEST_HOST)) == INADDR_NONE)
        {
                if((hp = gethostbyname(DEST_HOST)) != NULL)
                {
                        memcpy(&(dest.sin_addr),hp->h_addr_list[0],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()", __FILE__, __LINE__ );
                }
        }
        printf( "dest IP %s\r\n", inet_ntoa( dest.sin_addr ) );

        /*填充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(50000); /*源端口号*/
        tcp_header.th_dport=htons(DEFAULT_DEST_PORT); /*目的端口号*/
        tcp_header.th_seq=htonl(SEQ); /*SYN序列号*/
        tcp_header.th_ack=0; /*ACK序列号置为0*/
        tcp_header.th_lenres=(sizeof(TCP_HEADER)/4<<4|0); /*TCP长度和保留位*/
        tcp_header.th_flag=2; /*SYN 标志*/
        tcp_header.th_win=htons(16384); /*窗口大小*/
        tcp_header.th_urp=0; /*偏移*/
        tcp_header.th_sum=0; /*校验和*/

        /*填充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));

        /*计算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()", __FILE__, __LINE__ );

        /*接收数据*/
        DWORD timeout = 2000;
        DWORD start = GetTickCount();
        while(true)
        {
                /*计时,2s超时*/
                if((GetTickCount() - start) >= timeout)
                        break;
                memset(RecvBuf, 0, sizeof(RecvBuf));
                iErrorCode = recv(sockListen, RecvBuf, sizeof(RecvBuf), 0);
                CheckSockError(iErrorCode, "recv", __FILE__, __LINE__ );
                if(DecodeIPHeader(RecvBuf,iErrorCode))
                        break;
        }

        /* 退出前清理 */
        if(sockRaw != INVALID_SOCKET) closesocket(sockRaw);
        WSACleanup();

        return 0;
}

论坛徽章:
0
2 [报告]
发表于 2006-10-25 14:15 |只看该作者
我调了一下,SOCKET创建成功了,目的地址dest也设置正确了,怎么sendto就失败了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP