updated some material
This commit is contained in:
83
Sniffing_Spoofing/Experiment_Guide.md
Normal file
83
Sniffing_Spoofing/Experiment_Guide.md
Normal file
@@ -0,0 +1,83 @@
|
||||
# 网络安全实验:数据包嗅探与伪造(Sniffing & Spoofing)演示指南
|
||||
|
||||
这份文档旨在帮助你快速回顾实验步骤、关键命令以及核心理论,应对老师的实验验收。
|
||||
|
||||
---
|
||||
|
||||
## 0. 准备工作:启动实验环境
|
||||
|
||||
在 `Labsetup` 目录下执行以下操作:
|
||||
|
||||
1. **启动容器**:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
2. **确认网络接口**:
|
||||
由于实验代码中硬编码了网卡名称(如 `br-c031fbf1a197`),请务必在宿主机执行 `ifconfig` 或 `ip addr`,找到 IP 为 `10.9.0.1` 的网桥名称。
|
||||
* **重要提示**:如果演示时报错 `Device not found`,请立即修改代码中的 `iface` 参数为实际查到的名称。
|
||||
|
||||
---
|
||||
|
||||
## 1. 任务集 1:使用 Scapy (Python)
|
||||
|
||||
### 任务 1.1: 基础嗅探 (Sniffer)
|
||||
* **运行命令**:`sudo python3 sniffer.py`
|
||||
* **测试步骤**:在 HostA 或 HostB 执行 `ping 10.9.0.x`。
|
||||
* **验收提问**:
|
||||
* **为什么需要 sudo?** 因为创建原始套接字(Raw Socket)和开启混杂模式需要 Root 权限。
|
||||
* **如何过滤流量?** 解释 BPF 过滤器(如 `icmp`, `tcp port 23`)。
|
||||
|
||||
### 任务 1.2: 数据包伪造 (Spoofing)
|
||||
* **运行命令**:`sudo python3 spoofer.py`
|
||||
* **测试现象**:HostA 会收到一个来自虚假源 IP(如 `1.2.3.4`)的 ICMP 请求包。
|
||||
|
||||
### 任务 1.3: 自定义 Traceroute
|
||||
* **运行命令**:`sudo python3 traceroute.py`
|
||||
* **核心原理**:利用 **TTL (Time To Live)** 字段。从 1 开始递增 TTL,每一跳路由器丢弃包并返回 `ICMP Time Exceeded`,直到到达目标返回 `Echo Reply`。
|
||||
|
||||
### 任务 1.4: 嗅探并伪造响应 (Sniff-and-Spoof)
|
||||
* **演示重点**:
|
||||
1. Attacker 运行 `sudo python3 sniff_and_spoof.py`。
|
||||
2. HostA 执行 `ping 1.2.3.4` -> **成功收到回复**(Attacker 伪造的)。
|
||||
3. HostA 执行 `ping 10.9.0.99` (局域网内不存在的 IP) -> **失败**。
|
||||
* **原理深度解析**:因为 HostA 会先发送 **ARP 请求** 寻找 `10.9.0.99` 的 MAC 地址。由于该 IP 不存在,ARP 无响应,IP 包根本发不出去,Attacker 也就嗅探不到请求。
|
||||
|
||||
---
|
||||
|
||||
## 2. 任务集 2:使用 C 语言 (libpcap & Raw Socket)
|
||||
|
||||
### 编译与运行
|
||||
```bash
|
||||
# 在容器或挂载目录下编译
|
||||
gcc -o sniffer_c sniffer.c -lpcap
|
||||
gcc -o spoofer_c spoofer.c
|
||||
gcc -o sniff_and_spoof_c sniff_and_spoof.c -lpcap
|
||||
|
||||
# 运行(记得 sudo)
|
||||
sudo ./sniffer_c
|
||||
```
|
||||
|
||||
### 核心技术点 (验收常考)
|
||||
* **libpcap 流程**:`pcap_open_live` -> `pcap_compile` -> `pcap_setfilter` -> `pcap_loop`。
|
||||
* **Raw Socket 伪造**:必须设置 `IP_HDRINCL` 选项,手动构造整个 IP 和 ICMP 首部。
|
||||
* **校验和 (Checksum)**:计算前必须将校验和字段清零,否则计算结果错误,包会被丢弃。
|
||||
* **字节序 (Endianness)**:网络传输使用大端序,多字节字段(如 IP、Port)需使用 `htons()` / `htonl()` 转换。
|
||||
|
||||
---
|
||||
|
||||
## 3. 验收常见 Q&A
|
||||
|
||||
1. **Q: 为什么攻击者能看到其他机器的流量?**
|
||||
* A: 容器处于 `host` 网络模式,且开启了 **混杂模式 (Promiscuous Mode)**,允许网卡接收目的 MAC 不是本机的帧。
|
||||
2. **Q: 交换式网络环境下嗅探有什么限制?**
|
||||
* A: 在真实物理交换机下,除非进行 ARP 欺骗或配置端口镜像,否则混杂模式只能看到广播帧和发往本机的帧。Docker 虚拟网桥模拟了这种环境。
|
||||
3. **Q: Scapy 与 C 语言开发相比有什么优缺点?**
|
||||
* A: Scapy 开发效率极高,一行代码搞定协议堆叠;C 语言执行效率高,能更深入底层,适合学习协议栈细节。
|
||||
|
||||
---
|
||||
|
||||
## 演示清单 (Checklist)
|
||||
- [ ] `docker-compose up -d` 环境就绪。
|
||||
- [ ] 找到正确的 `br-xxxx` 网桥接口名。
|
||||
- [ ] 所有代码已针对当前环境的网桥名完成更新。
|
||||
- [ ] 准备好两个终端:一个运行嗅探/伪造脚本,一个在 HostA 执行测试命令。
|
||||
0
Sniffing_Spoofing/volumes/.gitignore
vendored
0
Sniffing_Spoofing/volumes/.gitignore
vendored
@@ -1,76 +0,0 @@
|
||||
#include <pcap.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
unsigned short in_cksum (unsigned short *buf, int length) {
|
||||
unsigned short *w = buf;
|
||||
int nleft = length;
|
||||
int sum = 0;
|
||||
unsigned short temp=0;
|
||||
while (nleft > 1) { sum += *w++; nleft -= 2; }
|
||||
if (nleft == 1) { *(u_char *)(&temp) = *(u_char *)w ; sum += temp; }
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
return (unsigned short)(~sum);
|
||||
}
|
||||
|
||||
void send_raw_ip_packet(struct iphdr* ip) {
|
||||
struct sockaddr_in dest_info;
|
||||
int enable = 1;
|
||||
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &enable, sizeof(enable));
|
||||
dest_info.sin_family = AF_INET;
|
||||
dest_info.sin_addr.s_addr = ip->daddr;
|
||||
sendto(sock, ip, ntohs(ip->tot_len), 0, (struct sockaddr *)&dest_info, sizeof(dest_info));
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
|
||||
struct iphdr *ip = (struct iphdr *)(packet + 14); // Skip Ethernet header (14 bytes)
|
||||
if (ip->protocol != IPPROTO_ICMP) return;
|
||||
|
||||
struct icmphdr *icmp = (struct icmphdr *)(packet + 14 + (ip->ihl * 4));
|
||||
if (icmp->type == 8) { // Echo request
|
||||
printf("Intercepted ICMP Echo Request from %s to %s\n", inet_ntoa(*(struct in_addr *)&ip->saddr), inet_ntoa(*(struct in_addr *)&ip->daddr));
|
||||
|
||||
char buffer[1500];
|
||||
int ip_header_len = ip->ihl * 4;
|
||||
int icmp_len = ntohs(ip->tot_len) - ip_header_len;
|
||||
memcpy(buffer, ip, ntohs(ip->tot_len));
|
||||
|
||||
struct iphdr *new_ip = (struct iphdr *)buffer;
|
||||
struct icmphdr *new_icmp = (struct icmphdr *)(buffer + ip_header_len);
|
||||
|
||||
// Swap addresses
|
||||
new_ip->saddr = ip->daddr;
|
||||
new_ip->daddr = ip->saddr;
|
||||
new_ip->ttl = 64;
|
||||
|
||||
// Change to Echo Reply
|
||||
new_icmp->type = 0;
|
||||
new_icmp->checksum = 0;
|
||||
new_icmp->checksum = in_cksum((unsigned short *)new_icmp, icmp_len);
|
||||
|
||||
printf("Sending spoofed ICMP Echo Reply from %s back to %s...\n", inet_ntoa(*(struct in_addr *)&new_ip->saddr), inet_ntoa(*(struct in_addr *)&new_ip->daddr));
|
||||
send_raw_ip_packet(new_ip);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
pcap_t *handle;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
struct bpf_program fp;
|
||||
char filter_exp[] = "icmp";
|
||||
handle = pcap_open_live("br-c031fbf1a197", BUFSIZ, 1, 1000, errbuf);
|
||||
pcap_compile(handle, &fp, filter_exp, 0, PCAP_NETMASK_UNKNOWN);
|
||||
pcap_setfilter(handle, &fp);
|
||||
printf("C-based Sniff-and-Spoof active...\n");
|
||||
pcap_loop(handle, -1, got_packet, NULL);
|
||||
pcap_close(handle);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from scapy.all import *
|
||||
|
||||
def spoof_reply(pkt):
|
||||
# Only respond to ICMP Echo Requests
|
||||
if ICMP in pkt and pkt[ICMP].type == 8:
|
||||
print(f"Intercepted ICMP Echo Request from {pkt[IP].src} to {pkt[IP].dst}")
|
||||
|
||||
# Build spoofed ICMP Echo Reply
|
||||
ip = IP(src=pkt[IP].dst, dst=pkt[IP].src)
|
||||
icmp = ICMP(type=0, id=pkt[ICMP].id, seq=pkt[ICMP].seq)
|
||||
|
||||
# Add payload if present
|
||||
payload = pkt[Raw].load if Raw in pkt else b""
|
||||
|
||||
new_pkt = ip/icmp/payload
|
||||
print(f"Sending spoofed reply from {pkt[IP].dst} to {pkt[IP].src}...")
|
||||
send(new_pkt, verbose=0)
|
||||
|
||||
print("Sniff-and-Spoof active on br-c031fbf1a197...")
|
||||
# Filter: icmp echo-request
|
||||
sniff(iface='br-c031fbf1a197', filter='icmp and icmp[icmptype]=8', prn=spoof_reply)
|
||||
Binary file not shown.
@@ -1,39 +0,0 @@
|
||||
#include <pcap.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {
|
||||
printf("Got a packet\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
pcap_t *handle;
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
struct bpf_program fp;
|
||||
char filter_exp[] = "icmp";
|
||||
bpf_u_int32 net;
|
||||
|
||||
// Step 1: Open pcap session on the interface
|
||||
handle = pcap_open_live("br-c031fbf1a197", BUFSIZ, 1, 1000, errbuf);
|
||||
if (handle == NULL) {
|
||||
fprintf(stderr, "Couldn't open device: %s\n", errbuf);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Step 2: Compile filter_exp into BPF code
|
||||
if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
|
||||
fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
|
||||
return 2;
|
||||
}
|
||||
if (pcap_setfilter(handle, &fp) == -1) {
|
||||
fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Step 3: Capture packets
|
||||
printf("Sniffing ICMP packets using C and libpcap...\n");
|
||||
pcap_loop(handle, -1, got_packet, NULL);
|
||||
|
||||
pcap_close(handle);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from scapy.all import *
|
||||
|
||||
def print_pkt(pkt):
|
||||
pkt.show()
|
||||
|
||||
print("Sniffing ICMP packets from spoofed IP 1.2.3.4...")
|
||||
pkt = sniff(iface='br-c031fbf1a197', filter='icmp and src host 1.2.3.4', prn=print_pkt, count=1)
|
||||
Binary file not shown.
@@ -1,81 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Checksum calculation function */
|
||||
unsigned short in_cksum (unsigned short *buf, int length) {
|
||||
unsigned short *w = buf;
|
||||
int nleft = length;
|
||||
int sum = 0;
|
||||
unsigned short temp=0;
|
||||
|
||||
while (nleft > 1) {
|
||||
sum += *w++;
|
||||
nleft -= 2;
|
||||
}
|
||||
|
||||
if (nleft == 1) {
|
||||
*(u_char *)(&temp) = *(u_char *)w ;
|
||||
sum += temp;
|
||||
}
|
||||
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
return (unsigned short)(~sum);
|
||||
}
|
||||
|
||||
void send_raw_ip_packet(struct iphdr* ip) {
|
||||
struct sockaddr_in dest_info;
|
||||
int enable = 1;
|
||||
|
||||
int sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (sock < 0) {
|
||||
perror("Socket creation failed");
|
||||
return;
|
||||
}
|
||||
|
||||
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &enable, sizeof(enable));
|
||||
|
||||
dest_info.sin_family = AF_INET;
|
||||
dest_info.sin_addr.s_addr = ip->daddr;
|
||||
|
||||
if (sendto(sock, ip, ntohs(ip->tot_len), 0, (struct sockaddr *)&dest_info, sizeof(dest_info)) < 0) {
|
||||
perror("Sendto failed");
|
||||
} else {
|
||||
printf("Spoofed ICMP packet sent.\n");
|
||||
}
|
||||
close(sock);
|
||||
}
|
||||
|
||||
int main() {
|
||||
char buffer[1500];
|
||||
memset(buffer, 0, 1500);
|
||||
|
||||
struct iphdr *ip = (struct iphdr *) buffer;
|
||||
struct icmphdr *icmp = (struct icmphdr *) (buffer + sizeof(struct iphdr));
|
||||
|
||||
// Construct ICMP Header
|
||||
icmp->type = ICMP_ECHO;
|
||||
icmp->code = 0;
|
||||
icmp->un.echo.id = htons(1234);
|
||||
icmp->un.echo.sequence = htons(1);
|
||||
icmp->checksum = 0;
|
||||
icmp->checksum = in_cksum((unsigned short *)icmp, sizeof(struct icmphdr));
|
||||
|
||||
// Construct IP Header
|
||||
ip->version = 4;
|
||||
ip->ihl = 5;
|
||||
ip->ttl = 64;
|
||||
ip->saddr = inet_addr("1.2.3.4");
|
||||
ip->daddr = inet_addr("10.9.0.5");
|
||||
ip->protocol = IPPROTO_ICMP;
|
||||
ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmphdr));
|
||||
|
||||
send_raw_ip_packet(ip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from scapy.all import *
|
||||
|
||||
print("Spoofing ICMP echo request from 1.2.3.4 to 10.9.0.5...")
|
||||
a = IP()
|
||||
a.src = '1.2.3.4'
|
||||
a.dst = '10.9.0.5'
|
||||
b = ICMP()
|
||||
p = a/b
|
||||
send(p)
|
||||
Binary file not shown.
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
from scapy.all import *
|
||||
|
||||
target = "8.8.8.8"
|
||||
print(f"Traceroute to {target}...")
|
||||
|
||||
for i in range(1, 31):
|
||||
pkt = IP(dst=target, ttl=i) / ICMP()
|
||||
reply = sr1(pkt, verbose=0, timeout=1)
|
||||
|
||||
if reply is None:
|
||||
print(f"{i}: * * *")
|
||||
elif reply.type == 3: # Destination unreachable
|
||||
print(f"{i}: {reply.src} (Unreachable)")
|
||||
break
|
||||
else:
|
||||
print(f"{i}: {reply.src}")
|
||||
if reply.src == target:
|
||||
print("Reached target!")
|
||||
break
|
||||
Reference in New Issue
Block a user