11 января 2026 в 11:52

Техники сокрытия файлов или как прячут исполняемые файлы в Linux

«Всё чисто» – самый опасный диагноз в ИБ. Как APT-группы годами скрываются в Linux-системах, превращая картинки в трояны, а процессы в призраков? Практическое руководство по охоте на невидимок.

«Всё чисто, как стеклышко!» – бодро отрапортовал парень из SOC’а. А в это самое время... где-то в темных уголках сети, троян уже третий месяц методично сливал данные, как старый водопроводный кран в подвале забытого офиса.

Правдивая история? Еще какая. Одна крупная финансовая контора, имя не назову, но вы их кредитку точно в кошельке носите, проморгала продвинутую APT-атаку. Результат? Данные четверти миллиона клиентов уплыли к злодеям. А эти ребята? Мастера камуфляжа! Их код прятался так ловко, что:

  • Антивирусы стояли столбами, как охранники у пустого склада.
  • Сисадмины? Копались в процессах – чистота, хоть на операционный стол ложись. Ни пылинки, ни соринки подозрительной.
  • Сеть? Трафик нескончаемо лился как ручеёк в погожий денёк. Ничего криминального мониторы не высмотрели.
  • Сканеры файлов... Ха! Нашли только то, что и должно было там быть. Легитимный мусор, не больше.

В чём же был фокус-покус? А в том, что ядовитый код даже файлом-то не был! Вообще. Ни одной строчки отдельной. Вплетён искусно, как узор в персидский ковёр – прямо в безобидные картинки на их же корпоративном сайте. Засунут в системные библиотеки, в которые никто не заглядывает. Забит в мёртвые зоны нормальных программ, как контрабанда в двойное дно чемодана. Гениально и просто, черт возьми.

А вы в курсе, сколько в современном Линуксе лазеек, куда можно воткнуть зловредный кусок кода? Серьёзно, пальцев на всех руках команды не хватит, чтобы пересчитать! От впихивания в картинку (стеганография, это называется, если по-умному), до таких изощрённых методов, что у меня волосы дыбом встают. Инъекции прямо в память живых процессов... Некоторые артефакты вообще только в ОЗУ болтаются, призраками. На диске? Ни следа. Воткни потом хоть десять сканеров, ничего не найдешь. Это вам не вирусы девяностых, которые кричали «Я здесь!».

Вам хватит 20 минут, чтобы понять, как эти тени прячутся, научиться их выслеживать не надеясь на «волшебную таблетку» антивируса и наконец-то осознать, почему ваша стандартная защита иногда выглядит беспомощнее новичка с деревянным мечом против танка. Давайте разбираться без воды, только суть. Покажу, как самому искать то, что другие не видят. Даже самое хитрое.

Когда «всё чисто» – это самый страшный диагноз

«Знай противника и знай себя, и ты будешь непобедим.» Сунь-цзы

Представьте на минутку: ваша сеть тихо поёт от счастья, сканеры моргают зелёными лампочками, будто новогодняя ёлка... а где-то в тенях уже поселился незваный гость. Знакомо? Антивирус молчит, как партизан на допросе, но нутром чуешь что-то нечистое. Злодеи сегодня настоящие мастера камуфляжа, их код прячется так, что стандартные защиты проходят мимо, как слепой котёнок мимо миски с молоком. Добро пожаловать в джунгли файлового стелса – место, где красиво только со стороны, а на деле сплошные колючки и ядовитые змеи.

В прошлых разговорах мы ковырялись в файлах обычными линуксовыми инструментами. Классика! Но что если оппонент знает ваши фишки лучше вас? Что если он специально играет в прятки? Сегодня мы сами станем... ммм, скажем так, наблюдателями за теми, кто прячет исполняемые файлы там, где свет не падает. Темная сторона, так сказать. Интересно? Чертовски!

💡 Внимание

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

Стеганография: код в теле картинки – как микрофильм в пуговице шпиона

Стеганография... Звучит умно, да? По сути это просто искусство спрятать секрет прямо под носом. В нашем случае, запихнуть опасный исполняемый файл куда угодно: в милого котика на корпоративном сайте, в скучнейший PDF-отчёт, хоть в аудиозапись гимна компании. Выглядит чистоплотно. А внутри – бомба замедленного действия.

💡 На пальцах, без фанатизма

Сегодня рассмотрим только самый примитивный метод стеганографии. Глубины оставим академикам, а нам бы суть ухватить.

Как это вообще работает? Ну, в двух словах...

Представьте: у каждого файла есть свой «родной» хвостик: конец данных, который программа ждёт увидеть. У PNG это блок IEND, у JPEG – маркер EOI (типа «всё, хватит»). А теперь фокус! Всё, что идёт ПОСЛЕ этого маркера большинство просмотрщиков игнорирует. Как если мусор за забором глаз не мозолит, то его и нет. Вот и весь секрет! Хакер берёт безобидную картинку и... приклеивает к ней свой зловредный бинарник. Просто. До безобразия.

Сделать такое? Легче пареной репы. Гляньте в консоль:

cat src/image.png build/binary_file > build/hidden_image.png

Берем картинку (image.png), приклеиваем к её задней части наш бинарь (binary_file) и вуаля! Получаем файл-франкенштейн (hidden_image.png). Откроешь его в просмотрщике и увидишь только котика. Но если кто-то запустит ЭТО как программу... ну, вы поняли. Жуть? Ага. И это только цветочки.

Спрятано на виду: когда PNG – не совсем PNG

Короче, возьмём этот самый hidden_image.png из нашей кучи файлов и ткнём в него утилитой file. Что выдаст?

$ file build/hidden_image.png
build/hidden_image.png: PNG image data, 400 x 300, 1-bit colormap, non-interlaced

С виду чистейшая картинка, ангельская простота. Но вы ж помните наши танцы с ELF? Там же магические байты как отпечатки пальцев. Вот и здесь: где-то в теле файла должна торчать эта чёртова сигнатура 7F 45 4C 46 (ELF, если кто забыл). Берём xxd и лопатим бинарник:

# Роемся в байтах как крот
$ xxd build/hidden_image.png | grep -E "7f\s?45\s?4c\s?46"
000000b0: 44ae 4260 827f 454c 4602 0101 0000 0000  D.B`..ELF.......

Ага! Вот же она торчит на смещении 0xb0 плюс ещё 5 байтов до 7f (математика простая: 0xb5 в шестнадцатеричном, а это... пауза... 181 в нашем, человеческом). Теперь дело за малым – выдрать заголовок обычным dd. Стандартный размер? 64 байта, как пить дать.

dd if=build/hidden_image.png of=binary_header bs=1 skip=181 count=64
💡 Расшифровываем эту абракадабру

if=build/hidden_image.png – откуда читаем (input file), тут всё ясно.

of=binary_header – куда плюхаем результат (output file), логично.

bs=1 – читаем по одному байтику, медленно, но верно. Никуда не спешим, правда?

skip=181 – перепрыгиваем 181 байт ненужного барахла. Начинаем с чистого листа, так сказать.

count=64 – хватаем ровнехонько 64 байта. Не больше, не меньше – как в аптеке.

# Ну-ка, что у нас в коробочке?
$ file binary_header
binary_header: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV)

$ readelf -h binary_header
Заголовок ELF:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00  # Классика!
  Класс:                             ELF64
  Данные:                            дополнение до 2, от младшего к старшему
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V  # Старый добрый...
  Версия ABI:                        0
readelf: Ошибка: Слишком много заголовков программы — 0xd — файл не такой большой  # А вот и первая заноза!
  Тип:                               DYN (Совм. исп. объектный файл)
  Машина:                            Advanced Micro Devices X86-64
  Версия:                            0x1
  Адрес точки входа:               0x1080
  Начало заголовков программы:          64 (байт в файле)
  Начало заголовков раздела:          12616 (байт в файле) # ← Вот это важняк!
  Флаги:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         29 # ← Считаем!
  Section header string table index: 28
readelf: Ошибка: Reading 1856 bytes extends past end of file for заголовки разделов  # Ну конечно, куда ж без ошибок...

Теперь главное не утонуть в этой каше из цифр. Смотрите: чтобы вычислить размер всей программы, хватаемся за соломинку – «Начало заголовков раздела» (12616). Потом считаем: 29 заголовков × 64 байта каждый. Складываем? 12616 + (29 * 64) = 14 472. Элементарно, Ватсон!

# Последний рывок:
dd if=build/hidden_image.png of=binary_file bs=1 skip=181 count=14472

И вуаля! Мы только что выковыряли целый исполняемый файл из безобидной картинки! Вот так сюрприз, а? Иногда самое интересное действительно прячется на виду...

Когда файлы играют в прятки: выслеживаем стеганографию

Знаете, иногда файлы напоминают мне шкатулки с двойным дном. С виду обычный PNG, а внутри... Ладно, не буду забегать вперёд. Вот смотрите: берём наш подозрительный hidden_image.png и запускаем против него binwalk. Эта штука как рентген для файлов, просвечивает насквозь:

# Запускаем цифровую ищейку
$ binwalk build/hidden_image.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 400 x 300, 1-bit colormap, non-interlaced  ← Внешняя обёртка
181           0xB5            ELF, 64-bit LSB shared object, AMD x86-64, version 1 (SYSV)  ← Ага! Вот и хвост торчит!

Видите? Маскировка первоклассная: картинка как картинка. Но binwalk учуял подвох на смещении 181. Прямо как в шпионских фильмах, когда в зубной пломбе важную информацию прячут!

Архивы: цифровые матрёшки

Ох уж эти архивы... Зловреды их обожают больше, чем такса – норы. Запакуют исполняемый файл в семь обёрток, будто луковицу. И каждая со своей хитрой защитой: пароли, битые архивы, поддельные расширения. Надёжный метод? Ещё бы! Но и мы не лыком шиты.

Распаковываем матрёшку

Представьте: скачали вы якобы «документик» secret_data.tar.gz. Чует моё сердце нечистое. Первым делом тычем в него командой file:

# Первый взгляд на "документ"
$ file secret_data.tar.gz
secret_data.tar.gz: gzip compressed data, from Unix, original size modulo 2^32 20480  # Типичная волчья шкура!

Подозрительно уже то, что размер указан «оригинальный по модулю 2^32» – пахнет подлогом. Вскрываем обёртку:

# Заглядываем под капот
$ tar -tf secret_data.tar.gz
bin/network_client  # Ой! А где обещанные документы?

Ну конечно, вместо текстовых файлов какой-то network_client. Вынимаем содержимое (осторожно, руками в перчатках):

# Распаковываем сюрприз
$ tar -xf secret_data.tar.gz

И вот он момент истины. Снова тычем file в то, что вылезло из архива:

$ file bin/network_client
bin/network_client: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked...  # Бинго! Исполняемый файл!

Вот так сюрприз. Под видом безобидного архива нам подсунули бинарник! Кстати, обратите внимание на пометку «stripped» – символы удалены. Значит, кто-то очень старался спрятать следы... Как думаете, что этот «сетевой клиент» делает при запуске? Держу пари, ничего хорошего.

А ведь могли бы запаковать ещё в пять архивов и тогда пришлось бы прыгать как обезьяна между tar, gzip и zip. Но это уже, как говорится, совсем другая история...

Когда буквы притворяются: шифры на службе зловредов

Знаете, что меня бесит больше всего? Когда бинарный файл рядится в невинные буковки. Будто волк в овечьей шкуре: с виду текст, а внутри... эх. Base64 и прочие кодировки – это же любимая маскировка для всякой нечисти! Они превращают исполняемый код в безобидную абракадабру, которую даже антивирусы часто пропускают.

Base64: цифровая личина

Вот вам классика жанра. Берём файлик hello_encoded.txt (название-то какое беззащитное) и тыкаем в него стандартной командой:

# Наивно проверяем тип
$ file hello_encoded.txt
hello_encoded.txt: ASCII text  # Ох уж эти "текстовые файлы"!

Сразу видно подвох. Смотрим первые сто символов:

# Принюхиваемся к содержимому
$ head -c 100 hello_encoded.txt
f0VMRgIBAQMAAAAAAAAAAAIAPgABAAAAMBVAAAAAAABAAAAAAAAAABiaCwAAAAAAAAAAAEAAOAAK
AEAAHgAdAAEAAAAEAAAAAAA

Ба! Да это же классическая Base64-абракадабра. Эти равномерные буковки, знаки равенства в конце... Прямо как отпечаток пальца! Берём декодер и вскрываем обманку:

# Срываем маскировку
$ base64 -d hello_encoded.txt > decoded_file

И вот он момент истины:

$ file decoded_file
decoded_file: ELF 64-bit LSB executable...  # Ага! Нашли червячка в яблоке!

Вот так «текстовый файлик» оказался полноценным ELF-исполняемым файлом. И ведь даже не stripped, наглецы не потрудились скрыть символы! Как думаете, что он делает при запуске? Гадайте...

Конфиги-обманки: файлы с сюрпризом

А вот более изощрённая схема. Представьте: лежит себе config_file.txt, вроде обычный конфиг. Даже комментарии приличные:

# Заглядываем в "безобидный" конфиг
$ head -20 config_file.txt
# System Configuration File
# Generated automatically - DO NOT EDIT
...
# Логирование
log_level=INFO
log_file=/var/log/application.log

# === НАЧАЛО ДАННЫХ КОНФИГУРАЦИИ (НЕ РЕДАКТИРОВАТЬ) ===
f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAQBAAAAAAAAAAgAEAAAAAAABAQAAAAQAAAAAAAAA4AAoAQAAeACsA...

Видите этот внезапный переход к мусору после 18-й строки? Прямо как в плохом триллере, где герой открывает шкаф, а там труп! Хитрецы специально добавляют валидный конфиг сверху, а в хвост – закодированную гадость.

Выковыриваем «сюрприз»:

# Отрезаем "чистую" часть и декодируем хвост
$ tail -n +18 config_file.txt | base64 -d > hidden_config_binary

И, о чудо! Вместо конфига получаем:

$ file hidden_config_binary
hidden_config_binary: ELF 64-bit LSB pie executable...  # Опять эта ELF-нечисть!

Знаете, что самое смешное? Если бы злодеи добавили пароль к архиву поверх base64, то пришлось бы вскрывать как сейф. Но видимо, они рассчитывали, что никто не полезет в «скучный» конфиг... Как же они ошибались!

Когда файлы надевают чужие маски: высший пилотаж обмана

Представьте: вы открываете «документ», а он вам бац, исполняемый файл в зубы! Как так? Всё просто: у каждого формата есть магические числа – типа ДНК файла в первых байтах. Поменяешь их и система клюнет как карп на кукурузу.

Фрагменты правды: криминалистический анализ поврежденного изображения
Практическое задание
В вашем распоряжении загадочный файл corrupted_image.png, который отказывается открываться в стандартных редакторах. Похоже, что кто-то постарался скрыть его истинное содержимое! Сможете ли вы восстановить поврежденный заголовок, найти спрятанный флаг и вернуть изображению его истинный облик?
Бросить вызов

Файлы-оборотни: два в одном

А вот полиглоты – это уже высший пилотаж. Файл, который одновременно и PDF, и ZIP, и ELF – примерно как трансформер, притворяющийся тостером. Выглядит безобидно, а внутри – полноценная программа-зловред. Чёртов кулинарный миксер!

Простейшая маскировка: имя решает всё

Самый топорный, но чертовски работающий метод? Переименовать virus в kitten_photo.jpg или что-то столь же невинное. Люди клюют чаще, чем рыба на спиннинг.

Когда расширения лгут

Вот вам пара перлов из реальной жизни:

# "Конфиг", который явно нервно курит в сторонке  
$ file system.conf  
system.conf: ELF 64-bit LSB pie executable... # Конфиг? Серьёзно? Да это же бинарник!

Объясняю на пальцах: если конфиг весит как слон – это красный флаг размером с пароход. Настоящие конфиги редко превышают пару КБ.

Файлы-невидимки: Linux-специфика

В Unix-системах всё, что начинается с точки – автоматически скрыто. Идеальная маскировка! Посмотрите на эту красоту:

# Ищем невидимок в папке  
$ ls -la | grep "^\."  
drwxr-xr-x  3 user user    4096 Nov 15 10:30 .  
drwxr-xr-x 12 user user    4096 Nov 15 10:29 ..  
-rwxr-xr-x  1 user user   14512 Nov 15 10:30 ..hidden  # Опа! Чёртова точка-два!  
-rw-r--r--  1 user user  762264 Nov 15 10:30 .bashrc_backup  # 700 КБ бэкапа? Серьёзно?  

# Вскрываем обман  
$ file ..hidden  
..hidden: ELF 64-bit LSB pie executable... # Ага, попался, гаденыш!  

Важное примечание: видите этот подозрительный .bashrc_backup на 700 КБ? Настоящий .bashrc – максимум пару КБ! Типичная тактика: спрятать зловреда среди системных файлов, рассчитывая что админ не полезет в «резервную копию».

Знаете, что самое ироничное? Чаще всего такие фокусы вскрывает... обычный file.

Когда файлы не существуют: высший пилотаж маскировки

Представьте зловреда, который даже не записывается на диск! Как призрак. Вроде он есть, но не поймаешь. Такие штуки живут в оперативке или пайпах. Жуть!

Тайные переговоры через FIFO

Вот вам реальный сценарий: именованные каналы в Linux. Будто секретный туннель между процессами:

# Создаём подпольный канал связи  
mkfifo /tmp/secret_chat  # Типа "установили прослушку"  

# Серверная часть (прячем в фоне)  
{  
  echo "Сервер запущен! Шшш..." >&2  # >&2 — это крик в пустоту терминала  
  while true; do  
    # Шпионим за сообщениями  
    message=$(cat /tmp/secret_chat)  # Тихо читаем из канала  
    echo "Клиент шепчет: $message" >&2  
    
    # Шлём ответ как ничего не бывало  
    echo "Сервер отвечает: $(date)" > /tmp/secret_chat  
  done  
} &  # & — знак "работай в тени!"  

# Клиент 
{  
  # Первый выстрел  
  echo "Ты меня слышишь?" > /tmp/secret_chat  
  sleep 0.3  # Искусственная пауза — как в плохом детективе  
  
  # Ловим ответ  
  echo "Сервер огрызнулся: $(cat /tmp/secret_chat)"  
  
  # Провокация  
  echo "Пароль: qwerty123" > /tmp/secret_chat  # Ох, наивный!  
  sleep 0.3  
  echo "Сервер клюнул: $(cat /tmp/secret_chat)"  
  
  # Зачистка следов  
  kill %1 >/dev/null 2>&1  # Бесшумно "убираем" сервер  
  rm -f /tmp/secret_chat  # Стираем улики  
}  

Что здесь происходит:

  1. Создаётся невидимый канал (/tmp/secret_chat). Не файл, а интерфейс обмена.
  2. Сервер висит в фоне, перехватывая всё, что пишут в канал.
  3. Клиент передаёт данные, даже не зная, что его «подслушивают».
  4. Зловред сливает инфу через ответы, маскируясь под системные сообщения.

Фишка в том, что никаких файлов на диске! Всё в памяти. После завершения – ноль улик. Именно так могут сливать данные различные руткиты вроде Diamorphine.

💡 Примечание

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

Финал: вечная игра в кошки-мышки

«Кто сражается с чудовищами, тому следует остерегаться, чтобы самому при этом не стать чудовищем.» Фридрих Ницше

Знаете, борьба со скрытыми угрозами напоминает мне гонку вооружений. Только вместо ракет – техники маскировки. Каждый день:

  • Злоумышленники изобретают новые способы прятать код.
  • Защитники создают детекторы для этих методов.
  • И так по кругу...

Как не стать жертвой?

Главное не надеяться на одну линию обороны. Представьте, что охраняете банк:

  • Многослойность – ставьте решётки, сейфы, сигнализацию и охрану (аналог: сигнатурный анализ + эвристика + песочницы)
  • Автоматизация – сканеры должны рычать на подозрительное, как цепные псы (ручная проверка – путь в ад).
  • Наблюдение за поведением – если «охранник» видит, что «бухгалтер» вдруг полез в ядро системы, это повод для тревоги.
  • Регулярные облавы – проводите аудиты так, будто ищете иголку в стоге сена (новые техники появляются еженедельно!).
💡 Внимание

Важнее всего помнить: мы изучаем эти методы не для создания вирусов, а чтобы понимать врага.