ПР № 4-6 Шифрование. Защита данных. Задания. Приемы работы с защищенными программами
Скачать 34.35 Kb.
|
Практическая работа №4 Тема: Приемы работы с защищенными программами Цель: освоить технологию работы с дизассемблером и декомпилятором Общие теоретические сведения: Дизассе́мблер — транслятор, преобразующий машинный код, объектный файл или библиотечные модули в текст программы на языке ассемблера. По режиму работы с пользователем делятся на Автоматические Интерактивные Примером автоматических дизассемблеров может служить Sourcer. Такие дизассемблеры генерируют готовый листинг, который можно затем править в текстовом редакторе. Пример интерактивного — IDA. Он позволяет изменять правила дизассемблирования и является весьма удобным инструментом для исследования программ. Дизассемблеры бывают однопроходные и многопроходные. Основная трудность при работе дизассемблера — отличить данные от машинного кода, поэтому на первых проходах автоматически или интерактивно собирается информация о границах процедур и функций, а на последнем проходе формируется итоговый листинг. Интерактивность позволяет улучшить этот процесс, так как просматривая дамп дизассемблируемой области памяти, программист может сразу выделить строковые константы, дать содержательные имена известным точкам входа, прокомментировать разобранные им фрагменты программы. Чаще всего дизассемблер используют для анализа программы (или ее части), исходный текст которой неизвестен — с целью модификации, копирования или взлома. Реже — для поиска ошибок (багов) в программах и компиляторах, а также для анализа оптимизации создаваемого компилятором машинного кода. Обычно однопроходный дизассемблер (как и построчный ассемблер) является составной частью отладчика. Защита от дизассемблированияПервое направление защиты, как правило, реализуется значительно легче, чем второе, поэтому будет приведен лишь краткий обзор данного направления. При реализации защиты программ от дизассемблирования можно применять различные приемы. Среди них наиболее часто используемым и эффективным приемом является зашифровка и \ или запаковка отдельных участков исходного кода или всего кода целиком, при этом необходимо позаботиться о распаковке \ расшифровке программы на точке входа. Таким образом, при просмотре исполняемого машинного кода исполняемого файла вместо рабочего кода программы будет отображен лишь бессмысленный набор операций. При реализации защиты от дизассемблирования используется также множество приемов, которые реализуются с целью запутать потенциального взломщика. Можно навести несколько примеров такого вида приемов: - увеличение исходного кода программы добавлением множества «бессмысленных» операций, а рабочий участок программы записать в определенное место этого множества; - замена местами адресов обработчиков (векторов) прерываний, например, поменять местами вектор прерывания видео сервиса (INT 10h) с вектором прерывания сервиса DOS (INT 21h), после такой замены для вызова из программы какой-либо функции прерывания INT 21h необходимо пользоваться вызовом прерывания INT 10h. Для достижения наиболее надежной и эффективной защиты используется комбинация нескольких приемов. Защита от отладки Для защиты программы от трассировки отладчиком также существует несколько способов. Наиболее распространенными являются два из них. Первый способ Идея: При трассировке программы команды выполняются по команде человека, поэтому длительность выполнения операций(время от начала одной операции до начала следующей) изменяется. Поэтому в программу можно включать точки для проверки времени выполнения одинаковых участков кода программы. Если время выполнения выполнения одинаковых участков различна, то это означает, что программа трассируется в данный момент, необходимо выйти из программы, иначе - продолжить выполнение. Алгоритм реализации: 1. Запомнить текущее время; 2. Выполнить контрольный участок кода; 3. Запомнить текущее время и разность текущего и предыдущего запомненного времени; 4. Выполнить контрольный участок кода повторно; 5. Сравнить разность текущего времени и предыдущего запомненного текущего времени с предыдущей запомненной разностью; 6. Если разности совпадают, продолжить выполнение, иначе – выйти из программы. - метаморфическое преобразование кода программы, позволяющее защитить программу от дизассемблирования и модификации; - защита ключом отдельных участков кода программы (поддерживается только в зарегистрированной версии); - полное разрушение логики защищенных фрагментов кода, не позволяющее анализировать программу с помощью дизассемблера или отладчика; - обнаружение и противодействие отладчикам SoftIce, NtIce, TD и др.; - защита точки входа; - защита от модификации кода; - защищенная работа с реестром, не позволяющая программам вроде RegMon определить, к какому ключу реестра обращается твоя программа; - технология "динамического импорта", которая разрушает имена всех импортируемых функций, а также не использует функцию GetProcAddress; - сжатие ресурсов и исполнимого кода приложения; - поддержка коротких серийных номеров (12 символов); - поддержка внешнего генератора серийных номеров с OLE/DLL-интерфейсом; - технология OneTouch Trial (о ней читай ниже). Самое главное, что нас интересует – это метаморфическое преобразование кода программы и поддержка серийных номеров. Метаморфическое кодирование позволяет изменить код программы до неузнаваемости и запутать отладчик и человека, который запустил этот отладчик. Декомпилятор. Он переводит двоичный код в символьный на языке команд какого-нибудь языка. Например, диассемблеры, деклиппер и многие другие. Эти средства появились раньше отладчиков, т.к. вначале не было архитектуры со встроенными средствами отлаживания программ. С помощью декомпиляторов можно изменять исходный код программы. Допустим необходимо внести крупные изменения в код программы. Прямая вставка двоичных кодов не помогает, т.к. нарушается расположение меток перехода и процедур. Программа – это линейка кода, по которой нужно перемещаться нелинейно, переходить с определенным смещением. Если линейка удлиняется из-за добавления чего-то в середине, все смещения будут показывать не туда куда нужно. Повторная перекомпиляция вписывает новые смещения. Среди декомпиляторов можно выделить: Hacker-VIEW (HVIEW), IDA (интерактивный дизассемблер). С помощью Hacker-VIEW можно посмотреть любой исполняемый файл по любому смещению. Можно выполнить какую-то часть программы. Это позволяет расшифровывать программы и обходить защиту от дизассемблирования. Этот декомпилятор «понимает» как старые форматы исполняемых файлов DOS-COM и DOS-EXE, так и форматы исполняемых файлов Windows. IDA очень мощное средство работы с ассемблерными текстами программ. Обладает широким спектром возможностей, имеет более удобный интерфейс, чем Hacker-VIEW. Очень хорошо предусмотрена архитектура работы программ в Windows (такие вещи, как DLL, расширенный режим работы с памятью и т.д.). Декомпиляторы программ занимают свое место в инструментарии взломщика. В основном это совместное использование с отладчиками. Второе средство – отладчики. Отладчики позволяют запускать отдельные части программы и следить за изменениями, которые она производит, за результатами ее работы. Защите от отладки не стоит уделять много времени, т.к. все возможные хитрости и приемы уже известны и взломщикам и программистам. Так же и шифрование. Любой хакер, если получает заказ на взлом, имеет доступ к нормальной копии программы. То есть он ее либо может купить, либо попользоваться ею на компьютере покупателя. Среди отладчиков выделим: SOFTICE и WINICE. С появлением Windows отладка программ стала на порядок проще и намного удобнее дизассемблирования. Принципиально изменился стиль некоторых атак на защиту программ. Теперь не надо шаг за шагом смотреть на ассемблерный код, «продираться» сквозь дебри незначащих кодов и защит. Теперь надо отловить нужное событие и понять как на него реагирует программа. Это, конечно, не всегда бывает так просто, как выглядит на словах. Как и ранее, отладка требует знание архитектуры операционной системы. Неважно насколько сложным был бы механизм защиты, все сводится к простейшей проверке или дешифровке. И взлом, в случае с проверкой, можно разбить на два этапа: установка «брейков» на «подозрительные» флаги, обнаруженные в процедуре защиты; анализ обращений к флагам. По реакции программы можно судить флаг это или просто переменная. Практическая часть. Изучить теоретическую часть. Сделать записи в тетради. Провести сравнение декомпилятора и отладчика. По данным составить таблицу сравнений. Ответить на контрольные вопросы Контрольные вопросы: Что такое дизассемблер? Как происходит защита программ от дизассемблирования? Как происходит защита программ от отладки? Какие виды отладчиков вы знаете? Что такое декомпилятор? Какие он функции выполняет? Что такое трассировка? Какие виды дизассемблеров вам известны? Какие приемы дизассемблирования вам известны? Практическая работа №5. Приемы работы с защищенными программами. Цель: освоить технологию работы с программой шифрования и дешифрования. Общие теоретические сведения: Основной ресурс системы, распределением которого занимается ОС - это оперативная память (ОП). Поэтому организация памяти оказывает большое влияние на структуру и возможности ОС. Используемые в операционных системах алгоритмы распределения ОП многообразны. Причинами этого многообразия являются: многоуровневая структура памяти (регистровая, оперативная, внешняя) стремление обеспечить пользователя характеристиками, отличными от реальных (виртуальная память) необходимость согласования распределения ОП с распределением центрального процессора Потребности отдельных программ в ресурсе памяти в процессе обработки могут меняться, что заранее, до запуска программы, не может быть учтено. В связи с этим необходимо распределять память динамически непосредственно в ходе вычислительного процесса, т.е. осуществлять динамическое распределение памяти. В любой момент времени все пространство ОП представляет собой чередующуюся последовательность из занятых (распределенных) и свободных (не распределенных в текущий момент) участков памяти. Последние также образно называют дырами. Задача распределения ОП распадается на три взаимосвязанные задачи: учета, выделения, возврата. Учету по определенным правилам подвергаются либо только дыры, либо, более часто, дыры и занятые участки. Задача выделения заключается в выборе по некоторому правилу дыры подходящего размера. Поиск подходящей дыры при этом может производится по одному из трех алгоритмов: поиск от начала, поиск от конца, оптимальный поиск. В первых двух случаях производится выделение первой обнаруженной (при просмотре списка дыр от начала и от конца, соответственно) подходящей дыры, в последнем случае выбирается подходящая дыра наименьшего размера. Более сложные алгоритмы распределения предполагают выделение участка памяти даже в том случае, когда дыра подходящего размера в ОП отсутствует. В этом случае производится некоторое переупорядочение дыр, имеющее целью объединение множества мелких дыр в единое целое. Задача возврата решается при освобождении занятых участков. Требования на освобождение могут исходить от процессов, когда они отказываются от некоторой части ресурса ОП. Кроме того, могут быть освобождения, инициируемые операционной системой без ведома процессов, например в случае выделения памяти за счет использования не только дыр, но и занятых участков. Единой проблемой для всех общецелевых способов динамического распределения является фрагментация памяти. Фрагментация имеет место, когда доступная свободная память разбита на множество несмежных блоков, каждый из которых слишком мал для использования. Одним из возможных решений данной проблемы является использование перемещаемых разделов (relocatable partitions). После окончания каждого задания (программы) освободившиеся области памяти передвигаются как можно дальше к одному концу памяти. В результате этого вся доступная свободная память собирается в один общий блок. Однако, подобные перемещения отнимают много времени. Кроме того, при таком способе решения проблемы фрагментации возникают трудности с переместимостью программ, поскольку перемещение программы во время выполнения осуществить намного сложнее, чем после начальной загрузки. В связи с этими обстоятельствами на практике часто используют некоторую аппаратную поддержку для механизмов дефрагментации памяти, например - специальный регистр перемещения, управляемый операционной системой и недоступный пользовательским программам. Если в памяти одновременно могут находиться несколько независимых программ, необходимы специальные меры для предотвращения или ограничения обращений одной программы к областям памяти, используемым другими программами. Иначе говоря, надо исключить воздействие программы пользователя на работу программ других пользователей и программ операционной системы. Шифрование текстовых строк. Алгоритм Triple DES Создадим новый проект Windows Forms. Добавим к проекту ссылку System.Security Для этого Меню Проект -> Добавить ссылку... На вкладке .NET добавляем нужную ссылку. На форму выносим кнопки: Encoding - Шифрование Decoding - Расшифровка Переходим в режим редактирования кода программы. (Двойной щелчок по форме) Первым делом импортируем пространство имен: Imports System.Security.Cryptography Создаем новый класс - TripleDESClass. Public NotInheritable Class TripleDESClass End Class В классе объявляем переменную для работы с алгоритмом шифрования Triple DES Private TripleDes As New TripleDESCryptoServiceProvider Создаем конструктор класса: Sub New(ByVal key As String) ' Инициализация ключа шифрования и вектора шифрования на основе hash данных TripleDes.Key = CreateHash(key, TripleDes.KeySize \ 8) TripleDes.IV = CreateHash("", TripleDes.BlockSize \ 8) End Sub Функция CreateHash: Private Function CreateHash(ByVal key As String, ByVal length As Integer) As Byte() Dim sha1 As New SHA1CryptoServiceProvider ' получение массива байтов из ключа Dim keyBytes() As Byte = System.Text.Encoding.Unicode.GetBytes(key) ' создание hash данных из байтового массива Dim hash() As Byte = sha1.ComputeHash(keyBytes) ' удаление не нужных данных ReDim Preserve hash(length - 1) ' возвращение результата Return hash End Function Функция шифрования данных: Public Function EncryptData(ByVal plaintext As String) As String ' Конвертация данных в байтовый массив Dim plaintextBytes() As Byte = System.Text.Encoding.Unicode.GetBytes(plaintext) ' Создание потока данных Dim ms As New System.IO.MemoryStream ' Создание зашифрованного потока Dim encStream As New CryptoStream(ms, TripleDes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write) ' запись данных в зашифрованный поток encStream.Write(plaintextBytes, 0, plaintextBytes.Length) encStream.FlushFinalBlock() 'конвертация данных в тип string Return Convert.ToBase64String(ms.ToArray) End Function Функция дешифровки: Public Function DecryptData(ByVal encryptedtext As String) As String ' Конвертация данных в массив байтов Dim encryptedBytes() As Byte = Convert.FromBase64String(encryptedtext) ' Создание нового потока данных Dim ms As New System.IO.MemoryStream ' Создание нового зашифрованного потока Dim decStream As New CryptoStream(ms, TripleDes.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write) ' Использование зашифрованного потока для получения данных decStream.Write(encryptedBytes, 0, encryptedBytes.Length) decStream.FlushFinalBlock() ' Преобразование байтов в тип string Return System.Text.Encoding.Unicode.GetString(ms.ToArray) End Function С помощью выше приведенных функций можно шифровать текстовые строки. Для тестирования данных функций создадим оболочку программы, задача которой получение текстовой строки, получение пароля, сохранение зашифрованных данных в текстовый файл. Перейдем в класс Form1: Создадим два метода: Sub EncodingData() и Sub DecodingData(). Sub EncodingData() Dim Text As String = InputBox("Текст для шифрования:") Dim password As String = InputBox("Введите пароль:") Dim TDSClass As New TripleDESClass(password) 'создание класса для шифрования Dim CryptographyText As String = TDSClass.EncryptData(Text) ' использование функции шифрования MsgBox("Зашифрованный текст: " & CryptographyText) ' запись данных в папку мои документы под именем Cryptography.txt My.Computer.FileSystem.WriteAllText(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\Cryptography.txt", CryptographyText, False) End Sub Sub DecodingData() ' чтение данных из файла Dim CryptographyText As String = My.Computer.FileSystem.ReadAllText(My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\Cryptography.txt") Dim password As String = InputBox("Введите пароль:") ' создание объекта для работы с Triple DES Dim TDSClass As New TripleDESClass(password) ' расшифровка данных и вывод результата Try Dim plainText As String = TDSClass.DecryptData(CryptographyText) MsgBox("Расшифрованный текст: " & plainText) Catch ex As System.Security.Cryptography.CryptographicException MsgBox("Ошибка расшифровки.") End Try End Sub Код для запуска процессов шифрования и расшифровки данных: Private Sub Encoding_Click(sender As System.Object, e As System.EventArgs) Handles Encoding.Click EncodingData() End Sub Private Sub Decoding_Click(sender As System.Object, e As System.EventArgs) Handles Decoding.Click DecodingData() End Sub End Class Запустим проект. Кнопка Шифрование запустит процесс. Практическая часть. Используя теоретическую часть, описать основные методы работы с защищенными программами. При помощи программы Visual Studio набрать код программы и выполнить её проверку При помощи данной программы, зашифруйте любое предложение, включающее в себя 5 слов, ключ сообщите преподавателю для проверки Ответить на контрольные вопросы и оформить отчет. Контрольные вопросы: В чем заключается задача распределения Оперативной памяти? Что такое фрагментация памяти? Как происходит защита записи? Практическая работа №5. Защита оперативной памяти компьютера. Цель: освоить технологию работы с программой защиты оперативной памяти Общие теоретические сведения: Чтобы воспрепятствовать разрушению одних программ другими, достаточно защищать область памяти данной программы от попыток записи в нее со стороны других программ, а в некоторых случаях и своей программы (защита от записи). При этом допускается обращение других программ к этой области памяти для считывания данных. В других случаях, например при ограничениях на доступ к информации, хранящейся в системе, необходимо иметь возможность запрещать другим программам производить как запись, так и считывание в данной области памяти. Такая защита от записи и считывания помогает отладке программ, контролируя каждый случай выхода за область памяти своей программы. Защита от вторжения программ в чужие области памяти может быть организована различным образом. При этом реализация зашиты не должна заметно снижать производительность машины и требовать слишком больших аппаратных затрат. В системах с. мультипрограммной обработкой большого числа программ защищаются области памяти или блоки, на которые делится память. При этом предусматривается возможность указывать для разных программ различные допустимые режимы обращения к отдельным областям или блокам памяти. Метод граничных регистров состоит во введении двух граничных регистров, указывающих верхнюю и нижнюю границы области памяти, куда программа имеет право доступа, и специальных индикаторов, определяющих допустимый режим обращения. При каждом обращении к памяти проверяется, находится ли используемый адрес в уставленных границах; при выходе за границы обращение к памяти подавляется и формируется запрос прерывания, передающий управление супервизору (диспетчеру памяти). Содержание граничных регистров устанавливается супервизором, перед активизацией очередной программы. Если для динамического распределения памяти используется базовый регистр, то он одновременно определяет и нижнюю границу. Верхняя граница подсчитывается супервизором в соответствии с длиной программы в оперативной памяти. Метод ключей защиты. По сравнению с предыдущим данный метод является более гибким, позволяя организовать доступ программы к несмежным областям памяти. Память в логическом отношении делится на одинаковые блоки. Каждому блоку памяти ставится в соответствие код, называемый ключом защиты памяти, а каждой действующей программе присваивается код ключа программы. Доступ программы к данному блоку памяти разрешен, если коды ключей соответствуют друг другу, т.е. если ключи равны или один из них имеет код 0. Для достижения гибкого динамического распределения памяти, устранения ее фрагментации, а также создания значительных удобств для программирования в современных ОС широко используется виртуальная память. При этом на всех этапах подготовки программ, включая загрузку в оперативную память, программа представляется в виртуальных адресах и лишь при самом исполнении машиной команды производится преобразование виртуальных адресов в адреса действующей памяти (в так называемые физические адреса). Это преобразование составляет содержание динамического распределения памяти. Объем виртуального адресного пространства может даже превосходить всю доступную реальную память на ЭВМ. Содержимое виртуальной памяти, неиспользуемой программой, хранится на некотором внешнем устройстве (внешней памяти). По необходимости части этой виртуальной памяти отображаются в реальную память. Ни о внешней памяти, ни о ее отображении в реальную память программа ничего не знает. Она написана так, как будто бы виртуальная память существует в действительности. Иногда возникает задача защиты данных хранящихся в оперативной памяти компьютера, что бы злоумышленник не получил к ним доступ. Для таких случаев используется ProtectedData. Практическая часть Для демонстрации методов шифрования и расшифровки данных в оперативной памяти создадим приложение ConsoleApplication. Создаем новый проект ConsoleApplication. Импортируем в проект ссылку: Imports System.Security.Cryptography Так же необходимо подключить эту библиотеку к проекту, Меню Проект -> Добавить ссылку.. На вкладке .NET выбираем System.Security Далее стираем весь код и создаем новый класс DataProtection. Объявляем переменную: Private Shared s_aditionalEntropy As Byte() = {3, 6, 2, 1, 5} ' Байтовый массив - ключ шифрования В класс помещаем функции. Функция_расшифровки'>Функция шифрования: Public Shared Function ProtectData(ByVal data() As Byte) As Byte() Try ' DataProtectionScope.CurrentUser - доступ к данным может произвести только пользователь Return ProtectedData.Protect(data, s_aditionalEntropy, DataProtectionScope.CurrentUser) Catch e As CryptographicException Console.WriteLine("Ошибка шифрования.") Console.WriteLine(e.ToString()) Return Nothing End Try End Function Функция расшифровки: Public Shared Function UnprotectData(ByVal data() As Byte) As Byte() Try 'Расшифровка данных Return ProtectedData.Unprotect(data, s_aditionalEntropy, DataProtectionScope.CurrentUser) Catch e As CryptographicException Console.WriteLine("Ошибка расшифровки.") Console.WriteLine(e.ToString()) Return Nothing End Try End Function Функция вывода результата на экран: Public Shared Sub PrintData(ParamArray Array() As Byte) Dim i As Byte For Each i In Array Console.Write(vbTab + "{0}", i) Next i Console.WriteLine() Console.ReadKey() End Sub И метод Main(), запускающий процесс шифрования и расшифровки памяти. Public Shared Sub Main() ' Данные для шифрования Dim secret As Byte() = {3, 6, 8, 1, 5, 4} 'Шифрование Dim encryptedSecret As Byte() = ProtectData(secret) Console.WriteLine("Зашифрованный массив данных:") PrintData(encryptedSecret) ' Расшифровака Dim originalData As Byte() = UnprotectData(encryptedSecret) Console.WriteLine("{0} Расшифрованные данные:", Environment.NewLine) PrintData(originalData) End Sub Ход работы Набрать код данной программы Запустив программу, выведется результат шифрования и расшифровки оперативной памяти компьютера. Что отображено и всегда ли данное шифрование будет одинаковым? От чего этого зависит? Ответить на контрольные вопросы. Контрольные вопросы: Какие методы защиты данных вы знаете? Является ли данная программа сверхнадежной? Почему? Возможно ли зашифровать информацию не переводя её в байты? Как бы вы улучшили эту программу Рассмотрите и законспектируйте основные положения из ГОСТ 28147 – 89. Система обработки информации. Защита криптографическая. Алгоритм криптографического преобразования. М. |