Перейти к содержимому
GitHub

Процессы и память

Alt-M или Команда → Монитор процессов открывает монитор процессов. Он входит во встроенный плагин «Система», который включён по умолчанию и отключается в «Параметры → Плагины». Список процессов занимает активную панель, а другая панель показывает сводку по памяти выбранного процесса. Enter или двойной щелчок открывает этот процесс в окне поверх монитора: одна сторона показывает карту памяти, а другая показывает предпросмотр байтов выбранной области. Esc закрывает окно, а Tab переключает между сторонами. Alt-W или кнопка [+] разворачивает панель в фокусе, [=] восстанавливает разделение, а [-] скрывает монитор. Пока монитор открыт, он снимает показания раз в секунду и прекращает, когда вы его закрываете. Во время исследования памяти сбор показаний приостанавливается и возобновляется, когда приходит результат.

В списке показаны загрузка CPU, резидентная память, рост памяти и скорость чтения и записи на диск. CPU 100% означает одно полностью загруженное ядро. Резидентные страницы, общие для нескольких процессов, учитываются у каждого из них, поэтому сумма RAM всех процессов не равна общему объёму занятой памяти в системе. Скорости CPU и диска появляются со второго замера.

Загрузка CPU усредняется за последние несколько секунд, и старая нагрузка постепенно теряет вес, как в top. Поэтому список, отсортированный по CPU, стоит на месте, даже когда процесс работает короткими всплесками. Сводка и загрузка CPU всей системы вверху монитора усредняются так же. H скрывает процессы, которые за это время не использовали CPU, а строка фильтра показывает, сколько их скрыто. Затихший процесс остаётся в списке, пока его среднее не опустится до 0.0. В дереве вместе с занятым процессом остаются процессы, от которых он происходит. Повторное нажатие H снова показывает все процессы.

Клавиша Действие
Enter Открыть карту памяти процесса / перейти к предпросмотру области
/ Фильтр по имени или PID; ↑↓ по-прежнему перемещают, Enter оставляет фильтр, Esc сбрасывает его
C / M / G / N / P Сортировка по CPU / RAM / росту / имени / PID; повторное нажатие меняет порядок
I / O Сортировка по скорости чтения / записи
T Показать или скрыть дерево процессов
H Скрыть или показать процессы, не использовавшие CPU последние несколько секунд
Left / Right В дереве свернуть или развернуть ветвь выбранного процесса
K Отправить сигнал или изменить приоритет, в том числе из окна процесса
E Искать высокую энтропию во всех процессах
Alt-N Показать трафик выбранного процесса на сетевом экране
Alt-O Открыть папку программы выбранного процесса рядом со списком
Space Приостановить или возобновить сбор показаний
R Обновить текущее представление
Esc Вернуться назад; в списке процессов закрыть монитор или перейти обратно на сетевой экран

Alt-O открывает на другой панели папку программы выбранного процесса, ставит курсор на программу и передаёт клавиши файлам. Список сохраняет фильтр, порядок и выбранный процесс. Tab переключает клавиши между списком и файлами, а Alt-O на другой строке переводит файлы туда. В этих файлах можно просматривать, редактировать, удалять, сжимать и извлекать, а также создавать папки. Копированию и перемещению нужна другая панель, поэтому они ждут, пока монитор закроется. Esc в списке или Alt-M возвращает сводку, а повторное Alt-M закрывает монитор. В открытых файлах и в карте памяти Alt-O показывает выбранный открытый файл или файл, который отображает область. Если программу удалили, пока она работает, её папка открывается с уведомлением. Уведомление появляется и тогда, когда файла нет в его папке на этом компьютере, как бывает с программой, которая работает внутри контейнера. Оповещения, автозагрузка и представление Docker работают так же.

Каждый экран сохраняет фильтр при закрытии и снова показывает его при открытии. Чтобы сбросить фильтр, нажмите /, а затем Esc.

Щёлкните заголовок столбца, чтобы отсортировать по нему, или дважды щёлкните процесс, чтобы открыть его карту памяти. Сводка показывает текущую резидентную память, наибольшее замеченное значение, изменение с начала наблюдения, загрузку CPU, виртуальное адресное пространство и график резидентной памяти за последние 60 секунд. Итоги «Занято», а также выгруженной, частной и общей памяти появляются после чтения карты памяти, если система их сообщает. Enter на панели памяти открывает карту памяти. Карта памяти читается по запросу; нажмите R, чтобы перечитать её после того, как процесс изменит свои отображения.

Под графиком Дерево процессов перечисляет процессы, от которых происходит выбранный, сам процесс и всё, что он запустил. Каждый стоит с отступом под запустившим его процессом и показан со своей резидентной памятью. Если места на всех не хватает, последняя строка сообщает, сколько процессов не поместилось.

В дереве, которое показывает T, каждый процесс стоит под тем, который его запустил, а ▾ отмечает процесс, под которым есть другие. Left сворачивает ветвь выбранного процесса; на процессе, под которым ничего нет, Left сворачивает ветвь, в которую он входит, и выбирает запустивший его процесс. Right разворачивает свёрнутую ветвь, а на открытой переходит к первому процессу в ней. Свёрнутый процесс показывает ▸ и число скрытых под ним процессов. Ветвь остаётся свёрнутой, пока её процесс не завершится. Пока действует фильтр, список плоский.

K открывает Сигнал или приоритет для выбранного процесса: в списке и в окне процесса с картой памяти или открытыми файлами. Нажмите букву нужного варианта или перейдите к нему и нажмите Enter. Esc закрывает диалог, ничего не отправляя.

Клавиша Вариант Что происходит
T Завершить Отправляет TERM, который просит процесс закрыться
I Прервать Отправляет INT, как Ctrl-C в его терминале
H Разрыв связи Отправляет HUP; многие службы перечитывают настройки
K Принудительно завершить Отправляет KILL, который сразу завершает процесс, не давая ему прибраться
S Остановить Отправляет STOP, который приостанавливает процесс
C Продолжить Отправляет CONT, который возобновляет остановленный процесс
L Понизить приоритет Увеличивает nice на 5, но не выше 19, и при загруженной системе процесс дольше ждёт CPU
R Повысить приоритет Уменьшает nice на 5, но не ниже -20

Перед самой отправкой Borg проверяет, что PID по-прежнему принадлежит выбранному процессу с тем же временем запуска, поэтому новый процесс, получивший тот же PID, не пострадает. Строка состояния подтверждает, что отправлено, а список сразу обновляется. Обзор сообщает, что процесс остановлен, и показывает его значение Nice, если оно не равно 0.

Своим процессам можно отправлять сигналы и понижать приоритет. Остальное система запрещает: процессы других пользователей и повышение приоритета, которое доступно только администратору. Тогда Borg предлагает A Администратор и отправляет тот же вариант через вспомогательный процесс, описанный в разделе Права администратора. Самому себе Borg сигналы не отправляет; F10 закрывает его.

В карте три столбца:

  • Занято показывает память, учитываемую за одним этим процессом: записанные им страницы плюс страницы, выгруженные в своп или сжатые. Именно за этим числом стоит следить при поиске утечек; в macOS оно совпадает со столбцом Память в Мониторинге системы.
  • В ОЗУ показывает страницы, которые находятся в оперативной памяти прямо сейчас, включая общие с другими процессами.
  • Отображено показывает адресное пространство, включая зарезервированное. О расходе оперативной памяти это число ничего не говорит.

Процесс может отображать гигабайты (в основном системные библиотеки, общие со всеми остальными процессами) и при этом занимать всего несколько мегабайт. Изначально области сгруппированы по назначению: куча и выделения, стеки потоков, собственный код и данные программы, общие библиотеки, отображённые файлы, общая память, системные и прочие выделения, а также зарезервированные диапазоны и сторожевые страницы. Группы и области в них упорядочены по столбцу «Занято», зарезервированное идёт последним. Для библиотек и отображённых файлов выводится одна строка на файл; раскройте файл, чтобы увидеть его области. Названия групп выводятся из меток, которые даёт операционная система. При выборе группы или файла показывается, что это такое, его доля в «Занято» и крупнейшие элементы. Enter или Right раскрывает группу или файл; Left сворачивает её или ту группу, в которую входит выбранная строка. G переключает между сгруппированным и исходным списком.

1 Память и 2 Открытые файлы переключают вкладки исследования; их также можно щёлкнуть. Список открытых файлов показывает каждый дескриптор, режим доступа, тип и путь или сетевую конечную точку; другая панель показывает полные сведения, размер файла и текущее смещение, если они доступны. В macOS туда входят и такие записи, как cwd (текущий каталог) и txt (отображённый исполняемый файл). R обновляет список. Каждая вкладка при переключении сохраняет положение в списке. Если доступ ограничен, Borg предлагает повторить попытку с правами администратора. Для обычного файла в подробностях также показан предпросмотр его содержимого, как в быстром просмотре: Tab переводит фокус в предпросмотр, чтобы его можно было прокрутить, а F3 открывает файл в просмотрщике. Borg открывает файл по пути с вашими собственными правами и не трогает дескриптор процесса.

Когда вы выбираете доступную для чтения область, Borg снимает до 64 КиБ из неё и показывает на другой панели. Если начало области заполнено одними нулями, снимок пропускает их до первой страницы с данными, а строка над байтами показывает, где в области находится окно. Каждая строка начинается со смещения от начала области, а на широкой панели в строке больше байт. Если вы быстро перемещаетесь, Borg немного ждёт перед чтением; выбор другой области очищает старый предпросмотр и отменяет его незавершённое чтение. Для областей, которые нельзя прочитать, вместо этого выводится сообщение. Нажмите Tab или Enter, чтобы прокручивать предпросмотр. Esc в нём возвращает к списку, а Esc в карте возвращает к списку процессов с прежним положением курсора и фильтром.

Подряд идущие нулевые строки сворачиваются в одну, например «· 60K нулевых байт ·». ] и [ переходят к следующему и предыдущему блоку данных, а > и < снимают следующие и предыдущие 64 КиБ области. H переключает между шестнадцатеричным и текстовым видом, R заново снимает показанное окно, а D подсвечивает изменения с предыдущего снимка того же процесса и адреса. Текстовый вид показывает печатные символы ASCII, а остальные байты заменяет точками. Снимки делаются с работающего процесса без его приостановки, поэтому снимок не является согласованным образом всего процесса. Снимки хранятся в памяти, если вы их не экспортируете. E сохраняет сырые байты в новый файл в папке активной файловой панели, доступный для чтения только вам. Существующие файлы никогда не перезаписываются.

M переключает предпросмотр между байтами и картой страниц области: одна ячейка на страницу 4 КиБ (или на группу страниц в большой области), помеченная по содержимому: указатели в собственную память процесса, текст, текст UTF-16, код, сжатые или зашифрованные данные, прочие данные, заполнитель, нули и страницы, отсутствующие в памяти. Легенда показывает долю каждого вида в области. Когда карта в фокусе, стрелки, PgUp, PgDn, Home и End перемещают курсор, а Enter открывает страницу под ним в виде байтов. Области больше 16 384 страниц просматриваются равномерной выборкой. В Linux карта запрашивает у системы, какие страницы находятся в памяти, и не читает остальные, поэтому не возвращает выгруженные страницы и не затрагивает новые; в macOS страницы, к которым никогда не обращались, читаются как нули. Виды определяются только по байтам, поэтому считайте их подсказкой.

Страницы, энтропия которых достигает 7,2 бит на байт, выделяются жирным красным, а там, где красный плохо читается, только жирным, к какому бы виду они ни относились. Так упакованный или зашифрованный код заметен в исполняемой области, где Borg считает кодом каждую страницу, кроме нулей и заполнителя. Легенда показывает их долю как высокая энтропия, строка курсора добавляет энтропию страницы под ним и заканчивается наибольшей энтропией в области. Примечание под легендой объясняет, что обычно означают высокая и низкая энтропия. У сжатых кэшей, изображений, архивов и ключей энтропия тоже высокая, поэтому прежде чем подозревать область, посмотрите, что в ней хранится.

Чтобы искать в памяти, нажмите / на панели памяти или Ctrl-F на любой из панелей. Выберите режим, учитывать ли регистр и где искать: в доступной для чтения памяти процесса или в текущем снимке. Форма открывается с тем, что в ней было при последнем закрытии. Режим Текст ищет в UTF-8, UTF-16 (при обоих порядках байтов) и UTF-32 (при обоих порядках байтов). Режим Юникод дополнительно нормализует символы совместимости и составные последовательности: например, 𝐁𝐨𝐫𝐠 совпадает с Borg. При этом разные буквы не считаются одинаковыми только потому, что похожи. Режим Шестнадцатеричные байты принимает пары байтов, например 42 6F 72 67.

Режимы Строки и Индикаторы читают только ту память, которую процесс заполнил сам: память, не связанную с файлом и доступную процессу для записи; в macOS пропускаются и области, в которые он ни разу не писал. Режим Строки выводит каждую последовательность не менее чем из шести печатных символов ASCII или UTF-16LE один раз вместе с числом её копий в памяти и пропускает заполнители вроде повторяющихся символов или знаков препинания; если задан запрос, остаются только строки, которые его содержат. Режим Индикаторы оставляет строки, похожие на URL, IP-адрес, адрес электронной почты, путь к файлу, командную строку, секрет (закрытый ключ, токен доступа или присваивание пароля) или длинную последовательность base64, и помечает каждую из них.

Borg также читает строки из файлов, отображённых процессом (до 1 ГиБ), и помечает знаком • строки, найденные только в памяти: текст, который процесс построил, получил или декодировал и которого нет ни в одном из его файлов. Сначала идут индикаторы, затем строки, найденные только в памяти, затем те, что есть и в файлах, а строки, похожие на слова, идут раньше остальных. В списке остаются 2000 лучших. Там, где у других совпадений показана область, здесь в каждой строке показаны вид и число копий, а предпросмотр показывает строку на её месте; C перебирает её копии. Считайте эти результаты зацепками, которые стоит изучить подробнее. В обычных программах тоже полно URL, путей и ключей.

Совпадения занимают панель списка, для каждого указаны адрес, кодировка и область. При выборе совпадения на другой панели показываются байты вокруг него с выделенным совпадением. Enter переводит фокус в предпросмотр, а Esc возвращает к совпадениям. Esc в списке совпадений возвращает к карте памяти или списку процессов, откуда вы пришли. Поиск по сохранённому снимку использует его байты, не читая работающий процесс. Поиск в процессе читает память частями, сообщает о байтах, которые не удалось прочитать, и останавливается после 2000 совпадений или 60 секунд. N продолжает поиск с места остановки, а Ctrl-C останавливает его, сохраняя результаты. Отчёт о покрытии отдельно указывает просмотренные и нечитаемые байты. Процесс может менять свою память во время поиска.

I в карте памяти или в списке совпадений проверяет, выполняет ли процесс тот код, который содержится в его файлах. Проверка сравнивает код в памяти с файлами, из которых он отображён, и сообщает об отличающихся страницах, ищет в памяти, не связанной с файлами, заголовки исполняемых образов (ELF, Mach-O и PE) и перечисляет исполняемую память без файла, память, доступную одновременно для записи и выполнения, и код из удалённых, безымянных или временных файлов. Проверяется и процесс в целом: библиотеки, внедрённые через LD_PRELOAD, LD_AUDIT, DYLD_INSERT_LIBRARIES или /etc/ld.so.preload, пути поиска библиотек, трассировщик в Linux, программа, файл которой удалён или заменён, и имя процесса, отличающееся от имени его программы.

Находки занимают панель списка: сначала тревоги, затем предупреждения, затем замечания. При выборе находки показываются байты, к которым она относится, с выделенными признаками, а строки под списком объясняют, чем ещё это может быть вызвано. Программы, компилирующие код во время работы, например браузеры и движки Java и JavaScript, всегда содержат код без файла, поэтому для них такие находки остаются замечаниями. R повторяет проверку, Ctrl-C останавливает её, сохраняя уже найденное, а Esc возвращает назад. Проверка читает не более 512 МиБ кода и 1 ГиБ прочей памяти, не дольше 45 секунд, и сообщает, если остановилась раньше.

В Linux таблицы страниц показывают, какие страницы кода процесс изменил, поэтому читаются только они; в macOS области без изменённых страниц тоже не читаются. Код в общем кэше macOS не имеет собственного файла и не сравнивается. Память, которую проверка не может прочитать, подсчитывается, и Borg предлагает A Администратор. Считайте находки зацепками, потому что отладчики, профилировщики, программы обновления и средства безопасности оставляют такие же следы.

Y в карте памяти или в списке совпадений проверяет память, которую процесс заполнил сам, теми же правилами, что и проверка файлов: правилами Borg и правилами из вашей папки (см. Проверка файлов правилами). Как и режим Строки, она читает память, не связанную с файлами, и память, в которую процесс может писать; в macOS пропускаются и области, в которые он ни разу не писал. Область, ни одна страница которой не находится в памяти или в подкачке, не читается, а в Linux таблицы страниц показывают, каких страниц процесс ни разу не касался, поэтому они тоже не читаются. Страницы в подкачке читаются, потому что там может ждать вредоносная нагрузка. Память читается блоками по 16 МиБ, которые перекрываются на 4 КиБ, поэтому совпадение на стыке двух блоков тоже находится. Каждое правило показывается один раз на область, на месте первого совпадения.

Совпадения занимают панель списка, сначала тревоги. Каждое называет правило и то, откуда оно: из правил Borg или из вашего файла, затем найденные байты и то, что ищет правило, а строки под списком объясняют, чем ещё это может быть вызвано. При выборе совпадения показываются байты вокруг него, а само совпадение выделено. Пропущенные файлы правил идут последними, с сообщением компилятора. R повторяет проверку, Ctrl-C останавливает её, сохраняя уже найденное, а Esc возвращает назад. Проверка читает не более 1 ГиБ, не дольше 45 секунд, показывает до 2000 совпадений и сообщает, если остановилась раньше. Память, которую не удалось прочитать, подсчитывается, и Borg предлагает A Администратор: тогда проверка выполняется во вспомогательной программе с вашей папкой правил.

Проверка правилами служит для быстрой оценки: это беглый осмотр одного процесса или папки на шаблоны, которые кто-то уже описал. Она не следит за системой, ничего не блокирует и ничего не удаляет: этим занимается защита конечных точек. Некоторые вещи ей недоступны:

  • macOS защищает память собственных программ и программ, собранных с Hardened Runtime, от всех остальных программ, включая администраторов (см. Права администратора).
  • В Linux параметр kernel.yama.ptrace_scope определяет, чью память вам можно читать. При значении 1, как в Ubuntu, можно читать только собственные дочерние процессы, поэтому для остальных Borg предлагает A Администратор. При значении 3 никто не может читать чужой процесс, даже администратор.
  • Руткит ядра может скрыть память, файлы и процессы от любой программы, в том числе от Borg, поэтому чистый результат проверки мало что доказывает.
  • Упакованная или зашифрованная программа показывает свой настоящий код только во время работы. Проверка её памяти в этот момент видит то, чего не видит проверка её файла.

Borg читает память, не подключаясь как отладчик, через process_vm_readv в Linux и mach_vm_read в macOS, поэтому процесс не видит трассировщика, а именно его ищет большинство проверок против отладки. Мониторы, работающие от имени администратора, например auditd, инструменты eBPF и клиенты Endpoint Security в macOS, всё же могут записать эти чтения. Проверка файлов открывает каждый файл, который читает, и inotify и fanotify об этом сообщают. В Linux она не меняет время доступа у принадлежащих вам файлов.

E в списке процессов открывает диалог Проверка энтропии: Borg читает выборку страниц всех процессов и ищет байты, такие же плотные, как у упакованного кода. Нажмите букву варианта или перейдите к нему и нажмите Enter. Esc закрывает диалог.

Клавиша Вариант Что читается
C Код всех процессов Исполняемые области, где виден упакованный или зашифрованный код
M Вся память всех процессов Все читаемые области, а значит, и данные вроде ключей и сжатых файлов
L Последние результаты Ничего нового: снова показываются находки последней проверки

Borg читает до 1024 страниц по 4 КиБ из области и до 32 768 из процесса, равномерно. Процесс со многими областями получает меньше страниц на область, но не меньше 16. Область, в которой хотя бы одна страница достигает 7,2 бит на байт, считается находкой. Находки занимают панель списка: сначала код, затем память, в которую писал процесс, затем файлы, отображённые в память в том виде, в каком они лежат на диске. Внутри каждой группы первой идёт область с большей долей страниц с высокой энтропией. Код, у которого высокую энтропию имеют 70% страниц или больше, выделяется жирным по тому же правилу, что и в поиске упакованных программ. В каждой строке указаны вид (код, запись или файл), эта доля с наибольшей энтропией, а также имя процесса, PID и область. Другая панель показывает адреса, размер и права доступа области, сколько страниц выборки имеют высокую энтропию, где начинается первая из них и чем обычно бывают такие байты. Сохраняются 2000 самых сильных находок, а сводка подсчитывает отброшенные более слабые.

Enter на находке открывает карту памяти процесса на этой области с включённой картой страниц, и курсор стоит на первой плотной странице выборки, чтобы можно было посмотреть байты вокруг неё. Esc возвращает к карте, а повторное нажатие возвращает к находкам.

Borg читает 4 процесса одновременно. Область, ни одна страница которой не находится в памяти или в подкачке, не читается, а в Linux таблицы страниц показывают, какие страницы находятся в памяти, поэтому проверка не затрагивает новые страницы и не возвращает выгруженные. Кэши, которые все процессы отображают одинаково, пропускаются: общий кэш dyld в macOS и страницы, которые ядро отображает в каждый процесс в Linux. Файл, отображённый без изменений, например общая библиотека, читается только в первом процессе, который его отображает.

Проверка останавливается через 90 секунд и оставляет остальное для N, которая продолжает с процессами, до которых проверка не дошла. Ctrl-C останавливает её раньше, сохраняя находки, а R начинает проверку заново. Над находками одна строка показывает число проверенных процессов и находок, а следующая перечисляет пропущенные процессы: нечитаемые, защищённые и непроверенные. В macOS vmmap несколько секунд перечисляет области одного процесса, поэтому для проверки всех процессов может понадобиться несколько раз нажать N.

Процессы, память которых защищает macOS, подсчитываются и пропускаются, потому что их никто не может прочитать. Для процессов, которые Borg не смог прочитать, он предлагает A Администратор: вспомогательный процесс проверяет их не дольше 60 секунд, чтобы уложиться в свой лимит в 2 минуты даже после долгого запроса пароля. Плотные байты встречаются часто: у сжатых кэшей, изображений, шрифтов и ключей энтропия высокая по природе, поэтому считайте находки зацепками и прочитайте подробности, прежде чем подозревать процесс.

Если чтение карты памяти или снимка ограничено, поиск не смог прочитать часть памяти, проверка энтропии не смогла прочитать некоторые процессы или система отказала в отправке сигнала или смене приоритета, Borg предлагает A Администратор. В macOS открывается системный запрос авторизации; в Linux используется pkexec, и нужен запущенный агент авторизации. С повышенными правами работает только кратковременный вспомогательный процесс. Сам Borg продолжает работать как обычно, а вспомогательный процесс возвращает только данные карты, ограниченное число байтов или находки проверки либо отправляет выбранный вами сигнал или приоритет.

macOS защищает память собственных программ (System Integrity Protection) и программ, собранных с Hardened Runtime, от любых других программ, включая администраторов. Borg определяет это по подписи программы: в подробностях процесса указано Память защищена, при отказе в чтении объясняется причина, а A Администратор не предлагается, поскольку не поможет. Карты памяти и открытые файлы таких программ всё равно показываются. Не предлагается этот вариант и тогда, когда Borg уже работает с правами администратора. В Linux доступ всё равно может запретить политика безопасности; Borg показывает ошибку, а монитор процессов продолжает работать как обычно.

Процесс идентифицируется вместе со временем запуска, поэтому новый процесс, получивший тот же PID, не наследует историю другого. Карты памяти, результаты исследования, снимки и история ограничены по размеру. Название Borg Commander всегда видно в правом нижнем углу: в консоли, просмотрщике, мониторе, диалогах и на заставке.

Borg может следить за тем, что запускается на машине, и сообщать, когда что-то выглядит неладно. Включите Наблюдение: необычные запуски процессов в F9 → Параметры → Плагины. Наблюдатель живёт в фоновой службе, общей для всех ваших Borg на машине, поэтому каждый Borg читает одни и те же оповещения. Эта служба работает, пока открыт хотя бы один Borg. Чтобы следить и без открытого терминала, настройте запуск службы при загрузке, как описано в разделе Именованные сеансы и фоновая служба.

Оповещения остаются на этой машине, пока вы не укажете, куда их отправлять, и страница напоминает об этом всё это время (см. Оповещения за пределами машины).

Alt-L или Команда → Оповещения открывает страницу. Список занимает активную панель, самое свежее оповещение сверху, а вторая панель показывает выбранное оповещение целиком. В каждой строке видны время, сработавшее правило, программа, родитель, который её запустил, пользователь, от имени которого она работала, и что стало с процессом. Строка над списком считает оповещения и те, которые ещё никто не прочитал.

Подробности сначала одной фразой говорят, почему сработало правило, а затем показывают команду, программу, родителя, пользователя, куда ведут стандартные потоки, и где процесс находится сейчас. В разделе Дерево процессов каждый родитель стоит над своим потомком, так что путь от службы до насторожившей вас команды читается сверху вниз. Соединения перечисляют сокеты, которые процесс держал в тот момент, Хеш программы это SHA-256 её файла, а Правила показывают, что правила Borg и ваши нашли в этой программе (см. Проверка файлов правилами).

Команда длиннее 2 KiB сохраняет начало и конец, вместе 2 KiB, с … между ними. Команды родителей и значения переменных предзагрузки обрезаются так же. Благодаря этому 200 самых свежих оповещений помещаются в журнал, какими бы длинными ни были их команды, а длинный первый аргумент не может вытеснить из виду конец команды. Ctrl-C копирует команду в том виде, в каком её хранит журнал.

Клавиша Действие
Enter Показать процесс в мониторе процессов
C Дать замороженному процессу работать дальше
K Завершить процесс, после вопроса
A Разрешить такие запуски впредь
Alt-O Открыть папку программы оповещения рядом со списком
/ Фильтр строк; ↑↓ по-прежнему двигают, Enter сохраняет фильтр, Esc очищает его
R Перечитать журнал
Ctrl-C Копировать команду, которую выполнял процесс
Alt-W Развернуть список
Esc Закрыть страницу, сохранив фильтр

Фильтр оставляет оповещения, в которых есть все введённые слова: он смотрит на правило, его краткое имя, причину, программу, родителя, пользователя, команду и на то, что сделал Borg. Поставьте ! перед словом, чтобы исключить то, что оно находит: shell-on-socket !root оставит удалённые оболочки всех остальных пользователей.

Оповещения лежат в файле alerts.json в папке состояния, доступном только владельцу, и это 200 самых свежих. Оповещение о процессе, который всё ещё заморожен, остаётся и сверх этого числа, чтобы вы всегда могли дать ему работать дальше или завершить его. Borg держит файл в пределах 8 MiB, столько он читает обратно, и отбрасывает самые старые оповещения, если они не помещаются. Окно Файлы Borg учитывает их в разделе Состояние (см. Файлы Borg). Открытие страницы помечает показанные оповещения как прочитанные, а счётчик непрочитанных следует за журналом, пока Borg открыт, независимо от того, открыта ли страница.

Если Borg находит alerts.json, который не может прочитать, например файл, который старая версия позволила раздуть больше 8 MiB, он переименовывает его в alerts-unreadable.json и только потом пишет новый журнал, так что оповещения из него остаются на диске. Следующий такой файл получает имя с номером, например alerts-unreadable (2).json. Пока этот файл на месте, страница оповещений показывает его путь под списком. Удалите его, когда просмотрите.

Каждое правило называет одну странность в только что запустившемся процессе. Уровень говорит, как много это значит: тревога редко бывает безобидной, у внимания часто есть обычная причина, замечание стоит здесь, чтобы картина была полной.

Правило Что его вызывает Уровень
Оболочка на сетевом сокете У оболочки ввод, вывод или поток ошибок идут в сетевой сокет: так выглядит удалённая оболочка. Сокет, который не покидает машину, например тот, через который systemd передаёт вывод службы в журнал, не считается тревога
Удалённая оболочка на терминале Оболочка на терминале, который для неё открыла программа, причём ввод, вывод или поток ошибок самой этой программы идут в сетевой сокет, или программа служит ретранслятором, как socat или nc. Так выглядит удалённая оболочка, превращённая в полноценный терминал, например через pty.spawn в Python тревога
Программа удалена во время работы Файла программы больше нет, и на диске не осталось ничего, что говорит о процессе тревога
Программа без файла Borg вообще не нашёл файла программы для этого процесса тревога
Библиотека, навязанная программе В её окружении задана LD_PRELOAD, LD_AUDIT или DYLD_INSERT_LIBRARIES тревога
Оболочка из службы Веб-сервер, среда выполнения приложений или база данных запустила оболочку внимание
Оболочка без терминала У оболочки нет терминала ни с одной стороны, значит её никто не набирал внимание
Оболочка на терминале программы Оболочка на терминале, который программа открыла для себя сама и в который никто не входил, например тот, что открывают expect или docker exec внимание
Осмотр машины Четыре разные команды, например whoami, id, uname и ss, от одной программы в пределах часа, когда в терминал, где они работают, никто не входил. Команды, которые она запускает через одну оболочку за другой, считаются вместе, так что веб-оболочка, запускающая sh -c для каждой команды, тоже попадается внимание
Программа во временной папке Программа лежит в /tmp, /var/tmp, /dev/shm или /run/shm внимание
Имя не совпадает с программой Процесс называет себя одним, а запускает другое внимание
Родитель раньше его не запускал Этот родитель ещё никогда не запускал эту программу на этой машине замечание

О каждом процессе Borg читает программу, которую он запускает, и удалён ли её файл, команду, пользователя, терминал, которому процесс принадлежит, и кто этот терминал открыл, куда ведут его стандартный ввод, вывод и поток ошибок, переменные предзагрузки в его окружении и цепочку родителей над ним. Сокет считается сетевым, когда сеть процесса числит его как TCP или UDP.

Вошёл ли кто-то в терминал, решается так же, как при заморозке (см. Заморозка процесса): по SSH, с консоли, в tmux или screen, через sudo или su или в окне терминала. Терминал, который программа открыла для себя сама, не считается, будь то удалённый сервер редактора, docker exec или обратная оболочка.

Borg сначала изучает машину и только потом действует. Первые 7 дней он записывает, какой родитель какую программу здесь запускает, и ничего не замораживает, а в столбце «Реакция» там, где он заморозил бы, стоит Заморозил бы. После этого пара, которую он уже видел, молчит для правил, которые можно выучить: трёх правил об оболочках, несовпадающего имени и родителя, который раньше её не запускал. Череда команд выучивается по программе, от которой она идёт: она молчит, если эта программа запускала каждую из её команд за неделю обучения, поэтому агент мониторинга, который весь день запускает df и ps, молчит, а веб-сервер, который никогда не запускал id, нет. Пять правил уровня «тревога» срабатывают всегда, потому что оболочка на сокете или навязанная библиотека не становятся нормой от того, что случаются часто. Всё, что запускается за эту неделю, считается нормой, поэтому включайте наблюдатель, пока доверяете машине. Запуски, на которых сработало правило, которое обучение не может заглушить, в выученное не попадают.

A на оповещении разрешает такие запуски впредь, по его программе и его родителю. Эти разрешения ложатся в файл watch-allowed.json в папке состояния, который наблюдатель читает и принимает в течение минуты. Раздел [watch] в настройках хранит то же самое, записанное вручную (см. Настройка). Borg записывает не больше 20 процессов в минуту и замораживает не больше 5, а строка над списком говорит, сколько находок он пропустил, когда сработало больше. Процесс, который Borg замораживает, записывается всегда, сколько бы оповещений ни было до него, чтобы вы могли дать ему работать дальше. Замечания считаются отдельно, так что их череда никогда не отнимает места у оповещений уровня «внимание», а до 20 процессов в минуту, которые Borg заморозил бы сверх предела в 5, тоже записываются.

Когда период обучения заканчивается, Borg замораживает процесс, на котором сработало правило уровня «тревога» или «внимание». Заморозка отправляет сигнал остановки процессу и всему, что под ним. Замороженный процесс не завершился, поэтому его служба продолжает работать, systemd и Docker нечего перезапускать, а то, что процесс собирался сделать, ждёт на месте, пока вы не посмотрите. В столбце «Реакция» стоит Заморожен, C даёт процессу работать дальше, а K завершает его. Завершение необратимо, поэтому Borg сначала спрашивает.

Заморозка начинается, когда вы увидите все оповещения недели обучения со словами Заморозил бы, или через 3 дня после конца недели, смотря что наступит раньше. Открытие страницы оповещений отмечает их прочитанными, и наблюдатель замечает это в течение минуты. Так вы можете проверить, что поймала неделя, и разрешить безобидную программу клавишей A до того, как что-то остановится, а машина, на которую никто не смотрит, всё равно защищена. До тех пор в нижней строке страницы указано, до какого времени ждёт заморозка, а в подробностях нового оповещения сказано, что она ждёт.

Borg никогда не замораживает первый процесс системы, самого себя и всё, что он запустил, программу из списка, который он никогда не замораживает (init, systemd, sshd, sudo, su, login и подобные, плюс любое имя, добавленное в keep-running), процесс на терминале, в который кто-то вошёл, и запуск, который вы разрешили. Замечание никогда не останавливает программу. Подробности говорят, что именно из этого оставило процесс работать.

Программа из встроенного списка щадится только там, где система хранит свои программы, например в /usr и /bin, поэтому копия с именем sshd в другой папке замораживается, как и всё остальное. Имена, добавленные в keep-running, совпадают, где бы ни лежала программа. Терминал считается, когда в него кто-то вошёл: по SSH, с консоли, в tmux или screen, через sudo или su или в окне терминала. Терминальный мультиплексор считается только для root и учётных записей людей, с номерами от UID_MIN из /etc/login.defs (1000 в большинстве систем), потому что служебная учётная запись тоже может его запустить. Терминал, который программа открыла для себя сама, не считается, и удалённая оболочка не может за ним спрятаться. Терминалы, которые открывает удалённый сервер редактора или docker exec, тоже не считаются, поэтому если Borg заморозит то, что вы запустили там, C даст ему работать дальше, а A разрешит.

Прямо перед сигналом Borg заново проверяет личность процесса, его номер вместе с моментом запуска, так что номер, который за это время занял другой процесс, остаётся в покое.

Без дополнительных прав Borg знает только о процессах своего пользователя, просматривая список процессов четыре раза в секунду, и страница говорит об этом под списком. Короткая команда может исчезнуть до следующего просмотра.

Чтобы знать о каждом процессе в момент его запуска, установите часть, которая работает от имени root:

Окно терминала
borg service watch install

Она один раз спросит ваш пароль и установит отдельный юнит borg-commander-watch.service, который запускает borg --watch-root. Эта часть загружает в ядро небольшие собственные программы Borg, которые считывают каждый запуск программы ещё до того, как новая программа начнёт работать: программу, командную строку в точности такой, какой её передали, процесс, который её запустил, и пользователя. Команда, которая сразу завершилась, всё равно попадает в отчёт, как и командная строка процесса, который потом её переписывает. Часть с правами root читает остальное из /proc и останавливает, продолжает или завершает процесс, когда Borg об этом просит. Больше она не делает ничего: юнит отказывается от всех возможностей, которые ему не нужны, а сам интерфейс Borg продолжает работать от вашего имени. Две стороны говорят через сокет в папке состояния, доступный только владельцу, Borg принимает соединение лишь от процесса, работающего от имени root, а часть с правами root подключается лишь к сокету, принадлежащему тому пользователю, для которого она установлена. borg service watch uninstall удаляет её, а borg service watch status печатает, откуда приходят события и что уже найдено. Установка и состояние предупреждают, пока оповещениям некуда уходить (см. Оповещения за пределами машины).

Программам нужен Linux 5.8 или новее. На более старом ядре или там, где часть с правами root не может их загрузить, она слушает события процессов от ядра и читает всё из /proc, а страница сообщает об этом под списком. После обновления Borg снова выполните borg service watch install, чтобы юнит получил права, которые нужны новой версии.

Оповещения с обеих сторон это одни и те же оповещения в одном журнале. Процесс другого пользователя может заморозить только часть с правами root, поэтому продолжение или завершение такого процесса со страницы идёт через наблюдателя в службе. Когда до него не добраться, страница говорит, что это может только владелец или администратор.

Пока наблюдатель работает только в Linux. В macOS страница открывается и читает свой журнал, а источник сообщает, что наблюдения нет.

Страница «Оповещения» находится на той машине, за которой наблюдает, поэтому тот, кто захватит машину, может стереть журнал. Отправляйте каждое оповещение куда-то ещё в тот момент, когда оно появляется: дошедшая копия будет вне его досягаемости, а пульс сообщит, когда наблюдатель замолчит. Добавьте [watch.notify] в конфигурацию на сервере и укажите одно или несколько из этих мест. Адреса начинаются с https://, а http:// допускается только для самого сервера:

[watch.notify]
name = "web-01" # how messages name this machine, its host name otherwise
level = "warning" # the least an alert needs to be sent: alert, warning or notice
[watch.notify.telegram]
token = "123456:ABC-your-bot-token"
chat = "123456789"
[watch.notify.ntfy]
url = "https://ntfy.sh/a-long-random-topic"
token = "tk_your_token" # where the topic needs one
[watch.notify.webhook]
url = "https://example.com/borg"
secret = "a long random string"
[watch.notify.heartbeat]
url = "https://hc-ping.com/your-check-id"
minutes = 5

Затем выполните borg service watch notify. Команда отправляет проверочное сообщение в каждое место и печатает, что ответило каждое из них.

  • Telegram: создайте бота через @BotFather, он выдаст токен. Отправьте боту сообщение, затем откройте https://api.telegram.org/bot<token>/getUpdates и возьмите из ответа chat.id.
  • ntfy: подпишитесь в приложении ntfy на тему с длинным именем, которое никто не угадает, или на тему на собственном сервере ntfy.
  • Веб-хук: Borg отправляет каждое сообщение на адрес в виде JSON. Если задан secret, каждый запрос несёт X-Borg-Signature: t=<time>,v1=<signature>: HMAC-SHA256 от времени, точки и тела сообщения с этим секретом, чтобы получатель мог отличить сообщения Borg от поддельных. X-Borg-Event говорит, что это за сообщение: alert, evidence (SHA-256 программы и совпадения правил, которые приходят вслед за оповещением, когда Borg прочитает программу), started, armed или test.
  • Пульс: пока наблюдатель работает, Borg обращается к адресу каждые minutes минут и добавляет /fail, когда что-то не так: остановился поток, который считает хеши программ, какое-то место 30 минут не принимает сообщения, Borg отказался от одного из них или не смог прочитать свою очередь отправки. Сервис вроде healthchecks.io сообщит вам, когда обращения прекратятся, а так и бывает, когда кто-то убивает наблюдателя.

Пока ни одно место не принимает оповещения, они остаются в журнале на машине, и Borg говорит об этом везде, где вы имеете дело с наблюдателем. Страница «Оповещения» показывает Оповещения остаются на этой машине. над подробностями выбранного оповещения или в последней строке списка, когда список развёрнут. Та же строка появляется, когда вы включаете наблюдателя в Параметры → Плагины, в выводе borg service watch install и borg service watch status и в выводе службы при запуске наблюдателя. Один только пульс предупреждение не снимает. Он сообщает, что наблюдатель работает, и оповещений не несёт, поэтому добавьте ещё Telegram, ntfy или веб-хук.

Предупреждение становится строже, когда Borg близок к действиям. За день до конца периода обучения оно гласит Borg вот-вот начнёт замораживать процессы здесь, и об этом никто не узнает., а после начала заморозки: Borg замораживает процессы здесь, и об этом никто не узнаёт. Borg продолжает наблюдать, учиться и замораживать и без места для оповещений, поэтому настройте его до конца периода обучения на машине, в которую вы заглядываете не каждый день.

Служба отправляет каждое оповещение в течение нескольких секунд после того, как запишет его, а ещё сообщает, когда наблюдатель запускается и когда начинается заморозка. Оповещения уровня «замечание» остаются только на странице, если level не равен notice. Сообщение, которое место не приняло, ждёт в watch-outbox.json в папке состояния и отправляется снова: первый раз через 5 секунд, затем не реже чем раз в 30 минут. Borg хранит до 500 ожидающих сообщений (меньше, если длинные сообщения не помещаются в 16 MiB) и пытается отправить каждое в течение 48 часов. Следующее сообщение говорит, от скольких он отказался.

Сообщение несёт не больше 1000 байт командной строки, пути к программе и причины оповещения. У более длинного текста остаются начало и конец с многоточием между ними, поэтому заполнение начала команды не скроет, что она делает.

Если Borg находит watch-outbox.json, который не может прочитать, он переименовывает файл в watch-outbox-unreadable.json и начинает новую очередь. Следующий такой файл получает имя с номером, например watch-outbox-unreadable (2).json. Ожидавшие сообщения остаются в этом файле и никогда не отправляются, поэтому пульс один раз сообщает о сбое и объясняет причину, а нумерация для каждого места начинается заново с 1. Просмотрите файл, а затем удалите его.

Каждое место нумерует свои сообщения с 1, а JSON каждого сообщения несёт в previous SHA-256 предыдущего. Пропуск в нумерации или previous, который не совпадает, означает, что сообщение потерялось или было изменено по пути. Нумерация ведётся на сервере, поэтому она не поможет против того, кто управляет сервером.

Токены лежат в конфигурации, которую может прочитать всё, что работает на сервере от имени вашего пользователя. С ними можно отправлять сообщения, похожие на сообщения Borg, и продолжать нумерацию без пропусков, а бот Telegram может удалить то, что отправил за последние 48 часов. Тот, кто захватит сервер, может также удалить сообщения, которые ещё ждут отправки. Пришедшее до этого остаётся как было, а веб-хук на машину, которую контролируете вы, сохраняет его таким, каким оно пришло. Когда наблюдатель замолкает, об этом сообщает пульс.

Наблюдатель судит о каждой программе в момент её запуска, и кое-что остаётся вне его поля зрения. Узнайте об этом, прежде чем полагаться на него.

  • Код, который выполняется внутри уже работающей программы, ничего нового не запускает, поэтому ни одно правило на него не смотрит. Веб-приложение, чей собственный интерпретатор захвачен, сохраняет прежнее имя и прежнего родителя.
  • Процессы, работавшие до запуска наблюдателя, никогда не проверяются, а всё, что запускается в неделю обучения, считается нормой.
  • Без наблюдателя от имени root Borg видит только ваши собственные процессы, а команда, которая завершается быстрее четверти секунды, может исчезнуть раньше, чем Borg посмотрит. Службам, работающим от имени другого пользователя, например www-data или postgres, нужен наблюдатель от имени root. Когда наблюдатель от имени root останавливается, Borg снова следит за вашими собственными процессами, пока тот не запустится опять.
  • До Linux 5.8 или там, где часть с правами root не может загрузить свои программы, Borg читает каждый новый процесс в /proc после того, как ядро о нём сообщит. Команда, которая сразу завершилась, к этому времени может исчезнуть, а процесс может успеть изменить свою командную строку.
  • Некоторые ядра не присылают событий о процессах, например в некоторых виртуальных машинах и средах контейнеров. Тогда Borg, работающий от имени root, и наблюдатель от имени root просматривают все процессы четыре раза в секунду, и короткая команда может завершиться раньше, чем они посмотрят.
  • Всплеск новых процессов может переполнить очередь между ядром и Borg, и тогда ядро отбрасывает события, так что некоторые запуски так и не проверяются.
  • Команда, завершившаяся раньше, чем Borg успел прочитать /proc, несёт только то, что считали программы: её программу, командную строку, родителя и пользователя. Её терминал, стандартные потоки и переменные предзагрузки исчезли вместе с ней, поэтому правила о них сработать не могут. Программа удалена во время работы срабатывает на ней, только если её файла уже не было в момент запуска, как у программы, запущенной из памяти.
  • Программы сохраняют первые 4 КиБ командной строки, а более длинную Borg берёт из /proc, пока процесс ещё существует. Командную строку и файл программы они находят по сведениям о типах, которые ядро публикует в /sys/kernel/btf/vmlinux. На ядре, собранном без них, командная строка тоже берётся из /proc. Команда, завершившаяся раньше, тогда указывается тем путём, которым её запустили. Этот путь может быть относительным к её рабочей папке или вести через символическую ссылку, поэтому Программа во временной папке может её пропустить.
  • Всё, что работает от имени того же пользователя, что и наблюдатель, может остановить наблюдатель, изменить его файлы в папке состояния или дать замороженному процессу работать дальше с помощью kill -CONT. Заморозка даёт вам время посмотреть, а владелец процесса всё равно может её отменить.
  • Процесс на терминале, в который кто-то вошёл, никогда не замораживается, даже если вход выполнен с украденным паролем или ключом. Правила всё равно срабатывают и записывают оповещения.
  • Осмотр машины считает команды одной программы в пределах часа. Тот, кто выжидает между командами дольше или запускает каждую из другой программы, остаётся ниже порога.
  • Процесс, который отделился от своего родителя до того, как Borg заморозил родителя, продолжает работать.
  • Без [watch.notify] оповещения доходят до вас, только когда вы открываете страницу. С ним тот, кто захватит машину в первые секунды после оповещения, ещё может остановить сообщение до того, как оно уйдёт, и тогда о беде скажет молчание пульса.

Руководство описывает ветку main · Borg 0.11.0 · 1f6bce6
В последнем выпуске может быть не всё, что здесь описано. Список изменений

Перевод с английского. Будем рады исправлениям. Команды и сочетания клавиш не переводятся.