Tinshea/WireOwl

GitHub: Tinshea/WireOwl

一款用纯 Python 从头编写的 Wireshark 风格网络数据包分析器,通过逐层手动解析十六进制转储文件来帮助用户理解协议栈结构。

Stars: 0 | Forks: 1

WireOwl — a packet analyzer that takes hex dumps apart, layer by layer

Python 3.11+ tkinter 2 dependencies Cross-platform

# WireOwl 一款受 Wireshark 启发、完全使用 Python 从头编写的网络数据包分析器。只需将其指向一个十六进制转储(hex dump),它就会沿着协议栈逐层解析字节 —— Ethernet 帧、接着是 IPv4 头、然后是 TCP 段、最后是 HTTP 负载 —— 将每一层渲染为可读的字段,绘制出会话流图,并将整个分析结果导出为 PDF。 每个协议解码器都是纯手工编写的:**没有使用 scapy,也没有使用 dpkt**。该项目的初衷是为了阅读 RFC 并手动切片字节,因此解析器完全基于原始偏移量和位掩码进行工作。 ## 快速开始 你需要安装带有 tkinter 的 **Python 3.11+**。除此之外无需其他依赖 —— 两个运行时依赖会自动安装。 ``` git clone https://github.com/Tinshea/WireOwl.git cd WireOwl ``` **Linux / macOS** ``` chmod +x run.sh ./run.sh ``` **Windows (PowerShell)** ``` .\run.ps1 ``` 或者,如果你有 `make`: ``` make setup && make run ``` 以上三种方式都会创建一个 `.venv`,安装相关依赖并启动应用程序。按下 **Start**,从 `sample/` 中挑选任意文件,你就可以开始使用了。 ## 界面展示 加载捕获文件后,每一帧都会被总结为一行:源地址和目标地址、端口、TCP 标志、序列号和确认号以及窗口大小。属于同一会话的帧会共享同一种颜色,HTTP 帧会以洋红色突出显示,点击其中一帧即可在下方的面板中查看其解码细节 —— 如下图所示的一个 SYN 的 TCP 层。

Frame list showing a TCP handshake, with the TCP layer of the selected frame decoded below

左侧的五个图标用于切换详情面板显示的层级:原始帧、Ethernet、IPv4、TCP 或重组后的 HTTP 负载。 ### 过滤 输入一个表达式,帧列表就会自动筛选出匹配的帧。当表达式能够被成功解析时,输入框会变为**青色**;若解析失败则变为**红色**,这样拼写错误就会一目了然。过滤机制的实现方式是:将解析后的帧加载到内存中的 SQLite schema 里,并将表达式作为 `WHERE` 子句进行执行 —— 如下图所示,从一个 2.3 MB 的捕获文件中提取出了 477 个 TCP 帧。

The filter protocol == 6 applied, narrowing a large capture to its TCP frames

| 字段 | 匹配目标 | 示例 | |---|---|---| | `protocol` | IP 协议**编号**(见下表) | `protocol == 6` | | `ip.src` / `ip.addr` | IPv4 源 / 目标地址 | `ip.src == 192.168.1.102` | | `tcp.src` / `tcp.addr` | TCP 源 / 目标端口 | `tcp.addr == 80` | | `eth.src` / `eth.addr` | MAC 源 / 目标地址 | `eth.src == f0189859ae32` | | `http.version` | HTTP 版本字符串 | `http.version == 1.1` | 支持的运算符为 `==` 和 `!=`,并可以通过 `and` / `&&` / `or` / `||` 进行组合: ``` protocol == 6 and ip.src == 192.168.31.69 ip.src == 192.168.1.102 or ip.addr == 192.168.1.117 ``` 关于该语法有两点需要注意: - `protocol` 存储的是数字形式的 IANA 值,而不是名称 —— 应使用 `protocol == 6`,而不是 `protocol == TCP`。后者的语法本身没有问题,但不会匹配到任何结果。 - **复合表达式必须限制在同一字段族(family)内。** 每个字段族都存在于独立的 SQLite 表中(`protocol` 和 `ip.*` 同属一个表,此外还有 `tcp.*`、`eth.*`、`http.version`),生成的查询会针对由*第一个*条件所指定的表进行检索。`protocol == 6 and ip.src == …` 是有效的;而 `protocol == 6 and tcp.addr == 80` 则会被拒绝。 ### 流图 流图将主机布局为列,将帧布局为行,将每一次交互绘制为带有端口注释的箭头 —— 让你能够一目了然地看清会话的全貌。

Flow graph with hosts as columns and one arrow per frame, annotated with ports

### PDF 报告 只需点击一下,即可将一份完整的报告写入 `PDF/` 目录:包含带链接的目录、流图,随后是每一帧的独立详情页,其中展示了所有解码后的字段。

A page of the generated PDF report showing a fully decoded frame

## 工作原理 `traitement()` 负责读取转储文件,将偏移量为 `0000` 的行视为一个新帧的起始,并剔除偏移量列和 ASCII 侧边栏,最终为每一帧留下一个十六进制字符串。这些字符串随后会流经四个解析器,每个解析器会消耗(解析)它所能识别的头部,并将剩余部分传递给下一个解析器: ``` hex text ──▶ trame.tramecalcul MAC addresses, EtherType ──▶ paquetip.paquetipv4 IPv4 header: TTL, flags, protocol, addresses ──▶ tcp.tcpaquet ports, sequence numbers, flags, window ──▶ httpmodule.req_or_rep request/response, method, status, headers ``` 每个阶段都会将其人类可读的输出追加到 `Trames/TrameN.txt` 中,并填充以帧编号为键的模块级字典(如 `Source_Address`、`Port_Source`、`flagdic` 等)。GUI、过滤引擎和 PDF 导出器读取的都是这些字典中的数据 —— 解析过程只需进行一次,之后的所有操作都只是纯粹的数据查询。 ### 支持的协议 | 层级 | 解码内容 | |---|---| | **Ethernet** | 源和目标 MAC 地址,EtherType | | **IPv4** | 头长度、TOS、总长度、标识符、DF/MF 标志、分片偏移、TTL、协议、头部校验和、地址 | | **TCP** | 端口、序列号和确认号、数据偏移、全部六个标志位、窗口大小、校验和、紧急指针、选项 | | **HTTP** | 请求与响应、方法、版本、状态码、头部 | IP 协议号通过 `dico_protocol` 进行解析:`1` 为 ICMP,`2` 为 IGMP,`6` 为 TCP,`8` 为 EGP,`9` 为 IGP,`17` 为 UDP,`36` 为 XTP,`46` 为 RSVP。 **目前仅解析 IPv4。** 携带其他协议(如 IPv6、ARP)的帧会列出其类型,并被标记为 `n'est pas pris en charge par le programme`,而不会被解码。同样地,只有 TCP 会进行传输层解码;UDP 帧会被计数并支持过滤,但不会被详细拆解。 ## 示例捕获文件 `sample/` 目录同时也是测试套件 —— 其中有几个文件是专门为了测试错误处理路径而存在的。 | 文件 | 内容 | |---|---| | `Trace.txt`, `TCP_1..3.txt` | 干净的 TCP 握手 —— 最佳入门起点 | | `HTTP_2.txt`, `HTTP_TCP.txt` | 基于 TCP 的 HTTP 请求/响应 | | `ARP_UDP_ICMP_IGMP.txt` | 63 个混合帧;适合用于测试过滤器 | | `test-3f.txt` | 大小为 2.3 MB,包含约 500 个帧 —— 用于压力测试 | | `HTTP_1.txt` | 单个 IPv6 帧,即触发不支持协议路径的场景 | | `Corrupted.txt`, `Empty.txt`, `Text.txt` | 格式错误的输入;程序应发出警告,而不是崩溃 | ## 项目结构 ``` WireOwl/ ├── run.sh / run.ps1 # set up the venv and launch ├── Makefile # setup / run / clean ├── core/ │ ├── main.py # entry point │ ├── source.py # tkinter GUI, dump parsing, all screens │ ├── trame.py # Ethernet layer │ ├── paquetip.py # IPv4 layer │ ├── tcp.py # TCP layer │ ├── httpmodule.py # HTTP layer │ ├── filtrage.py # SQLite-backed filter engine │ └── pdf.py # report + flow graph export ├── affichage/ # icons, backgrounds, logo ├── sample/ # hex dump captures (see above) ├── Tools/requirements.txt ├── Trames/ # per-frame decode output (generated) └── PDF/ # generated reports ``` `main.py` 必须在仓库的根目录作为工作目录时才能运行:`source.py` 加载图片时使用的是类似 `./affichage/bg.png` 的相对路径。启动脚本已经为你处理好了这些设置。 ## 注意事项 - **`tkmacosx` 是可选的。** 它的存在仅仅是为了在 macOS 上提供一个支持自定义 `bg`(背景色)的按钮控件;在所有其他平台上,`source.py` 都会回退使用 `tkinter.Button`,因此该库仅在 macOS 上才会被安装。 - **在许多 Linux 发行版上,需要单独安装 tkinter** —— 例如在 Debian/Ubuntu 上执行 `sudo apt install python3-tk`。`run.sh` 会自动检查并给予提示。 - **每次加载时都会清空 `Trames/` 目录。** 该目录用于保存逐帧解码的转储数据和过滤器数据库,每次打开捕获文件时,这些内容都会从头重新构建。 - UI 界面和解码输出均使用**法语**,这与该项目最初的课程作业要求保持一致。 ## 致谢 - **Malek Bouzarkouna** — [@Tinshea](https://github.com/Tinshea) - **Sevag Baboyan** — [@SesevagB](https://github.com/SesevagB) Sorbonne Université — 网络课程。 未指定许可证。
标签:Cutter, PDF报告, Python, SQLite, Tkinter, 数据包解析, 无后门, 系统分析, 网络分析, 逆向工具