飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2538|回复: 1

[C/C++] 原始套接字伪造A的IP地址给B发送TCP数据包(类似三次握手第一步)

[复制链接]
  • TA的每日心情

    2024-3-29 19:10
  • 签到天数: 53 天

    [LV.5]常住居民I

    发表于 2017-3-6 11:50:44 | 显示全部楼层 |阅读模式


    楼主在校生,在做一个项目,改良版的nmap扫描器中的idle扫描。
    下面的代码实现的功能是:原始套接字伪造A的IP地址给B发送TCP数据包(类似三次握手第一步)
    下面代码中setsockopt这个函数一直报错,请各位指正,参考书是刘文涛的《网络安全编程技术与实例》、李瑞民的《网络扫描技术揭秘》以及诸位大佬的相关代码额。。。。。

    [C] 纯文本查看 复制代码
    #include "stdafx.h"
    #include <WinSock2.h>
    #pragma warning(disable:4996)        
    #include <stdio.h>
    #include <string.h>
    #include <WS2tcpip.h>
    #include "mstcpip.h"                
    #include <time.h>
    #pragma comment(lib,"ws2_32.lib")
    
    #define MAXSIZE 1024
    char  *CHAR_SOURCE_IP = "10.251.93.11";                        //所伪造的IP地址
    char  *CHAR_TARGET_IP = "10.252.245.38";                        //目标的IP地址
    
    //重定义IP数据包头部
    typedef struct ip_header
    {
            unsigned char h_verlen;         //版本号+头长度--------------1组
            unsigned char tos;                                 //分区服务(默认为0)--------1组
            unsigned short total_len;                //首部及数据总长度-----------2组
            unsigned short ident;                         //分片标识-------------------2组
            unsigned short frag_and_flags;  //分片设置3bit---------------3/4组
    
            unsigned char ttl;                                 //生存周期(跳数限制)-------1组
            unsigned char proto;                         //携带的协议-----------------1组
            unsigned short checksum;                //首部校验和-----------------2组
            unsigned int sourceIP;                         //源IP地址-------------------4组
            unsigned int destIP;                         //目的IP地址-----------------4组
    };
    
    //重定义TCP数据包首部
    typedef struct tcp_header
    {
            USHORT th_sport;                                                //16位源端口 
            USHORT th_dport;                                                //16位目的端口 
            unsigned int th_seq;                                        //32位序列号seq
            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伪首部
    typedef struct psd_tcp_header
    {
            unsigned long saddr; //源地址 
            unsigned long daddr; //目的地址 
            char mbz; char ptcl; //协议类型 
            unsigned short tcpl; //TCP长度 
    };
    
    //计算首部校验和的函数
    unsigned short checksum(unsigned short * buffer, int size)
    {
            unsigned long cksum = 0;
            unsigned short answer = 0;
            while (size > 1)
            {
                    cksum += *buffer++;                                                                        
                    size -= sizeof(USHORT);
            }
            if (size == 1)
            {
                    *(char *)&answer = *(char *)buffer;
                    cksum += answer;
            }
            while (cksum >> 16)
                    cksum = (cksum >> 16) + (cksum & 0xffff);
            return (USHORT)(~cksum);
    };
    
    
    int attacker2target(int port)
    {
            SOCKET sendsocket;
            SOCKADDR_IN addr_in;
            WSADATA wsa;
            ip_header IP_HEADER;
            tcp_header TCP_HEADER;
            psd_tcp_header PSD_TCP_HEADER;
            int SOURCE_PORT = 80;
            char szSendBuf[MAXSIZE] = { 0 };
            unsigned long desip = inet_addr(CHAR_TARGET_IP);
    
            if (WSAStartup(MAKEWORD(2, 2), &wsa) == SOCKET_ERROR)
            {
                    printf("error !\n%d\n", GetLastError());
                    return false;
            }
    
            srand((unsigned)time(NULL));                //随机种子生成,留出时间
    
            if ((sendsocket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
            {
                    printf("WSASocket failed with error !\n%d\n", GetLastError());
                    return false;
            }
            
            bool bOpt = true;
            if (setsockopt(sendsocket, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt)) == SOCKET_ERROR )
            {
                    printf("setsocketopt error !\n %d \n", WSAGetLastError());
                    return false;
            }
    
            int nTimeOver = 1000;
            if (setsockopt(sendsocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver)) == SOCKET_ERROR)
            {
                    printf("setsockopt failed with error %d\n\n", WSAGetLastError());
                    return false;
            }
    
            addr_in.sin_family = AF_INET;
            addr_in.sin_port = htons(port);
            addr_in.sin_addr.S_un.S_addr = inet_addr(CHAR_TARGET_IP);
    
            //填充IP报头
            IP_HEADER.h_verlen = (4 << 4 | sizeof(IP_HEADER) / sizeof(unsigned long));
            // IP_HEADER.tos=0;
            IP_HEADER.total_len = htons(sizeof(IP_HEADER) + sizeof(TCP_HEADER));
            IP_HEADER.ident = 1;
            IP_HEADER.frag_and_flags = 0;
            IP_HEADER.ttl = 128;
            IP_HEADER.proto = IPPROTO_TCP;
            IP_HEADER.checksum = 0;
            IP_HEADER.sourceIP = inet_addr("localhost");
            IP_HEADER.destIP = desip;
    
            //填充TCP报头
            TCP_HEADER.th_dport = htons(port);
            TCP_HEADER.th_sport = htons(SOURCE_PORT); //源端口号
            TCP_HEADER.th_seq = htonl(0x12345678);
            TCP_HEADER.th_ack = 0;
            TCP_HEADER.th_lenres = (sizeof(TCP_HEADER) / 4 << 4 | 0);
            TCP_HEADER.th_flag = 2; //标志位探测,2是SYN 
            TCP_HEADER.th_win = htons(512);
            TCP_HEADER.th_urp = 0;
            TCP_HEADER.th_sum = 0;
    
            PSD_TCP_HEADER.saddr = IP_HEADER.sourceIP;
            PSD_TCP_HEADER.daddr = IP_HEADER.destIP;
            PSD_TCP_HEADER.mbz = 0;
            PSD_TCP_HEADER.ptcl = IPPROTO_TCP;
            PSD_TCP_HEADER.tcpl = htons(sizeof(TCP_HEADER));
    
            memcpy(szSendBuf, &PSD_TCP_HEADER, sizeof(PSD_TCP_HEADER));
            memcpy(szSendBuf + sizeof(PSD_TCP_HEADER), &TCP_HEADER, sizeof(TCP_HEADER));
            TCP_HEADER.th_sum = checksum((unsigned short*)szSendBuf, sizeof(PSD_TCP_HEADER) + sizeof(TCP_HEADER));
    
            memcpy(szSendBuf, &IP_HEADER, sizeof(IP_HEADER));
            memcpy(szSendBuf + sizeof(IP_HEADER), &TCP_HEADER, sizeof(TCP_HEADER));
            memset(szSendBuf + sizeof(IP_HEADER) + sizeof(TCP_HEADER), 0, 4);
            IP_HEADER.checksum = checksum((unsigned short*)szSendBuf, sizeof(IP_HEADER) + sizeof(TCP_HEADER));
    
            memcpy(szSendBuf, &IP_HEADER, sizeof(IP_HEADER));
    
            int rect = sendto(sendsocket, szSendBuf, sizeof(IP_HEADER) + sizeof(TCP_HEADER), 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(sendsocket);
            WSACleanup();
    
            return rect;
    }
    
    
    int main()
    {
            int port;
            printf("please enput port number=\n");
            scanf("%d", &port);
            attacker2target(port);
            return 0;
    }

    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2017-6-4 04:19
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2017-6-4 04:30:51 | 显示全部楼层
    学习了,谢谢楼主。
    PYG19周年生日快乐!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表