Skip to content
KitploitKITPLOIT
工具博客
Log in
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
sigwire — 实时内核信号可观测性工具,利用 eBPF 跟踪点流式传输 Linux 主机上引发的每个信号,实时显示发送者、目标、处置方式、处理程序延迟以及系统调用中断。 | Kitploit
工具/GitHubGitHub/yeet-src/sigwire
动态分析 (沙盒)调试器取证分析事件响应日志分析
GitHubyeet-src/sigwire

sigwire

实时内核信号可观测性工具,利用 eBPF 跟踪点流式传输 Linux 主机上引发的每个信号,实时显示发送者、目标、处置方式、处理程序延迟以及系统调用中断。

查看仓库
1594571个月前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
网站

sigwire

tail -f 用于信号。 系统上每个进程引发的每个信号——谁发送的、谁接收的、哪个信号、如何引发的(kill(2)、内核、POSIX 定时器)、目标是否捕获了它以及其处理程序运行了多长时间、它是否用 EINTR 撕开了阻塞的系统调用——从内核的信号跟踪点解码并实时流式传输到您的终端。无需对单一 pid 使用 strace -f,无需 ptrace,无需被涉及进程的配合。

Linux yeet + eBPF Dual BSD/GPL Discord

sigwire streaming live signals as a switchboard in the terminal

sigwire 将内核的信号机制转变为实时配线架:每一行是 sender ──SIGNAL──▶ target,按严重性着色,标记引发方式,目标是否捕获了它(以及其处理程序运行了多长时间),是否中断了阻塞的系统调用**(↯ EINTR read),当某个信号大量出现时折叠为 ×N,并且当它是真正的致命一击时标记 ☠。** 侧边栏统计着传输中的信号;暂停并选择一行以查看完整画面——信号处置、处理程序地址、sigaction 标志以及目标当时正在阻塞的信号。

因为它挂钩内核的跟踪点,而不是任何单一进程,一次运行即可同时监控主机上的每个信号——您的应用程序、监督程序、内核自身的故障机制——而它们都不会意识到自己正在被跟踪。

[!TIP] 每个信号的两个方面。 sigwire 同时监控 signal:signal_generate(发送者的视角——谁引发了什么,配线架线路)和 signal:signal_deliver(目标的视角——是否捕获了它,使用哪个处理程序和标志,当时阻塞了什么,以及是否中断了系统调用)。另外两个钩子——rt_sigreturn(2) 和系统调用退出跟踪点——对处理程序进行计时并捕获 EINTR。所有这些都被关联回同一行。这种分离也是为什么 ☠ fatal 计数故意保守的原因(参见什么算作致命):信号的产生发生在传递之前,因此发送方无法知道信号的命运——只有传递方可以,而且仅限于它观察到的情况。

快速开始```sh

curl -fsSL https://yeet.cx | sh # install the yeet daemon (one time) yeet run github:yeet-src/sigwire # run the dashboard (the daemon does the privileged BPF load)

[手动安装指南](https://yeet.cx/docs/manual-installation) | 仅限 Linux

无需配置 — 信号在任何机器上都是持续的背景流量,因此行会立即从顶部开始出现。想自己生成一些?`kill -USR1 <pid>`、对前台作业按 `Ctrl-C`,或者启动任何托管运行时并观察其 GC/调度器 ping 自己的线程(`↯ EINTR futex` 滚动而过)。

## 控制

信号流默认跟随最新信号;选择一行或暂停后,它会保持静止,同时数据在下方继续流动。

| 键 | 操作 |
| --- | ------ |
| `p` · `Space` | 暂停/恢复信号流(冻结以阅读) |
| `↑`/`↓`, `k`/`j` | 暂停并检查一行 — 打开详情面板 |
| `/` | 模糊过滤 — 匹配进程、PID、信号、来源和处置方式;匹配字符实时高亮 |
| `e` | 过滤至**仅中断的系统调用**(`↯ EINTR` / `↺ restarted`) |
| `s` | 打开**信号选择器** — 实时静音或显示任何信号 |
| `Esc` | 退出一层 — 清除过滤/关闭选择器/取消选择,然后退出 |
| `q` | 退出 |

## 您正在查看的内容

每一行是一个生成的信号,最新的在最顶部:```
 WHEN            SENDER  SIGNAL        TARGET               NOTE
  now       bash·4402──SIGINT───▶  node·8813        kill(2)  ↯ EINTR read  caught 41µs
 1.2s    systemd·1──────SIGTERM──▶  nginx·1291       kill(2)  caught 1.2ms
 3.4s     kernel·8813──SIGSEGV──▶  chrome·8813       fault    default  ☠
 4.1s   postgres·507──SIGUSR1───▶  postgres·509 ×6  kill(2)  caught 9µs

每一行都是一个块:发送方 → 目标 为 comm·pid(发送方是发起信号的一方,current;目标是信号指向的进程),中间的导线承载着根据严重性着色的信号名称,×N 将相同信号的一次突发合并为一行,右侧的注释给出来源,然后是任何系统调用中断,最后是处置方式。

每一行在交付解析完成时冻结,此后永远不会再改变——因此一次突发会作为一条稳定的日志滚动显示,而不是闪烁的聚合。

导线根据严重性着色,采用与 UI 其余部分相同的 256 色调色板:

严重性信号颜色
致命SIGKILL热红
致命(生成 core 文件)SEGV BUS ABRT ILL FPE TRAP SYS QUIT红色
终止TERM INT HUP PIPE ALRM …琥珀色
作业控制STOP TSTP TTIN TTOU黄色
继续CONT绿色
用户USR1 USR2青色
实时SIGRTMIN+n紫色
内务CHLD URG WINCH …灰色

注释 是来源(kill(2)、tgkill、sigqueue、timer、kernel、fault);然后,如果它中断了阻塞的系统调用,会显示 ↯ EINTR read(或 ↺ restarted read,当 SA_RESTART 自动恢复它时);最后是处置方式——caught 41µs(处理程序运行了,以及耗时多久)、default(没有处理程序,采用了默认行为)或 ⊘ ignored。☠ 标记真正的致命一击(参见什么算致命)。

[!NOTE] ↯ EINTR 是需要关注的重点。 当一个信号到达时,线程正阻塞在慢速系统调用(read、poll、accept、futex、nanosleep……)中,该线程会被强制唤醒:系统调用返回 -1 / EINTR,并且除非处理程序设置了 SA_RESTART,否则它不会恢复——应用程序必须重试。忘记这一点是一个经典的、令人抓狂的、与时机相关的 bug(“为什么我的 read() 失败了一次?”)。sigwire 实时显示这种情况的发生,以及是哪个系统调用受到了影响。按 e 键隐藏所有其他内容,只观察这些中断。

右侧的轨道是聚合视图:按数量排列的顶部信号、按来源的分类,以及交付统计——捕获了多少信号、默认处理了多少、忽略了多少。

检查信号

按 ↑/↓(或 p)冻结流并选择一行;轨道变为一个详细信息面板,显示关于该确切信号的交付侧所知的一切:``` SIGNAL SIGUSR1 (10) user from ctarget·3980913 to ctarget·3980913 RAISED via tgkill code SI_TKILL scope thread result delivered DELIVERY handled caught syscall EINTR ← read handler 0x55f0a1c3 ran 3.0ms flags SA_SIGINFO TARGET BLOCKS SIGINT SIGQUIT SIGTERM

- **handled** — `caught`(运行了用户空间处理程序)、`default`(→ 默认动作:终止/核心转储/停止/忽略)或 `ignored`。
- **syscall** — 如果该信号中断了一个阻塞的系统调用:`EINTR ← read`(用户空间看到 `EINTR`)或 `restarted read`(`SA_RESTART` 透明地恢复它)。
- **ran** — 处理程序执行的时间,从递送到结束它的 `rt_sigreturn(2)` 计算。(只会在 C 处理程序中设置标志并在以后执行实际工作的运行时——CPython、Go——在这里显示一个很小的时间;那是它们的问题,不是 sigwire 的。)
- **flags** — 处理程序上的 `sigaction` 标志(`SA_RESTART`、`SA_SIGINFO`、`SA_NODEFER`……)。
- **TARGET BLOCKS** — 目标在递送时刻已阻塞的信号(其 `sigprocmask`),直接来自其 `task_struct`。

`Esc` 关闭检查器;`p` 恢复实时显示。

## 什么算作致命

`☠ fatal` 计数器和 `☠` 行徽章故意严格。因为 `signal_generate` 在*产生*时触发,sigwire 无法看到目标是否安装了处理程序——`SIGTERM` 可能被捕获并转换为干净关闭,或者完全被忽略。因此,只有当死亡是明确无误时,它才会计数:

- **`SIGKILL` 递送**——不可捕获、不可忽略、始终致命;**或**
- **内核自身引发的**(同步故障,而非用户空间的 `kill`)一个**核心转储信号**(`SEGV`/`BUS`/`ABRT`/`ILL`/`FPE`/`TRAP`/`SYS`/`QUIT`)。

其他所有信号——来自 `systemd` 的 `SIGTERM`、来自你的 `Ctrl-C` 的 `SIGINT`、运行时发给自己线程的 `SIGPWR`——都会被显示和着色,但不计为死亡,因为很可能不是。

## 信号选择器(一个实时的内核旋钮)

在任何繁忙的机器上,三个信号都是纯背景噪音:`SIGCHLD`(每次子进程回收)、`SIGURG`(Go 的异步抢占心跳)和 `SIGWINCH`(终端大小变化,广播给所有前台进程)。sigwire 默认在**内核内**静音这三个信号,以便显示感兴趣流量——但哪些信号是噪音取决于你。

按下 `s` 打开**信号选择器**:一个模态列表,包含每个信号及其实时严重性颜色和你已经看到的数量,每个信号可在 `shown`(显示)和 `muted`(静音)之间切换。用箭头移动到某个信号(或**输入其数字**——`1`、`5` → 跳到 15),然后按 `space`,该信号立即切换。`a` 一次性切换**所有**信号。标题栏中的 `muted` 计数跟踪当前隐藏的数量。

这是演示的双向部分:静音掩码是正在运行的 BPF 程序的 `.data` 部分中的一个 `__u64` 全局变量,切换一行会通过 `DataSec.patch()` 修补匹配的位,而程序持续运行。内核在静音信号到达环形缓冲区之前就丢弃它们,因此静音不会消耗任何成本——而且取消静音会在流式过程中恢复信号,无需重新加载。

## 工作原理

核心是 [`src/bpf/sigwire.bpf.c`](https://github.com/yeet-src/sigwire/blob/master/src/bpf/sigwire.bpf.c) + [`src/bpf/deliver.bpf.c`](https://github.com/yeet-src/sigwire/blob/master/src/bpf/deliver.bpf.c)(内核,链接成一个对象)和 [`src/probes/sigwire.js`](https://github.com/yeet-src/sigwire/blob/master/src/probes/sigwire.js)(用户空间)。所有内容通过 `(target tid, signal)` 关联。

### BPF 侧

两个源文件链接成一个可加载对象 `bin/probe.bpf.o`,包含四个 tracepoint 程序:

| 程序 | 附加到 | 捕获内容 |
|---|---|---|
| `on_signal_generate` | `signal:signal_generate` | 发送者(`current`)+ 目标(`comm`/`pid`)、信号、`si_code`、`group` 标志、`result`——如果该信号的位在实时 `mute_mask` 中设置,则在内核中丢弃 |
| `on_signal_deliver` | `signal:signal_deliver` | 目标的处置(`sa_handler`)、`sa_flags`,以及来自 `task_struct` 的 `blocked` 信号集;为处理程序计时标记递送 |
| (rt_sigreturn) | `syscalls:sys_enter_rt_sigreturn` | 与标记的递送进行差异比较,得到处理程序的运行时间 |
| (sys_exit) | `raw_syscalls:sys_exit` | 记录罕见的 `-ERESTART*` 返回值,以便下一个 `signal_deliver` 将其解析为 `EINTR`/`restarted` 以及被中断的系统调用号 |

映射连接内核和用户空间:

- `events` — `RINGBUF`,每次产生一个 `signal_event`。
- `dispatch` — `RINGBUF`,每次递送/处理程序返回一个 `dispatch_event`。
- `mute_mask` — `.data` 部分中的一个 `__u64` 全局变量;选择器通过修补单个位在内核中丢弃信号。
- `handler_start` / `restart_pending` — `HASH`,以 tid 为键,每个线程的临时空间,用于将一次递送与其 `rt_sigreturn` 配对,以及将系统调用的 `-ERESTART*` 退出与后续递送配对。

### JS 侧
下载工具