跳转到内容
GitHub

搜索与集合

“搜索”菜单中提供集合以及按文件名或内容的递归搜索。两者都以可排序列表的形式显示结果,并列出每个文件的源路径,也都支持查看器和快速预览。

  • Ctrl-F: 搜索当前文件夹及其下的所有内容。所有词都必须匹配:main rs 能找到 main.rs,a | b 则匹配其中任意一个词。全小写的词不区分大小写;含大写字母的词则严格区分大小写。还可以使用 *.log 这样的 glob 通配符、带引号的短语、带斜杠的路径(如 src/lib),以及用 -word 排除匹配项;此外还支持以下筛选条件:ext:rs,toml、type:file、type:dir、type:link、size:>10M、size:1M..50M、mod:<7d(最近一周内修改过)、mod:>1y 和 in:src(路径中任意位置的文件夹)。最近的搜索会列在表单下方,在同一文件夹中进行的搜索排在前面;点击其中一条,或在查询框中按 Ctrl-P 和 Ctrl-N,即可再次使用。对话框打开时会保留你上次留下的查询和选项,并设为你当前所在的文件夹。无论 glob 写成大写还是小写,任何文字的文件名都能正确匹配;无论文件系统如何存储带重音的字母,也都能正确匹配。靠近搜索文件夹的匹配项会最先显示,此时目录树的其余部分仍在读取中。
  • Alt-K: 把已标记的文件(或当前文件)收入另一个面板中的集合。集合中保存的是引用,不会复制文件内容。
  • Alt-V: 从可滚动列表中选择已保存的集合,列表会显示每个集合的条目数和估算大小。按 F7 或 N 新建集合。重启 Borg 后集合仍会保留。
  • Esc: 隐藏结果,同时保留光标、滚动位置、标记、筛选和分组。
  • Alt-Shift-R: 重新显示已隐藏的结果。结果被隐藏时,扫描仍会继续进行。
  • Alt-D: 打开“文件夹大小”,按总大小或文件数量查找文件夹。默认包含隐藏文件。Alt-D 会打开 Ctrl-F 对话框,并设为 文件夹总计;更改 查找对象 即可在两种模式之间切换。按 Ctrl-C 停止扫描。
  • Alt-S: 计算所选文件夹的大小。Alt-Shift-D: 打开当前文件夹的大小树。
  • Alt-W: 最大化或还原当前结果窗格。结果默认在普通窗格中打开。标题栏中的 [+](最大化)、[=](还原)和 [-](折叠)按钮都可以点击。折叠会隐藏视图;按 Alt-Shift-R 可将其恢复,布局和选择保持不变。
  • Ctrl-S: 按名称或源路径筛选结果。筛选条件为空时显示全部结果。

在 Ctrl-F 对话框的 包含文本 中输入文字,即可列出该文件夹下包含这段文字的文件。名称模式仍然有效,因此 *.rs 加上 包含文本 中的 fn main,会找到含有它的 Rust 文件。字段旁的开关与查找栏中的相同:Alt-C 精确匹配大小写(否则全小写的查询不区分大小写),Alt-W 匹配整个单词,Alt-R 把文字当作正则表达式。这些开关也可以点击。在该字段中按 Ctrl-P 和 Ctrl-N,可以调出查找栏中最近的查询和之前搜索过的文字。按文本搜索只列出文件,因此不能与文件夹总计或最小文件数一起使用,文件夹大小 中也没有 包含文本 字段。

每个结果都会在 匹配 列中显示第一处匹配所在的行及其行号,状态行也会在文件路径后加上行号。按 F3 会在查看器中打开该文件并定位到这处匹配,查找栏已按该查询打开,按 Enter 即可跳到下一处;按 Ctrl-Q 则会在快速预览中显示这处匹配,并标出查询。Markdown 和 JSON 文件在两者中都会以源码形式打开,因为搜索读取的是文件原本的内容;按 s 可切换到格式化视图。按 F4 会在 Borg 的编辑器中打开该文件并定位到这处匹配,匹配已选中,查找栏也已按该查询打开;Alt-E 则在另一个面板中这样打开,让搜索结果保持可见。Borg 在后台读取文件,上下文行会统计已读取的文件数。二进制文件(前 8 KiB 中含有 NUL 字节)和超过 64 MiB 的文件不会被读取,并计为二进制或过大。按 Ctrl-C 可停止搜索;与其他搜索一样,最多找到 20,000 个文件。

在结果中按 Ctrl-R,或在“文件”菜单中选择 在文件中替换…,会替换已标记文件中的文本;没有标记任何文件时,则替换结果中显示的每个文件。输入替换后的内容并按 Enter;字段留空则删除该文本。随后会再询问一次,列出该文本和文件,并默认选中 否。按 Y 才会修改文件。Borg 不会保留原文本的副本。搜索的开关同样适用:按整词搜索时只替换整词;使用正则表达式时,$1 会填回第一个分组。Borg 以编辑器保存文件的方式写入每个文件,因此权限和链接保持不变。不是文本、大于 32 MiB 或在任务运行期间发生变化的文件会被跳过。任务会显示在 Alt-J 中,结束后结果会自动刷新。

在 Ctrl-F 对话框中把 查找对象 设为 规则匹配,即可用 YARA 规则扫描该文件夹及其下的文件:包括 Borg 自带的规则和你自己的规则。名称模式、最小大小 和 排除构建输出、缓存和被忽略的文件 仍然生效。要找什么由规则决定,因此对话框不再显示 包含文本 和 最小文件数。

每个结果会在 匹配 列中显示该文件匹配到的最严重的规则、另外还匹配了多少条规则,以及该规则找到的最初几个字节,以带引号的文本或十六进制显示。F3 会在查看器中打开文件并定位到这些字节,查找栏中已填好它们;F4 和快速查看也会定位到同一处。上下文行会统计已扫描的文件数和运行的规则数。超过 64 MiB 的文件不会被读取,计为过大;与其他搜索一样,扫描在 20,000 个文件处停止。Ctrl-C 可停止扫描。

Borg 自带的规则会查找:

  • reverse_shell:通过 /dev/tcp、运行 shell 的 nc 或 socat 建立的交互式 shell,或在伪终端上启动的 shell。
  • download_and_run:下载脚本并直接通过管道交给 shell 执行。
  • decode_and_run:解码 base64,并把结果作为 shell 命令或 Python 代码运行。
  • crypto_miner:矿池地址,或常见挖矿程序的设置。
  • upx_packed:用 UPX 加壳的可执行文件,运行时会在内存中自行解压。
  • execve_shellcode:漏洞利用代码在启动 shell 之前构造的 shell 路径。
  • ssh_key_planted:向 authorized_keys 文件追加公钥。
  • reboot_job_fetch:每次开机都会运行,并从临时文件夹下载、解码或运行内容的 cron 任务。
  • password_prompt:以隐藏输入方式索要密码的 AppleScript 对话框,macOS 窃密程序常用这种手法。
  • launch_agent_from_temp:从临时或共享文件夹启动程序的 macOS 启动代理或守护进程。
  • preload_write:写入 /etc/ld.so.preload,这会让 Linux 上的每个程序都加载某个库。
  • history_wiping:关闭 shell 历史记录,或清空系统日志。
  • agent_unattended:在关闭审批的情况下启动 AI 编程智能体,Nx 供应链攻击就是这样在机器上搜寻机密的。
  • hidden_prompt:一串不可见的 Unicode 标签字符,可用来在提示词、规则文件和网页中向 AI 模型隐藏指令。
  • pickle_runs_code:加载时会运行命令的 pickle,pickle 是 Python 和 PyTorch 保存模型所用的格式。

把你自己的规则放在 rules 文件夹中,它位于 config.toml 旁边:~/.config/borg-commander/rules,或者 $XDG_CONFIG_HOME 或 $BORG_CONFIG_DIR 下的同名文件夹。Borg 会读取其中及其下各级文件夹中的每个 .yar 和 .yara 文件,每个文件使用独立的命名空间,因此两个文件可以使用相同的规则名称。每个文件单独编译。有错误的文件会被整个排除,状态行会给出它的名称和编译器信息,上下文行会统计被排除的文件数,其他文件照常运行。由于每个文件都单独加载,使用 include 的文件也会被排除,它所包含的文件会各自运行。

规则可以导入 hash、math、string、time、elf、macho、pe、dotnet 和 dex 模块;导入 magic、cuckoo 或 console 的文件会被排除。变量 filename、filepath 和 extension 分别保存被扫描文件的名称、路径和扩展名,这正是为 THOR 和 LOKI 编写的规则集所需要的;filetype 和 owner 为空。规则的 severity 元数据决定匹配的严重程度:alert、critical 或 high 为警报,warning、medium 或 suspicious 为警告,notice、low 或 info 为提示。没有该元数据时,score 达到 80 及以上为警报,达到 60 及以上为警告,更低则为提示。两者都没有的规则按警告处理。规则的 description 和 false_positives 会随每个匹配一起显示。

Borg 不附带任何公开规则集,因为它们的许可证各不相同。请把你信任的规则集下载到规则文件夹中,并在工作中使用之前查看各自的许可证:

规则匹配的是字节模式,并不了解意图。安装程序、安全工具及其测试数据同样会被匹配,而没有任何规则匹配的文件仍可能是恶意的。请把匹配结果当作线索。用规则扫描内存 一节说明了扫描看不到哪些内容。

在 Ctrl-F 对话框中把 查找对象 设为 加壳程序,即可列出该文件夹下代码与压缩或加密字节一样密集的程序。加壳工具和保护工具会留下这样的代码,把代码藏到运行时才显露的恶意软件也是如此。Borg 读取每个 ELF、Mach-O 和 PE 文件中由加载器映射为可执行的部分(包括通用 Mach-O 二进制文件的每个切片),并在其中均匀抽取最多 1,024 个 4 KiB 的块测量熵。至少 70% 的块达到每字节 7.2 位时,该程序就会被列出。按常规方式编译的代码远低于这个比例。名称模式、最小大小 和 排除构建输出、缓存和被忽略的文件 仍然生效,对话框不再显示 包含文本 和 最小文件数。

匹配 列给出高熵块所占的比例和测得的最高熵,例如“97% 高熵 · 最高 8”。F3 会在查看器的十六进制行中打开该程序并定位到第一个高熵块,旁边就是 查看器与快速预览 中介绍的熵条。上下文行会统计已读取的程序和其他文件,其他文件是 Borg 无法从中找到代码的文件。Ctrl-C 可停止搜索;与所有搜索一样,它最多列出 20,000 个文件。加壳程序只有在运行时才会显露真正的代码,对所有进程进行熵扫描 正是在这时检查程序。

点击列标题可按该列排序,再次点击则反转顺序。“左侧”和“右侧”菜单中也提供排序选项,“搜索”菜单还增加了按源文件夹排序以及按文件夹或文件类型分组的功能。在分组标题上按 Enter 可折叠该组;按 Insert 可标记组中匹配的文件。排序或筛选时标记会保留,页脚还会统计被筛选条件隐藏的已标记文件。

F3 和 Ctrl-Q 打开原始文件;按文本搜索后,两者都会定位到文件中的第一处匹配。快速预览会随光标在结果中移动,在每个文件的匹配处显示,并像查找栏那样标出查询。Alt-E 在另一个面板中用 Borg 的编辑器打开文件,让搜索结果保持可见。Esc 或 F10 关闭这个编辑器,焦点回到搜索结果;如果之前开着快速预览,它也会重新出现。F5 复制到真实文件夹;如果另一个面板是集合,F5 则会向集合添加引用。F6 的目标必须是真实文件夹。在集合中,F8 只移除引用,不会动文件本身;在搜索结果中,F8 会询问是否删除原始文件。在集合中按 Shift-F8 也可以删除原始文件,但需要先确认。如果同时标记了某个文件夹和其中的文件,任务只会处理该文件夹一次。定位原文件 或 Alt-O 会在另一个面板中打开文件所在的文件夹,并把光标放在该文件上。按 Left 或 Esc 隐藏结果,按 Alt-Shift-R 可在原来的位置恢复。即使 Shell 中有未完成的命令,Tab 也能在面板之间切换。Shell 始终位于一个真实的文件夹中。按 F10 退出前总会先询问。

Git 和压缩包操作目前只能在真实文件夹面板中使用。要对集合中的文件执行这些操作,请先用 定位原文件 打开它所在的文件夹。

搜索在可取消的后台工作线程中读取文件名和元数据,找到 20,000 个匹配项后停止。上下文行会显示搜索是否已完成、出现的错误和跳过的条目,以及是否达到该上限。只有开启 显示隐藏文件 时才会搜索隐藏文件夹。搜索不会离开起始位置所在的文件系统,也不会跟随指向文件夹的符号链接。搜索窗口可以将结果限定为文件或文件夹,并设置最小大小。

选择 文件夹总计 后,Borg 会先统计每个文件夹下的所有文件,再按名称、大小或最少文件数进行筛选。Borg 保留最大的 20,000 个匹配文件夹,并按大小排序;点击“文件”列可改为按文件数排序。可以使用 node_modules 或 *cache* 这样的模式,或用 * 查看起始文件夹下的所有文件夹。

总计是文件内容大小之和。删除文件夹后实际释放的磁盘空间可能与之不同。嵌套的文件夹也会计入其父文件夹的总计。符号链接永远不会被跟随,扫描不会离开起始位置所在的文件系统,包含自身的文件夹(通过绑定挂载或硬链接文件夹)只计算一次。如果因为这类边界,或者因为某个子文件夹无法读取或被排除,导致总计不完整,则会以 ≥ 标示。文件夹扫描只读取元数据,从不读取文件内容。测量完成后才会显示结果,你可以随时取消扫描。

文件夹大小树 在当前面板中显示起始文件夹及其子文件夹的总大小。Right 展开分支,若分支已展开则进入该分支;Left 折叠分支或选中其上级。Enter 打开文件夹本身。点击分支箭头可折叠或展开分支,点击列标题可将同一层级的文件夹按名称、大小或文件数排序。Esc 隐藏大小树,Alt-Shift-R 可恢复其分支、标记和光标。文件操作作用于真实路径;如果同时标记了某个文件夹和它的子文件夹,复制或删除任务只会处理父文件夹。

勾选 排除构建输出、缓存和被忽略的文件 时,按名称搜索会跳过生成的文件夹:node_modules、.git、Python 缓存和虚拟环境、target 和 dist 等与构建文件(Cargo.toml、package.json)相邻的文件夹,以及任何带有 CACHEDIR.TAG 文件的文件夹。同时还会跳过被 .gitignore、.ignore、.rgignore 或 .borgignore 排除的文件,以及 [search] exclude 中的 glob 所匹配的内容。

要更改排除的内容,请在搜索对话框中按 F4,或点击 F4 编辑。你可以分别开启或关闭对生成文件夹和忽略文件的排除,也可以添加(Ins)、编辑(Enter)或删除(Del)模式。更改会保存到配置文件中。被排除的文件夹如果自身名称匹配,仍会出现在结果中;上下文行会统计被排除的文件夹数量。在查询中加入 excluded:yes 可临时搜索全部内容,加入 hidden:yes 则会包含隐藏文件。大小扫描始终读取全部内容。

在 macOS 上,从 ~/Library/Containers 和 ~/Library/Group Containers 的上层开始的搜索和大小扫描会跳过这两个文件夹:读取其中的内容时,macOS 会挂起读取操作,直到有人回答是否允许访问其他应用的数据。如果搜索是从这两个文件夹内部开始的,则会正常读取。

搜索历史保存在本机,只有你能读取。设置 history = false(位于 [search] 下)即可停止保存。

搜索 → 为此文件夹建立索引以便即时搜索 会为当前文件夹下的所有名称维护一份索引,之后在该文件夹或其任意子文件夹中按 Ctrl-F 都会立即得到结果。上下文行会显示索引的建立时间。Borg 启动后,以及索引超过 15 分钟时,会在后台重建索引;新索引就绪之前,旧索引会继续提供结果。不排除任何内容或使用不同排除规则的搜索会改为直接读取文件夹;按文本搜索也是如此,因为索引中只有名称。再次选择该菜单项可停止索引并删除索引。索引与大小扫描结果一起保存在缓存文件夹中,配置中的 [index] 列出了已建立索引的文件夹。

如果想在测量大小的同时保持普通文件面板打开,请按 Alt-I 或选择 搜索 → 在后台计算大小。Borg 会扫描当前文件夹下的每个文件夹(包括隐藏文件),每完成一个文件夹就填入其总大小。扫描期间你可以继续浏览或使用控制台。仍在测量的文件夹会显示一个不断增长、标有 ≥ 的总计;离开文件夹再回来时,总计依然保留。面板页脚显示进度;再次按 Alt-I 或点击页脚,可停止扫描并保留已测得的总计。开始复制、移动或删除任务时,正在进行的大小扫描会停止。已完成的扫描与大小树和文件夹总计共享缓存。

已完成的扫描会保存在本机。文件夹总计和大小树都会复用针对同一文件夹、采用相同隐藏文件设置所保存的扫描结果。重新打开之前测量过的文件夹时,保存的大小会立即显示并标有 ~,大小树上方会显示测量日期。在任一大小视图中按 Ctrl-R 重新扫描,按 Ctrl-C 取消。刷新期间,旧的大小树保持可见;如果新扫描被取消或失败,旧的大小树也会保留。普通文件夹列表中也会显示已保存的总计(如果有)。在 Borg 之外所做的更改可能使这些数据过时,而浏览本身绝不会自动触发递归扫描。Borg 中的复制、移动和删除任务会丢弃涉及其所改动路径的已保存扫描。

本地 SQLite 缓存最多为 16 个起始文件夹保存每个已测量的文件夹。大小树会在你展开分支时才加载其子文件夹。一个分支最多显示 20,000 个文件夹,文件夹总计最多保留最大的 20,000 个匹配项;这些显示上限不会中止扫描,也不会改变总计。“该文件夹中的文件”一行统计的是直接存放在已展开文件夹中的字节数。出错和被跳过的子文件夹会使总计被标记为不完整。缓存位于 ~/.cache/borg-commander,如果设置了 XDG_CACHE_HOME,则位于其下;BORG_CACHE_DIR 可覆盖该位置。缓存只保存可以重新生成的测量结果,与集合相互独立。硬链接文件的每条路径都会各计算一次。所有大小衡量的都是文件内容,因此文件在磁盘上实际占用的空间可能更大,也可能更小。

本指南跟随 main 分支更新 · Borg 0.11.0 · 1f6bce6
最新发布版本可能尚未包含此处介绍的全部功能。 发布说明

译自英文指南,欢迎指正。命令和键盘快捷键不作翻译。