Перекрытие кода с переходом назад по коду программы. Часть 9.

Дата публикации 9 апр 2019 | Редактировалось 17 май 2019
Рассмотрение этой части невозможно без изучения предыдущей части.

При рассмотрении программы, в котором применена технология перекрытия кода необходимо с начала открыть отладчик, т.к. только в нем приведены все коды операций и данные в машинном представлении. В программе 7.4 применена технология перекрытия кода с переходом назад по коду программы.

Программа 7.4.
Код (ASM):
  1. include win64a.inc
  2. .code
  3. WinMain proc
  4. sub rsp,28h;
  5. mov rbp,rsp
  6. mov ax,05EBh
  7. jmp $ - 2  ; пропуск 2 байтов EB 05 и остановка на EB
  8. ; EB 05 – это jmp на 5 байтов вперед с учетом своих 2-х байтов
  9. dec r9  ; пропускаем, 3 байта: 49:FFC9
  10. inc r10  ; выполняем с этой команды
  11. mov r8,1
  12. mov eax,06EB0000h
  13. jmp $ - 2  ; пропуск 2 байтов 06 и EB и остановка на EB
  14. ; EB 06 – это jmp на 6 байтов вперед с учетом своих 2-х байтов
  15. dec cl  ; пропускаем, 2 байта: FE C9
  16. dec al      ; пропускаем, 2 байта: FE C8
  17. dec dl   ; выполняем с этой команды
  18. nop
  19. mov rax,09EB000000000000h
  20. jmp $ - 2  ; пропуск 2 байтов EB 09 и остановка на EB
  21. ; EB 09 – это jmp на 9 байтов вперед с учетом своих 2-х байтов
  22. mov r15,1  ; пропускаем, 7 байтов: 49:C7C7 01000000
  23. nop  ; выполняем с этой команды
  24. invoke RtlExitUserProcess,0 ; invoke ExitProcess,0
  25. WinMain endp
  26. end
Скомпилируем программу и откроем ее ехе-файл в отладчике x64Dbg. В начале программы приведен блок кода:
Код (ASM):
  1. mov ax,05EBh
  2. jmp $ - 2
В рассматриваемом случае применен 16-разрядный регистр. Поэтому в отладчике команда mov располагается в памяти как
66:B8 EB05 mov ax,05EB
Первый байт с содержимым 66 – это префикс замены размера операнда (16-битный регистр ах); B8 – код команды mov; EB 05 – константа 05EBh, записанная по правилу «младший байт – по младшему адресу» (рис. 7.4).
upload_2019-4-9_21-22-3.png

Следующая команда в тексте программы 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 на строке
00007FF7D0CB100BEB FCjmp rp l2-3.3.1.7FF7D0CB1009
эта строка выполнится и команда mov ax,05EB преобразится в команду
jmp rp l2-3.3.1.7FF7D0CB1010 (рис. 7.5).
upload_2019-4-9_21-22-26.png

Кодировка машинной команды EB 05 обозначает, что команда EB – это код операции, а 05 – число байт, через которые команда осуществит переход. Это байты EB FC (2 байта) и 49: FF C2 (3 байта). Следует также серьезное внимание уделить тому факту, что на этот же адрес в отладчике указывают стрелочки переходов слева, а также в самой команде jmp записан этот адрес. В программе нельзя записывать непосредственно адрес перехода, но при отладке заранее можно командой jmp $- подобрать этот адрес.
Рассмотрим в программе следующие строки, в которых осуществляется перекрытие кода
Код (ASM):
  1. mov eax,06EB0000h
  2. jmp $ - 2
В этом блоке кода применен 32-разрядный регистр. Поэтому и запись в него происходит 32-разрядным числом и сначала записаны младшие числа, а затем – старшие.
После выполнения этого блока произойдет прыжок назад во внутрь команды mov eax,06EB0000h на байты ЕВ06 (рис. 7.6).

upload_2019-4-9_21-23-5.png


Рассмотрим следующие строки, в которых осуществляется перекрытие кода
Код (ASM):
  1. mov rax,09EB000000000000h
  2. jmp $ - 2
В этом блоке кода применен 64-разрядный регистр. Поэтому и запись в него происходит 64-разрядным числом и сначала записаны младшие числа, а затем – старшие (48:B8 000000000000EB09). Каждый байт в машинном коде имеет адрес и к любому байту по их адресу можно обратиться.
После выполнения команды jmp $ - 2 произойдет переход во внутрь команды mov (48:B8 000000000000EB09) на байты ЕВ06 (рис. 7.7).

upload_2019-4-9_21-23-21.png



После рассмотрения перекрытия кода с переходом назад по коду программы можно сделать вывод: следует применять этот способ достаточно осторожно и остерегаться зацикливания кода. Этот способ хорошо подходит для неявного, но «перепрыгивания» ненужного кода или данных в секции кода.

0 2.180
Alex81524

Alex81524
New Member

Регистрация:
12 фев 2008
Публикаций:
5