Методика применения языка Ассемблер для стеговложения информации в исполняемые файлы

МЕТОДИКА ПРИМЕНЕНИЯ ЯЗЫКА АССЕМБЛЕР ДЛЯ СТЕГОВЛОЖЕНИЯ ИНФОРМАЦИИ

«и»

В ИСПОЛНЯЕМЫЕ ФАЙЛЫ

Изложена методика использования языка программирования низкого уровня для стеганографического вложения в исполняемые файлы формата elf. Актуальность исследования объясняется широким распространение операционной системы Linux и необходимостью решения задачи определения вирусов среди исполнимых файлов, необходимостью определения частей программного обеспечения созданного различными пользователями, отсутствием в настоящее время устоявшихся эффективных методик решения подобных задач скрытого вложения информации в исполнимые файлы.

Сравнивать язык команд с алгоритмическими языками имеет смысл только в отношении сложности и трудоемкости процесса программирования. Безусловно, при таком сравнении ассемблер уступает алгоритмическим языкам, но это не означает, что его не следует знать и уметь применять в случае необходимости. Неоспоримым достоинством ассемблера является возможность составления программ, рационально использующих все особенности системы команд конкретной ЭВМ. Он предоставляет неограниченные возможности для семантических замен и операций по взаимодействию с операндами в коде программы. Другим положительным свойством является универсальность языка, - он позволяет составить программу для любой задачи, которая имеет решение и может быть решена на машинах данного семейства. Это утверждение основано на том очевидном факте, что любая программа, составленная на языке высокого уровня, при компиляции преобразуется в последовательность машинных команд. К коду, генерируемому компилятором, предъявляются следующие требования: он должен быть полностью перемещаемым (т.е. независимым от базового адреса загрузки), не модифицировать никакие ячейки памяти, за исключением стекового пространства, и не использовать стандартные механизмы импорта функций, либо подключая все необходимые библиотеки самостоятельно, либо обращаясь в native-API. Этим требованиям не удовлетворяет подавляющее большинство компиляторов. Дизассемблер позволяет конвертировать машинный код в код на языке ассемблера. Код на языке ассемблера является читабельной формой машинного кода. С помощью дизассемблера можно узнать, какие машинные инструкции используются в машинном коде. Машинный код является специфическим для конкретной аппаратной архитектуры (например, для чипа PowerPC или Intel Pentium) и прост для реализации стеговложения.

Штеренберг Станислав Игоревич,

аспирант СПбГУТ им. проф. М.А.Бонч-Бруевича, г. Санкт-Петербург, Россия, shterenberg.stanislaw@yandex.ru

Ключевые слова: Ассемблер, исполняемый файл, стеганография, компилятор, hex-редактор.

Для цитирования:

Штеренберг С.И. Методика применения языка Ассемблер для стеговложения информации в исполняемые файлы // T-Comm: Телекоммуникации и транспорт. - 2016. - Том 10. - №6. - С. 42-47.

For citation:

Shterenberg S.I. The method of application assembler programming language for concealed attachment information in executables. T-Comm. 2016. Vol. 10. No.6, рр. 42-47.

Введение

Прием по скрытому вложению информации возможно реализовать на распространенных языках объектно-ориентированного программирования. Достаточно рассмотреть простой пример вложения на примере 64-битного формата РЕ, который распространен в современных версиях операционной системы Windows. Известно, что файл РЕ состоит из нескольких заголовков и секций, которые указывают динамическому компоновщику, как отображать файл в память. Исполняемый образ состоит из нескольких различных секций, каждая из которых требует различных прав доступа к памяти. Таким образом, начало каждой секции должно быть выровнено по границе страницы. Например, обычно секция .text, которая содержит код программы, отображена как исполняемая/доступная только для чтения, а секция .data, содержащая глобальные переменные, отображена как нсисполняемая/доступная для чтения и записи. Однако, чтобы не тратить впустую пространство на жёстком диске, различные секции на нём на границу страницы не выровнены. Часть работы динамического компоновщика состоит в том, чтобы отобразить каждую секцию в память отдельно и присвоить корректные права доступа получившимся областям согласно указаниям, содержащимся в заголовках.

Известно, что идентифицировать формат возможно по первым двум байтам в заголовке по сигнатуре 0x4D 0х5А — «MZ». Последние четыре байта заголовка образуют поля пустых секций - bfofffiits — число типа DWord, которое содержит важную для нас информацию— начало в файле собственно байтового массива с изображением, в который мы и будем вносить изменения. После заголовка собственно файла qitmapfileheader идет структура bitmapinf oheader, которая и содержит нужные нам сведения. Первые четыре байта этой структуры мы пропускаем, а в следующих восьми (начиная с номера 18, считается от начала файла с нуля) идет ширина (biwidth) и длина (biHeight) изображения в пикселах - по четыре байта (одному числу с word) на каждое измерение. Если пропустить еще два байта, то в следующем двухбайтном поле biBitCount будет число бит на пиксел (для

TnieColor гам будет стоять число 24=$ 18). А после него, начиная с байта помер 30, будет нужное нам двухбайтное поле compressed: если оно содержит нули, то файл не использует сжатия, в противном случае он для нашей цели непригоден. [1]

Для стеговложения в эти участки можно разобрать известный типовой пример «заражения» файла компьютерным вирусом. В классификации вирусов можно выделить именно файловые вирусы, т.к. вредоносные программы этого типа пишутся преимущественно на языке Ассемблера. Алгоритм заражения в общем виде выглядит так: вирус находит жертву, убеждается, что она еще не заражена и что все необходимые права на модификацию этого файла у него присутствуют. Затем он считывает жертву в память (временный файл) и записывает себя поверх заражаемого файла. |2] Оригинальный файл дописывается в хвост вируса как оверлей, либо же помещается в сегмент данных (рис. 1).

Получив управление, вирус извлекает из своего тела содержимое оригинального файла, записывает его во временный файл, присваивает ему атрибут исполняемого и запускает «излеченный» файл на выполнение, после чего удаляет с диска вновь. Поскольку подобные манипуляции редко остаются незамеченными, некоторые вирусы «отваживаются на ручную» загрузку жертвы с диска. Характерной чертой подобных вирусов является крошечный сегмент кода, за которым следует огромный сегмент данных (оверлей), представляющий собой самостоятельный исполняемый файл.

Реализация

Чтобы осуществить вложение в исполнимые файлы, не наделяя его характеристиками вредоносного типа, рекомендуется применить следующую методику. Короткий код позволяет работать с минимальными затратами данных, а именно несколькими битами информации. Один из методов, где возможно применение ассемблерных инструкций базируется на том, что можно переставлять местами две рядом стоящие операции присваивания, результат работы которых не зависит от последовательности выполнения.

ELF-заголовок

КОД и ДАННЫЕ программы

2S Е8

ELF-jokmobok вируса

КОД и ДАННЫЕ вируса

ориг eif-

заг оловок

КОД и ДАННЫЕ программы

ELF-заголовок

КОД и ДАННЫЕ программы

КОД и ДАННЫЕ программы

а.

б.

КОДиДАННЫЕ вируса

Рис. I, Типовая схема заражения исполняемого файла: а) путем его поглощения; б) путем расширения его последней секции

Простая перестановка здесь изменяет ход (порядок) вычислений, но не искажает результат. Если операции идут и лексикографическом порядке, то спрятанный бит равен традиционно I или Ü. Главной задачей будет являться поиск подобных операций, которые можно менять местами. Особенность заключается именно в том, что некоторые файлы могут иметь безусловный переход типа JМР. из-за чего невозможно производить перестановку пар присваиваний (Листинг I),

метка А: а:=1; метка В: b:=b+1; тело цикла jmp [регистр]

Листинг 1. Пример с использованием безусловного перехода типа J Ml1.

Если регистр содержит адрес метки В, то при перестановке в теле цикла окажется другая операция, ЧТО вызовет нарушение работы алгоритма программы. Поэтому следует сформулировать требования к парам операций, которые можно использовать для передачи «скрытой» информации. Эти операции должны удовлетворять следующим условиям:

1. являться операциями присваивания;

2. располагаться рядом друг с другом,

3. быть независимыми друг от друга:

4. операции не должны быть одинаковыми.

Кроме того, в программе не должно быть переходов на вторую операцию минуя первую, в том числе м косвенных (относительных) переходов, адреса которых нельзя определить или исправить (Листинг 2).

xor as, ах mov dx, ах

tnov word ptr ds: [offset varl ], ax

Листинг 2. Фрагмент программы с реализацией косвенных (относительных переходов).

Теперь рассмотрим процесс сокрытия (процесс А) и получения сообщения (процесс Б). Если передаваемый бит скрытого сообщения равен 1, то операции расставляются в лексикографическом порядке (обозначим такую пару через <а, Ь>). Если передаваемый бит равен 0, то расставим операции в обратном порядке <Ь, а>.

Процесс А выбирает файл формата РЕ и осуществляет в н м поиск пар операций присваивания. Далее Процесс А изменяет последовательность операций в найденных парах в соответствии с передаваемым сообщением и отсылает процессу Б. Процесс Б также осуществляет поиск пар операций присваивания и в соответствии с лексикографическим порядком операций в парах получает переданное скрытое сообщение [3J.

В дополнение следует заметить, что синтаксис Ассемблера позволяет вынести описание вложенной структуры файлов за пределы текущей структуры. Для экспериментов по стеганографическому вложению стоит рассмотреть именно тот формат исполняемого файла, который при по-

мощи компилятора и текстового редактора возможно написать самостоятельно. Сначала в пример пойдет простой исходник на С "имя-файла.с". Файл компилируется с настройками по умолчанию (gcc имя-файла.с -о имя-файла).

Образовавшийся файл загружается в Иех-редактор, в котором реален просмотр Ассемблерного кода. Редактор предложит несколько вариантов ассемблирования на наш выбор: 5Eh и 8Fh C6h. Как правило выбирается 5P.h, как самый короткий, затем точно также ассемблируем команду хог ebp,ebp. Можно теперь заменить pop esi/xor ebp,ebp на jmp на наш код, откуда возможно сделать все операции, выполнить эти команды и вернуться обратно.

В режиме просмотра файла в hex-редакторе, найдем и выпишем стартовые адреса всех цепочек NOP'ob, пригодных для внедрения. Если две соседние цепочки расположены в пределах досягаемости короткого перехода, трех NOP'ob будет вполне достаточно (2 бай га на команду перехода, один - на любую однобайтовую команду полезного кода, например, inc ebx или pop esi). В противном случае нам необходимо иметь цепочку, по крайней мере, из 6-ти NOP'ob - пять на команду близкого перехода и один на полезную команду.

Замена цепочек NOP - наиболее простой способ, который возможно выполнить при помощи языка программирования Ассемблер, что сказывается в пользу применения данной методики для стеговложения. Малые затраты объемов используемой информации инфомацнн (несколько бит), простая замена операторов гарантируют простой и легкий способ самого вложения. Однако стоит разобрать теперь стойкость методики, представленной в данной работе к сте-гоанализу. |4|

Для начала, следует выделить базовое представление о siiellcode [6], В настоящее время shellcode принято называть последовательность опкодов процессора, представимую в виде строки символов и удовлетворяющую ряду свойств:

1. Отсутствие в коде нуль-байтов (символов с кодом 0x00) - это свойство следует из требования того факта, что код должен быть представим в виде прок и. В Си (и еще ряде языков) нуль-байт служит признаком конца строки, следовательно, если в shellcode будет нуль-байт, то при его копировании (или еще какой-нибудь строковой операции) обработается только часть строки до первого нуль-байта, что может вызвать ошибки,

2. Shellcode должен выполниться корректно в любой момент, когда на него будет передано управление (свойство вызвано спектром использования шеллкодов - в различных атаках, в ходе которых повреждается структура памяти), и его работа не должна зависеть от того, в какой области памяти находится байт-код.

3. Shellcode по возможности должен быть универсальным, то есть уметь работать корректно на всех системах одного типа (данное свойство наиболее критично в \viti32-системах).

4. Чем меньше размер байт-кода, тем лучше (больше вероятность того, что мы успешно поместим его в какой-нибудь буфер). В принципе, это свойство можно отнести к категории универсальности.

Одно из решений для скрытия Shellcode - шифрование рабочего тела. Это происходит следующим образом:

1, Само тело Shellcode шифруется при помощи какого-нибудь алгоритма шифрования, позволяющего осуществить

m

однозначную расшифровку крипто ванн ого текста (далее, па деталях шифрования, будем использовать XOR).

2. Перед зашифрованным телом помещается компактный (по возможности) расшифровщик, который придает байт-коду в памяти его первоначальный вид.

3. После расшифровки управление передается па расшифрованный байт-код.

Предлагается использование следующей методики для поддержки шифрования:

1. В зашифрованном коде почти наверняка будут отсутствовать различные сигнатуры наподобие "\xcd\x80", а значит, обнаружить его при помощи IDS будет практически невозможно.

2. Если в написанном коде очень сложно обойтись без нуль-байтов (или их использование дает серьезный выигрыш по размерам кода), то, зашифровав код так, чтобы в зашифрованном виде их не встречалось, мы забудем про эту проблему (следует отметить, что SII31lG0d так выбирает XOR-юноч, чтобы Ох 0-байтов в зашифрованном байт-коде не возникло). В случае XOR-шифровапмя, для выполнения этого условия достаточно, чтобы значение ключа не совпадало ни с одним из байтов кода (т.к. а хог а = 0). [б]

Избавиться от константной структуры кода поможет именно методика замены цепочек NOP (Рис.4). NOP - пустая команда, которая просто передает выполнение на следующую команду. Цепочки NOP-ов используются для того, чтобы можно было проще найти Siiellcode в памяти (достаточно попасть значением EIP на адрес одного из NOP-ов, и управление по цепочке дойдет до нашего байт-кода). Однако всем IDS хорошо известен 0х90-байт, и пакет, содержащий эту субстанцию в необходимых количествах, будет отвергнут системой обнаружения вторжений как потенциально опасный.

BITS 32

mOv еах, еах

mov dl, dl

mov ex,

ex

mov esi, esi mov esp, esp mov si, si inc eax dec dl

[root@id: —/work/cOding/shellgodJ# nasm nops.asm [root@id: ~/work/cOding/shellgod]# ndisasm -b 32 nops mov eax,eax mov dl.dl mov ex,ex mov esi,esi mov esp,esp

mov si,si inc eax dec dl

00000000 89CO 00000002 88D2 00000004 6689C9 00000007 89F6 00000009 89E4 OOOOOOOB 6689F6 OOOOÛOÛE 40 0000000F К EC A

Листинг 3. Пример инструкций, которые не имеют воздействия на процесс исполнения и, следовательно, могут послужить заменой NOP.

самого себя. Однако здесь есть одна проблема - почти у всех этих команд опкоды занимают в памяти минимум два байта. Таким образом, нет никакой гарантии, что попадем мы именно на начало необходимой нам команды, а не на середину, получив в результате Illegal Instruction. [5]

Избавляться от сигнатур можно гю-разному, тут нужно не забывать, что запрограммировать при помощи языка Ассемблера один и тот же алгоритм можно довольно большим количеством способов. Чтобы избавиться от постоянного вида нашего кода, достаточно добавить в случайные места нашего кода некоторое количество случайно выбранных псевдо-NOP-ob, Здесь необходимо помнить, что мы уже не можем модифицировать содержимое пользовательских регистров, однако можем заменять команды вида "mov al, 5" на что-нибудь типа "raov al, 4; inc al" Применяя подобные преобразования к Siiellcode удается надежно защитить его от обнаружения IDS, SH311G0d также умеет случайным образом модифицировать данные на входе Shellcode, уменьшая вероятность его обнаружения. Для этого используется ключ -т. В случае использования ключа -т совместно с -с, программа сначала зашифрует байт-код, а потом модифицирует расшифровщик. Результат — каждый раз обновленный код, что приводит к практически полному отсутствию сигнатур.

Исполнимый код формируется на основе потока выполнения функции. Данный метод может использоваться для проверки целостности отдельных участков исполняемого файла формата .ехе для реализации скрытого вложения информации. Машинный код функции исполнимого файла (рис. 2а) можно представить в виде схемы (рис. 26), в вершинах которого расположены инструкции, а рёбра соответствуют возможным переходам управления между ними. Такая схема имеет ровно одну начальную команду и, как минимум, одну завершающую команду. Истоком этого графа является инструкция, расположенная по адресу точки входа в функция (например, стр или mov), а стоками -инструкции возврата из функции (например, ret) [5].

crop

emp [ebp-8], 0 jnz L1

mov eax, [edp-8] jmp L4 Ll: xor ecx, ecx

jmp L3 L2: inc ecx L3: call firne emp ecx, 10 jnz L2 L4: ret

[ebp-8, 0| ]

Ц

( jnzLÏ J-1 ' [mov eax, jebp-8|]

-[ jmp U ]

[ xor ecxT

[ jmpL3 )-

С

X

>

call func i

Г emp ecx, 10 ] l

-[ jnz 12 ]

I

ret

1

Очевидно, в псевдо-цепочке мы можем различными способами модифицировать содержимое пользовательских регистров, а также переносить данные из любого регистра в

Рис. 2. а) Ассемблерный код функции исполнимого файла; б) Ассемблерный код функции, представленные в виде схемы

7Т>

Исходя из перечисленных методов, возможно, сложить общий алгоритм для реализации методики применения языка Ассемблер для реализации стегано граф и чес ко го вложения. Следует уточнить, что в основу данной методики лежит использование упомянутого Shellcode, что позволит обновлять код без последствий коллизий файла (переполнение буфера или нарушение работоспособности отдельных функций). Состоит он из следующих последовательностей действий:

1. Осуществление первичного безусловного перехода типа J MP

2. Использование особенностей косвенной адресации

3. Реализация последующей замены цепочек NOP

4. Проверка целостности уязвимых участков файлов после стеговложения.

Данные операции позволяют вложить скрываемую информацию в исполнимый файл без типичных признаков вредоносных эффектов, т.е. нарушения целостности файлов. Блок-схема (рис, 3) иллюстрирует порядок использования предложенной методики.

1 бит = о

1 г

пара через <Ь, а> = 0

замена цепочек NOP

ret - false

I'iic. 3. Блок-схема методики скрытого вложения информации в исполнимые файлы при помощи базовых команд и инструкций (JMP, MOV, NOP) языка Ассемблер

Заключение

В основе методики стеганографического вложения в исполняемые файлы с использованием низкоуровневого языка программирования лежит анализ структуры файла, поиск в структуре пар операций присваивания, замена их последовательности в соответствии с передаваемым сообщением передача управления другому процессу, который согласно лексикографическому порядку операций в парах получает переданное скрытое сообщение. При этом синтаксис Ассемблера позволяет вынести описание вложенной структуры файлов за пределы текущей структуры. Замена цепочек NOP на случайные инструкции, не имеющие воздействия на процесс исполнения файла и написанные на языке программирования Ассемблер, позволяет повысить безопасность стеговложения в каждом текущем и всех будущих состояниях системы. Указанное обстоятельство, гарантирует непрерывность обеспечения безопасности стеговложения от вскрытия в текущем и во всех возможных состояниях относительно заданных условий безопасности.

Таким образом, в статье описан объект исследования, даны основные понятия предметной области, приведены свойства опкодов процессора, предложен общий алгоритм использования языка программирования низкого уровня для стеганографического вложения в исполняемые файлы.

Необходимо отметить новизну результата исследования: предлагаемая методика отличается от известных тем, что использование низкоуровневого языка программирования для преобразования, к примеру Shellcode, позволяет каждый раз создавать обновленный код, надежно защитить его от обнаружения, повысить скрытность стеганографического вложения за счет модификации данных случайным образом и создания каждый раз обновленного кода, что приводит к практически полному отсутствию сигнатур.

Литература

1. Штеренберг С.И., Андрианов В.И. Варианты модификации структуры исполнимых файлов формата РЕ // Перспективы развития информационных технологий.-2013.-№ 16.-С. 134-143.

2. Штеренберг С.И., Андрианов В.И, Исследование методики адаптивных атак на основе скрытого вложения в исполнимые файлы // Наука, Техника, Инновации 2014 сборник статей Международной научно-технической конференции, г. Брянск. Под общей редакцией А.Л. Сафонова.-2014, -С, 287-294.

3. Красов A.B., Верещагин A.C.. Абатуров B.C. Методы скрытого вложения информации в исполняемые файлы // Известия Санкт-Петербургского государственного электротехнического университета ЛЭТИ. - 2012. - № 8. - С. 51 -55.

4. Штеренберг С.И.. ВитковаЛ.А., Андрианов В.И. Методы использования пустых секций исполнимого файла для стеговложения саморазвивающегося кода в распределенной системе однозначного отождествления // Системы управления и информационные технологии. - 2015. - Т. 59.-№ 1.1.-С. 189-194.

5. Shterenberg S.I., Krasov A.V., Ushakov I.A. Analysis of using equivalent instructions at the hidden embedding of information into the executable files // Journal of Theoretical and Applied In form at ion Technology. - 2015. - T. 80. - № 1. - C. 28-34.

6. Электронный ресурс - [http://www.secuntylab.ru/ contest/212114.php].

THE METHOD OF APPLICATION ASSEMBLER PROGRAMMING LANGUAGE FOR CONCEALED ATTACHMENT INFORMATION IN EXECUTABLES

Stanislaw I. Shterenberg, post-graduate student SUT prof. Bonch-Bruevich, St. Petersburg, Russia,

shterenberg.stanislaw@yandex.ru

Abstract

In this paper, the technique of using low-level programming language for the steganographic embedding into executables elf format. The relevance of the study is due to the wide distribution of the Linux operating system and the necessity of solving the problem of the definition of viruses in executable files need to define pieces of software created by different users, the current lack of established effective methods of solving such problems hidden attachment information in executables. Compare the language of instruction with algorithmic language has meaning only in relation to the complexity and the complexity of the programming process. Of course, when such a comparison assembler gives algorithmic languages, but this does not mean that it does not need to know and be able to apply in case of need. The undeniable advantage is the ability to assembler programming, rationally using all the features of the particular system computer commands. It provides unlimited possibilities for semantic replacements and surgeries for interaction with the operands in the program code. Another positive feature is the universal language - it allows you to make a program for every problem that has a solution and can be solved on the machines of this family. This statement is based on the obvious fact that any program written in high level language is converted into a sequence of machine instructions at compile time.

For code generated by the compiler, it must meet the following requirements: it must be fully relocatable (independent of base load es) not modify any memory, except stack space, and do not use standard mechanisms for import functions, or connecting all necessary libraries on their own or referring to the native-API. This does not satisfy the requirements of the vast majority of compilers. Disassembler allows you to convert the machine code to the code in assembly language. assembly language code is the human readable form of machine code. With disassembler can find out which machine instructions are used in machine code. Machine code is specific to a particular hardware architecture (for example, for the PowerPC chip or Intel Pentium) and is easy to implement hidden information investments.

Keywords: Assembler, executable, steganography, the compiler, hex-editor.

References

1. Shterenberg S.I., Andrianov V.I. Options for modifying the structure of PE executable file format / Prospects of development of information technologies. 2013. No. 16. Pp. 134-143.

2. Shterenberg S.I., Andrianov V.I. Research methodology of adaptive attacks based on concealed attachments executables / Science, Technology, Innovation in 2014 a collection of articles of the International Scientific Conference., Bryansk. Edited by AL Safonov. 2014. Pp. 287-294.

3. Krasov A.V., Vereshchagin A.S., Abaturov V.S. Methods for embedding hidden information into executable files / Proceedings of the St. Petersburg State Electrotechnical University LETI. 2012. No. 8. Pp. 51-55.

4. Shterenberg S.I., Vitkova L.A., Andrianov V.I. Methods of use of empty sections of executable code for stegovlozheniya self-developing in a distributed unambiguous identification system / Control systems and information technologies. 2015. Vol. 59. No. 1.1. Pp. 189-194.

5. Shterenberg S.I., Krasov A.V., Ushakov I.A. Analysis of using equivalent instructions at the hidden embedding of information into the executable files / Journal of Theoretical and Applied Information Technology. 2015. Vol. 80. No. 1. Pp. 28-34.

6. Electronic resource. [http://www.securitylab.ru/contest/2l2ll4.php].

r I >