本文主要是介绍从入门到入土:[SEED-Lab]- Packet Sniffing and Spoofing Lab|嗅探与欺骗实验|详细说明|实验步骤|实验截图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
此博客仅用于记录个人学习进度,学识浅薄,若有错误观点欢迎评论区指出。欢迎各位前来交流。(部分材料来源网络,若有侵权,立即删除)
本人博客所有文章纯属学习之用,不涉及商业利益。不合适引用,自当删除!
若被用于非法行为,与我本人无关
[SEED-Lab]-Packet Sniffing and Spoofing Lab
- 实验环境
- PDF文件
- 实验步骤
- 环境配置
- Labsetup
- 操作步骤
- Lab Task Set 1: Using Scapy to Sniff and Spoof Packets
- Task 1.1: Sniffing Packets
- task1.1A
- task1.1B
- Task 1.2: Spoofing ICMP Packets
- Task 1.3: Traceroute
- Task 1.4: Sniffing and-then Spoofing
- Task 2.1
- Task 2.1A: Understanding How a Sniffer Works
- Task 2.1B: Writing Filters
- Task2.1C: Sniffing Passwords
- Task 2.2
- Task 2.2A: Write a spoofing program
- Task 2.2B: Spoof an ICMP Echo Request
- Task 2.3: Sniff and then Spoof
实验环境
- seed-ubuntu 20.04
PDF文件
- 嗅探与欺骗实验
实验步骤
环境配置
Labsetup
传送门
-
解压后
-
导入虚拟机环境中
-
关于docker的build和up就轻车熟路了
-
先看看PDF的任务吧
操作步骤
- 包嗅探和欺骗是网络安全中的两个重要概念;它们是网络通信中 的两大威胁。能够理解这两种威胁对于理解网络中的安全措施至关重 要。有许多包嗅探和欺骗工具,如 Wireshark、Tcpdump、Netwox 等。 其中一些工具被安全专家以及攻击者广泛使用。能够使用这些工具对 学生来说很重要,但对于网络安全课程的学生来说,更重要的是了解 这些工具是如何工作的,即包嗅探和欺骗是如何在软件中实现的。 本实验的目标是让学生掌握大多数嗅探和欺骗工具的基本技术。 学生们将使用一些简单的嗅探和欺骗程序,阅读它们的源代码,修改 它们,并最终对这些程序的技术方面有深入的了解。在本实验结束时, 学生应该能够编写自己的嗅探和欺骗程序。
- 数据包嗅探和欺骗是网络安全中的两个重要概念;它们是网络通信中的两个主要威胁。能够理解这两种威胁对于理解网络中的安全措施至关重要。有许多数据包嗅探和欺骗工具,如线鲨,Tcpdump,Netwox,Scapy等。其中一些工具已被安全专家和攻击者广泛使用。能够使用这些工具对学生来说很重要,但对于网络安全课程中的学生来说,更重要的是了解这些工具是如何工作的,即数据包嗅探和欺骗是如何在软件中实现的。这个实验室的目标有两个方面:学习使用这些工具和理解这些工具背后的技术。对于第二个目标,学生将编写简单的嗅探器和欺骗程序,并获得一个深入的了解这些程序的技术方面。本实验室涵盖以下主题:
- How the sniffing and spoofing work
- Packet sniffing using the pcap library and Scapy
- Packet spoofing using raw socket and Scapy
- Manipulating packets using Scapy
Lab Task Set 1: Using Scapy to Sniff and Spoof Packets
- 许多工具可以用来做嗅探和欺骗,但其中大多数只提供固定的功能。Scapy是不同的:它不仅可以作为一个工具,还可以作为一个构建块来构建其他的嗅探和欺骗工具,也就是说,我们可以将Scapy功能集成到我们自己的程序中。在这组任务中,我们将对每个任务使用Scapy。要使用Scapy,我们可以编写一个Python程序,然后使用Python执行这个程序。请参阅下面的示例。我们应该使用根权限运行Python,因为欺骗数据包需要该特权。在程序的开始(第➀行),我们应该导入所有的Scapy的模块。
Task 1.1: Sniffing Packets
- 安装并启动docker
- 这部分主要是利用工具来嗅探数据包,这里用的是 scapy。 可以用下面的命令进行安装。
sudo pip3 install scapy
task1.1A
- 下面是使用 scapy来嗅探数据包的一个例子:
- 代码:
- 代码简单就上图了
- 先使用如下命令添加执行权限:
chmod a+x sniffer.py
- ifconfig查看本机IP
- 手贱PING一下
- 先使用root权限运行上面的程序 sudo ./sniffer.py, 结果如下,可以看到其成功嗅探到了不同协议的数据包,图中只包括ICMP包。
- 然后使用普通权限运行该程序 ./sniffer.py。结果如下,可以看到报错了,提示无权限。
- 这说明嗅探包是一件拥有高权限才能做的事情,没有高权限,系统是不让你嗅探数据包的。
task1.1B
- 一般在嗅探包时我们只对特定类型的数据包感兴趣,所以我们需要对数据包进行一些过滤。scapy的过滤机制使用BPF的语法,这部分我们需要实现几个过滤的方法。
- 通常,当我们嗅探数据包时,我们只对某些类型的数据包感兴趣。我们可以通过在嗅探中设置过滤器来实现这一点。Scapy的过滤器使用BPF(伯克利数据包过滤器)语法;你可以找到SBPF手册从互联网上提供。请设置以下过滤器,并再次演示您的嗅探器程序(每个过滤器应单独设置)
- 仅捕获ICMP包捕获来自特定IP和目标端口号为23的任何TCP包。•捕获数据包来自或转到一个特定的子网。您可以选择任何子网,如128.230.0.0/16;您不应该选择虚拟机连接到的子网。
- 只捕捉ICMP数据包,代码修改如下:
- 手再PING试一下
- 运行结果如下,可以看到捕获到了ICMP数据包:
- 只捕捉来自特定IP,且目标端口号为23的TCP数据包,查看自己的IP地址如下:
- 本机ip地址:10.0.2.1
- 设定一个ip地址:10.0.2.2
- 创建发送数据包的代码:datapak.py、并指定tcp端口是23
- 修改sniffer.py文件:
- 运行
- 捕获了前三次发的包
- 捕获来自或去往特定子网的数据包。您可以选择任何子网,如128 . 230 . 0 . 0/16;您不应该选择虚拟机所连接的子网
修改嗅探的过滤条件:
#!/usr/bin/python3
from scapy.all import *ip = IP()
ip.src ="10.0.2.4"
ip.dst ="192.169.0.1"tcp=TCP()
tcp.dport =23
send(ip/tcp)
- 修改datapak.py文件:
- 嗅探结果如下:
Task 1.2: Spoofing ICMP Packets
- 作为一个数据包欺骗工具,Scapy允许我们将IP数据包的字段设置为任意值。此任务的目的是用任意的源IP地址来欺骗IP数据包。我们将欺骗ICMP回波请求包,并将它们发送到同一网络上的另一个虚拟机。我们将使用线鲨来观察我们的请求是否会被接收人接受。如果它被接受,一个回波回复包将被发送到欺骗的IP地址。下面的代码展示了如何欺骗ICMP数据包的一个示例。
>>> from scapy.all import *
>>> a = IP() ➀
>>> a.dst = ’10.0.2.3’ ➁
>>> b = ICMP() ➂
>>> p = a/b ➃
>>> send(p) ➄ .
Sent 1 packets.
- 在上面的代码中,行➀从IP类创建一个IP对象;为每个IP头字段定义一个类属性。我们可以使用ls(a)或ls(IP)来查看所有的属性名称/值。我们也可以使用。show()和IP.show()来这样做。第➁行显示了如何设置目标IP地址字段。如果未设置字段,则将使用默认值。
- 行➂创建了一个ICMP对象。默认类型是echo请求。在第➃行中,我们将a和b堆叠在一起以形成一个新对象。/操作符被IP类重载,因此它不再表示划分;相反,它意味着将b添加到a作为a的有效负载字段,并相应地修改a的字段。因此,我们得到了一个表示ICMP数据包的新对象。我们现在可以使用行➄中发送()发送这个包。请对示例代码进行任何必要的更改,然后证明您可以用任意的源IP地址欺骗ICMP回波请求包。
- 安装wireshark:
sudo apt-get update
sudo apt-get install wireshark
- 启动wireshark:
- sudo wireshark:(root权限下、报错忽略)
- 准备抓包:
- 运行发包程序:
#!/usr/bin/python3
from scapy.all import *ip = IP()
ip.src ="10.0.2.4"
ip.dst ="192.169.0.1"icmp=ICMP()
send(ip/icmp)
Task 1.3: Traceroute
- 此任务的目的是使用Scapy来估计虚拟机和选定目的地之间的路由器数量方面的距离。这基本上是由跟踪工具实现的。在这个任务中,我们将编写我们自己的工具。这个想法非常简单:只需发送一个数据包(任何类型)到目的地,首先将其实时时间(TTL)字段设置为1。这个数据包将被第一个路由器丢弃,该路由器将向我们发送一个ICMP错误消息,告诉我们它的运行时间已经超过。这就是我们如何得到第一个路由器的IP地址。然后,我们将TTL字段增加到2,发送另一个数据包,并获得第二个路由器的IP地址。我们将重复此过程,直到我们的数据包最终到达目的地。需要注意的是,这个实验只得到一个估计结果,因为理论上,不是所有这些包采取相同的路径(但在实际中,它们可能在短时间内)。下面的代码显示了这个过程中的一轮。
a = IP()
a.dst = ’1.2.3.4’
a.ttl = 3
b = ICMP()
send(a/b)
- 如果您是一个经验丰富的Python程序员,您可以编写工具来自动执行整个过程。如果您是Python编程的新手,您可以通过手动更改TTL字段,并根据Wireshark的观察记录IP地址。这两种方法都是可以接受的,只要你得到了结果。
- 模拟一个traceroute,循环每次TTL+1,中间节点都发回ICMP TTL字段过期的错误信息,目的节点发回ICMP reply就结束:
- 创建一个trace.py文件:
from scapy.all import *
import sysdef traceroute(target, minttl=1, maxttl=30, dport=80):print("target: %s(port=%s)" % (target, dport))ans, unans = sr(IP(dst=target, ttl=(minttl,maxttl),id=RandShort())/TCP(flags=0x2, dport=dport), timeout=10)for snd,rcv in ans:print(snd.ttl, rcv.src)if __name__ == '__main__':if len(sys.argv) <= 1:traceroute("baidu.com")else:traceroute(sys.argv[1])
- 运行结果如下所示
Task 1.4: Sniffing and-then Spoofing
- 在此任务中,您将结合嗅探和欺骗技术来实现以下嗅探和欺骗程序。您需要在同一局域网上的两台机器:虚拟机和用户容器。从用户容器中,您可以生成一个IPX。这将生成一个ICMP回波请求包。如果X被激活,ping程序将收到一个回波响应,并打印出响应。您的嗅探和欺骗程序运行在VM上,它通过数据包嗅探来监视局域网。每当它看到ICMP回波请求时,无论目标IP地址是什么,您的程序都应该立即使用数据包欺骗技术发送回波回复。因此,无论机器X是否活动,ping程序将始终收到回复,表明X激活。您需要使用Scapy来完成此任务。在您的报告中,您需要提供证据来证明您的技术是有效的。在您的实验中,您应该从用户容器中获取以下三个IP地址。报告你的观察结果,并解释这些结果。
- 提示:您需要解释ARP协议是如何工作的,以便正确地解释您的观察结果。您还需要了解一点关于路由的知识。以下命令可帮助您找到指定目的地的路由器:
- 创建sniffer2.py
#!/usr/bin/python3
from scapy.all import *def print_pkt(pkt):send(IP(src=pkt[IP].dst, dst=pkt[IP].src)/ICMP(type="echo-reply", code= 0, id=pkt[ICMP].id, seq=pkt[ICMP].seq))pkt = sniff(filter="icmp[icmptype]==icmp-echo",prn=print_pkt)
- 运行结果如下
Task 2.1
Task 2.1A: Understanding How a Sniffer Works
- 可以使用pcap库很容易地编写嗅探器程序。有了pcap,嗅探器的任务就变成了调用pcap库中的一个简单的过程序列。在序列的最后,一旦数据包被捕获,就将被放入缓冲区中进行进一步处理。数据包捕获的所有细节都由pcap库处理。SEED的书提供了一个示例代码,展示了如何使用pcap编写一个简单的嗅探器程序。我们在下面包括了示例代码(详细说明请参阅本书)。
- 在这个任务中,学生需要编写一个嗅探器程序来打印出每个捕获的数据包的源和目标IP地址。学生可以输入上面的代码或从SEED书的网站(https://www.handsonsecurity。net/figurecode.html)。学生应该提供屏幕截图作为证据,以表明他们的嗅探程序可以成功运行,并产生预期的结果。另外,请回答以下问题:
- 这部分主要是写一个打印捕获的包的源IP和目的IP地址。代码如下:
#include <pcap.h>
#include <stdio.h>
#include <arpa/inet.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; /* protocol type (IP, ARP, RARP, etc) */
};/* IP Header */
struct ipheader {unsigned char iph_ihl:4, //IP header lengthiph_ver:4; //IP versionunsigned char iph_tos; //Type of serviceunsigned short int iph_len; //IP Packet length (data + header)unsigned short int iph_ident; //Identificationunsigned short int iph_flag:3, //Fragmentation flagsiph_offset:13; //Flags offsetunsigned char iph_ttl; //Time to Liveunsigned char iph_protocol; //Protocol typeunsigned short int iph_chksum; //IP datagram checksumstruct in_addr iph_sourceip; //Source IP addressstruct in_addr iph_destip; //Destination IP address
};void got_packet(u_char *args, const struct pcap_pkthdr *header,const u_char *packet)
{struct ethheader *eth = (struct ethheader *)packet;if (ntohs(eth->ether_type) == 0x0800) { // 0x0800 is IP typestruct ipheader * ip = (struct ipheader *)(packet + sizeof(struct ethheader)); printf(" From: %s\n", inet_ntoa(ip->iph_sourceip)); printf(" To: %s\n", inet_ntoa(ip->iph_destip)); /* determine protocol */switch(ip->iph_protocol) { case IPPROTO_TCP:printf(" Protocol: TCP\n\n");return;case IPPROTO_UDP:printf(" Protocol: UDP\n\n");return;case IPPROTO_ICMP:printf(" Protocol: ICMP\n\n");return;default:printf(" Protocol: others\n\n");return;}}
}int main()
{pcap_t *handle;char errbuf[PCAP_ERRBUF_SIZE];struct bpf_program fp;char filter_exp[] = "tcp and dst portrange 10-100";bpf_u_int32 net;// Step 1: Open live pcap session on NIC with name enp0s3handle = pcap_open_live("enp0s3", BUFSIZ, 1, 1000, errbuf);printf("listening on network card, ret: %p...\n", handle);// Step 2: Compile filter_exp into BPF psuedo-codeprintf("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 packetsprintf("start to sniff...\n");pcap_loop(handle, -1, got_packet, NULL);pcap_close(handle); //Close the handlereturn 0;
}
- 使用如下命令编译:
gcc -o sniff sniff.c -lpcap
-
运行,并尝试ping baidu.com,可以看到发送的包出现在结果中:
-
运行的结果如下:
-
ping
- Q1: 描述在你的嗅探程序中的库函数的调用
- A1: 第一步,启动pcap监听网卡。
- 第二步就是编译BPF过滤器并设置过滤器。
- 第三步就是设置嗅探的处理函数。
- 最后关闭嗅探即可。
- Q2: 为什么需要root权限才能运行嗅探程序?不使用root权限运行该程序会在哪里报错?
- A2: 嗅探数据包是一个高权限的操作,因为涉及到隐私,安全相关问题。如果普通用户也能嗅探数据包,那么他就能窃取别人的隐私,甚至盗取账号密码等等。不使用root权限运行该程序。对比如下,可以看到在没有权限时第一步监听网卡就失败了:
- Q3: 打开嗅探程序的混杂模式。打开和关闭这个模式有什么区别?
- A3: 使用混杂模式可以监听所在网段下其他机器的数据包,关闭则不能。打开混杂模式,可以监听到本网段的机器 ping baidu.com的数据包,关闭后则嗅探不到。
Task 2.1B: Writing Filters
- 这部分主要是写一些过滤器。这部分还是复用 task 2.1A的代码,只是修改其中的过滤器而已。Pcap过滤器的例子:
- 只捕捉两个特定主机之间的ICMP包,使用的过滤器为 icmp and src hostand dst host 10.0.2.4, 只捕捉从 发送到 10.0.2.4的ICMP包。、
- 这边改成了百度的IP
- 结果如下,可以看到全是从百度IP发送到 10.0.2.4的ICMP包,没有其他类型的包。
- 捕捉目的端口在10到100之间的TCP包:
- 结果如下,可以看到全是从 10.0.2.15 发送到 10.0.2.4的ICMP包,没有其他类型的包。
- 捕捉目的端口在10到100之间的TCP包:使用的过滤器为 tcp and dst portrange 10-100, 只捕捉从 10.0.2.15 发送到 10.0.2.4的ICMP包。
- 结果如下,用浏览器访问baidu.com的包出现在结果中,用浏览器访baidu.com:111的包没有出现在结果中。
Task2.1C: Sniffing Passwords
-
当普通用户发送数据包时,操作系统通常不允许用户设置协议头中的所有字段(如TCP、UDP和IP头)。操作系统将设置大部分字段,而只允许用户设置少数字段,如目标IP地址、目标端口号等。但是,如果用户具有根权限,他们可以在数据包头中设置任何任意字段。这被称为数据包欺骗,它可以通过原始套接字来完成。原始套接字为程序员提供了对数据包构造的绝对控制,允许程序员构造任何任意的数据包,包括设置头字段和有效负载。使用原始套接字非常简单;它涉及四个步骤:(1)创建一个原始套接字,(2)集套接字选项,(3)构建数据包,以及(4)通过原始套接字发送数据包。有许多在线教程可以教您如何在C编程中使用原始套接字。我们已经将一些教程链接到该实验室的网页。请阅读它们,并学习如何编写一个数据包欺骗程序。我们展示了这样一个程序的一个简单的骨架。
-
嗅探密码。请说明当有人在您监控的网络上使用telnet时,您如何使用嗅探器程序来捕获密码。您可能需要修改您的嗅探器代码来打印出捕获的TCP数据包的数据部分(telnet使用TCP)。如果您打印出整个数据部分,然后手动标记密码(或部分密码)的位置,这是可以接受的。
-
这边可以看到运行代码之后对tcp包的截获情况
Task 2.2
- 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 lengthiph_ver:4; //IP versionunsigned char iph_tos; //Type of serviceunsigned short int iph_len; //IP Packet length (data + header)unsigned short int iph_ident; //Identificationunsigned short int iph_flag:3, //Fragmentation flagsiph_offset:13; //Flags offsetunsigned char iph_ttl; //Time to Liveunsigned char iph_protocol; //Protocol typeunsigned short int iph_chksum; //IP datagram checksumstruct in_addr iph_sourceip; //Source IP addressstruct in_addr iph_destip; //Destination IP address
};/* ICMP Header */
struct icmpheader {unsigned char icmp_type; // ICMP message typeunsigned char icmp_code; // Error codeunsigned short int icmp_chksum; //Checksum for ICMP Header and dataunsigned short int icmp_id; //Used for identifying requestunsigned short int icmp_seq; //Sequence number
};/* 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 */
};/* 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];
};
- checksum.c
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>#include "myheader.h"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 16sum += (sum >> 16); // add carryreturn (unsigned short)(~sum);
}/****************************************************************TCP checksum is calculated on the pseudo header, which includesthe TCP header and data, plus some part of the IP header.Therefore, we need to construct the pseudo header first.
*****************************************************************/unsigned short calculate_tcp_checksum(struct ipheader *ip)
{struct tcpheader *tcp = (struct tcpheader *)((u_char *)ip +sizeof(struct ipheader));int tcp_len = ntohs(ip->iph_len) - sizeof(struct ipheader);/* pseudo tcp header for the checksum computation */struct pseudo_tcp p_tcp;memset(&p_tcp, 0x0, sizeof(struct pseudo_tcp));p_tcp.saddr = ip->iph_sourceip.s_addr;p_tcp.daddr = ip->iph_destip.s_addr;p_tcp.mbz = 0;p_tcp.ptcl = IPPROTO_TCP;p_tcp.tcpl = htons(tcp_len);memcpy(&p_tcp.tcp, tcp, tcp_len);return (unsigned short) in_cksum((unsigned short *)&p_tcp,tcp_len + 12);
}
Task 2.2A: Write a spoofing program
- 请用c编写您自己的数据包欺骗程序。您需要提供证据(例如,有线鲨鱼数据包跟踪),以表明您的程序成功地发送了欺骗的IP数据包。
- 这部分主要是伪造IP包。这里伪造是UDP包, 代码如下:
- spoof.c
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>#include "myheader.h"/*************************************************************Given an IP packet, send it out using a raw socket.
**************************************************************/
void send_raw_ip_packet(struct ipheader* ip)
{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);
}
- task22A
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>#include "myheader.h"void send_raw_ip_packet (struct ipheader* ip);/******************************************************************Spoof a UDP packet using an arbitrary source IP Address and port
*******************************************************************/
int main() {char buffer[1500];memset(buffer, 0, 1500);struct ipheader *ip = (struct ipheader *) buffer;struct udpheader *udp = (struct udpheader *) (buffer +sizeof(struct ipheader));/*********************************************************Step 1: Fill in the UDP data field.********************************************************/char *data = buffer + sizeof(struct ipheader) +sizeof(struct udpheader);const char *msg = "Hello Server!\n";int data_len = strlen(msg);strncpy (data, msg, data_len);/*********************************************************Step 2: Fill in the UDP header.********************************************************/udp->udp_sport = htons(12345);udp->udp_dport = htons(9090);udp->udp_ulen = htons(sizeof(struct udpheader) + data_len);udp->udp_sum = 0; /* Many OSes ignore this field, so we do notcalculate it. *//*********************************************************Step 3: Fill in the IP header.********************************************************/ip->iph_ver = 4;ip->iph_ihl = 5;ip->iph_ttl = 20;ip->iph_sourceip.s_addr = inet_addr("1.1.1.1");ip->iph_destip.s_addr = inet_addr("8.8.8.8");ip->iph_protocol = IPPROTO_UDP; // The value is 17.ip->iph_len = htons(sizeof(struct ipheader) +sizeof(struct udpheader) + data_len);/*********************************************************Step 4: Finally, send the spoofed packet********************************************************/send_raw_ip_packet (ip);return 0;
}
- 使用gcc -o task22A task22A.c spoof.c -lpcap编译,sudo ./task22A运行,查看后台wireshark,可以看到我们伪造的UDP包
Task 2.2B: Spoof an ICMP Echo Request
- 这部分是伪造ICMP Echo请求。伪造的代码如下, 其中源IP10.0.2.5是局域网内另一个虚拟机的IP,
- task22B.c
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>#include "myheader.h"unsigned short in_cksum (unsigned short *buf, int length);
void send_raw_ip_packet(struct ipheader* ip);/******************************************************************Spoof an ICMP echo request using an arbitrary source IP Address
*******************************************************************/
int main() {char buffer[1500];memset(buffer, 0, 1500);/*********************************************************Step 1: Fill in the ICMP header.********************************************************/struct icmpheader *icmp = (struct icmpheader *)(buffer + sizeof(struct ipheader));icmp->icmp_type = 8; //ICMP Type: 8 is request, 0 is reply.// Calculate the checksum for integrityicmp->icmp_chksum = 0;icmp->icmp_chksum = in_cksum((unsigned short *)icmp,sizeof(struct icmpheader));/*********************************************************Step 2: Fill in the IP header.********************************************************/struct ipheader *ip = (struct ipheader *) buffer;ip->iph_ver = 4;ip->iph_ihl = 5;ip->iph_ttl = 20;ip->iph_sourceip.s_addr = inet_addr("10.9.0.5");ip->iph_destip.s_addr = inet_addr("8.8.8.8");ip->iph_protocol = IPPROTO_ICMP;ip->iph_len = htons(sizeof(struct ipheader) +sizeof(struct icmpheader));/*********************************************************Step 3: Finally, send the spoofed packet********************************************************/send_raw_ip_packet (ip);return 0;
}
- 其中用到额外的文件,
- 使用gcc -o task22B task22B.c spoof.c checksum.c -lpcap 进行编译, sudo ./task22B运行,查看后台的wireshark,如下:
- 可以看到我们发送的源IP为10.0.2.5, 目的IP为8.8.8.8的ICMP包,并且还有回复
- Q4: 能把IP包的长度设置为任意数值,而不管实际的包的大小吗?
- A4: 将代码中设置长度该成下面的代码,运行可知其为28B,修改长度为10B,wireshark没有捕捉到包,说明没有发出去。
- 修改成1000B,结果如下,可以看到正常发送出去,且收到了相应。说明可以调大length,不能调小length。
- Q5: 使用 raw socket 编程, 我们要计算IP头部的checksum吗?
- A5: 不用计算IP头部的checksum,但是需要计算ICMP头部的checksum。
- Q6: 为什么使用raw socket 编程需要root权限?没有root权限执行时程序会在哪里报错?
- A6:因为能任意读取发送包意味着很大的安全风险,所以需要root权限。使用普通权限运行结果如下:
Task 2.3: Sniff and then Spoof
- 在此任务中,您将结合嗅探和欺骗技术来实现以下嗅探和欺骗程序。你需要在同一局域网上的两台机器。从机器A开始,你就可以得到一个IPX。这将生成一个ICMP回波请求包。如果X被激活,ping程序将收到一个回波响应,并打印出响应。您的嗅探和欺骗程序在攻击者机器上运行,它通过数据包嗅探监视局域网。每当它看到ICMP回波请求时,无论目标IP地址是什么,您的程序都应该立即使用数据包欺骗技术发送回波回复。因此,无论机器X是否活动,ping程序将始终收到回复,表明X激活。您需要用C编写这样的程序,并在报告中包含屏幕截图,以显示您的程序可以工作。也请在您的报告中附上代码(并有足够数量的评论)。
- 准备两个在同一个局域网的虚拟机,这部分主要是同时嗅探和伪造包,实现一个机器ping任意IP x,另一个机器伪造ICMP回复请求,使得其有回复,而IP x所对应的机器可能根本不存在。
准备两个在同一个局域网的虚拟机,这部分主要是同时嗅探和伪造包,实现一个机器ping任意IP x,另一个机器伪造ICMP回复请求,使得其有回复,而IP x所对应的机器可能根本不存在。 - 代码如下task23.c
#include <pcap.h>
#include <stdio.h>
#include <arpa/inet.h>
#include "myheader.h"void got_packet(u_char *args, const struct pcap_pkthdr *header,const u_char *packet)
{struct ethheader *eth = (struct ethheader *)packet;if (ntohs(eth->ether_type) == 0x0800) { // 0x0800 is IP typestruct ipheader * ip = (struct ipheader *)(packet + sizeof(struct ethheader));printf("From: %s ", inet_ntoa(ip->iph_sourceip)); printf("To: %s ", inet_ntoa(ip->iph_destip));if (ip->iph_protocol == IPPROTO_ICMP)printf("protocal: ICMP\n");elseprintf("protocal: Others\n");struct icmpheader *icmp_pkt = (struct icmpheader *)(packet + sizeof(struct ethheader) + sizeof(struct ipheader)); if (ip->iph_protocol == IPPROTO_ICMP) {char buffer[1500];memset(buffer, 0, 1500);/*********************************************************Step 1: 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;printf("icmp id: %d, seq: %d\n", ntohs(icmp_pkt->icmp_id), ntohs(icmp_pkt->icmp_seq));// Calculate the checksum for integrityicmp->icmp_chksum = 0;icmp->icmp_chksum = in_cksum((unsigned short *)icmp,sizeof(struct icmpheader));/*********************************************************Step 2: Fill in the IP header.********************************************************/struct ipheader *ipp = (struct ipheader *) buffer;ipp->iph_ver = 4;ipp->iph_ihl = 5;ipp->iph_ttl = 64;ipp->iph_sourceip.s_addr = ip->iph_destip.s_addr;ipp->iph_destip.s_addr = ip->iph_sourceip.s_addr;ipp->iph_protocol = IPPROTO_ICMP;ipp->iph_len = htons(sizeof(struct ipheader) +sizeof(struct icmpheader));printf("send tt source :%s\n", inet_ntoa(ipp->iph_sourceip));printf("send tt dest: %s\n", inet_ntoa(ipp->iph_destip));/*********************************************************Step 3: Finally, send the spoofed packet********************************************************/// icmp_pkt->icmp_type = 0;// icmp_pkt->icmp_code = 0;// icmp->icmp_chksum = 0;// icmp->icmp_chksum = in_cksum((unsigned short *)icmp,// sizeof(struct icmpheader));send_raw_ip_packet (ipp);}}
}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 enp0s3handle = pcap_open_live("enp0s3", BUFSIZ, 1, 1000, errbuf);printf("listening on network card, ret: %p...\n", handle);// Step 2: Compile filter_exp into BPF psuedo-codeprintf("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 packetsprintf("start to sniff...\n");pcap_loop(handle, -1, got_packet, NULL);pcap_close(handle); //Close the handlereturn 0;
}
- 使用 gcc -o task23 task23.c checksum.c spoof.c -lpcap编译程序,sudo ./task23运行
- 使用另一台机器ping 1.1.1.1,此机器运行上面的程序,结果如下:
这篇关于从入门到入土:[SEED-Lab]- Packet Sniffing and Spoofing Lab|嗅探与欺骗实验|详细说明|实验步骤|实验截图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!