чи сравниваются, на выходе нечеткого экстрактора получим меру схожести шаблонов.
Рассмотренный нечеткий экстрактор демонстрирует устойчивое кодирование непостоянных биометрических данных, что не только позволяет применить шифрование в биометрической системе, но и восстанавливать утерянные или искаженные части биометрического идентификатора.
5. Заключение
В данной работе предложена такая технология биометрической криптографии как нечеткий экстрактор. Корректирующая способность нечеткого экстрактора зависит от образующего полинома, управление которым поможет настроить программу для работы с шаблоном любого биометрического признака. Но главным достоинством нечеткого экстрактора является все же способность создания эффективной биометрической криптосистемы.
Список литературы:
1. Stan Z. Li. Encyclopedia of Biometrics [Текст] / Z. Li Stan. - Berlin: Springer Science+Business Media, 2009. - 1500 с.
2. Васильев В.И. Интеллектуальные системы защиты информации: учеб. пособие [Текст] / В.И. Васильев. - М.: Машиностроение, 2010. - 163 с.
3. The Error Correcting Codes (ECC) Page [Электронный ресурс] // The Error Correcting Codes (ECC) Page. - Режим доступа: www.eccpage.com (дата обращения: 25.04.2013).
4. ГОСТ Р ИСО/МЭК 19794-2-2005 [Электронный ресурс] // Все ГОСТы. - Режим доступа: http://docs.cntd.ru/document/1200044529 (дата обращения: 3.04.2013).
5. Кухарев Г.А. Биометрические системы. Методы и средства идентификации личности человека [Текст] / Г.А. Кухарев. - СПб.: Политехника, 2001. - 240 с.
ВАРИАНТЫ МОДИФИКАЦИИ СТРУКТУРЫ ИСПОЛНИМЫХ ФАЙЛОВ ФОРМАТА РЕ
© Штеренберг С.И.*, Андрианов В.И.*
Санкт-Петербургский государственный университет телекоммуникаций им. профессора М.А. Бонч-Бруевича, г. Санкт-Петербург
Объект исследования включает в себя скрытое вложение информации в исполнимые файлы формата РЕ.
* Аспирант кафедры Защищенных систем связи.
* Доцент, кандидат технических наук.
Целью статьи является исследование вариантов модификации структуры файла формата PE для дальнейшего описания процесса внедрения не только в начало программы, но и в некоторые её функции, а также внедрение в GUI. Актуальность исследования объясняется необходимостью обладания у внедряемого водяного знака некоторой степенью устойчивости, то есть противостоять удалению или модификации.
Тип реализующего ЭВМ (персональные компьютеры и рабочие станции), вид и версия операционной системы (Linux, Mac OS, Windows), программная среда OllyDump.
Ключевые слова: стеганография, контейнер, исполнимые файлы, библиотечные файлы, формат PE.
Цель стеганографии состоит в организации передачи секретных данных так, чтобы сам факт передачи был скрыт от стороннего наблюдателя. Обычно в «невинное» сообщение, так называемый контейнер, с помощью специального алгоритма встраивается стегосообщение. Контейнер подбирается таким образом, чтобы содержание и сам факт его передачи не вызывал никакого подозрения у третьих лиц. Широкое применение стеганография получила в сфере защиты авторских прав. В каждую продаваемую копию цифрового объекта (изображение, видео, программа) с помощью специальных алгоритмов внедряется специальное сообщение - водяной знак, по которому в случае обнаружения нелегальной (пиратской) копии с легкостью может быть прослежен исходный файл, с которого была снята эта копия, и соответственно пользователь, нарушивший лицензионное соглашение.
Очевидно, что внедряемый водяной знак должен обладать некоторой степенью устойчивости, то есть противостоять удалению или модификации. Считается, что заранее можно предугадать, содержится ли водяной знак или нет. В настоящее время существуют методы, позволяющие защитить подобным образом от нелегального копирования различные цифровые объекты, такие как файлы мультимедиа и программ. В частности, ряд публикаций, например, посвящен методам внедрения скрытой информации в программы. В данной статье речь пойдет о методе, размещающем секретное сообщение в неиспользуемых местах секции исполняемых файлов формата Portable Executable (PE).
Portable Executable - формат исполняемых файлов, объектного кода и динамических библиотек, используемый в 32- и 64-битных версиях операционной системы Microsoft Windows. Формат PE представляет собой структуру данных, содержащую всю информацию, необходимую PE загрузчику для проецирования (отображения) файла в память. Исполняемый код включает в себя ссылки для связывания динамически загружаемых библиотек, таблицы экспорта и импорта API функций, данные для управления ресурсами и данные локальной памяти потока (TLS). В операционных системах семейства Windows NT формат PE используется для EXE, DLL, SYS (драйверов устройств), и других типов исполняемых файлов.
Каждая секция такого файла должна быть размером, кратным полю FileAligment. Таким образом, секция кода состоит из двоичных инструкций программы и нулевых байтов выравнивания, увеличивающих секцию до требуемых размеров. Вместо байтов выравнивания предлагается записывать секретное сообщение. По их мнению, это имеет некоторые преимущества: размер файла семейства остается неизменным и внедренное сообщение никак не влияет на ход выполнения программы. Предполагается, что передаваемое сообщение будет предварительно зашифровано и для его прочтения необходимо знать секретный ключ, а также начальную позицию сообщения в файле. Однако, как будет показано ниже, данный подход не является устойчивым из-за различных статистических свойств кода программы и передаваемого зашифрованного сообщения.
Исполняемый файл может содержать не только код, но и многочисленные дополнительные данные: пиктограммы, различные служебные данные и информация об экспортируемых и импортируемых функциях. Каждый вид данных, содержащихся в файле, это отдельный объект, занимающий секцию фиксированного размера. Если объект не занимает всего объема секции, то эта часть секции не используется. Поэтому в файле формата РЕ всегда достаточно свободного места для записи.
Файл PE состоит из нескольких заголовков и секций, которые указывают динамическому компоновщику, как отображать файл в память. Исполняемый образ состоит из нескольких различных областей (секций), каждая из которых требует различных прав доступа к памяти; таким образом, начало каждой секции должно быть выровнено по границе страницы. Например, обычно секция .text, которая содержит код программы, отображена как исполняемая / доступная только для чтения, а секция .data, содержащая глобальные переменные, отображена как неисполняемая / доступная для чтения и записи. Однако, чтобы не тратить впустую пространство на жёстком диске, различные секции на нём на границу страницы не выровнены. Часть работы динамического компоновщика состоит в том, чтобы отобразить каждую секцию в память отдельно и присвоить корректные права доступа получившимся областям согласно указаниям, содержащимся в заголовках.
Файлы PE не содержат позиционно-независимого кода. Вместо этого они скомпилированы для предпочтительного базового адреса, и все адреса, генерируемые компилятором / компоновщиком, заранее фиксированы. Если PE файл не может быть загружен по своему предпочтительному адресу (потому что он уже занят чем-то ещё), операционная система будет перебазировать его. Это включает в себя перевычисление каждого абсолютного адреса и изменение кода для того, чтобы использовать новые значения. Загрузчик делает это, сравнивая предпочтительный и фактический адреса загрузки, и вычисляя значение разности. Тогда для получения нового адреса ячейки памяти эта разность складывается с предпочтительным адресом. Базовые
адреса перемещений хранятся в списке и при необходимости добавляются к существующей ячейке памяти. Полученный код является теперь отдельным по отношению к процессу и не является больше разделяемым, так что при таком способе теряются многие из преимуществ экономии памяти динамически загружаемых библиотек. Такой способ также значительно замедляет загрузку модуля. По этой причине следует избегать перебазирования везде, где это возможно; например, библиотеки, поставляемые Microsoft, имеют предварительно вычисленные неперекрывающиеся базовые адреса. В случае отсутствия необходимости перебазировании PE файлы имеют преимущество очень эффективного кода, но при наличии перебазирования издержки в использовании памяти могут быть значительными [9].
MS-DOS-за головок
MS-DOS заглушка
Сигнатура РЕ
РЕ-за головок
Опциональный РЕ-заголовок
Таблица секций
данные
Рис. 1. Структура файла формата PE
В данной статье предлагается два варианта - так как места в секции кода почти всегда мало (RawSize - размер в исполняемом файле), а размер в памяти VirtualSize >> RawSize, то в конце кода у нас есть достаточно большой нулевой блок. Можно поступить одним из двух способов - записать свой код поверх этих нулей, потом сделать дамп из памяти и получить то, что нужно, а возможно также заранее создать свою секцию и писать в неё. Что касается имеющейся секции данных, то там, как правило, место всегда есть, но если создавать свою секцию кода, то свою секцию данных создать -уже не проблема. А можно сделать её одновременно и секцией данных, разрешив писать в неё.
В первом варианте наиболее успешно срабатывает связка - это OllyDump без восстановления импорта совместно с ImpRec. Поэтому закрываем OllyDump и открываем наш файл в LordPE или PETools [10].
Рис. 2. Файл в Olly Debugger
Рис. 3. PE Editor
Необходимо запоминать в VirtualOffset и RawOffset наши секции (60000h и 59E00h). Это необходимо, потому что есть в PE-заголовке такое поле, как BaseOfCode. В нём сейчас записан VirtualOffset (сокращенно - RVA) секции «CODE», и OllyDump, которым нужно пользоваться дальше. RVA не будет анализировать нашу секцию, считая её лишней частью и не понимая, как туда попадает данная программа. RVA ориентируется как раз на BaseOfCode. Далее в BaseOfCode прописывается запомненный RVA. После проделанных операций смотрим на важный параметр EntryPoint, запоминаем его значение
(4CA98), и пишем туда (RVA нашей секции + 5). Открываем taiget.exe во FlexHex и переходим в самый конец файла. Теперь осуществляется поиска места, где будет новая секция. Начинается секция с запомненного нами Raw-Offset (назовём его Raw = 59E00). Если последний существующий байт файла имеет адрес, отличный от (Raw-1), то забиваем нулями всё место от конца файла до этого числа.
Рис. 4. Редактирование структуры в target.exe
В результате проделанных операций получается валидный PE-файл с ошибкой (рис. 4).
Рис. 5. Ошибка запуска
Необходимо вновь вернуться в OИyDump. Жмём пробел, находясь на самой первой строчке, и пишем «jmp 44CA98» (это та самая исходная En-tryPoint, вернее (EntryPoint + ImageBase) (далее OEP), где ImageBase тоже можно посмотреть в PE-заголовке, но вообще-то он всегда равен 400000к
Вот этот «далёкий прыжок» и «забрал» первые 5 байт секции. Затем проверяем работоспособность программы. Для этого из EP - то место, где сейчас остановлена программа, переходим на OEP, то есть в начало секции: (чтобы попасть на место, где сейчас остановлена программа, можно нажать правую кнопку ^ Go to ^ Origin или просто «*» на NumPad^.). Пишем в EP: «jmp 460000». Пустой прыжок сразу на OEP, сделанный для проверки, нам уже не нужен, поэтому начинаем писать поверх него. Пытаемся создать файл с помощью CreateFileA: параметры мы, разумеется, не помним, поэтому пишем несколько раз «push 0», а потом «call CreateFileA». А теперь то, ради чего мы меняли BaseOfCode: жмём «Ctrl-A», и OllyDump анализирует наш код [11].
2 CPU - main thread, module target
EH .- E9 93CAFEFF JMP target.0О4ЧСАЭ8
00460005 $ 6A 00 PUSH 0
6A 00 PUSH 0 rhTemplateFile = NULL
00Ч60009 6A 00 PUSH 0 Attributes = 0
0ОЧ6000В 6A 00 PUSH 0 Mode 0
0O4S000D 6A 00 PUSH 0 pSecurity : NULL
0046000F ISA 00 PUSH 0 ShareMode ■ 0
00460011 6A 00 PUSH 0 Access : 0
0OH6O013 6A 00 PUSH 0 Filename = NULL
004S0015 ES 0A1A3A7C CALL kernel32.CreateFileA -CreateFileA
0046001Й . 0000 ADD BVTE PTR DS:[EAX], AL
Рис. 6. Анализ секции
Трассируем по F8 до прыжка: eax = 1, после чего программа покажет успешную работу. Выделяем всё изменённое (это делается так же, как и в любом текстовом редакторе - с помощью Shift и стрелок или мышки), не забывая про 461000 с «a.txt». Возможно, что данные файлы не влезут в размер секции в файле! Можно попробовать перенести его раньше: на 460600, а там удалить (или аналогично через «Patches», или выделяем, правая кнопка ^ Binary ^ Fill with 00's) и поправим код (выделяем команду push 461000 ^ пробел ^ push 460600) [12].
OllyDump предлагает сохраниться, например в target_.exe. Так, у нас в папке уже имеется a.txt. Удаляем его и запускаем вновь программу. Пробуем запустить файл на другом компьютере - и, скорее всего, ничего не получится. Всё дело в том, что, если теперь нажать пробел на «call функция из библиотеки», то будет видно сообщение «CALL 7C801A24», то есть абсолютный адрес в библиотеке. Если, например, имеется другая версия kernel32.dll, тогда произойдёт ошибка, и программа работать не будет. Поэтому нам надо внимательно импортировать все используемые нами функции. Для этого существует механизм под названием Import Address Table (IAT). Используя данный механизм, программа при загрузке в память вычисляет адреса импортируемых функций по их символьным именам.
Итак, нам надо описать должным образом нужные нам функции. Если программа ещё и запакована, что, кстати, в случае отсутствия проверки CRC
никоим образом не отражается на нашей работе, то там эта оригинальная IAT ещё и спрятана [13].
Для следующего способа необходимы следующие функции: CreateFileA, WriteFile, CloseHandle из библиотеки kernel32.dll и WSAStartup, connect, send, recv и WSACleanup из WS2_32.dll. Нам нужен ThunkRVA - по этому адресу будет находиться адрес функции в памяти после загрузки программы (разумеется, +ImageBase). И в данном адресе вместо «call CreateFileA» надо писать «call xxxxxxxx», где по адресу xxxxxxxx находится команда «jmp dword ptr [464035]», или просто «jmp [464035]», так как 464035 = ImageBase + ThunkRVA фунуции CreateFileA. Необходимо делать call на jmp - это очень логичная операция, так как, во-первых, к одной функции программа может стучаться несколько раз, а, во-вторых, важно чтобы к функциям обращение шло через обычный call. После чего нужно записать эти самые прыжки. Записывать их для начала с адреса 460500 (они должны попадать внутрь файла, то есть до 461000). Переключаемся в OllyDump, переходим на этот адрес (быстрый переход - Ctrl+G), нажимаем пробел и пишем по очереди jmp [464035], jmp [464039], jmp [46403D] - импорт из kernel32.dll, и также с WS2_32.dll - jmp [64082], jmp [64086] и т.д.
004604FF 00460500 0G46G505 0046050Й 004605OF 00 - Е9 303В0О00 - Е9 2F3B0000 - Е9 2ЕЗВ0О00 - ЕЭ 6ЕЗВ0О00 DB 00 JMP <Skernel32.CreateFi1еА> JMP <8kernel32.Uri teFi1е> JMP <Skernel32.CloseHandle> JMP <aiilS2 32.lilSflStartup>
0046051Ч - ЕЭ 6D3B0O0O JMP <SlüS2 32.connect>
0046051Э 0046051Е 00460523 00460523 0046052Й 0046052В - ЕЭ 6СЗВ0000 - ЕЭ 6ВЗВ0000 - ЕЭ 6ЙЗВ0000 0000 00 00 JMP <£US2_32.send> JMP <aWS2_32.recu> JMP <aiüS2_32.USflCleanup> ADD BVTE PTR DS: [EflX] , flL DB 00 DB 00
Рис. 7. Использование ThunkRVA
Теперь идём в начало секции, и изменяем «call CreateFileA» на «call 460500», аналогично - CloseHandle. (Для этого выделяем команду, жмём пробел и пишем новый код):
$
00460007 0046000Э 0046000В 0046000D 0046000F 00460014 00460019
ей оо ей оо 6Й 02 ей оо ей оо
es оооооочо es оооечеоо
ES E204O0OO
PUSH 0
PUSH 0
PUSH 2
PUSH 0
PUSH 0
PUSH 40000000
PUSH target..00160600
CALL <JMP.£kerne!32.CreateFileA>
hTemplateFile = NULL Attributes = 0 Mode : CREflTE_ALldflYS pSecurity NULL ShareMode 0 Access GENERIC_URITE FileName = "a.txt-' ■CreateFileA
0046001E
50
PUSH
EAX
-hObject
0046001F 00460024 00460026
ES E8040000 ЕВ DA 00
CALL <JMP.&kernel32.CloseHandle> JMP SHORT target..00460000 DB 00
-CloseHandle
Рис. 8. Изменяем «call CreateFileA» на «call 460500»
Если нажать Ctrl+A, то он точно так же выводит список параметров функции. Можно убедиться, что всё действительно работает, сохранив уже имеющиеся изменения уже описанным способом.
Если всё прошло без ошибок, то тогда в eax после выполнения recv лежит размер полученных данных. Нужно его запомнить, чтобы потом Write-File знал, сколько байт писать. Затем нужен дескриптор файла, открытого в CreateFileA. Здесь имеется 2 варианта. Первый - «занопить» тот вызов Create-FileAX то есть забить командами nop (выделяем ^ пр. кнопка ^ Binary ^ Fill with NOP's) и вызвать её уже после операций с сокетами. А в другом случае можно воспользоваться другим - поставить прыжок дальше (заменяя его, лучше поставить галочку «Fill with NOP's»), а там, выполнить call, сохранив результат и вернуться обратно [14].
CALL <JMP.&kernel32.CreateFileA>
Рис. 9. Схема с заменой при помощи команды nop
Сохраняем результат гест'а, то есть размер полученных данных, к примеру, в [463000]:
MOV [463000], EAX Закрываем сокет: Push [461040] CALL 0046053C
Выделяем весь код от начала секции до 460999 включительно (до последнего использованного адреса), и сохраняем их в файл, например, «fin.exe». Запускаем дальше программу в OllyDump по F9 или F8, чтобы убедиться в отсутствии ошибок, а можем закрыть отладчик и запустить fin.exe.
Выводы
В данной статье были рассмотрены несколько вариантов модификации исполняемых файлов PE, основные ошибки, встречающиеся при модификации и методы их устранения. В первом варианте можно записать свой код поверх этих нулей, потом сделать дамп из памяти, а возможно также заранее создать свою секцию и писать в неё. Во втором варианте использовать за-
мены при помощи команды nop. В тестировании работы модифицируемых файлов использовался отладчик в OllyDump, в котором успешно обрабатывались необходимые запросы.
Использование модификации структуры файла важно для дальнейшего описания процесса внедрения не только в начало программы, но и в некоторые её функции, а также внедрение в GUI.
Список литературы:
1. Кип Ирвин. Язык ассемблера для процессоров Intel. - Вильямс, 2005. -912 с.
2. Красов А.В., Верещагин А.С., Абатуров В.С., Резник М.В. Методы скрытого вложения информации в исполняемые файлы. - Известия СПбГЭТУ «ЛЭТИ». - СПб., 2012. - № 8. - С. 51-55.
3. Красов А.В., Верещагин А.С., Цветков А.Ю. Аутентификация программного обеспечения при помощи вложения цифровых водяных знаков в исполняемый код. // Телекоммуникации. - М., 2013. - Спецвыпуск. - С. 27-30.
4. Hattanda K., Ichikawa S. The Evaluation of Davidson's Digital Signature Scheme // I EICE transactions on Fundamentals of Electronics, Communications and Computer Sciences. - 2004. - V E87-A, № 1. - P. 224-225.
5. Naji A., Teddy S. Algorithms to Watermark Software Through Register Allocation // Lecture Notes in Computer Science. - 2006. - V 3919. - P. 180-191.
6. Нечта И.В. Стеганография в файлах формата Portable Executable // Вестник СибГУТИ. - 2009. - № 1. - С. 85-89.
7. Naji A., Teddy S. New Approach of Hidden Data in the portable Executable File without Change the Size of Carrier File Using Statistical Technique // International Journal of Computer Science and Network Security. - 2009. - V 9, № 7. - P. 218-224.
8. Zaidan A., Zaidan B., Jalab H.A. A New System for Hiding Data within (Unused Area Two + Image Page) of Portable Executable File using Statistical Technique and Advance Encryption Standard // International Journal of Computer Science and Network Security. - 2010. - V 2, № 2.
9. http ://www. insidepro.com/kk/019/019r. shtml.
10. http://tuts4you.com.
11. http://redxak.net.
12. http://antichat.ru.
13. http://cracklab.ru.
14. http://wasm.ru.