Основной алгоритм добавления новой секции
Решение проблемы доступного пространства при помощи добавления новой секции имеет некоторые недостатки. Практически все антивирусы опознают нестандартные секции, и если, к тому же, там есть полный набор флагов на чтение/запись/выполнение, то эта ситуация выглядит еще более подозрительно. Но такой способ дает огромное преимущество в объеме внедренного кода.
В начале проведения внедрения необходимо получить общие сведения о файле: определение языка программирования (или компилятора), разрядности архитектуры (32/64), название упаковщика или криптора. Для этого надо использовать программы-анализаторы РЕ-файла, например CFF Explorer, PeStudio или др.
В общем случае алгоритм добавления новой секции может быть таким:
- При помощи программ-анализаторов РЕ-файла.
- определяем язык программирования, название упаковщика или криптора;
- определяем объем свободных ячеек основной секции кода для вставки команды jmp перехода на новый блок;
- добавляем новую секцию, проставляем ее физический и виртуальный размеры, а также флаги секции
- При помощи шестнадцатеричного редактора, например FlexHex, заполняем ячейки нового блока нулями.
- При помощи отладчика кода, например x64Dbg, перемещаем одну или две команды по адресу новой ячейки и на освободившееся место поставить команду перехода jmp на этот адрес.
В новой секции пишем новый блок кода, последней командой которого должна быть команда возврата jmp на продолжение кода в основной секции.
Добавление новой секции
Рассмотрим добавление новой секции на конкретном примере. Предположим, что существует программа (программа 6.1), написанная в среде masm64 с использованием команд SSE, которая вычисляет математическое уравнение. В эту программу необходимо внедрить свое сообщение функцией MessageBox и добавить его в новую секцию.
Программа 6.1. Сложение 32-разрядных дробных чисел одного массива с использованием команд SSEРезультатами выполнения программы являются последовательно появляющиеся окна сообщений (рис. ).Код (ASM):
; masm64. include win64a.inc ; подключаемые библиотеки .data mas1 dd 1.,2.,3.,4. tit0 db "Сложение чисел массива ",0 ; inf0 db "Использование SSE команд",0 titl1 db "Сложение чисел массива ",0 ; fmt db "Сложение 32-разрядных дробных чисел одного массива",10, "с использованием команд SSE",10, "mas1: 1., 2., 3., 4.", 10,13, "Сумма: %d",10, "Автор: Рысованый А.Н., каф. ВТП, фак. КИТ, НТУ ХПИ",10, 9,"Сайт: http://blogs.kpi.kharkov.ua/v2/asm/",0 buf1 dq 0,0 ; буфер .code WinMain proc sub rsp,28h; cтек: 28h=32d+8; 8 - возврат mov rbp,rsp invoke MessageBox,0,addr inf0,ADDR tit0,0 movaps XMM0,mas1 ; XMM0:= 4. 3. 2. 1. movaps XMM1,XMM0 ; XMM1:= 4. 3. 2. 1. shufps XMM1,XMM1,11111001b ; XMM1:= 4. 4. 3. 2. addss XMM0,XMM1 ; XMM0:= 4. 3. 2. 3. shufps XMM1,XMM1,11111001b ; XMM1:= 4. 4. 4. 3. addss XMM0,XMM1 ; XMM0:= 4. 3. 2. 6. shufps XMM1,XMM1,11111001b ; XMM1:= 4. 4. 4. 4. addss XMM0,XMM1 ; XMM0:= 4. 3. 2. 10. cvttss2si eax,xmm0 movsxd r15,eax invoke wsprintf,addr buf1,addr fmt,r15 invoke MessageBox,0,addr buf1,ADDR titl1,MB_ICONINFORMATION invoke RtlExitUserProcess,0 ; invoke ExitProcess,0 WinMain endp end
Рассмотрим процесс добавления новой секции кода и внедрение сообщения при помощи функции MessageBox между двумя функциями MessageBox.
Этапы внедрения рассмотрим по пунктам.
После сохранения файла под новым именем с расширением ехе выведется окно сообщения (рис. 6.20).
- Определяем объем свободных ячеек основной секции кода для вставки команды jmp перехода на новый блок. Для этого в программе-анализаторе РЕ-кода LordPE выполняем действия:
- открываем исследуемый файл;
- нажимаем на кнопку меню Sections;
- выделяем мышкой секцию кода text;
- нажимаем правую клавишу мышки и выбираем кнопку меню hex edit section…
- подсчитываем объем свободных ячеек основной секции кода. Содержимое выделенной секции выводится на черном фоне. Для расчета необходимо из начального адреса следующей секции вычитаем адрес первой свободной ячейки после окончания кода:
600h – 482h = 17Еh = 382 байта.- Добавляем новую секцию кода. Для этого в программе-анализаторе РЕ-кода LordPE выполняем действия:
- нажимаем на кнопку меню Sections (рис. );
- выделяем любую секцию и добавляем новую секцию при помощи кнопки меню add section header (рис. );
- в появившемся окне выделяем новую секцию и для изменения свойств новой секции нажимаем на кнопку меню edit section header… (рис. ).
При этом необходимо запомнить смещение ROffset новой секции. В рассматриваемом случае оно равно 00000А00h;
Если предполагается использовать почти весь объем секции, то и виртуальный размер VSize должен быть таким же как и физический или больше чтобы не тормозить запись и чтение данных секции (рис. );
- для изменения признаков секции выбираем кнопку меню Flags (рис. ).
Если после проведенных действий попытаться открыть ехе-файл исследуемой программы в отладчике x64Dbg, то такая попытка не завершится успешно. Дело в том, что новая секция объявлена, в ней проставлены признаки, но ничего не записано (даже нули).
- Заполняем ячейки нового блока нулями.
Для записи в новую секцию нулей необходимо использовать 16-ричный редактор. Выберем, например редактор FlexHex. Открываем программу с новой секцией в редакторе FlexHex и перемещаемся в конец секции.
Ищем место в секции, где расположена (объявлена) новая секция. А она начинается с адреса RawOffset (ROffset). В нашем случае – это адрес 00000А00h (рис. ).
Ставим курсор на первый байт новой секции (по адресу 00000А00h).
Выбираем пункты меню Edit / Insert Zero Block.
- в появившемся окне проставляем размер новой секции: Block Size = 200h (рис. );
- сохраняем изменения;
- желательно проверить готовность новой секции программой-анализатором LordPE. Для этого необходимо выбрать новую секцию, нажать правую клавишу мышки и нажать пункт меню hex edit section. В появившемся окне memory buffer выбранная секция выделится темным цветом (рис. ).
При нажатии левой клавиши мышки на любом окне программы LordPE темный фон исчезает.- Вносим изменения в код, используя отладчик x64Dbg.
В отладчике x64Dbg открываем исследуемую программу и еще раз убеждаемся, что новая секция готова к использованию. Для этого выбираем последнюю строку основного меню и в ней пункт Карта памяти (рис. ).
Если выделить новую секцию и дважды нажать на левую клавишу мышки, то можно вносить изменения в эту секцию.- Проанализируем исследуемую программу в отладчике x64Dbg. Внешний вид кода показан на рис.
Между двумя функциями MessageBox необходимо вставить новую функцию MessageBox. По заданию новая функция MessageBox должна размещаться в новой секции, которую мы уже создали. Для перехода на эту секцию кода надо в исследуемую программу вставить команду jmp на адрес этой секции.
- Освободим место для команды jmp. Выберем команду
Дважды выделяем эту строку (рис. ) и ее копируем (нажимаем Ctrl + C).Код (ASM):
movaps xmm0, xmmword ptr ds:[0x00007FF65DE13000]
- Затем в последней строке основного меню выбираем пункт Карта памяти (см. рис. 6.10). Подводим курсор к строке с названием новой секции и дважды нажимаем на этой строке.
Попадаем в новую секцию. Нажимаем на первую строчку кода, появляется окно (рис. 6.13),
в которое вставляем перенесенную строку при помощи сочетания клавиш Ctrl+V (рис. 6.14).
- Копируем адрес первой строки, чтобы на нее поставить команду перехода jmp в основной секции кода. Для этого, на первой строке секции выбираем кнопки меню Копировать/Адрес.
- Переходим на основную секцию кода. Для этого в нижней (последней) строке основного меню выбираем пункт Карта памяти (см. рис. 6.10). После этого подводим курсор на строку кода с названием основной секции кода text, дважды нажимаем на этой строке и попадаем в основную секцию.
Дважды нажимаем на строку кода, которую уже перенесли в новую секцию, пишем слово jmp, а затем вставляем из буфера Ctrl+V (рис. 6.15).
- В качестве примера вставки выбираем вторую функцию MessageBox и построчно переносим сначала параметры функции, а затем и вызов самой функции в новую секцию. Для этого, для каждой переносимой строчки выполняем последовательность действий:
Результат переноса параметров и самой функции показан на рис. 6.17.
- копируем строчку кода. На выбранной строчке кода дважды нажимаем левую клавишу мышки и нажимаем Ctrl+C;
- выбираем пункт Карта памяти;
- дважды нажимаем на строчке кода с названием новой секции;
- выбираем место для вставки кода и нажимаем Ctrl+V.
- Последней командой должна быть команда возврата jmp на адрес продолжения кода в основной секции. Для этого перейдем на основную секцию и скопируем адрес на неизмененную строку кода (рис. 6.18).
- Правим содержимое параметров функции MessageBox.
Меняем адреса ячеек в параметрах. Будем выводить в титуле и окне функции MessageBox одну и туже информацию. Для этого выделяем первую свободную строку новой секции кода (после последней команды jmp), нажимаем правую клавишу мышки и выбираем пункты меню Копировать/Адрес.
Последовательно выделяем строки кода с передачей параметров через регистры rdx и r8 и заменяем адреса (Ctrl+V).
Изменяем содержимое ячеек памяти через дамп. Для этого на строке кода, например регистра rdx, нажимаем правую клавишу мышки и выбираем пункты меню Перейти к дампу/Константа.
После этого ставим курсор на начальный байт в дампе памяти отладчика, нажимаем правую клавишу мышки и выбираем меню Двоичные операции/Редактировать. В появившемся окне в строке ASCII пишем текст (рис. 6.19).
- Сохраняем все изменения.
Для этого можно выбрать пиктограмму с названием Исправления, нажать на кнопку Исправить файл, а далее новое имя и расширение ехе.
Добавление новой секции и внедрение в нее успешно осуществлено.
Внедрение кода. Добавление новой секции. Часть 7.
Дата публикации 5 апр 2019
| Редактировалось 2 окт 2019