00011011 发表于 2017-3-6 11:50:44

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



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

#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 = { 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;
}

niebin412 发表于 2017-6-4 04:30:51

学习了,谢谢楼主。
页: [1]
查看完整版本: 原始套接字伪造A的IP地址给B发送TCP数据包(类似三次握手第一步)