基于套接字发送伪造IP包[转]

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情
这 里介绍Windows Sockets的一些关于原始套接字(Raw Socket)的编程。同Winsock1相比,最明显的就是支持了Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制Windows下的多种协议,而且能够对网络底层的传输机制进行控制。

1、创建一个原始套接字,并设置IP头选项。

SOCKET sock;
sock = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
或者:
s = WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);

这 里,我们设置了SOCK_RAW标志,表示我们声明的是一个原始套接字类型。创建原始套接字后,IP头就会包含在接收的数据中,如果我们设定 IP_HDRINCL 选项,那么,就需要自己来构造IP头。注意,如果设置IP_HDRINCL 选项,那么必须具有 administrator权限,要不就必须修改注册表:
HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/Afd/Parameter/
修改键:DisableRawSecurity(类型为DWORD),把值修改为 1。如果没有,就添加。

BOOL blnFlag=TRUE;
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&blnFlag, sizeof(blnFlag);

对于原始套接字在接收数据报的时候,要注意这么几点:
1、如果接收的数据报中协议类型和定义的原始套接字匹配,那么,接收的所有数据就拷贝到套接字中。
2、如果绑定了本地地址,那么只有接收数据IP头中对应的远端地址匹配,接收的数据就拷贝到套接字中。
3、如果定义的是外部地址,比如使用connect(),那么,只有接收数据IP头中对应的源地址匹配,接收的数据就拷贝到套接字中。


2、构造IP头和TCP头

这里,提供IP头和TCP头的结构:
// Standard TCP flags
#define URG 0x20
#define ACK 0x10
#define PSH 0x08
#define RST 0x04
#define SYN 0x02
#define FIN 0x01
typedef struct _iphdr //定义IP首部
{
unsigned char h_lenver; //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地址
}IP_HEADER;

typedef struct psd_hdr //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSD_HEADER;

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

TCP伪首部并不是真正存在的,只是用于计算检验和。校验和函数:

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头部和TCP头部的时候,就同时需要自己计算他们的检验和。

3、发送原始套接字数据报

填充这些头部稍微麻烦点,发送就相对简单多了。只需要使用sendto()就OK。

sendto(sock, (char*)&tcpHeader, sizeof(tcpHeader), 0, (sockaddr*)&addr_in,sizeof(addr_in));

下面是一个示例程序,可以作为SYN扫描的一部分。

#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define SOURCE_PORT 7234
#define MAX_RECEIVEBYTE 255

typedef struct ip_hdr //定义IP首部
{
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;

typedef struct tsd_hdr //定义TCP伪首部
{
unsigned long saddr; //源地址
unsigned long daddr; //目的地址
char mbz;
char ptcl; //协议类型
unsigned short tcpl; //TCP长度
}PSDHEADER;

typedef struct tcp_hdr //定义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;

//CheckSum:计算校验和的子函数
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);
}

void useage()
{
printf("******************************************/n");
printf("TCPPing/n");
printf("/t Written by Refdom/n");
printf("/t Email: refdom@263.net/n");
printf("Useage: TCPPing.exe Target_ip Target_port /n");
printf("*******************************************/n");
}

int main(int argc, char* argv[])
{
WSADATA WSAData;
SOCKET sock;
SOCKADDR_IN addr_in;
IPHEADER ipHeader;
TCPHEADER tcpHeader;
PSDHEADER psdHeader;

char szSendBuf[60]={0};
BOOL flag;
int rect,nTimeOver;

useage();

if (argc!= 3)
{ return false; }

if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0)
{
printf("WSAStartup Error!/n");
return false;
}

if ((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
{
printf("Socket Setup Error!/n");
return false;
}
flag=true;
if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR)
{
printf("setsockopt IP_HDRINCL error!/n");
return false;
}

nTimeOver=1000;
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR)
{
printf("setsockopt SO_SNDTIMEO error!/n");
return false;
}
addr_in.sin_family=AF_INET;
addr_in.sin_port=htons(atoi(argv[2]));
addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1]);

//
//
//填充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=inet_addr("本地地址");
ipHeader.destIP=inet_addr(argv[1]);

//填充TCP首部
tcpHeader.th_dport=htons(atoi(argv[2]));
tcpHeader.th_sport=htons(SOURCE_PORT); //源端口号
tcpHeader.th_seq=htonl(0x12345678);
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(512);
tcpHeader.th_urp=0;
tcpHeader.th_sum=0;

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

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

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

memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));

rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader),
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(sock);
WSACleanup();

return 0;
}

4、接收数据
和 发送原始套接字数据相比,接收就比较麻烦了。因为在WIN我们不能用recv()来接收raw socket上的数据,这是因为,所有的IP包都是先递交给系统核心,然后再传输到用户程序,当发送一个raws socket包的时候(比如syn),核心并不知道,也没有这个数据被发送或者连接建立的记录,因此,当远端主机回应的时候,系统核心就把这些包都全部丢 掉,从而到不了应用程序上。所以,就不能简单地使用接收函数来接收这些数据报。

要达到接收数据的目的,就必须采用嗅探,接收所有通过的数据包,然后进行筛选,留下符合我们需要的。可以再定义一个原始套接字,用来完成接收数据的任务,需要设置SIO_RCVALL,表示接收所有的数据。

SOCKET sniffersock;
sniffsock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);

DWORD lpvBuffer = 1;
DWORD lpcbBytesReturned = 0 ;
WSAIoctl(sniffersock, SIO_RCVALL, &lpvBuffer, sizeof(lpvBuffer), NULL, 0, & lpcbBytesReturned, NULL, NULL);

创建一个用于接收数据的原始套接字,我们可以用接收函数来接收数据包了。然后在使用一个过滤函数达到筛选的目的,接收我们需要的数据包。
Teardrop攻击——发送虚假IP信息 一、原始套接字概述 原始套接字,指在传输层下面使用的套接字。流式套接字和数据报套接字这两种套接字工作在传输层,主要为应用层的应用程序提供服务,并且在接收和发送时只能操作数据部分,而不能对IP首部或TCP和UDP首部进行操作,通常把这两种套接字称为标准套接字。 但是,如果我们开发的是更底层的应用,比如发送一个自定义的IP、UDPTCP或ICMP,捕获所有经过本机网卡的数据,伪装本机的IP,想要操作IP首部或传输层协议首部,等等,这些功能对于这两种套接字就无能为力了。这些功能需要使用另一种套接字 阅读详情

相关推荐

LAB 13 数据嗅探和伪造

Packet Sniffing and Spoofing Lab数据时如何被接收的Lab Task Set 1: Using Tools to Sniff and Spoof PacketsTask 1.1: Sniffing PacketsTask 1.1A.Task 1.1B.Task 1.2: Spoofing ICMP PacketsTask 1.3: TracerouteTask 1.4: Sniffing and-then SpoofingLab Task Set 2: Writing Pro

qq_39411845的博客 4195

如何伪造ip伪造IP的方法以及代码

下面是一个伪造IP的代码,大家可以发挥自己的想象而去做一些更实际的东西 利用伪造IP达到禁止端口访问的目的,大家都知道TCP是面向连接的,连接时有三次握手,之后才能确认连接成功。那么我们就应该能在第一次握手之后伪造一个服务方的握手返回,从而达到TCP连接不成功,无法访问某端口。程序如下:void DeCodeIP(buf,iBufSize) //解析侦听到的IP数据{

blackoto的专栏 4764

NTP伪造ip→DDOS [ntp.c]

33m使用方法:\x1b[1;35m %s IP地址 端口号 表文件 线程数 -1 时间\n", argv[0]);31m 破晓(ZeroDown)官方频道:https://t.me/ZeroDawnTeam \n");35m创建套接字...\n");36m攻击中....\n");

2401_87376254的博客 845

伪造TCP/IP数据, 刷票?!!

前言 最近,有一同学给我发来一投票的链接,当然希望我帮他投某某的票了o(︶︿︶)o 我立马投了票, 再投第二下那时 限制了IP了~ 我却突然萌生一个想法, 如果我伪造TCP数据, 伪造TCP头上的IP地址,不是可以想多少票,就多少票了~ PS:因为之前看过有关SYN攻击的描述,知道可以发出大量伪造的SYN数据,使到服务器建立大量半连接,占用服务器的资源 先...

dianmufang3977的博客 469

使用C++实现DNS欺骗攻击

其中,domain_name表示需要欺骗的域名,dns_server_ip表示实际DNS服务器的IP地址,fake_ip表示需要重定向到的IP地址。在DNS查询过程中,当客户端向DNS服务器请求解析某个域名时,DNS服务器会返回该域名对应的IP地址。DNS劫持是一种常见的网络攻击方式,通过篡改DNS响应数据,使得用户访问的网站被重定向到攻击者指定的恶意站点。我们使用C++编写一个简单的DNS欺骗程序,使得当客户端请求解析特定的域名时,我们可以将其重定向到指定的IP地址。使用C++实现DNS欺骗攻击。

wtujoxk的博客 489

VC++实现字符串IP地址DWORD地址(附带源码)

VC++ 中,您可以使用 Windows 提供的 inet_addr 函数或 inet_pton 函数将 IP 地址字符串换为 DWORD 地址。inet_addr 可以将一个点分十进制格式的 IPv4 地址(如 "192.168.1.1")换为一个 DWORD 类型的网络字节顺序表示,而 inet_pton 函数则更通用,支持 IPv4 和 IPv6 地址。

欢迎来到我的博客!这里是一个专注于计算机技术的分享平台,涵盖编程开发、算法研究、系统架构、软件工程等多个领域。无论你是初学者还是资深开发者,都能在这里找到有价值的内容。 592

计网:IP分组发协议实验(c语言)

#include<stdio.h> #include<stdlib.h> #include<windows.h> #include<time.h> typedef struct ip{ unsigned char one; unsigned char two; unsigned char three; unsigned char four; }IP; typedef struct message{ IP sourceIP; IP targetIP.

weixin_44943308的博客 1786

基于套接字发送伪造IP

 这里介绍Windows Sockets的一些关于原始套接字(Raw Socket)的编程。同Winsock1相比,最明显的就是支持了Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制Windows下的多种协议,而且能够对网络底层的传输机制进行控制。 1、创建一个原始套接字,并设置IP头选项。 SOCKET sock; sock = socket(AF_INET,SOCK_RA

雨中怡然 1801

原始套接字编程:Teardrop伪造IP

目录原始套接字概述功能含义原始套接字和标准套接字的区别Teardrop伪造IPTeardrop 攻击原理Teardrop 防御方法编写teardrop代码 原始套接字 概述 raw socket,即原始套接字,可以接收本机网卡上的数据帧或者数据,对于监听网络的流量和分析是很有作用的,一共可以有4种方式创建这种socket。 1.socket(PF_INET, SOCK_RAW, IPPROTO_TCP|IPPROTO_UDP|IPPROTO_ICMP)发送接收ip数据 2.socket(PF_PAC

weixin_45189408的博客 849

学习teardrop攻击并伪造一个ip

编译环境:Ubuntu18.04 编程语言:c语言 使用原始套接字编程中的 Teardrop 代码编程,伪造一个虚假地址的 IP 的内容填入 Fake News ,发送,并用 wireshark 抓进行验证。 一、了解teardrop攻击原理 1.什么是原始套接字 原始套接字的含义就是在传输层之下使用的套接字,它提供了一些 TCP 和 UDP 套接字无法提供的功能,即: (1)使用原始套接字可以读写 ICMP 和 IGMP 协议的数据,如著名的 Ping 程序; (2)使用原始套接字可以读

qq_46051625的博客 986

linux下通过伪造udp来实现指定网卡发送数据

1.含头文件 #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <stdbool.h> 2

17岁boy的博客 3215

原始套接字 发送 TCP SYN

通过原始套接字、setsockopt、IP_HDRINCL套接字选项,我们可以在应用进程里面构造自己的IP:所以我们在初始化原始套接字之后,可以调用setsockopt函数来开启IP_HDRINCL套接字选项,并且构造自己的IP头,TCP/UDP头,最后再像发送普通一样调用sendto 、sendmsg等函数发送构造好的数据。1.首先我们可以先得到一个原始套接字,并且设置IP_HDRINCL套...

nia305的博客 9484

原始套接字编程——Teardrop

文章目录一、介绍套接字二、 一、介绍套接字套接字(SOCK_STREAM) 用于提供面向连接、可靠的数据传输服务。使用TCP协议。 数据报套接字(SOCK_DGRAM) 提供一种无连接的服务,不能够保证数据传输的可靠性,可能出现数据的丢失情况。使用UDP协议。 原始套接字(SOCK_RAW) 可以内核没有处理的IP数据,用于处理其他协议(除TCP、UDP之外)发送的数据。 本文章主要讲述使用原始套接字进行处理数据 二、 ...

Harriet的博客 1139

伪造IP

#include #include #include #define ICMP_ECHO 8 /*定义IP报头数据结构*/ typedef struct iphdr {  unsigned char verlen;    //头的版本和长度  unsigned char tos;     //服务类型  unsigned short total_len;    //

zhihu008的专栏 2724

伪造IP发送数据(UDP)

#include <iostream> #include <winsock2.h> #include <cstdio> #include <windows.h> #include <WS2tcpip.h> #include "protoinfo.h" #pragma comment (lib,"ws2_32.lib") using...

chen249191508的专栏 2181

windows 基于套接字发送伪造IP——摘自网络

这里介绍Windows Sockets的一些关于原始套接字(Raw Socket)的编程。同Winsock1相比,最明显的就是支持了Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制Windows下的多种协议...

cixieku3433的博客 552

伪造ip发起tcp sync攻击

#include #include #include #include #include #include #include #include #include #include #include #include #include /* #ifndef __USE_BSD #def

xiaolei1982致力于Web开发 1880

原始套接字伪造

这里介绍Windows Sockets的一些关于原始套接字(Raw Socket)的编程。同Winsock1相比,最明显的就是支持了Raw Socket套接字类型,通过原始套接字,我们可以更加自如地控制Windows下的多种协议,而且能够对网络底层的传输机制进行控制。 1、创建一个原始套接字,并设置IP头选项。 SOCKET sock; sock = socket(AF_INET

xiao628945的专栏 657
上一篇: IP地址漂移技术[转]
下一篇: 浅谈编程能力的培养与提高——卓越的程序设计之道[转]
Garyhou
博客等级 码龄20年 41粉丝 62原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值