Перекрытие кода с переходом вперед по коду программы. Часть 10.

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

Рассмотрим программу 7.5, в которой применена технология перекрытия кода, но с переходом вперед по коду программы.
Программа 7.5.
Код (ASM):
  1. include win64a.inc
  2. .data
  3. .code
  4. WinMain proc
  5. sub rsp,28h;
  6. mov rbp,rsp
  7. mov ax,05EBh
  8. jmp $ + 5 ; перепрыгивает свои 2 байта и 3 байта dec r9
  9. dec r9    ; 49:FFC0
  10. inc r10   ; выполняем с этой команды
  11. mov r8,1
  12. mov eax,06EB0000h
  13. jmp $ + 6  ; перепрыгивает свои 2 байта и следующие 4
  14. dec cl   ; FEC9
  15. dec al  ; FEC8
  16. dec dl  ; FECA; выполняем с этой команды
  17. nop
  18. mov rax,09EB000000000000h
  19. jmp $ + 9  ; перепрыгивает свои 2 байта и следующие 7
  20. mov r15,1  ;  49:C7C7 0100 0000
  21. nop    ; выполняем с этой команды
  22. invoke RtlExitUserProcess,0 ; invoke ExitProcess,0
  23. WinMain endp
  24. end
В приведенной программе применяется строковый идентификатор $ с различными положительными приращениями. Такое идентичное необходимо для того, чтобы рассмотреть особенности переходов через регистры с разной разрядной сеткой.
В первом интересующим нас блоке кода
Код (ASM):
  1. mov ax,05EBh
  2. jmp $ + 5 ; перепрыгивает свои 2 байта и 3 байта dec r9
  3. dec r9  ; 49:FFC0
  4. inc r10  ; выполняем с этой команды
команда mov ax,05EBh ни на что не влияет.
Значение имеет команда jmp $ + 5, которая занимает в памяти 2 байта: EB03. По результатам выполнения этой команды происходит переход через свои 2 байта и 3 байта, расположенных за ней строки кода. Всего получилось смещение на 5 байтов. Для простоты рассмотрения применена команда dec r9 с кодом операции 49:FFC0, которая имеет размерность 3 байта. Но если есть логический смысл и задумка программиста, то можно указать другое смещение адреса и войти во внутрь этой команды и выполнить совсем другой код операции.
Следующие блоки кода со смещениями +6 и +9 имеют аналогичный смысл и эти блоки хорошо прокомментированы.

Рассмотрим применение положительных смещений в строковом идентификаторе $ (программа 7.6).
Программа 7.6.
Код (ASM):
  1. include win64a.inc
  2. .data
  3. a1 db 1
  4. b1 db 2
  5. c1 db 4
  6. d1 db 3
  7. .code
  8. WinMain proc
  9. sub rsp,28h;
  10. mov rbp,rsp
  11. ; блок1 : ab + c/d
  12. mov al,a1
  13. mul b1
  14. mov cl,al
  15. mov al,c1
  16. div d1
  17. add al,cl
  18. nop
  19. ; блок2 : ab + c/d
  20. mov al,a1 ; 6 байтов: 8A05 D61F0000
  21. jmp $+4    ; 2 байта: EB 02
  22. nop ;
  23. nop ;
  24. mul b1    ; 6 байтов: F625 CD1F0000
  25. jmp $+5    ; 2 байта: EB 03
  26. dec dx    ; 3 байта:  66:FFCA
  27. mov cl,al  ;
  28. jmp $+9   ; 2 байта: EB 07
  29. mov r15,1 ; 7 байтов: 49:C7C7 01000000
  30. mov al,c1  ;
  31. jmp $+7  ; 2 байта: EB 05
  32. mov esi,1234 ; 5 байтов: BE D2040000
  33. div d1  ;
  34. add al,cl ;
  35. invoke RtlExitUserProcess,0 ; invoke ExitProcess,0
  36. WinMain endp
  37. end
Программа состоит из двух частей, которые выполняют вычисление одного и того же целочисленного выражения: ab + c/d.
В блоке 1 кода отсутствуют какие-либо запутывания кода. А в блоке 2 вычисляется тоже самое выражение, но с применением строкового идентификатора для небольшого затруднения анализа. Для простоты анализа в блоке 2 отсутствуют вхождения во внутрь машинного кода команд, что является существенным недостатком этой программы. Но даже и такое применение затрудняет анализ этого кода.
Перед тем, как применить перекрытие кода рассмотрим обычную программу пересылки целочисленного массива из одного места памяти в другой при помощи команд SSE (программа 7.7).

Программа 7.7.
Код (ASM):
  1. include win64a.inc
  2. .data
  3. mas1 DD 20 dup(1,2,4,6) ; резервирование ячеек памяти для mas1
  4.   dd 16 dup(1)  ; 80+16=96
  5. len1 equ ($-mas1)/type mas1
  6. mas2 DD len1 dup(0) ; резервирование ячеек памяти для mas2
  7. ifmt db "… masm64",10,
  8. "…",0
  9. titl1 db "Пересылка целых чисел, SSE",0
  10. .code
  11. WinMain proc
  12. sub rsp,28h;
  13. mov rbp,rsp
  14. mov rcx,len1/4 ; количество блоков массива mas1
  15.  lea rsi,mas1  ; адрес начала массива mas1
  16.  lea rdi,mas2  ; адрес начала массива mas2
  17. @@: movups xmm0,dword ptr [rsi] ; пересылка 4-x 32-разрядных целых чисел
  18. movups dword ptr [rdi],xmm0
  19. add rsi,16;
  20. add rdi,16;
  21. loop @b
  22. invoke MessageBox,0,addr ifmt,addr titl1,MB_ICONINFORMATION
  23. invoke RtlExitUserProcess,0 ; invoke ExitProcess,0
  24. WinMain endp
  25. end
Для затруднения анализа этой программы внесем в нее незначительные изменения путем внесения данных в секцию кода. Данные можно переносить только те, которые при выполнении программы не требуют записи (изменений) в секцию кода (в последующем будет рассмотрена такая возможность при помощи изменений атрибутов секции) (программа 7.8).

Программа 7.8.
Код (ASM):
  1. include win64a.inc
  2. .data
  3. mas1 DD 20 dup(1,2,4,6) ; резервирование ячеек памяти для mas1
  4.   dd 16 dup(1)  ; 80+16=96
  5. len1 equ ($-mas1)/type mas1
  6. mas2 DD len1 dup(0) ; резервирование ячеек памяти для mas2
  7. .code
  8. WinMain proc
  9. sub rsp,28h;
  10. mov rbp,rsp
  11. mov rcx,len1/4 ; количество блоков массива mas1
  12.  lea rsi,mas1    ; адрес начала массива mas1
  13.   lea rdi,mas2  ; адрес начала массива mas2
  14. jmp m2
  15. ifmt db "Проверка перекрытия кода на masm64",10,
  16. "Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
  17. m2:
  18. @@: movups xmm0,dword ptr [rsi] ; пересылка 4-x 32-разрядных целых чисел
  19. movups dword ptr [rdi],xmm0
  20. add rsi,16;
  21. jmp m1
  22. titl1 db "Пересылка целых чисел, SSE",0
  23. m1:
  24. add rdi,16;
  25. loop @b
  26. invoke MessageBox,0,addr ifmt,addr titl1,MB_ICONINFORMATION
  27. invoke RtlExitUserProcess,0 ; invoke ExitProcess,0
  28. WinMain endp
  29. end
Получим из этого файла ехе-файл. Откроем его в отладчике x64Dbg (рис. 7.8) и обратим внимание на строку кода
00007FF7F4121070EB 1Bjmp rp l2-13.7FF7F412108D
upload_2019-4-9_21-26-29.png


В этой строке команда jmp обращается к адресу, который находится уже внутри другой команды:
00007FF7F412108B45:0048 83add byte ptr ds:[r8-7D],r9b
Так отладчик отреагировал на команду jmp, которая размещена внутри другого цикла – тем самым применив собственное перекрытие кода.
Принимаем решение на применение перекрытия кода на примере команды jmp, которая обрамляет последний блок данных. Эта команда размещена по адресу 7FF7F4121070h, а передает управление на адрес 7FF7F412108Dh. Получаем разницу между адресами 1Dh. Эту разницу будем применять при перекрытии кода.
Следующим шагом в изменении первоначальной программы является применение перекрытия кода. В учебных целях проще это делать на командах jmp потому, что на других командах применение перекрытия приводит к зацикливанию этой части программы (программа 7.9).
Программа 7.9.
Код (ASM):
  1. include win64a.inc
  2. .data
  3. mas1 DD 20 dup(1,2,4,6) ; резервирование ячеек памяти для mas1
  4.   dd 16 dup(1)  ; 80+16=96
  5. len1 equ ($-mas1)/type mas1
  6. mas2 DD len1 dup(0) ; резервирование ячеек памяти для mas2
  7.  
  8. mySg1 segment READ WRITE EXECUTE alias ("mySeg")
  9. ;.code
  10.  
  11. WinMain proc
  12. sub rsp,28h;
  13. mov rbp,rsp
  14. mov rcx,len1/4 ; количество блоков массива mas1
  15. lea rsi,mas1  ; адрес начала массива mas1
  16. lea rdi,mas2  ; адрес начала массива mas2
  17. jmp m2
  18. ifmt db "Проверка перекрытия кода на masm64",10,
  19. "Рысованый А.Н., каф. ВТП, НТУ ХПИ",0
  20. m2:
  21. @@: movups xmm0,dword ptr [rsi] ; пересылка 4-x 32-разрядных целых чисел
  22. movups dword ptr [rdi],xmm0
  23. add rsi,16;
  24. mov ax,1debh
  25. jmp $-2
  26.   ; jmp m1
  27. titl1 db "Пересылка целых чисел, SSE",0
  28.   ; m1:
  29. add rdi,16;
  30.  loop @b
  31. invoke MessageBox,0,addr ifmt,addr titl1,MB_ICONINFORMATION
  32. invoke RtlExitUserProcess,0 ; invoke ExitProcess,0
  33. WinMain endp
  34. mySg1 ends
  35. end
В программе для затруднения анализа, данные, которые в процессе выполнения не изменяются, размещены в секции кода и эта секция переименована управляющим словом segment в новое имя mySeg. Данные обрамлены командой jmp и соответствующей меткой.

Результат выполнения программы приведен на рис. 7.9.
upload_2019-4-9_21-27-21.png

Команда jmp заменена на строки кода
Код (ASM):
  1. mov ax,1debh
  2. jmp $-2
В регистр AX заносится код операции jmp – значение 0EBh и смещение – 1Dh (рис. 7.10).

upload_2019-4-9_21-27-49.png

Непосредственный результат пересылки целочисленных данных можно посмотреть в дампе памяти отладчика x64Dbg.

0 2.758
Alex81524

Alex81524
New Member

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