Оновлено 19.05.2026
У статті детально розглядається практичний приклад реалізації методу за допомогою бібліотеки PyCdlib, пояснюється логіка поділу даних і створення прихованих директорій. Показуємо, що навіть застарілі технології можуть стати цікавим полем для експериментів у цифровій стеганографії. Матеріал буде корисним для фахівців з безпеки, дослідників, CTF-ентузіастів та всіх, хто цікавиться прихованим зберіганням інформації.
Під час пошуку матеріалів про стеганографію зустрілася цікава стаття про приховування даних у файлових системах, яка навела на ідею застосувати подібний підхід до оптичних дисків. Сьогодні оптичні носії рідко використовуються в повсякденному житті — більшість віддає перевагу флеш-накопичувачам — проте це не означає, що дискам зовсім немає застосування.
Навіть на застарілому носії можна реалізувати схему приховування секретної інформації всередині структури файлової системи та передати її іншій стороні, не викликаючи підозр. Саме таке завдання й розглядається далі: для кодування вмісту текстового файлу використовується Python-бібліотека, яка дозволяє вбудувати закодовані дані в образ диска.
Перед початком практичної частини варто розглянути кілька технічних деталей і дати визначення тому, що мається на увазі під оптичним диском, щоб краще зрозуміти обмеження й можливості цього підходу.
Оптичний диск ( optical disc ) – збірна назва для носіїв інформації , виконаних у вигляді дисків , читання з яких ведеться за допомогою оптичного ( лазерного ) випромінювання .
Кожен диск у комп’ютерній системі представлений у певному форматі — образі, який містить усю інформацію та структуру носія. Такий образ дає змогу працювати з даними без використання фізичного диска, а також застосовується для архівування інформації на твердих носіях.
Стандартним форматом для оптичних дисків є ISO 9660, хоча існують і інші варіанти. Важливо враховувати, що образ зазвичай містить менше даних, ніж оригінальний диск, адже останній включає службову інформацію, наприклад, елементи захисту від копіювання. У цьому випадку робота здійснюється саме з форматом ISO 9660, який залишається базовим стандартом для більшості оптичних носіїв.
Структура ISO 9660 організована так, щоб забезпечити системне розташування даних на оптичному носії. У її основі лежать два ключові елементи — Boot Record і Primary Volume Descriptor (PVD). Перший відповідає за можливість завантаження з диска: у ньому зазначено, чи є носій завантажувальним, де знаходиться початковий сектор і який код виконується під час старту. Якщо диск не призначений для цього, Boot Record все одно присутній, але містить лише службову інформацію.
Другий компонент, Primary Volume Descriptor, відіграє центральну роль у структурі образу. Він описує основні параметри тому — його ім’я, розмір, розташування каталогів, таблицю файлів, часові позначки та інформацію про файлову систему. Саме завдяки PVD операційна система “бачить” структуру диска, визначає, які каталоги існують і де зберігаються потрібні файли.
Дескриптори розміщуються послідовно, починаючи приблизно з 16-го сектора образу. Їх можна переглянути за допомогою шістнадцяткового редактора, наприклад 010 Editor, де видно всі службові підписи, текстові позначення і байтову структуру ISO. Це дозволяє не лише дослідити внутрішню будову образу, а й зрозуміти, у яких його частинах можливо реалізувати приховане вбудовування даних, не порушуючи цілісності файлової системи.
Boot Record може бути використаний системами, яким необхідно ініціалізувати багато типів даних перед тим, як зробити диск доступним, хоча ISO 9660 не вказує на те, яка інформація в Boot Record або як її взагалі використовувати.
PVD ж – стартова точка в ідентифікації iso9660, виглядає вона так:
Для любителів схем:
Робота буде виконуватися в кореневій директорії образу: у ній створюватимуться потрібні підкаталоги та додаватимуться необхідні файли. Для цього використовується бібліотека pycdlib.
Тепер можна переходити до написання програми:
#робимо всі необхідні операції імпорту import base64 import pycdlib
На початковому етапі необхідно підготувати файли, які будуть інтегровані у структуру створюваного ISO-образу. Процес складається з кількох послідовних кроків.
Спершу із заданих текстових файлів зчитується вміст, який зберігається у змінних. Обсяг тексту може бути будь-яким — від кількох речень до великих фрагментів даних, однак для демонстрації достатньо коротких прикладів. Далі отриманий текст піддається кодуванню за допомогою стандартного алгоритму Base64, що дозволяє перетворити його у формат, придатний для подальшого запису без втрати символів чи структури.
Після кодування результат записується у два нові файли з назвами UP і DOWN. Такий поділ обрано не випадково: у файл UP заноситься перша частина з кожного вихідного документа, а у файл DOWN — друга. Таким чином формується логічна перестановка, що ускладнює пряму ідентифікацію вихідних даних і додає елемент приховування у подальшому розміщенні в образі диска.
with open('/home/ul/stegist1.txt','rb') as stegist1: # відкриваємо файл
for line1 in stegist1.readlines(2):
print(line1) # читаємо перше речення 1 файлу
for line2 in stegist1.readlines(2):
print(line2) # читаємо друге речення 1 файлу
stegist1.close()
enc_line1 = base64.b64encode(line1) # кодуємо наші речення за допомогою base64
enc_line2 = base64.b64encode(line2)
with open('/home/ul/stegist2.txt','rb') as stegist2:
for line3 in stegist2.readlines(2): # читаємо перше речення 2 файлу
print(line3)
for line4 in stegist2.readlines(2): # читаємо друге речення 2 файлу
print(line4)
stegist2.close()
enc_line3 = base64.b64encode(line3) # кодуємо вміст речень
print(enc_line3)
enc_line4 = base64.b64encode(line4)
print(enc_line4)
with open('/home/ul/UP.txt','ab') as up: # У файл UP записуємо закодовані речення
up.write(enc_line1)
up.write(enc_line3)
with open('/home/ul/DOWN.txt','ab') as down: # У файл DOWN записуємо закодовані речення
down.write(enc_line2)
down.write(enc_line4)
Далі використовується бібліотека pycdlib, про яку згадувалося раніше. Вона забезпечує простий і зрозумілий інтерфейс для роботи з ISO-образами. Спочатку створюється об’єкт, який виступає основою майбутнього диска, а потім через нього додаються файли та каталоги у потрібну структуру.
Такий підхід дозволяє гнучко керувати вмістом образу, створювати нові директорії, вставляти підготовлені дані й формувати завершену файлову систему оптичного носія без зайвих складнощів у реалізації.
iso = pycdlib.PyCdlib() # створюємо об'єкт класу PyCdlib
iso.new(rock_ridge='1.09') # використовуємо розширення rockridge (про використовувані в стандарті ISO розширення поговоримо трохи пізніше)
iso.add_directory(iso_path='/A1', rr_name='a1') # додаємо різні папки (якщо вважаємо за потрібне)
iso.add_directory(iso_path='/B1', rr_name='b1')
iso.add_directory(iso_path='/B1/B2', rr_name='b1b2')
iso.add_directory(iso_path='/A1/A2', rr_name='a1a2')
iso.add_file('/home/ul/stegistup.txt', iso_path='/A', rr_name='a') # додаємо наш файл up
iso.add_file('/home/ul/stegistdown.txt', iso_path='/B', rr_name='b') # додаємо наш файл down
iso.write('papastegisto.iso') # створюємо образ ISO (записуємо)
Текст успішно записався.
Варто звернути увагу на важливу особливість роботи з бібліотекою pycdlib: шлях, який задається під час створення об’єктів у структурі ISO, може відповідати або файлу, або директорії — але не одночасно. Наприклад, якщо спочатку створити каталог із шляхом /A, а потім спробувати створити файл із тим самим шляхом /A, програма повідомить про помилку.
Це пов’язано з тим, що система чітко розрізняє тип об’єкта у файловій структурі, і шлях до каталогу не може одночасно вказувати на файл. Інакше кажучи, створення файлу всередині папки /A потребує повного шляху на кшталт /A/filename.txt, а не просто /A.
Є 2 основних розширення для файлової системи iso, це: RockRidge та Joilet .
Це розширення файлової системи ISO 9660, розроблене для зберігання файлових атрибутів, що використовуються в операційних системах POSIX (тобто Unix-сумісних).
Розширення Rock Ridge записуються поверх файлової системи ISO 9660 так, що оптичний диск Rock Ridge може бути прочитаний програмним забезпеченням, розрахованим на роботу з ISO 9660.
Rock Ridge може зберігати наступну додаткову інформацію про вміст диска:
довгі імена файлів (до 255 символів);
менше обмежень використання символів в іменах файлів;
структуру каталогів довільної вкладеності.
для кожного файлу записуються атрибути:
права доступу до файлу, у тому числі поля uid та gid;
кількість жорстких посилань на файл;
часи створення, модифікації, доступу, зміни атрибутів та ін.
підтримуються спеціальні файли:
розріджені файли;
символьні посилання;
файли пристроїв;
файли сокетів;
FIFO-файли.
Ці дані записуються у спеціальні каталоги, імена яких зазвичай ховаються.
Joliet — це розширення файлової системи ISO 9660, створене для усунення обмежень на довжину та формат імен файлів, які існували в базовій специфікації. Його розробила компанія Microsoft, і воно підтримується всіма версіями Windows, починаючи з Windows 95 та Windows NT 4.0. Починаючи з 1995 року, Joliet за замовчуванням використовується на більшості CD-ROM-дисків із даними.
Розширення вводить додатковий набір імен файлів, довжина яких може сягати 64 символів Unicode, що зберігаються у кодуванні UCS-2. Для цього використовується окремий заголовок — Supplementary Volume Descriptor (SVD). Такий підхід забезпечує зворотну сумісність, оскільки звичайні ISO 9660-програми просто ігнорують цей додатковий дескриптор, продовжуючи працювати зі стандартними назвами.
Joliet підтримується більшістю сучасних операційних систем, серед яких Windows, Linux, macOS та FreeBSD. Це дозволяє обмінюватися файлами між платформами без втрати коректного відображення імен, навіть коли використовуються нелатинські алфавіти — арабський, японський чи кирилиця, що було неможливо у звичайному ISO 9660.
Окрім Joliet, існує ще одне менш відоме розширення — Romeo. Його також розробила Microsoft для Windows 95 як спробу подолати частину обмежень ISO 9660. Проте через слабку документованість і відсутність широкої підтримки це розширення майже не використовується і фактично зникло з практики.
Код для кодування інформації з файлу і приміщення файлів з закодованою інформацією в iso виглядає так:
# виконуємо всі необхідні операції імпорту
import base64
import pycdlib
# підготовлюємо наш вміст
with open('/home/ul/stegist1.txt', 'rb') as stegist1: # відкриваємо файл
for line1 in stegist1.readlines(2):
print(line1) # читаємо вміст
for line2 in stegist1.readlines(2):
print(line2) # читаємо вміст
enc_line1 = base64.b64encode(line1)
print(enc_line1)
enc_line2 = base64.b64encode(line2)
print(enc_line2)
with open('/home/ul/stegist2.txt', 'rb') as stegist2: # відкриваємо файл
for line3 in stegist2.readlines(2): # читаємо вміст
print(line3)
for line4 in stegist2.readlines(2): # читаємо вміст
print(line4)
enc_line3 = base64.b64encode(line3) # кодуємо вміст
print(enc_line3)
enc_line4 = base64.b64encode(line4)
print(enc_line4)
with open('/home/ul/UP.txt', 'ab') as up: # У файл UP записуємо закодовані дані
up.write(enc_line1)
up.write(enc_line3)
with open('/home/ul/DOWN.txt', 'ab') as down: # У файл DOWN записуємо закодовані дані
down.write(enc_line2)
down.write(enc_line4)
# заносимо все в ISO
iso = pycdlib.PyCdlib()
iso.new(rock_ridge='1.09')
iso.add_directory(iso_path='/A1', rr_name='a1')
iso.add_directory(iso_path='/B1', rr_name='b1')
iso.add_directory(iso_path='/B1/B2', rr_name='b1b2')
iso.add_directory(iso_path='/A1/A2', rr_name='a1a2')
iso.add_file('/home/ul/stegistup.txt', iso_path='/A', rr_name='a')
iso.add_file('/home/ul/stegistdown.txt', iso_path='/B', rr_name='b')
iso.write('papastegisto.iso')
На завершальному етапі створений ISO-образ необхідно записати на фізичний носій. Для цього використовуються різні типи оптичних дисків — CD-ROM, CD-R та CD-RW. Кожен із них має свої особливості: CD-ROM призначений виключно для читання інформації, тобто дані на ньому вже записані під час виробництва і змінити їх неможливо. CD-R дозволяє одноразовий запис — після фіксації даних диск стає лише для читання. CD-RW, навпаки, підтримує багаторазовий перезапис, що робить його зручним для тестів або тимчасових проєктів.
Щодо DVD, то їхня головна відмінність полягає у збільшеному обсязі пам’яті. Стандартний DVD-диск може вмістити близько 4,7 ГБ інформації, що значно перевищує ємність CD, яка становить приблизно 650–700 МБ. Деякі формати DVD, наприклад двошарові, дозволяють записувати до 13–17 ГБ даних.
Після виконання запису програма завершує процес без помилок, а готовий диск успішно зчитується системою, підтверджуючи, що створений образ було правильно згенеровано й записано.
Після завершення запису створений диск можна безперешкодно передати будь-кому із запланованих отримувачів. Завдяки прихованій структурі всередині файлової системи передача виглядає цілком звичайно — як передавання звичайного диска з даними. Водночас закодована інформація залишається непомітною для сторонніх користувачів і може бути відновлена лише тими, хто знає точний порядок зчитування та декодування прихованих файлів.