feat: add host-sec-check
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
# host-sec-check
|
||||
|
||||
对一台 Linux/VPS 做入侵取向的安全检查:先取证,再给你一份结论和处置清单。默认不改机器。
|
||||
|
||||
## 什么时候用
|
||||
|
||||
- 「这台机做一次安全检查」
|
||||
- 「好像被黑了 / 有矿机 / 服务无故 OOM」
|
||||
- 「看看哪些端口对公网开着」
|
||||
- 检查另一台机器时,直接点名主机:`对 vvps4 跑 /host-sec-check`
|
||||
|
||||
适用于单台 Linux(systemd + 常见 Docker/k3s)。不是应用代码审计,也不是云账号合规审计。
|
||||
|
||||
## 使用前准备
|
||||
|
||||
- SSH 能上(别名或 `user@host`)
|
||||
- 尽量有 sudo 或 docker 组(没有也能做浅查)
|
||||
- 告诉 Agent 哪张 IP 是公网,方便从外面探测
|
||||
- 若要清理、关端口、重启:明确说「同意处置」
|
||||
|
||||
## 使用示例
|
||||
|
||||
```text
|
||||
对 ace@vvps2 做 host-sec-check,只出报告先不要改。
|
||||
```
|
||||
|
||||
```text
|
||||
用 host-sec-check 查 vora3,公网 IP 是 x.x.x.x,发现未授权的就列处置项问我。
|
||||
```
|
||||
|
||||
## Agent 会做什么
|
||||
|
||||
1. 采集账号、监听端口、cron/systemd、Docker/k3s、`ld.so.preload`、内存/hugepage。
|
||||
2. 怀疑进程隐藏时,用容器读宿主机,避免被矿机库骗过。
|
||||
3. 从另一台机器探测公网端口(含 IPv6,如果有)。
|
||||
4. 给出结论:是否沦陷、入口、对外端口、建议处置。
|
||||
5. 你点头后才停容器、占位矿机文件、收端口或重启。
|
||||
|
||||
## 如何判断完成
|
||||
|
||||
报告里有结论表;若做了处置,公网已关端口连不上,业务域名仍可用。密钥、token 不应出现在完整原文里。
|
||||
@@ -0,0 +1,130 @@
|
||||
---
|
||||
name: host-sec-check
|
||||
description: >-
|
||||
Linux/VPS 主机安全检查与入侵取证:先取证再处置。覆盖矿机、ld.so.preload 进程隐藏、带宽挂机容器、对外端口、SSH/Docker/k8s 入口、cron/systemd 持久化、hugepage/OOM。
|
||||
Use when: 安全检查, 被黑, 入侵, 矿机, 排查端口, 对公网放开, rpcbind, 挂机赚钱, Portainer, 安全审计, host security, compromise, cryptominer, exposure, /host-sec-check.
|
||||
---
|
||||
|
||||
# host-sec-check
|
||||
|
||||
对一台 Linux 主机做安全检查。默认 **只读取证 + 出报告**。清理、关端口、重启、轮换密钥必须用户明确同意后再做。
|
||||
|
||||
需要:SSH 目标(`user@host` 或 ssh config 别名)、哪张网卡/IP 算公网。没有公网 IP 就只报「监听面」,并标明未做外部探测。
|
||||
|
||||
## 不适用
|
||||
|
||||
- Web 应用代码审计、依赖 CVE 扫描(可在报告里列为后续)
|
||||
- 云厂商安全组控制台(能查就查,查不到就写「未验证」)
|
||||
- 未获准的破坏性操作(`rm -rf`、整盘 wipe、强制重启)
|
||||
|
||||
## 铁律
|
||||
|
||||
1. **先取证,后动手。** 重启、删文件、停服务会毁掉证据。
|
||||
2. **不要把密钥打进对话。** token、密码、authorized_keys、kubeconfig 只写「存在/已轮换/路径」,不贴原文。
|
||||
3. **sudo 失败不要停。** 用户在 `docker` 组时,用特权容器 `nsenter` 看宿主机(见 [references/access.md](references/access.md))。
|
||||
4. **怀疑进程隐藏时,不要只信宿主机 `ps`。** 从**不加载宿主机 `ld.so.preload` 的容器**读 `/proc` 和文件。
|
||||
5. 宿主机 `chattr` 可能被隐藏库挡住;改 immutable 文件用 **Ubuntu/Alpine 自带 chattr** 操作 bind-mount 的 `/host/...`。
|
||||
|
||||
收集脚本(可选,先跑再解读):
|
||||
|
||||
```bash
|
||||
bash <skill-dir>/scripts/collect.sh USER@HOST
|
||||
```
|
||||
|
||||
`<skill-dir>` 是本 skill 目录。脚本只采集,不修改系统。
|
||||
|
||||
## 流程
|
||||
|
||||
按顺序做。每步记下「正常 / 可疑 / 未查到」。完整项见 [references/checklist.md](references/checklist.md)。
|
||||
|
||||
### 1. 快照
|
||||
|
||||
- 主机名、发行版、uptime、负载、`free -h`、`df -h`、公网/内网/Tailscale IP
|
||||
- `ss -lntup`(最好 root)
|
||||
- `docker ps -a`、compose 项目
|
||||
- 若有 k3s/k8s:agent 是否在跑、能否 `kubectl get pods -A`
|
||||
|
||||
### 2. 入口
|
||||
|
||||
- sshd:`Port`、`PermitRootLogin`、`PasswordAuthentication`、`authorized_keys`(root 与所有 UID≥1000)
|
||||
- `last` / `lastb` / `journalctl -u ssh`:异常登录;**无交互登录却出现 docker run 也是入口信号**
|
||||
- sudoers、`docker` 组(= root)、NOPASSWD
|
||||
- 对公网的管理面:Portainer / Cockpit / 面板 / k8s apiserver / Docker 端口,尤其 `-p 0.0.0.0:…` 且挂了 `docker.sock` 或 `/:/host`
|
||||
- 单元文件或 compose 里的明文 token(k3s `--token`、agent secret)
|
||||
|
||||
### 3. 持久化
|
||||
|
||||
读 [references/persistence.md](references/persistence.md)。至少查:
|
||||
|
||||
- crontab(root 与所有用户)、`/etc/cron.*`
|
||||
- `/etc/systemd/system/*.service`、timers
|
||||
- `/etc/ld.so.preload`(用**外部** cat/hexdump,宿主机 cat 可能被藏空)
|
||||
- `chattr +i` 的异常二进制(`lsattr`)
|
||||
- 隐藏 Docker 数据根(非 `/var/lib/docker` 的 dockerd `--data-root`)
|
||||
|
||||
### 4. 进程与隐藏库
|
||||
|
||||
- 从特权容器列 `/proc/*/cmdline`(绕过 preload)
|
||||
- 对照宿主机 `ps`:只在容器视角出现的进程 = 隐藏
|
||||
- `/proc/*/maps` 是否映射陌生 `.so`(`libgcwrap`、`libprocesshider`、随机名)
|
||||
- 矿机常见名:`perfcc`、`xmrig`、`kdevtmpfsi`、`javavm64`;同体积多副本(例如都是 11MB)
|
||||
- hugepage:`grep Huge /proc/meminfo`。`nr_hugepages>0` 且进程列表对不上,多半是矿机预留
|
||||
|
||||
### 5. 容器与编排
|
||||
|
||||
- `docker ps -a`:镜像名含 earnfm / packetstream / repocket / traffmonetizer / honeygain / proxyrack / bitping / antgain 等挂机池
|
||||
- inspect:`Privileged`、Binds(`docker.sock`、`/:/host`)、Ports 是否 `0.0.0.0`
|
||||
- 第二套 dockerd / 异常 `--bridge`
|
||||
- k8s:节点上是否有与 Git 仓库无关的 workload;控制面不健康时从 kubelet `pods/*/etc-hosts` 读 Pod 名
|
||||
|
||||
### 6. 对外暴露
|
||||
|
||||
- 本机 `0.0.0.0` / `[::]` 监听
|
||||
- **从另一台机器探测公网 IP**(含 IPv6)。只看 `ss` 会漏安全组,只看安全组会漏「监听但没防火墙」
|
||||
- 高危:`rpcbind :111`、明文 HTTP 应用端口、Docker/Portainer、k8s 6443、数据库
|
||||
- 管理 SSH 若可走 Tailscale,公网 SSH 算多余攻击面
|
||||
|
||||
### 7. 资源与日志
|
||||
|
||||
- 无 swap + 高 hugepage → 应用易 OOM
|
||||
- `journalctl` / `auth.log` 在处置时间点附近;日志空也要记
|
||||
- 出站连接:`ss -tp` 看陌生 IP(不要把结果里的密钥打出来)
|
||||
|
||||
### 8. 补漏(本次 vvps2 没做或做得浅的)
|
||||
|
||||
见 checklist 后半:补丁、SUID、世界可写、意外用户、IPv6、定时器、内核模块、出站 C2、云安全组、备份是否可用。
|
||||
|
||||
## 报告格式
|
||||
|
||||
先给结论(是否沦陷、最可能入口、对外还开着什么),再给证据表,最后给 **需用户点头的处置清单**。不要默默清理。
|
||||
|
||||
```
|
||||
结论: 沦陷 / 可疑 / 未见异常
|
||||
最可能入口: …
|
||||
对外端口: …
|
||||
持久化: …
|
||||
隐藏/矿机: …
|
||||
容器/编排: …
|
||||
未查项: …
|
||||
建议处置: (等确认)
|
||||
```
|
||||
|
||||
## 处置(仅在用户同意后)
|
||||
|
||||
原则见 [references/cleanup.md](references/cleanup.md)。
|
||||
|
||||
- 停并删除未授权容器;镜像也删
|
||||
- 矿机二进制:删掉后用 **空文件 + `chattr +i` 占路径**
|
||||
- 清空并锁定 `/etc/ld.so.preload`
|
||||
- 关公网绑定:改成 `127.0.0.1` 或 Tailscale IP(若回源走 Tailscale 主机名,必须绑 TS IP,不能只绑 loopback)
|
||||
- 停无用服务(如 `rpcbind.socket` + `rpcbind.service`,必要时 mask)
|
||||
- 重启才能卸掉仍映射已删 `.so` 的老进程(sshd/dockerd)。先取证再重启
|
||||
- 轮换:暴露过的 token、面板、k3s bootstrap。控制面 API 不通就不要假轮换,写阻塞原因
|
||||
|
||||
## 验证
|
||||
|
||||
- 公网探测:已关端口失败;该留的业务域名仍 200
|
||||
- `ss`:无 `0.0.0.0:已关端口`
|
||||
- `grep -l libgcwrap /proc/*/maps`(或同类库)重启后为 0
|
||||
- 占位文件仍在且 immutable
|
||||
- 业务容器 `restart: always` 仍在
|
||||
@@ -0,0 +1,48 @@
|
||||
# 取证入口(无 sudo 时)
|
||||
|
||||
目标用户常见情况:`sudo` 要密码,但在 `docker` 组。Docker 组等价于 root。
|
||||
|
||||
## 读宿主机(绕过 preload)
|
||||
|
||||
容器用自己的 libc,**不会**加载宿主机 `/etc/ld.so.preload`。
|
||||
|
||||
```bash
|
||||
docker run --rm -i --privileged --pid=host --net=host -v /:/host alpine:latest \
|
||||
cat /host/etc/ld.so.preload
|
||||
hexdump -C /host/etc/ld.so.preload # 在容器内
|
||||
```
|
||||
|
||||
列隐藏进程:
|
||||
|
||||
```bash
|
||||
docker run --rm --privileged --pid=host alpine:latest sh -c \
|
||||
'for d in /proc/[0-9]*; do
|
||||
pid=${d#/proc/}
|
||||
cmd=$(tr "\0" " " < "$d/cmdline" 2>/dev/null) || continue
|
||||
[ -n "$cmd" ] && echo "$pid $cmd"
|
||||
done'
|
||||
```
|
||||
|
||||
## 改宿主机(systemctl / chattr)
|
||||
|
||||
`chroot /host /usr/bin/chattr` 会加载宿主机 preload,可能 **stat 不到** 被藏文件。
|
||||
|
||||
用发行版自带 chattr 操作 `/host/...`:
|
||||
|
||||
```bash
|
||||
docker run --rm -i --privileged --pid=host --net=host -v /:/host ubuntu:latest bash -s <<'SH'
|
||||
chattr -i /host/etc/ld.so.preload
|
||||
: > /host/etc/ld.so.preload
|
||||
chattr +i /host/etc/ld.so.preload
|
||||
lsattr /host/etc/ld.so.preload
|
||||
SH
|
||||
```
|
||||
|
||||
systemctl / reboot:
|
||||
|
||||
```bash
|
||||
docker run --rm --privileged --pid=host --net=host alpine:latest \
|
||||
nsenter -t 1 -m -u -i -n -- systemctl disable --now UNIT
|
||||
```
|
||||
|
||||
不要用业务容器当跳板;用 `alpine`/`ubuntu` 临时 `--rm`。查到一半时 `docker ps` 里出现的随机名容器就是这个跳板。
|
||||
@@ -0,0 +1,75 @@
|
||||
# 检查项
|
||||
|
||||
每项:做了 / 跳过(原因) / 可疑。
|
||||
|
||||
## A. 快照
|
||||
|
||||
- [ ] 主机名、OS、内核、uptime
|
||||
- [ ] CPU/负载、内存(含 hugepage、swap)、磁盘
|
||||
- [ ] 网卡:公网 v4/v6、内网、Tailscale/VPN
|
||||
- [ ] 监听端口 + 进程(root `ss -lntup`)
|
||||
- [ ] 本机防火墙:nft/iptables/ufw;INPUT 策略
|
||||
- [ ] 云安全组(做不到就写未查)
|
||||
|
||||
## B. 身份与入口
|
||||
|
||||
- [ ] sshd 配置:端口、root、密码、Pubkey
|
||||
- [ ] 所有 `authorized_keys`(含 `/root`、`/home/*`、git 用户)
|
||||
- [ ] `last` / `lastb` / ssh journal
|
||||
- [ ] `/etc/passwd` 里 UID 0、系统外用户、登录 shell
|
||||
- [ ] sudoers、NOPASSWD、docker/lxd/libvirt 组
|
||||
- [ ] 对公网的面板:Portainer/Cockpit/宝塔/1Panel/k8s/Docker TCP
|
||||
- [ ] 单元或 compose 里的明文 bootstrap token
|
||||
|
||||
## C. 持久化
|
||||
|
||||
- [ ] 用户与系统 crontab、`/etc/cron.*`
|
||||
- [ ] systemd 服务与 timer(非发行版默认)
|
||||
- [ ] `ld.so.preload` + 对应 `.so`(容器视角 hexdump)
|
||||
- [ ] `lsattr` 发现的 immutable 异常文件
|
||||
- [ ] rc.local、profile.d、bashrc 后门
|
||||
- [ ] 第二套 container runtime
|
||||
|
||||
## D. 进程
|
||||
|
||||
- [ ] 容器视角 vs 宿主机 `ps` 差集
|
||||
- [ ] maps 里的陌生 so
|
||||
- [ ] 矿机/挖矿/proxy 客户端特征名与同体积副本
|
||||
- [ ] hugepage 预留但无对应进程
|
||||
- [ ] 高 CPU 且不在业务名单里的进程
|
||||
|
||||
## E. 容器 / k8s
|
||||
|
||||
- [ ] `docker ps -a` 与 inspect(privileged、sock、`/:/host`、`0.0.0.0`)
|
||||
- [ ] 挂机赚钱镜像名单
|
||||
- [ ] k8s/k3s:节点 Ready、该节点 Pod 列表
|
||||
- [ ] API 不通时:kubelet `pods/*/etc-hosts`、crictl
|
||||
- [ ] 工作负载是否能在 Git/编排仓库里对上
|
||||
|
||||
## F. 暴露
|
||||
|
||||
- [ ] `0.0.0.0` 与 `[::]` 监听清单
|
||||
- [ ] **从外部**扫公网 IPv4(和 IPv6)
|
||||
- [ ] rpcbind :111、DB、Redis、应用明文端口
|
||||
- [ ] 管理 SSH 是否可收到 VPN
|
||||
- [ ] 证书/域名入口是否可被 IP:端口绕过
|
||||
|
||||
## G. 补漏(容易漏)
|
||||
|
||||
- [ ] IPv6 公网地址同样在听
|
||||
- [ ] 世界可写目录、异常 SUID
|
||||
- [ ] 未装补丁 / `apt` 过期很久
|
||||
- [ ] 出站长连接(C2)
|
||||
- [ ] 内核模块 `lsmod` 异常
|
||||
- [ ] 时间偏移(影响日志)
|
||||
- [ ] 备份是否还能用(清理前不要删数据盘)
|
||||
- [ ] 日志被清空或 journal vacuum
|
||||
- [ ] Web 根目录 webshell(若有 nginx/caddy/apache)
|
||||
- [ ] `.git` 或备份文件可下载
|
||||
- [ ] 云 metadata 是否对容器开放
|
||||
|
||||
## H. 报告与处置确认
|
||||
|
||||
- [ ] 结论表
|
||||
- [ ] 用户确认后再改
|
||||
- [ ] 改完公网+域名双侧验证
|
||||
@@ -0,0 +1,59 @@
|
||||
# 处置(用户同意之后)
|
||||
|
||||
## 顺序
|
||||
|
||||
1. 证据已落盘(collect 输出、关键 ls/hexdump/docker inspect)
|
||||
2. 停进程 / 停容器
|
||||
3. 删或占位文件
|
||||
4. 关公网端口
|
||||
5. 最后才重启(卸已加载的隐藏库)
|
||||
|
||||
## 占位
|
||||
|
||||
对矿机路径(`/usr/bin/perfcc`、`/tmp/javavm64`、隐藏 docker 根名等):
|
||||
|
||||
```bash
|
||||
chattr -i "$path" 2>/dev/null
|
||||
rm -f "$path"
|
||||
: > "$path"
|
||||
chmod 000 "$path"
|
||||
chattr +i "$path"
|
||||
```
|
||||
|
||||
`/etc/ld.so.preload` 占空文件,权限 `644` + immutable,让动态链接器能读到「没有库」。
|
||||
|
||||
目录型隐藏根:停进程并卸挂载后删除,再在同名路径放 immutable 空文件,阻止再 `mkdir`。
|
||||
|
||||
改 immutable 时用容器自带 `chattr` 操作 `/host/...`,不要 `chroot` 到宿主机再跑 chattr。见 access.md。
|
||||
|
||||
## 容器
|
||||
|
||||
```bash
|
||||
docker stop NAME && docker rm NAME
|
||||
docker rmi IMAGE
|
||||
```
|
||||
|
||||
不要 `docker system prune -a`。
|
||||
|
||||
## 端口
|
||||
|
||||
- 入口在本机 loopback → `127.0.0.1:PORT:CONTAINER`
|
||||
- 入口走 Tailscale 主机名 → 必须绑 **当前 Tailscale IPv4**,不能只绑 127.0.0.1
|
||||
- 可同时绑 loopback + Tailscale,禁止 `0.0.0.0` / `[::]`
|
||||
|
||||
改 compose 后 force-recreate,再从公网 IP 和业务域名两边探测。
|
||||
|
||||
## rpcbind
|
||||
|
||||
```bash
|
||||
systemctl disable --now rpcbind.socket rpcbind.service
|
||||
systemctl mask rpcbind.socket rpcbind.service
|
||||
```
|
||||
|
||||
无对外 NFS 再做。确认 `:111` 消失。
|
||||
|
||||
## 重启
|
||||
|
||||
重启前确认业务是 `restart: always`,并告知会短暂中断。
|
||||
|
||||
重启后:`grep -l <so名> /proc/*/maps` 为 0;若已清 hugepage 则 `HugePages_Total` 为 0;域名 200。
|
||||
@@ -0,0 +1,40 @@
|
||||
# 持久化位置
|
||||
|
||||
按这个名单扫。出现「刚被排查时时间戳又刷新」= 仍有 watchdog。
|
||||
|
||||
## 定时
|
||||
|
||||
- `crontab -u root -l` 以及 `/var/spool/cron/crontabs/*`
|
||||
- `/etc/cron.d/` `/etc/cron.hourly/` `/etc/cron.daily/` `/etc/cron.weekly/`
|
||||
- systemd timers:`systemctl list-timers --all`
|
||||
|
||||
## 服务
|
||||
|
||||
- `/etc/systemd/system/*.service`(尤其非发行版默认的)
|
||||
- `ExecStart` 指向 `/tmp`、`/dev/shm`、`/root/.config`、随机短名
|
||||
- `Restart=always` 的陌生服务
|
||||
|
||||
## 动态链接器
|
||||
|
||||
- `/etc/ld.so.preload`:内容常是 `/lib/libXXX.so`(约十几字节)。宿主机 `cat` 可能显示空,用容器 hexdump
|
||||
- 对应 `.so` 可能 `chattr +i`、setgid
|
||||
- 常见名:`libgcwrap.so`、`libpprocps.so`、`libfsnldev.so`、`libprocesshider.so`
|
||||
|
||||
## 二进制与分身
|
||||
|
||||
- `/usr/bin` `/bin` `/usr/local/bin` `/tmp` 下刚改过的可执行文件
|
||||
- 同字节大小的多份拷贝(矿机改名)
|
||||
- 占位对抗:空文件 `chmod 000` + `chattr +i`(见 cleanup.md)
|
||||
|
||||
## 隐藏运行时
|
||||
|
||||
- 第二套 dockerd:`--data-root` 不在 `/var/lib/docker`,`--host unix://` 异常路径
|
||||
- 混淆文件名(把 docker 子命令拼进无关单词)
|
||||
- k3s 的 `containerd-shim` 被借去跑 **moby** namespace + 异常 `--address`
|
||||
|
||||
## 登录与启动
|
||||
|
||||
- `~/.bashrc` / `/etc/profile.d` 里 curl|bash
|
||||
- `/etc/rc.local`
|
||||
- SSH `authorized_keys` 多出来的 key
|
||||
- 意外用户、UID 0 非 root
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# 只采集,不修改。用法: collect.sh [user@]host
|
||||
# 输出写到 stdout;完整日志建议重定向到文件。
|
||||
set -euo pipefail
|
||||
HOST="${1:?usage: collect.sh user@host}"
|
||||
SSH=(ssh -o BatchMode=yes -o ConnectTimeout=15 "$HOST")
|
||||
|
||||
echo "===== host-sec-check collect $(date -u +%Y-%m-%dT%H:%M:%SZ) host=$HOST ====="
|
||||
|
||||
remote() {
|
||||
"${SSH[@]}" bash -s <<'EOS'
|
||||
set +e
|
||||
echo "----- id / os / uptime -----"
|
||||
id; hostname; uname -a
|
||||
. /etc/os-release 2>/dev/null; echo "$PRETTY_NAME"
|
||||
uptime
|
||||
echo "----- mem / hugepage / disk -----"
|
||||
free -h
|
||||
grep -E "MemAvailable|HugePages_|Hugetlb|SwapTotal" /proc/meminfo
|
||||
df -h
|
||||
echo "----- addresses -----"
|
||||
ip -4 addr; ip -6 addr show scope global
|
||||
echo "----- listen (may miss pid without root) -----"
|
||||
ss -lntup 2>/dev/null || netstat -lntup 2>/dev/null
|
||||
echo "----- docker -----"
|
||||
docker ps -a --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}" 2>/dev/null || echo "no docker"
|
||||
echo "----- preload (host cat; may be hidden) -----"
|
||||
ls -la /etc/ld.so.preload 2>/dev/null
|
||||
echo "preload_host=[$(cat /etc/ld.so.preload 2>/dev/null)]"
|
||||
echo "----- cron files -----"
|
||||
ls -la /etc/cron.d /etc/cron.hourly /etc/cron.daily 2>/dev/null
|
||||
echo "----- systemd extras -----"
|
||||
ls /etc/systemd/system/*.service 2>/dev/null
|
||||
echo "----- users uid0 / human -----"
|
||||
awk -F: '$3==0 || ($3>=1000 && $3<65534) {print}' /etc/passwd
|
||||
echo "----- sshd -----"
|
||||
grep -E "^(Port|PermitRootLogin|PasswordAuthentication|PubkeyAuthentication)" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* 2>/dev/null
|
||||
echo "----- last -----"
|
||||
last -a | head -15
|
||||
EOS
|
||||
}
|
||||
|
||||
remote
|
||||
|
||||
# docker 组:从容器读 preload 真值
|
||||
if "${SSH[@]}" "groups | grep -qw docker" 2>/dev/null; then
|
||||
echo "----- preload via alpine (bypass host libc) -----"
|
||||
"${SSH[@]}" "docker run --rm --privileged -v /:/host alpine:latest hexdump -C /host/etc/ld.so.preload" 2>/dev/null \
|
||||
|| echo "alpine hexdump failed"
|
||||
fi
|
||||
|
||||
echo "===== collect done ====="
|
||||
echo "下一步: 按 SKILL.md 解读;不要把本输出里的密钥贴进聊天。"
|
||||
@@ -0,0 +1,89 @@
|
||||
---
|
||||
name: note-style
|
||||
description: 将现有材料整理、压缩或改写为可长期查阅的知识笔记,采用教科书、技术手册或标准说明文风格,并保留事实、公式、适用条件、安全警告和参考资料。适用于用户要求整理 Obsidian 笔记、消除聊天或 AI 写作痕迹、减少重复和空话、统一术语与技术表达,或将技术原理、操作方案改写为结构化知识文档的任务。
|
||||
---
|
||||
|
||||
# 整理知识笔记
|
||||
|
||||
## 工作流程
|
||||
|
||||
1. 识别材料的核心问题、目标读者和材料类型。
|
||||
2. 提取事实、定义、公式、条件、因果关系、步骤、例证、边界、安全警告和参考资料。
|
||||
3. 删除与核心问题无关的铺垫,并合并重复内容。
|
||||
4. 按材料类型选择结构并重写全文。
|
||||
5. 检查技术准确性、术语、格式、重复和表达密度。
|
||||
6. 输出完整笔记;存在事实或技术疑点时,追加“待核实项”。
|
||||
|
||||
## 保留与删减
|
||||
|
||||
- 保留原文中的事实、公式、适用条件、例外、安全限制和参考资料。
|
||||
- 不自行补充没有依据的结论,也不为缩短篇幅而删除必要条件或公式推导。
|
||||
- 围绕核心问题组织内容,删除无关铺垫。
|
||||
- 使每句话至少承担一种功能:定义概念、说明条件、解释因果、给出步骤、提供例证或指出边界。
|
||||
- 使同一知识点只完整解释一次。避免在摘要、正文、表格、总结和检查表之间复述。
|
||||
- 在不损失必要信息的前提下,默认将篇幅压缩约 30%;若用户另有篇幅要求,以用户要求为准。
|
||||
|
||||
## 语言规范
|
||||
|
||||
- 使用中性、准确、简洁的书面语。
|
||||
- 直接陈述内容,不添加聊天式过渡、开场铺垫、段末复述或写作过程说明。
|
||||
- 删除情绪化、评价性、劝导性、宣传性和表演式表达,如“非常美妙”“加分项”“更稳妥”“请仔细看”。
|
||||
- 不使用反问、口号、拟人化表达或用感叹号制造重点。
|
||||
- 减少“通常、可能、建议、优先、具体来看”等模糊限定词。确有不确定性时,明确不确定性的来源和适用条件。
|
||||
- 每段只表达一个主题;能用一句话说明的内容不扩写成多句。
|
||||
- 将评价句改写为“条件、机制、结果”或“对象、操作、限制”。
|
||||
|
||||
## 技术表达
|
||||
|
||||
- 首次出现专业术语时给出简短定义,后文统一名称。
|
||||
- 明确符号、变量、单位、对象类型、参考系、输入输出和变换方向。
|
||||
- 区分严格定义、直观解释和示例,不用比喻替代定义。
|
||||
- 每个概念最多保留一个必要的例子或比喻;使用比喻后,以正式术语重述结论。
|
||||
- 检查概括的适用范围,将无条件的“X 代表 Y”改为带条件的准确表述。
|
||||
- 不擅自修正不确定或可能有误的技术内容,将其列入“待核实项”。
|
||||
|
||||
## 结构选择
|
||||
|
||||
根据材料类型采用下列骨架,并按实际内容删去不需要的章节。
|
||||
|
||||
### 技术原理类
|
||||
|
||||
1. 问题或目标
|
||||
2. 符号与定义
|
||||
3. 原理或推导
|
||||
4. 示例
|
||||
5. 适用条件与限制
|
||||
6. 简短结论
|
||||
|
||||
### 操作与方案类
|
||||
|
||||
1. 目标与适用范围
|
||||
2. 基本原则
|
||||
3. 操作步骤
|
||||
4. 分类处理
|
||||
5. 安全边界
|
||||
6. 检查表
|
||||
|
||||
不要同时保留内容重复的“摘要”“重新解释”“具体调整”和“总结”。摘要已经给出结论时,正文只提供依据和展开。
|
||||
|
||||
## 格式规范
|
||||
|
||||
- 使用描述性标题,避免“到底是什么”“究竟该怎么做”等口语化标题。
|
||||
- 保持标题编号连续、层级一致。
|
||||
- 仅对首次定义的术语、关键条件和禁止事项使用粗体。
|
||||
- 减少引号和括号,统一数学符号、变量格式和单位格式。
|
||||
- 保留适合 Obsidian 的 Markdown、YAML frontmatter、Wiki-links、表格、公式和代码块;除非用户要求,不改变其语义。
|
||||
|
||||
## 完成检查
|
||||
|
||||
- 检查同一结论是否出现在两个以上位置,只保留信息最完整且位置最合适的一处。
|
||||
- 检查相邻段落能否分别用一句话概括;含义相同时合并。
|
||||
- 检查所有评价句是否已改为可验证的条件、机制、结果、操作或限制。
|
||||
- 检查技术概括、符号定义、事实和适用条件是否成立。
|
||||
- 检查内部链接、表格、公式、代码块、安全警告和参考资料是否完整保留。
|
||||
|
||||
## 输出
|
||||
|
||||
1. 先输出整理后的完整笔记。
|
||||
2. 仅在存在技术或事实疑点时追加“待核实项”,逐条列出疑点。
|
||||
3. 不解释改写过程,不输出修改心得,不复述本技能的要求。
|
||||
@@ -0,0 +1,4 @@
|
||||
interface:
|
||||
display_name: "教科书式笔记整理"
|
||||
short_description: "将材料压缩并改写为准确、简洁的结构化知识笔记"
|
||||
default_prompt: "使用 $note-style 将这份材料整理为可长期查阅的知识笔记。"
|
||||
Reference in New Issue
Block a user