Рассмотрение этой части невозможно без изучения предыдущей части.
При рассмотрении программы, в котором применена технология перекрытия кода необходимо с начала открыть отладчик, т.к. только в нем приведены все коды операций и данные в машинном представлении. В программе 7.4 применена технология перекрытия кода с переходом назад по коду программы.
Программа 7.4.Скомпилируем программу и откроем ее ехе-файл в отладчике x64Dbg. В начале программы приведен блок кода:Код (ASM):
include win64a.inc .code WinMain proc sub rsp,28h; mov rbp,rsp mov ax,05EBh jmp $ - 2 ; пропуск 2 байтов EB 05 и остановка на EB ; EB 05 – это jmp на 5 байтов вперед с учетом своих 2-х байтов dec r9 ; пропускаем, 3 байта: 49:FFC9 inc r10 ; выполняем с этой команды mov r8,1 mov eax,06EB0000h jmp $ - 2 ; пропуск 2 байтов 06 и EB и остановка на EB ; EB 06 – это jmp на 6 байтов вперед с учетом своих 2-х байтов dec cl ; пропускаем, 2 байта: FE C9 dec al ; пропускаем, 2 байта: FE C8 dec dl ; выполняем с этой команды nop mov rax,09EB000000000000h jmp $ - 2 ; пропуск 2 байтов EB 09 и остановка на EB ; EB 09 – это jmp на 9 байтов вперед с учетом своих 2-х байтов mov r15,1 ; пропускаем, 7 байтов: 49:C7C7 01000000 nop ; выполняем с этой команды invoke RtlExitUserProcess,0 ; invoke ExitProcess,0 WinMain endp endВ рассматриваемом случае применен 16-разрядный регистр. Поэтому в отладчике команда mov располагается в памяти какКод (ASM):
mov ax,05EBh jmp $ - 2
66:B8 EB05 mov ax,05EB
Первый байт с содержимым 66 – это префикс замены размера операнда (16-битный регистр ах); B8 – код команды mov; EB 05 – константа 05EBh, записанная по правилу «младший байт – по младшему адресу» (рис. 7.4).
Следующая команда в тексте программы jmp $ - 2 заставляет микропроцессор пропустить 2 байта из правой части (05 и EB) предыдущей строки кода, остановиться на коде операции EB и выполнить байты EB 05, что уже обозначает команду jmp $ + 5, т.е. переход на 5 байт вперёд по коду программы.
Если выполнить команду jmp $ - 1, то будет осуществлен переход на байт с содержимым 05, а он интерпретируется командой add eax,FF49FDEB, что в нашем случае не имеет (пока) никакого смысла.
Байт EB – код операции jmp, а байт с содержимым 05 – смещение на 5 байт вперед, т.е пропускаются байты EB FC (2 байта), 49: FF C9 (3 байта). После пропуска этих пяти байтов будет выполняться строка кода inc r10.
Для пошагового выполнении программы в отладчике x64Dbg последовательно нажимаем F8. И после нажатия F8 на строке
эта строка выполнится и команда mov ax,05EB преобразится в команду
00007FF7D0CB100B EB FC jmp rp l2-3.3.1.7FF7D0CB1009
jmp rp l2-3.3.1.7FF7D0CB1010 (рис. 7.5).
Кодировка машинной команды EB 05 обозначает, что команда EB – это код операции, а 05 – число байт, через которые команда осуществит переход. Это байты EB FC (2 байта) и 49: FF C2 (3 байта). Следует также серьезное внимание уделить тому факту, что на этот же адрес в отладчике указывают стрелочки переходов слева, а также в самой команде jmp записан этот адрес. В программе нельзя записывать непосредственно адрес перехода, но при отладке заранее можно командой jmp $- подобрать этот адрес.
Рассмотрим в программе следующие строки, в которых осуществляется перекрытие кода
В этом блоке кода применен 32-разрядный регистр. Поэтому и запись в него происходит 32-разрядным числом и сначала записаны младшие числа, а затем – старшие.Код (ASM):
mov eax,06EB0000h jmp $ - 2
После выполнения этого блока произойдет прыжок назад во внутрь команды mov eax,06EB0000h на байты ЕВ06 (рис. 7.6).
Рассмотрим следующие строки, в которых осуществляется перекрытие кодаВ этом блоке кода применен 64-разрядный регистр. Поэтому и запись в него происходит 64-разрядным числом и сначала записаны младшие числа, а затем – старшие (48:B8 000000000000EB09). Каждый байт в машинном коде имеет адрес и к любому байту по их адресу можно обратиться.Код (ASM):
mov rax,09EB000000000000h jmp $ - 2
После выполнения команды jmp $ - 2 произойдет переход во внутрь команды mov (48:B8 000000000000EB09) на байты ЕВ06 (рис. 7.7).
После рассмотрения перекрытия кода с переходом назад по коду программы можно сделать вывод: следует применять этот способ достаточно осторожно и остерегаться зацикливания кода. Этот способ хорошо подходит для неявного, но «перепрыгивания» ненужного кода или данных в секции кода.
Перекрытие кода с переходом назад по коду программы. Часть 9.
Дата публикации 9 апр 2019
| Редактировалось 17 май 2019