Вступ
Безпека програмного забезпечення в широкому змісті є властивістю даного програмного забезпечення функціонувати без прояву різноманітних негативних наслідків для конкретної комп'ютерної системи. Під рівнем безпеки програмного забезпечення (ПЗ) розуміється ймовірність того, що при заданих умовах у процесі його експлуатації буде отриманий функціонально придатний результат. Причини, що призводять до функціонально непридатного результату, можуть бути різними: збої комп'ютерних систем, помилки програмістів й операторів, дефекти в програмах. При цьому дефекти прийнято розглядати двох типів: навмисні й ненавмисні. Перші є, як правило, результатом злочинних дій, другі - помилкових дій людини.
При дослідженні проблем захисту ПЗ від навмисних дефектів неминуча постановка наступних питань:
хто потенційно може здійснити практичне впровадження програмних дефектів деструктивного впливу в програмний код?
які можливі мотиви дій суб'єкта, що здійснює розробку таких дефектів?
як можна ідентифікувати наявність програмного дефекту?
як можна відрізнити навмисний програмний дефект від програмної помилки?
які найбільш імовірні наслідки активізації деструктивних програмних засобів при експлуатації комп'ютерних систем?
При відповіді на перше питання слід зазначити, що це - безпосередні розроблювачі алгоритмів і програм для комп'ютерних систем. Вони добре знайомі з технологією розробки програмних засобів, мають досвід розробки алгоритмів і програм для конкретних прикладних систем і уявляють особливості експлуатації й цільового застосування розроблювальної комп'ютерної системи (КС). Крім того, при експлуатації програмних комплексів можливий наступний алгоритм внесення програмного дефекту: дизасемблювання програмного коду, одержання вихідного тексту, привнесення в нього деструктивної програми, повторна компіляція, корегування ідентифікаційних ознак програми (у зв'язку з необхідністю одержання програми «схожої» на оригінал). Таким чином, маніпуляції подібного роду можуть зробити сторонні висококласні програмісти, що мають досвід розробки й налагодження програм на асемблерному рівні.
Як припущення при відповіді на друге питання слід зазначити, що алгоритмічні й програмні закладки можуть бути реалізовані в складі програмного компонента внаслідок наступних факторів:
у результаті ініціативних злочинних дій безпосередніх розроблювачів алгоритмів і програм;
у результаті штатної діяльності спеціальних служб й організацій, а також окремих зловмисників;
у результаті застосування інструментальних засобів проектування ПО, що несуть шкідливу властивість автоматичної генерації деструктивних програмних засобів.
Для опису мотивів злочинних дій при розробці програмних компонентів необхідно створити психологічний «портрет» зловмисника, що вимагає проведення спеціальних досліджень психологів і кримінологів в області психології програмування. Однак деякі мотиви очевидні вже зараз:
нестійкий психологічний стан алгоритмістів і програмістів, обумовлений складністю взаємин у колективі, перспективою втратити роботу, різким зниженням рівня добробуту, відсутністю впевненості в завтрашньому дні й т.п., у результаті чого може виникнути, а згодом бути реалізована, думка помсти;
незадоволеність особистих амбіцій безпосереднього розроблювача алгоритму або програми, що вважає себе невизнаним талантом, у результаті чого може з'явитися прагнення довести й показати кому-небудь (у тому числі й самому собі) таким чином свої високі інтелектуальні можливості;
перспектива виїзду за кордон на постійне місце проживання (перспектива переходу в іншу організацію) з надією одержати винагороду за відомості про програмну закладку й механізм її активізації, а також можливість таким способом заблокувати застосування певного класу програмних засобів по обраному місцю проживання (місцю роботи);
потенційна можливість одержати винагороду за усунення виниклої при випробуваннях або експлуатації системи «програмної відмови» і т.п.
Крім того, необхідно мати на увазі, що в конструюванні шкідливої програми, так чи інакше, є присутнім притягальний творчий початок, що саме по собі може стати метою. При цьому сам «творець» може слабко представляти всі можливі результати й наслідки застосування своєї «конструкції», або взагалі не замислюватися про їх.
Таким чином, правомірно стверджувати, що шкідливі програми, на відміну від широко застосовуваних електронних закладок, є більш витонченими об'єктами, що володіють більшою скритністю й ефективністю застосування.
Дотепер ми розглядали захист програмного забезпечення від руйнуючих програмних засобів. Однак застосування зловмисником тільки цих деструктивних засобів, не вичерпує всього кола проблем, пов'язаних із проблематикою забезпечення безпеки програм. Існує широкий спектр загроз, віднесених до несанкціонованого копіювання, незаконному одержанню, поширенню й використанню програмних продуктів.
«Програмне піратство» є, у зв'язку з великими матеріальними втратами, однією з основних проблем для фірм-розробників, так чи інакше, пов'язаних зі створенням і реалізацією програмного забезпечення. Програмні пірати купують або «беруть на прокат» необхідне програмне забезпечення й, якщо в ньому немає відповідного захисту, вони можуть скопіювати програми й використати їх без відповідної оплати (реєстрації, підтвердження ліцензійних угод, авторських прав і т.п.) за своїм розсудом. Таким чином, питання захисту ПЗ від несанкціонованого копіювання, поширення й використання є одним з найбільш важливих у комп'ютерній практиці. Всі відомі методи захисту ПЗ від несанкціонованого копіювання й поширення відносяться до організаційно-правових й інженерно-технічних методів. При рішенні зазначених завдань захисту сьогодні практично повністю відсутні теоретичні підстави. Зокрема, немає чіткого визначення проблеми й визначення того, що повинно бути її задовільним рішенням.
Завдання захисту програм від несанкціонованого копіювання, полягає в забезпеченні неможливості знаходження ефективного методу створення копій програм, у той час як завдання захисту програм від несанкціонованого поширення полягає в забезпеченні того факту, що тільки виробник ПЗ зміг би довести в суді, що саме він розробив це ПЗ.
При відповіді на питання про несанкціоноване копіювання програм необхідно відповісти на наступні питання:
що може зробити зловмисник («пірат») у ході спроб вивчення програми?
що є істотними знаннями про програму?
що є специфікацією програми?
Для того щоб відповісти на вищезгадані питання необхідно розглядати найбільш зловмисне поводження зловмисника. Тобто необхідно розглядати сценарій найгіршого випадку, коли передбачається, що зловмисник може виконувати перетворену програму на довільних даних за своїм розсудом і може модифікувати дані, що циркулюють в обчислювальній системі, довільним чином.
Основні поняття щодо захисту програмного забезпечення
Програмне забезпечення є однією з базових складових сучасних ІКС.
Розглянемо застосування до ПЗ моделі порушника, яка визначена в НД ТЗІ 1.1-002-99. Відповідно до рівнів можливостей, що надаються потенційним порушникам штатними засобами КС, можна виділити чотири групи умов щодо порушення безпеки ПЗ:
перший рівень визначає найнижчий рівень можливостей впливу на ПЗ - можливість взаємодії з ПЗ тільки через інтерфейси, що надаються ним (наприклад — доступ до вебсерверу, програмні інтерфейси, інтерфейси користувача);
другий рівень визначається можливістю дослідження ПЗ в рамках повноважень (прав відповідно до авторизації), що надані користувачу, в тому числі створення і запуску необхідних додаткових програм;
третій рівень визначається створенням користувачем всіх необхідних умов для дослідження ПЗ, в тому числі шляхом впливу на базове програмне забезпечення системи, на склад і конфігурацію її устаткування;
четвертий рівень визначається всім обсягом можливостей осіб, що здійснюють проектування, реалізацію і модернізацію ПЗ, аж до включення до складу ПЗ власних програм з новими функціями обробки інформації.
Відповідно до такої класифікації можливими типовими ситуаціями, що потребують захисту ПЗ є:
злам ПЗ засобами АРМ, які надані користувачу;
злам ПЗ наявними та додатковими засобами АРМ;
створення найбільш зручного програмного (або програмно-апаратного) середовища для зламу ПЗ;
внесення в ПЗ таких властивостей, які сприяють зниженню його рівня захищеності.
Під час створення захищених автоматизованих систем, як правило розглядаються порушники першого та другого рівнів (або організаційно-технічними мірами створюють умови існування тільки таких порушників). Оскільки для зламу програмного забезпечення порушник прагне створити найбільш вигідні умови функціонування програми, як правило він може бути віднесений до порушників третього, в окремих випадках четвертого рівня.
Визначена вище різниця в умовах функціонування програмних засобів в складі захищених автоматизованих систем (в тому числі програмної складової їх КЗЗ) та окремих програмних засобів відображається в підходах до створення їх систем захисту, особливостях вибору методів та механізмів захисту.
Відмітимо також відмінність захисту ПЗ від захисту АС: З одного боку власник АС є зацікавленим в захисті її ресурсів, в тому числі і її ПЗ. З іншої точки зору, якщо використання нелегального ("зламаного") ПЗ дозволяє надавати АС додаткову функціональність і не призводить до появи суттєвих ризиків її функціонування, власник не завжди може надавати необхідної уваги всім аспектам захисту (в тому числі забезпеченню "ліцензійної чистоти") ПЗ.
Тому завдання захисту ПЗ доцільно розглядати в двох основних аспектах:
— захист програмної складової даної автоматизованої системи;
— захист окремої програми (прав, що пов'язані з нею) як об'єкту продаж або розповсюдження.
В рамках другого аспекту до основних цілей порушення безпеки ПЗ можна віднести:
незаконне використання ПЗ (всього ПЗ або його частини);
незаконне використання ідей, що реалізовані в ПЗ (алгоритмів, програмних інтерфейсів, інтерфейсів взаємодії з користувачем, інших технічних рішень);
незаконний продаж ПЗ;
незаконне виготовлення копій ПЗ.
Досягнення зазначених вище цілей пов'язане з реалізацією стосовно ПЗ наступних основних загроз:
несанкціоноване виконання програми або частини програмного коду;
несанкціонований доступ до програмного коду, в т.ч. з метою вивчення реалізованих в ньому алгоритмів, зміни або підміни програмного коду;
несанкціоноване копіювання програм.
Протидія визначеним вище загрозам безпеці ПЗ здійснюється з використанням таких груп методів захисту ПЗ:
1) технічні (в тому числі голографічні);
організаційні(наприклад порядок постачання та використання);
правові (наприклад, шляхом визначення законів, кодексів, інструкцій).
Наприклад до групи технічних методів захисту ПЗ можуть бути віднесені:
захист ПЗ засобами ОС;
перевірка і забезпечення цілісності ПЗ;
забезпечення стійкості до цілеспрямованих і випадкових дестабілізуючих впливів;
ідентифікація користувача та/або середовища виконання;
захист від відновлення та/або вивчення вихідного програмного коду та алгоритмів функціонування ПЗ.
2. Методи захисту ПЗ від несанкціонованого доступу до програмного коду
2.1 Класифікація засобів дослідження програмного коду
Всі засоби дослідження ПЗ можна розбити на 2 класи: статичні і динамічні. Перші оперують вихідним кодом програми як даними і будують її алгоритм без виконання, другі ж вивчають програму, інтерпретуючи її в реальному або віртуальному обчислювальному середовищі. Звідси випливає, що перші є більш універсальними в тому сенсі, що теоретично можуть отримати алгоритм всієї програми, в тому числі і тих блоків, які ніколи не отримають управління. Динамічні засоби можуть будувати алгоритм програми тільки на підставі конкретної її траси, отриманої при певних вхідних даних. Тому завдання отримання повного алгоритму програми в цьому випадку еквівалентно побудові вичерпного набору текстів для підтвердження правильності програми, що практично неможливо, і взагалі при динамічному дослідженні можна говорити тільки про побудову деякої частини алгоритму.
Два найбільш відомих типу програм, призначених для дослідження ПЗ, як раз і належать до різних класів: це відладчик (динамічний засіб) і дизасемблер (засіб статистичного дослідження). Якщо перший широко застосовується користувачем для налагодження власних програм і завдання побудови алгоритму для нього вторинні і реалізуються самим користувачем, то другий призначений виключно для їх вирішення і формує на виході асемблерний текст алгоритму.
Крім цих двох основних інструментів дослідження, можна використовувати:
«Діскомпілятори», програми, які генерують з виконуваного коду програму на мові високого рівня;
«Трасировщики», спочатку запам'ятовують кожну інструкцію, що проходить через процесор, а потім переводять набір інструкцій у форму, зручну для статичного дослідження, автоматично виділяючи цикли, підпрограми тощо;
«Слідкуючі системи», запам'ятовують і аналізують трасу вже не інструкції, а інших характеристик, наприклад викликаних програмою переривань.
2.2 Методи захисту ПЗ від дослідження
Для захисту програм від дослідження необхідно застосовувати методи захисту від дослідження файлу з виконуваним кодом програми, що зберігається на зовнішньому носії, а також методи захисту виконуваного коду, який завантажується в оперативну пам'ять для виконання цієї програми.
У першому випадку захист може бути заснований на шифруванні конфіденційної частини програми, а в другому - на блокуванні доступу до виконуваного коду програми в оперативній пам'яті з боку відгадчика. Крім того, перед завершенням роботи програми повинен обнулятися весь її код в оперативній пам'яті. Це запобігає можливості несанкціонованого копіювання з оперативної пам'яті дешифрованого виконуваного коду після виконання програми.
Таким чином, захищувана від дослідження програма повинна включати наступні компоненти:
ініціалізатор;
зашифровану конфіденційну частину;
деструктор (деіцініалізатор).
Ініціалізатор повинен забезпечувати виконання таких функцій:
збереження параметрів операційного середовища функціонування (векторів переривань, вмісту регістрів процесора і т.д.);
заборона всіх внутрішніх і зовнішніх переривань, обробка яких не може бути записана в програмі;
завантаження в оперативну пам'ять і дешифрування коду конфіденційної частини програми;
передача керування конфіденційної частини програми.
Конфіденційна частина програми призначена для виконання основних цільових функцій програми і захищається шифруванням для попередження внесення до неї програмної закладки.
Деструктор після виконання конфіденційної частини програми повинен виконати наступні дії:
обнулення конфіденційного коду програми в оперативній пам'яті;
відновлення параметрів операційної системи (векторів переривань, вмісту регістрів процесора і т.д.), які були встановлені до заборони неконтрольованих переривань;
виконання операцій, які неможливо було виконати при забороні неконтрольованих переривань;
звільнення всіх незадіяних ресурсів комп'ютера і завершення роботи програми.
Для більшої надійності ініціалізатор може бути частково зашифрованим, по мірі виконання може дешифрувати сам себе. Дешифруватися по мірі виконання може і конфіденційна частина програми. Таке дешифрування називається динамічним дешифруванням виконуваного коду. У цьому випадку чергові ділянки програм перед безпосереднім виконанням розшифровуються, а після виконання відразу знищуються.
Для підвищення ефективності захисту програм від дослідження необхідно внесення в програму додаткових функцій безпеки, спрямованих на захист від трасування. До таких функцій можна віднести:
періодичний підрахунок контрольної суми області оперативної пам'яті, займаної вихідним кодом; порівняння поточної контрольної суми з попередньо сформованою еталонною і прийняття необхідних заходів у випадку розбіжності;
перевірку кількості займаної програмою оперативної пам'яті;
порівняння з обсягом, до якого програма адаптована, і прийняття необхідних заходів у разі невідповідності;
контроль часу виконання окремих частин програми;
блокування клавіатури на час відпрацювання особливо критичних алгоритмів.
Для захисту програм від дослідження за допомогою дизассемблерів можна використовувати і такий спосіб, як ускладнення структури самої програми з метою заплутування зловмисника, який дізассемблює цю програму. Наприклад, можна використовувати різні сегменти адреси для звернення до однієї і тієї ж області пам'яті. У цьому випадку зловмисникові буде важко здогадатися, що насправді програма працює з однією і тією ж областю пам'яті.
2.3 Способи захисту ПЗ від дослідження
Способи захисту від дослідження можна розділити на чотири класи.
1. Спосіб, сутність якого полягає у наданні впливу на процес функціонування налагоджувальному кошти через спільні програмні або апаратні ресурси. В даному випадку найбільш відомі:
використання апаратних особливостей мікропроцесора (особливості черговості вибірки команд, особливості виконання команд і т.д.);
використання загального програмного ресурсу (наприклад, загального стека) і руйнування даних або коду відладчика, що належать загальному ресурсу, або перевірка використання загального ресурсу тільки захищуваною програмою (наприклад, визначення стека в області, критичній для виконання захищуваної програми);
переадресація обробників налагоджувальних подій (переривань) від налагоджувальних засобів до захищуваної програми.
Виділення трьох груп захисних дій у даному класі не випадково, оскільки об'єктивно існують загальні апаратні ресурси відладчика, і захищувана програма у випадку однопроцесорного обчислювача виконуються на одному й тому ж процесорі), спільні програмні ресурси (оскільки і відладчик, і захищувана програма виконуються в одному і тому ж операційному середовищі), нарешті, відладчик створює специфічні ресурси, які є важливими для його власної роботи (наприклад адресує собі налагоджувальні переривання).
2. Вплив на роботу налагоджувальних засобів шляхом використання особливостей його апаратного або програмного середовища. Наприклад:
переміщення фрагментів коду або даних за допомогою контролера прямого доступу до пам'яті;
впливу на процес регенерації оперативної пам'яті (на деякій ділянці коду регенерація пам'яті відключається, а потім знову включається, - при нормальній роботі ніяких змін немає, при повільному виконанні програми відладчиком вона «зависає»);
переходу мікропроцесора в захищений режим.
3. Вплив на роботу відладчика через органи управління або / та пристрої відображення інформації.
Видавана налагоджувальними засобами інформація аналізується людиною. Отже, додатковий спосіб захисту від налагодження це порушення процесу спілкування оператора і відладчика, а саме спотворення або блокування вводу з клавіатури і виводу на термінал інформації.
4. Використання принципових особливостей роботи керованого людиною відладчика. У даному випадку захист від дослідження полягає в нав'язуванні для аналізу надмірно великого обсягу коду (як правило, за рахунок циклічного виконання деякої його ділянки).
Розглянемо даний метод докладніше. Нехай є деяке повноциклове перетворення з N станів t: Т = t 1, t 2 ,..., t N (Наприклад, звичайний двійковий лічильник або, рекуррента). Значення N вибирається не надто великим. Наприклад, для k-бітового лічильника N = 2 k. Ділянка коду, що захищається від вивчення, динамічно перетворюється (шифрується) з використанням криптографічно стійкого алгоритму на ключі t, який вибирається випадково і рівноймовірно з безлічі станів Т.
Робота механізму захисту від дослідження виглядає таким чином. Програма повноциклового перетворення починає роботу з детермінованого або випадкового значення. На встановленому значенні проводиться дешифрування зашифрованої ділянки коду. Правильність дешифрування перевіряється підрахунком значення хеш-коду розшифрованої ділянки програмного коду з використанням елементів, пов'язаних з налагодженням (стек, налагоджувальні переривання та ін.) Хеш-функція повинна з імовірністю 1 визначати правильність дешифрування (для цього значення хеш-коду повинно бути не менше k).
Припустимо, що повноциклове перетворення стартує з першого значення. Тоді при нормальному виконанні програми (швидкість роботи висока) буде здійснено i циклів алгоритму, після чого захищувана ділянка буде коректно виконаний. При роботі відладчика, керованого людиною, швидкість виконання програми на кілька порядків нижчі, тому для досягнення необхідного значення 1 буде витрачено значний час.
Для чисельної оцінки даного методу введемо наступні значення. Припустимо, що i в середньому дорівнює N / 2. Нехай w 0 - час виконання циклу алгоритму (встановлення поточного значення, дешифрування, перевірка правильності дешифрування) у штатному режимі функціонування (без налагодження); w 1 - час виконання того ж циклу в режимі налагодження; z-граничний час затримки при штатній роботі захищеної програми. Тоді N = z / w 0. Витрати часу зловмисника обчислюються середньою величиною Т зл = Nw 1 / 2. Для приблизних розрахунків w 1 / w 0 »10000.
У ряді способів захисту від налагодження ідентифікація відладчика і направлення його по хибному шляху відбуваються одночасно, в одному і тому ж фрагменті коду (так, при визначенні стека в області коду захищуваної програми при роботі відладчика, що використовує той же стек, код програми буде зруйновано). В інших випадках помилковий шлях в роботі програми формується штучно. Часто для цього використовують динамічне перетворення програми (шифрування) під час її виконання.
Спосіб динамічного перетворення полягає в наступному: спочатку в оперативну пам'ять завантажується фрагмент коду, зміст частини команд якого не відповідає тим командам, які цей фрагмент у дійсності виконує; потім цей фрагмент по деякому закону перетворюється, перетворюючись на виконавчі команди, які потім і виконуються.
Перетворення коду програми під час її виконання може переслідувати три основні мети:
протидія файловому дизасемблюванню програми;
протидія роботі відладчика;
протидія зчитуванню коду програми у файл з оперативної пам'яті.
Перелічимо основні способи організації перетворення коду програми:
Заміщення фрагмента коду функцією від команди, що знаходиться на даному місці, і деяких даних.
Визначення стека в області коду і переміщення фрагментів коду з використанням стекових команд.
Перетворення коду в залежності від вмісту попереднього фрагмента коду або деяких умов, отриманих при роботі попереднього фрагмента.
Перетворення коду в залежності від зовнішньої до програми інформації.
Перетворення коду, поєднане з діями, характерними для роботи налагоджувальних засобів.
Перший спосіб полягає в тому, що за деякою адресою в коді програми розташовується, наприклад, побітова різниця між реальними командами програми і деякою хаотичної інформацією, яка розташовується в області даних. Безпосередньо перед виконанням даної ділянки програми відбувається підсумовування хаотичної інформації з вмістом області коду і в ній утворюються реальні команди.
Другий спосіб полягає у переміщенні фрагментів коду програми у визначене місце або накладення їх на вже виконані команди за допомогою стекових операцій.
Третій спосіб служить для захисту від модифікацій коду програми та визначення точок зупину у програмі. Він полягає в тому, що перетворення наступного фрагмента коду відбувається на основі функції, істотно залежить від кожного байта або слова попереднього фрагмента або декількох фрагментів коду програми. Таку функцію називають контрольною сумою ділянки коду програми. Особливості даного способу є те, що процес перетворення має відповідно залежати від порахованої контрольної суми (підрахованого значення хеш-коду) і повинен містити в явному вигляді операції порівняння.
Четвертий спосіб полягає в перетворенні коду програми на основі деякої зовнішньої інформації, наприклад зчитаної з ключовою дискети некопіюємої мітки, машинно-залежної інформації або ключа користувача. Це дозволить виключити аналіз програми, що не має ключового носія або розміщеної на іншому комп'ютері, де машино-залежна інформація інша.
П'ятий спосіб полягає в тому, що замість адрес налагоджувальних переривань подаються посилання на процедуру перетворення коду програми. При цьому або блокується робота відладчика, або невірно перетвориться в виконавчі команди код програми.
Важливим завданням захисту програм від досліджень є захист від трасування програми по заданій події (свого роду вибіркове дослідження). В якості захисту від трасування по заданій події (переривання) можна виділити три основних способи.
Пасивний захист - заборона роботи при перевизначенні обробників подій щодо заздалегідь відомої адреси.
Активний захист першого типу - замикання ланцюгів обробки подій минаючи програми трасування.
Активний захист другого типу - програмування функцій, виконуваних обробниками подій, іншими способами, не пов'язаними викликом штатних обробників або обробників подій, які на поточний момент не трасуються.
Наприклад, для захисту від трасування за дисковим перериваннях для ОС MS DOS при читанні некопіюємої мітки з дискети або вінчестера можна використовувати наступні прийоми:
робота з ключовою міткою шляхом прямого програмування контролера гнучкого диска (активний захист другого типу);
визначення одного з невикористовуваних переривань для роботи з диском (активний захист першого типу);
прямий виклик відповідних функцій в ПЗУ (BIOS) після відновлення різними способами їх фізичної адреси (активний захист першого типу);
визначення факту перевизначення адреси переривання на іншу програму і невиконання в цьому випадку дискових операцій (пасивний захист).
При операціях з жорстким диском, як правило, використовується переривання int 13h. Для запобігання трасування програми по заданому переривання (у даному випадку переривання int 13h) можна також використовувати зазначені вище способи, а саме:
перевизначення вихідного переривання в BIOS на невикористовуваний вектор переривання;
прямий виклик функцій BIOS.
При небезпеці трасування щодо подій операційного середовища можуть бути виділені наступні дії програм:
визначення факту заміни обробників подій на власні функції (зокрема, для захисту від відладчика);
файлові операції, пов'язані зі зчитуванням різних лічильників або паролів, обчислення контрольних сум і значень хеш-кодів;
файлові операції, пов'язані зі зчитуванням заголовків та іншої істотно важливої інформації у виконуваних файлах або завантажуваних бібліотеках.
2.4 Способи вбудовування захисних механізмів в програмне забезпечення
Вбудовування захисних механізмів можна виконати наступними основними способами:
вставкою фрагмента перевірочного коду у виконуваний файл;
перетворенням виконуваного файлу до невиконуваного вигляду (шифрування, архівація з невідомим параметром і т.д.) і застосуванням для завантаження не засобів операційного середовища, а деякої програми, в тілі якої і здійснюються необхідні перевірки;
вставкою перевірочного механізму у вихідний код на етапі розробки та налагодження програмного продукту;
комбінуванням зазначених методів.
Стосовно до конкретної реалізації захисних механізмів для конкретної обчислювальної архітектури можна говорити про захисний фрагмент в виконуваному або вихідному коді. До процесу і результату вбудовування захисних механізмів можна висунути наступні вимоги:
висока трудомісткість виявлення захисного фрагмента при статичному дослідженні (особливо актуальна при вбудовуванні в вихідний код програмного продукту);
висока трудомісткість виявлення захисного фрагмента при динамічному дослідженні (при налагодженні і трасування по зовнішніх подій);
висока трудомісткість обходу чи редукування захисного файлу.
Можливість вбудовування захисних фрагментів у виконуваний код обумовлена типовою архітектурою виконуваних модулів різних операційних середовищ, що містять, як правило, адресу точки входу в виконуваний модуль. У цьому випадку додавання захисного фрагмента відбувається наступним чином. Захисний фрагмент додається до початку або кінця виконуваного файлу, точка входу коригується таким чином, щоб при завантаженні управління передалося додатковому захисному фрагменту, а в складі захисного фрагмента передбачається процедура повернення до оригінальної точки входу. Досить часто оригінальний виконуваний файл піддається перетворенню. У цьому випадку перед поверненням управління оригінальній точці входу проводиться перетворення образу оперативної пам'яті завантаженого виконуваного файлу до вихідного виду.
У разі доповнення динамічних бібліотек можлива корекція зазначеним чином окремих функцій.
Істотним недоліком розглянутого методу є його легке виявлення і у випадку відсутності перетворення оригінальним коду виконуваного файлу - легка можливість обходу захисного фрагмента шляхом відновлення оригінальної точки входу.
2.5 Обфускація програмного коду
Обфускація, або заплутування коду - приведення вихідного тексту або виконуваного коду програми до виду, що зберігає її функціональність, але ускладнює аналіз, розуміння алгоритмів роботи та модифікацію при декомпіляції. «Заплутування» коду може здійснюватися на рівні алгоритму, на рівні початкового тексту, асемблерного тексту. Для створення заплутаного ассемблерного тексту можуть використовуватися спеціалізовані компілятори, що використовують неочевидні або недокументовані можливості середовища виконання програми. Існують також спеціальні програми, що проводять обфускацію, звані обфускаторами.
2.5.1 Символьна обфускація
Першою і, мабуть, найбільш легко виконуваною обфускацією є символьна обфускація. Обфускатори, які використовують символьну обфускацію називаються обфускаторамі першого покоління.
Символьна обфускація включає в себе обфускацію імен класів, назв методів, параметрів і т. п. Дані обфускатори застосовують такі методи:
Перейменування методів, змінних і т.д. в набір безглуздих символів Наприклад: метод класу GetPassword(), після обфускаціі буде мати ім'я KJHS92DSLKaf(). Проте існує одна проблема - багато декомпіляторів, зустрічаючи на своєму шляху подібного роду імена замінюють їх на більш читабельні (method_1, method_2), тим самим зводячи всю роботу обфускатора нанівець.
Перейменуванняв коротші імена. Проходячи по всіх класах, методах, параметрах, обфускатори замінюють імена на їх порядкові номери. Наприклад, метод - GetConnectionString(), після обфускаціїназивається 0(). Подібні обфускатори можна також використовувати як оптимізуючі компілятори. Також подібне рішення добре тим, що існує ймовірність того, що одне і те ж ім'я буде використано для іменування класу, методів класу (наприклад відрізняються тільки типом повертається значення). Це дозволить також заблокувати роботу окремих дизассемблерів.
Використання для імен змінних нечитабельних символів. Частина обфускаторов вставляють в імена нечитабельні символи, наприклад символи японської мови. Не всі декомпілятори адекватно обробляють такі символи. Деякі замінюють імена з такими символами на більш зрозумілі, деякі проставляють замість незрозумілих символів їх код, деякі просто відмовляються працювати з даними символами.
Використання ключових слів мов програмування. Цей вид символьної обфускаціі дозволить захиститися від самих примітивних декомпіляторов, які, побачивши в якості імені зарезервоване слово вважають, що файл не правильний і відмовляються з ним працювати.
Використання імен, які змінюють зміст. Цей тип обфускації використовує психологічний чинник. Припустимо, був клас SecurityInformation з методом GetInformation, а став Car, з методом Wash. Звичайно, це може заплутати голову недосвідченому зломщикові, але процесу декомпіляції ніяк не зашкодить.
2.5.2 Обфускація даних
До більш складних обфускаторів, що дають більше гарантій, що Ваш код не зможуть зрозуміти зловмисники, відносяться обфускатори другого порядку. Вони застосовують методи обфускаціі даних і графа потоку керування.
Обфускація даних складається з таких методів, як:
Зміна місця розташування даних - об'єднання декількох сутностей в одну або навпаки поділ однієї сутності на кілька. Наприклад: два рядки можуть бути об'єднані в масив рядків.
Кодуючі перетворення. Деякі дані кодуються і в процесі виконання або завантаження програми декодуються.
Заміна статичних членів на виклики методів. Деякі статичні члени замінюються на виклики методів.
Додавання невикористовуваних даних. На основі невикористовуваних даних надалі формують помилкові умови.
Зміна способу зберігання даних. Деякі відкриті члени робляться закритими і навпаки.
Виконання фіналізації (finalization). Для певних полів і методів класу може бути виконана фіналізація (Finalization), тобто дані можуть бути захищені від перевизначення у класах нащадків, створених від класу, якому належить даний член. Даний процес зменшує час виконання програми.
2.5.3 Обфускація графа потоку керування
Найбільш складною в плані реалізації, але найбільш стійкою до спроб злому є обфускація графа потоку керування. На сьогоднішній день існує лише кілька подібних обфускаторів. Обфускатори даного типу застосовують наступні методи:
Перетворення обчислень. Даний метод полягає у вставці в алгоритми помилкових умов.
Видалення або додавання абстракцій коду. Видалення абстракцій коду дозволяє крім рішення задачі обфускаціі також оптимізувати роботу програми. Наприклад: обфускатор може замінити виклик який-небудь функції безпосередньо тілом функції, або навпаки одну функцію замінити на кілька маленьких функцій.
Перемішування випадковим чином лінійних ділянок.
3. Захист від дослідження ПЗ створеного за допомогою технології .NET
3.1 .NET Framework
Microsoft .NET— програмна технологія, запропонована корпорацією Microsoft як платформа для створення як звичайних програм, так і веб-програм. Багато в чому є продовженням ідей та принципів, покладених в технологію Java.
Одною з ідей .NET є сумісність служб, написаних різними мовами.
Кожна бібліотека (збірка) в .NET містить інформацію про свою версію, що дозволяє усунути можливі конфлікти між різними версіями збірок.
.NET — кросплатформена технологія, на даний момент існує реалізація для платформи Microsoft Windows, FreeBSD (від Microsoft) і варіант технології для ОС Linux в проекті Mono (в рамках угоди між Microsoft з Novell).
Захист авторських прав відноситься до створення середовищ виконання (CLR — Common Language Runtime) для програм .NET. Компілятори для .NET випускаються багатьма фірмами для різних мов вільно.
.NET поділяється на дві основні частини — середовище виконання (по суті віртуальна машина) та інструментарій розробки.
Середовища розробки .NET-програм: Visual Studio .NET (C++, C#, J#), SharpDevelop, Borland Developer Studio (Delphi, C#) і т. д. Середовище Eclipse має додаток для розробки .NET-програм. Програми також можна розробляти в текстовому редакторі та використовувати консольний компілятор.
Також як і технологія Java, середовище розробки .NET створює байт-код, призначений для виконання віртуальною машиною. Вхідна мова цієї машини в .NET називається CIL (Common Intermediate Language), також відома як MSIL (Microsoft Intermediate Language), або просто IL. Застосування байт-кода дозволяє отримати кроссплатформеність на рівні скомпільованого проекту (в термінах .NET: збірка), а не на рівні початкового тексту, як, наприклад, в С. Перед запуском збірки в середовищі виконання (CLR) байт-код перетворюється вбудованим в середовище JIT-компілятором (just in time, компіляція на льоту) в машинні коди цільового процесора.
3.2 Декомпіляція .NETзбірок за допомогою .NET Reflector
У зв’язку з тим, що програми створені за допомогою .NETкомпілюються у проміжний MSILкод, а не у звичайні машинні коди, декомпіляція таких програм стає досить простою. Одним із найбільш функціональних декомпіляторів для .NETє .NETReflector.
.NET Reflector — безкоштовна утиліта для Microsoft .NET, комбінуюча браузер класів, статичний аналізатор и декомпілятор.
Програма може використовуватися для навігації, пошуку та аналізу вмісту. NET-компонентів, а також збірок і переводити двійкові дані у форму, придатну для читання людиною. Reflector дозволяє проводити декомпіляцію. NET-збірок на мови C#, Visual Basic.NET і MSIL. Reflector також включає дерево викликів, яке може використовуватися для навігації вглиб IL-методів з метою визначення, які методи вони викликають. Програма відображає метадані, ресурси і XML-документацію. .NET Reflector може бути використаний .NET-розробниками для розуміння внутрішньої роботи бібліотек коду, для наочного відображення відмінностей між двома версіями збірок, і того, як різні частини. NET-додатків взаємодіють один з одним.
.NET Reflector може використовуватися для знаходження місць, які мають проблеми з продуктивністю і пошуку багів. Він також може бути використаний для пошуку залежностей збірки. Програма може бути використана для ефективної конвертації коду між C # і VB.NET.
3.2.1 Приклад роботи .NET Reflector
Головне вікно .NET Reflector показує список збірок із складу .NET Framework. Про кожну із них можна подивитися інформацію, а також переглянути списки класів і тонкощі реалізації кожної із них.
Для демонстрації можливостей декомпілятора, відкриємо виконуваний файл популярного графічного редактору Paint.NETі переглянемо код методу PainDotNet.Tools.FloodToolBase, який, судячи з назви відповідає за заливку зображення деяким кольором.
Код програми можна дизасемблювати не тільки в C#, але й в MSIL, VB.NET, Delphi, MC++.
Як легко бачити із вищенаведеного прикладу, декомпіляція і дослідження коду .NETпрограм є дуже простим завданням навіть для мало кваліфікованого користувача. Виходячи з цього, постає проблема захисту програмного коду створеного за допомогою технології .NETFramework. Особливо це актуально для програм, що розповсюджуються на комерційній основі.
3.3 Способи захисту коду .NETпрограм від дослідження
Розглянемо методи захисту .NET збірки від дослідження:
Обфускація коду програми. Цей метод є найбільш простим і поширеним.
Компіляція збірки у машинний (native)код при його встановленні на комп’ютер користувача. Зокрема, це можна виконати з допомогою утиліти ngen, яка поставляється у комплекті із .NETFramework.Але, цей метод може призвести до деяких непередбачуваних наслідків, наприклад, при встановленні нової версії .NETFramework, програма, встановлена таким чином, може припинити працювати.
Використання оптимізуючих компіляторів.
Розроблення критичних частин програмного коду на ManagedC++, що дещо ускладнить процес декомпіляції.
Розроблення критичних частин програмного коду на С++, з компіляцією його в машинний (native)код у формі динамічних бібліотек (dll) та їх подальше використання в програмі на .NETFramework. Для захисту коду отриманої dll можна використовувати ті ж самі методи, що й для звичайних програм.
Виконання і зберігання критичних модулів програми на зовнішньому носії (наприклад, електронний ключ) чи в мережі (наприклад, інтернет), що унеможливлює доступ користувача до програмного коду цього модуля. Недоліком цього методу є необхідність використання деякого апаратного засобу або наявність підключення до мережі.
Висновки
В курсовій роботі були розглянуті проблеми захисту програмного забезпечення, засоби і методи унеможливлення несанкціонованого дослідження програмного коду. Також була розглянута технологія .NETFramework, та проблеми захисту ПЗ створеного на її основі. Технологія .NETFramework дає розробникам багато зручних і корисних засобів, які дозволяють швидко створювати і розповсюджувати (за рахунок незалежності від апаратної платформи і використання MSIL) якісні програмні продукти. Але вона має суттєвий недолік – програми на її основі дуже легко піддаються дослідженню за допомогою декомпіляторів, таких як .NETReflector, роботу якого було розглянуто в курсовій роботі. Найбільш простим і найменш трудомістким способом захисту таких програм, є використання обфускаторів. Нажаль, на даний час, не існує безкоштовних обфускаторів .NET коду, які забезпечують достатньо високий рівень захисту. Проте існує досить багато платних обфускаторів, які використовують одночасно і символьну обфускацію, і заплутування програмного коду і заплутування потоку управління. Зокрема всі ці функції має DotfuscatorProfessionalEdition безкоштовна версія якого постачається разом із середою розроблення VisualStudio.