who->who-rs;v8.0.0Rust重构已发布

admin 2026-09-25 05:12:22 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: Whoamifuck应急响应工具从4867行Bash脚本重构为Rust并发布v8.0.0。重构核心在于利用Rust的类型安全、模块化结构和静态编译特性解决Shell脚本维护难题,同时保留系统命令调用与原有命令行接口,确保老用户无感升级。工具内置DirtyCow等漏洞自查功能,支持多架构静态分发,建议应急场景直接使用musl版本。 综合评分: 88 文章分类: 应急响应,安全工具,安全开发,漏洞分析


who -> who-rs ; v8.0.0 Rust重构已发布

永恒之锋实验室 永恒之锋实验室

Eonian Sharp

2026年9月22日 11:07 上海

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

从 4867 行 Bash 到一颗静态二进制:司稽 Whoamifuck 的 Rust 重构之路

「司稽,察留连不时去者。」——《周礼·司稽》

2021 年写第一版 Whoamifuck 的时候,我没想过这个脚本最后会长到 4867 行。

那时候的想法很直接。

应急的时候经常要看进程、端口、登录记录、计划任务、WebShell、系统版本,来来回回敲的命令其实就那些。既然每天都要敲,不如把它们收进一个脚本里。

于是有了 who.sh。

后来功能一点点往里面加。

基线检查加进去,漏洞检查加进去,HTML 报告加进去,内核漏洞版本表也塞进去。版本一路从最开始跑到了 v7。

直到有一天再打开那个文件,已经很难一眼看明白某一段代码到底会影响哪里。

4867 行。

这个数字差不多就是这次重构真正开始的原因。

现在,司稽 Whoamifuck v8.0.0 发布了。

这一版最明显的变化只有一个:

整个项目从 Bash 搬到了 Rust。


一个脚本什么时候开始变得不好维护

Shell 本身没有什么问题。

甚至直到现在,我依然觉得应急响应工具用 Shell 起步非常合适。

ps、ss、last、find、systemctl 都在那里,脚本直接调就行。写完之后扔到机器上,也不用想太多。

Whoamifuck 最早能快速做起来,很大一部分原因就是 Bash 足够方便。

问题是,这种方便是有边界的。

当文件越来越大,很多当初无所谓的问题会慢慢变得麻烦。

比如变量。

Shell 里:

$FILE
"$FILE"
${FILE}

看起来差不了多少,实际行为却可能完全不同。

原来的代码里甚至还能翻到这样的历史痕迹:

rm -f /tmp/valid.$$.log/tmp/$$.log

两段路径粘在了一起。

这种东西在一个几百行的小脚本里,很容易发现。

放到将近 5000 行的脚本里,就不一定了。

另一个问题是,函数越来越多以后,很多数据是靠大家心照不宣地传下去的。

这个变量是谁定义的?

哪个函数会改它?

改完之后还有谁依赖它?

Shell 不会告诉你。

你只能搜。

再往后,就是不同机器上的兼容性问题。

正常的 Debian、Ubuntu、CentOS 通常没什么问题,但应急现场从来不会只遇到这些。

有些机器 Bash 版本很老。

有些发行版裁掉了一部分命令。

有些国产系统的行为和你预想的不一样。

脚本写得越大,这种环境差异越容易冒出来。

所以这次决定做一件拖了很久的事情:

把它拆开。


为什么最后选了 Rust

其实这几年也想过别的方案。

Python 写起来更快,生态也成熟。

Go 做单文件分发也很好。

最后还是选了 Rust。

原因和“性能”关系没有很多。

Whoamifuck 又不是在做高并发服务,很多时候真正耗时间的是系统命令本身。

我更在意的是另外几件事。

首先是类型。

很多 Shell 里的问题,本质上不是逻辑复杂,而是变量状态太自由。

Rust 会逼着你在编译阶段把很多问题解决掉。

其次是项目结构。

以前所有东西都挤在 who.sh 里。

现在一个功能对应一个模块:

src/
├── main.rs
├── color.rs
├── ui.rs
├── env.rs
├── sys.rs
├── util.rs
├── version.rs
└── modules/
    ├── baseinfo.rs
    ├── userlogin.rs
    ├── vulncheck.rs
    ├── baseline.rs
    ├── webshell.rs
    ├── report_html.rs
    ├── kernel_cve_data.rs
    └── ...

现在如果要改登录日志,就去 userlogin.rs。

改漏洞检测,就去 vulncheck.rs。

至少不用先在一个 4867 行的文件里翻半天。

还有一点很实际:

静态编译。

这一点对于这种需要扔到各种陌生 Linux 环境里的工具来说,挺重要。

编译好一个 musl 版本,上传到目标机器:

scp who root@target:/tmp/
sudo /tmp/who -r

能跑就行。

不需要先确认 Python 在不在,也不用再猜目标机器上的 Bash 到底是哪一版。


我们没有把系统命令重新造一遍

这次重构有一个原则一直没变:

原来该调系统命令的地方,继续调。

有时候看到“某某工具用 Rust 重写”,很容易理解成什么东西都要自己实现。

其实没这个必要。

比如:

ps
ss
last
find
systemctl

这些工具已经在 Linux 上跑了很多年。

为了追求“纯 Rust”,重新实现一套进程枚举、Socket 获取、systemd 查询,意义不大。

甚至还有可能让结果和原版出现差异。

所以现在 Rust 主要负责这些事情:

参数处理、执行流程、数据组织、版本比较、漏洞表匹配、输出和报告生成。

真正采集系统信息的地方,还是尽量沿用 Linux 本身的命令。

这样做还有一个好处。

v8 和旧版的结果更容易对得上。

对于应急工具来说,我觉得这个比“纯不纯”重要。


有些东西则很适合搬进 Rust

另外一类代码就不一样了。

比如版本比较。

原来 Bash 里是这样的:

version_lt() {
    [ "$1" = "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" ] && [ "$1" != "$2" ]
}

它能用。

而且用了很多年。

但第一次看到这段的人,大概率得停一下。

现在对应的代码变成了:

/// a < b
pub fn version_lt(a: &str, b: &str) -> bool {
&nbsp; &nbsp; a == min_version(a, b) && a != b
}

版本比较的语义没有改,还是按原来的 sort -V 行为处理。

只是终于变成了一个可以单独测试的函数。

漏洞版本表也是类似的情况。

Whoamifuck 里面一直保留着一份 Dirty Cow 的受影响内核版本表。

1217 条。

以前这些数据直接塞在 Shell 里。

现在它们单独放进:

kernel_cve_data.rs

需要改数据的时候,不会再碰到其他检测逻辑。

目前 v8 里的漏洞自查包括:

• CVE-2016-5195 Dirty Cow

• CVE-2022-0847 Dirty Pipe

• CVE-2026-31431 Copy Fail

• OpenSSH CVE-2018-15473、CVE-2024-6387

• Sudo CVE-2019-18634、CVE-2021-3156、CVE-2023-22809

• XZ Utils CVE-2024-3094

这些判断逻辑以后继续扩展,也比原来轻松很多。


老用户应该基本感觉不到变化

重构的时候有一个比较麻烦的问题:

如果新版本更“先进”,但老用户要重新学一遍怎么用,那这次升级其实挺失败的。

所以命令行接口基本没有动。

以前怎么跑,现在还是怎么跑。

比如:

sudo ./who -n
sudo ./who -a
sudo ./who -r
sudo ./who -m report.html

LOGO 也没动。

配色也尽量保留。

甚至一些看起来没那么“现代”的输出方式,我都没有急着改。

因为司稽用了这么多年以后,它已经有自己的使用习惯了。

v8 更像是把发动机和底盘换掉。

驾驶方式先别动。


下载和使用

如果只是想用,可以直接去 Releases 下载。

常规 x86_64 Linux 可以用:

whoamifuck-v8.0.0-x86_64-unknown-linux-gnu.tar.gz

如果不想管目标机器是什么发行版,我更建议:

whoamifuck-v8.0.0-x86_64-unknown-linux-musl.tar.gz

ARM64 则用:

whoamifuck-v8.0.0-aarch64-unknown-linux-musl.tar.gz

解压之后:

tar xzf whoamifuck-v8.0.0-x86_64-unknown-linux-musl.tar.gz
cd whoamifuck-v8.0.0-x86_64-unknown-linux-musl

sudo ./who -h
sudo ./who -n
sudo ./who -r
sudo ./who -m report.html

因为涉及不少系统级信息,建议直接使用 root 权限运行。

如果想自己编:

git clone https://github.com/enomothem/Whoamifuck.git
cd Whoamifuck
cargo build --release

产物在:

target/release/who

五年以后,再看这个工具

老的 who.sh 我没有删。

它还在仓库里。

一方面方便对照结果,另一方面我也不太想删。

毕竟从 2021 年一直改到现在,里面留下了很多很明显的时代痕迹。

有些写法现在看起来挺笨。

有些代码如果今天重新写,肯定不会那么处理。

但当时它确实解决了问题。

这次迁移到 Rust 以后,司稽本身没有突然变成一个完全不同的工具。

平时应急时关心的东西还是那些:

端口对应哪个服务。

服务后面是什么进程。

进程什么时候起来的。

它连过哪里。

谁登录过机器。

什么文件在那个时间点发生了变化。

最后还是要把这些东西串起来。

我一直很喜欢原来留下的这句话:

端口 → 服务,服务 → 进程,进程 → 网络。 时间线、轨迹、日志,最后都要对得上。

工具能帮你少敲一些命令。

至于异常到底藏在哪里,很多时候还是得靠经验。

有时候甚至真的是感觉。


”虽然现在AI能快速制造一些东西,但是这个是我一步一步累积出来的经验,每一次排查,每一个想法,每一个思路,每一个发现,改了无数次代码,微调,实战验证。“

”这次重构,借助AI的能力进行快速使用Rust重构,结构化,其实自己重构的版本早就写好了,只不过代码太乱了,虽然能跑起来,不利于后面的迭代,所以才使用AI全部重构“

”AI虽然能快速搞出炫酷的东西,但我们不需要,我们仍然保留原有功能和格式,实现如果rust能替换的直接用rust,更快一点,不能的,就原生命令,还是熟悉的whoamifuck。“


项目地址:

https://github.com/enomothem/Whoamifuck

如果你以前用过 who.sh,可以直接试试 v8。

遇到 Bug 就提 Issue。

WHOK-ID 还在。

—— 永恒之锋 · Enomothem

工具仅用于授权范围内的安全测试、应急响应与技术研究。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。

本文转载自:Eonian Sharp 永恒之锋实验室 永恒之锋实验室《who -> who-rs ; v8.0.0 Rust重构已发布》

评论:0   参与:  0