2 smaug Smaug 于 2016.04.15 22:42 提问

原始套接字实现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("不来自目标IP\n");
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("%d\n", 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;
}


1个回答

devmiao
devmiao   Ds   Rxr 2016.04.15 23:43
Smaug
Smaug 非常感谢,这个代码是我的参考代码之一,问题已经解决了一点,但现在又有了个新的问题。发出去的只是IP包,TCP包只作为data内容,我该怎么办?
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!