Нет доступа к записи в область памяти с кодом программы

Тема в разделе "WASM.BEGINNERS", создана пользователем ArhY, 13 июн 2010.

  1. ArhY

    ArhY New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2010
    Сообщения:
    4
    Уважаемые Експерты! Есть пока что простенькое приложение в котором данные находятся сразу же за кодом в одной области памяти. Вот исходный код:

    Код (Text):
    1.       .586
    2.       .model flat, stdcall
    3.       option casemap :none   ; case sensitive.
    4. ;#########################################################################
    5.       include \masm32\include\windows.inc
    6.       include \masm32\include\user32.inc
    7.       include \masm32\include\kernel32.inc
    8.  
    9.       includelib \masm32\lib\user32.lib
    10.       includelib \masm32\lib\kernel32.lib
    11. ;#########################################################################
    12.     .data
    13. ;#########################################################################
    14.     .code
    15.    
    16.     Modulation  proc
    17.         ret
    18.     Modulation  endp
    19.    
    20. start:
    21.       mov eax, offset CS:Dump   ; Занести в ЕАХ адрес Dump-а. Просто для теста правильности.
    22.       mov EBX, 0AAAAAAAAh;
    23.       mov [eax], EBX            ; Попытка записать в область памяти Dump-а число 0AAAAAAAAh. В отладчике да и в следующем ексепшене адреса правильные.
    24.                                 ; Но, вылетает Exception: Инструкция по адресу 0х0040100B обратилась к памяти по адресу 0x0040101F. Память
    25.                                 ; не может быть written.
    26.  
    27.       mov eax, CS:Dump          ; Занести в ЕАХ 4 байта из того что находиться в Dump-е, в моем примере FF00FF00h. Тоже для теста правильности.
    28.       call Modulation           ; Пока ничего не делает.
    29.       invoke ExitProcess, NULL  ; Звершение процесса.
    30.      
    31.       Dump dd 100h dup (00FF00FFh) ; Данные в области кода, которые следуют за размещением invoke ExitProcess, NULL.
    32. end start
    Нужно сделать так чтобы весь код (его численное представление), который идет после метки Start и до оглашения массива Dump записался в этот массив. Так сказать создалась резервная копия кода. Всё сводится к тому что нужно побайтно прочитать код после метки Start и записать его побайтно в массив Dump. Для демонстрации я пытаюсь записать число 0AAAAAAAAh в первые 4 байта массива Dump, но вылетает Exception: Инструкция по адресу 0х0040100B обратилась к памяти по адресу 0x0040101F. Память не может быть written. Но мне именно надо записывать сверху области кода. Перед вызовом процедури Modulation в EAX должно быть число 0AAAAAAAAh, а не 00FF00FFh.
    Использую masm32 (ml 6.14) Окошко OLLY DEBUGGER прилагается.
     
  2. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    в секции кода память не доступна для записи, так что сначала надо VirtualProtect
     
  3. VaZoNeZ

    VaZoNeZ New Member

    Публикаций:
    0
    Регистрация:
    12 июл 2009
    Сообщения:
    121
    При линковке файла, можно указать сооттветствующие аттрибуты.
     
  4. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Самое простое -- вынести массив в отдельную секцию с доступом rw.
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Защита это базовое понятие в архитектуре, на основе этого сама модель системы стоется. Как можно кодить на масме не понимая этого не понимаю.
     
  6. ArhY

    ArhY New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2010
    Сообщения:
    4
    Спасибо qwe8013.
    Ключевое слово твоего поста VirtualProtect позволило сформировать правильный запрос в Google. Действительно запись в области кода можно разрешить с помощью этой функции. Её я и буду использовать.

    Спасибо VaZoNeZ
    Указав сборщику такие параметры: link.exe /SUBSYSTEM:WINDOWS /section:.text,ERW можно разрешить запись во всей области кода, но иногда нужно разрешить запись только в некоторой части кода.

    Спасибо Mika0x65
    Я так и сделал. Вынес массив для сохранения кода в отдельную секцию. Но не использовал адресацию CS:lol: ump и размер блока равный размеру Dump-а. Вместо этого я ссылаюсь на адрес начала блока и вычисляю его размер (АдресКонцаБлока-АдресНачалаБлока).

    Всё вышло благодаря вашим ответам.
    Код (Text):
    1.       .586
    2.       .model flat, stdcall
    3.       option casemap :none; case sensitive.
    4. ;#########################################################################
    5.       include \masm32\include\windows.inc
    6.       include \masm32\include\user32.inc
    7.       include \masm32\include\kernel32.inc
    8.  
    9.       includelib \masm32\lib\user32.lib
    10.       includelib \masm32\lib\kernel32.lib
    11. ;#########################################################################
    12.     .data
    13.         OldData dd 00000000h            ;
    14. ;#########################################################################
    15.     .code
    16.    
    17.     Modulation  proc
    18.         ret
    19.     Modulation  endp
    20.    
    21. start:
    22.       mov ecx, Execute_Read_Write_Start ; Сохранить в ЕСХ адрес начала блока в которм теперь будет разрешена запись.
    23.       mov eax, Execute_Read_Write_End   ;
    24.       sub eax, ecx                      ; Записать в ЕАХ размер блока в байтах.
    25.  
    26.       xor edx, edx                      ;
    27.       mov ebx, 00000004h                ; Размер в байтах типа SIZE_T (для моей MustDie (Windows) XP x32).
    28.       div ebx                           ; Теперь в ЕАХ находится размер блока в единицах SIZE_T (потому что размер
    29.                                         ; блока для которого изменяются права на чтение-запись-выполнение в VirtualProtect
    30.                                         ; должен быть указан в единицах SIZE_T). В x32 размер SIZE_T равен 4 байта, в x64 - 8 байт.
    31.                                        
    32.       invoke VirtualProtect, ecx, eax, PAGE_EXECUTE_READWRITE, ADDR OldData ; Разрешаем запись в область между Execute_Read_Write_Start
    33.                                                                             ; и Execute_Read_Write_End.
    34.                                                                            
    35.       mov eax, offset CS:Dump   ; Занести в ЕАХ адрес Dump-а.
    36.       mov ebx, 0AAAAAAAAh       ;
    37.       mov [eax], EBX            ; Записать в область памяти Dump-а число 0AAAAAAAAh. Теперь этот код успешно выполняется.
    38.  
    39.       mov eax, CS:Dump          ; Занести в ЕАХ 4 байта из того что находиться в Dump-е.
    40.       call Modulation           ; Пока ничего не делает.
    41.  
    42.       invoke ExitProcess, NULL  ; Завершение процесса.
    43. Execute_Read_Write_Start:
    44.       Dump dd 100h dup (00FF00FFh) ; Данные в области кода, которые следуют за размещением invoke ExitProcess, NULL.
    45. Execute_Read_Write_End:
    46.  
    47. end start
    Теперь перед вызовом процедуры Modulation в ЕАХ находится значение 0AAAAAAAAh.

    Полезные ссылки
    1. Запись в сегмент кода http://forum.sources.ru/index.php?showtopic=84220&hl=
    2. VirtualProtect Function (MSDN) http://msdn.microsoft.com/en-us/library/Aa366898

    P. S. А нужно это всё было собственно для шифрования кода программы и последующей дешифровки перед её запуском.
     
  7. K10

    K10 New Member

    Публикаций:
    0
    Регистрация:
    3 окт 2008
    Сообщения:
    1.590
    Код (Text):
    1.       xor edx, edx                      ;
    2.       mov ebx, 00000004h                ; Размер в байтах типа SIZE_T (для моей MustDie (Windows) XP x32).
    3.       div ebx                           ; Теперь в ЕАХ находится размер блока в единицах SIZE_T (потому что размер
    4.                                         ; блока для которого изменяются права на чтение-запись-выполнение в VirtualProtect
    5.                                         ; должен быть указан в единицах SIZE_T). В x32 размер SIZE_T равен 4 байта,
    Оффтоп: вобщето это сдвигом делается...
    SHR EAX, 2
     
  8. google

    google New Member

    Публикаций:
    0
    Регистрация:
    10 авг 2007
    Сообщения:
    140
    Этот блок кода не нужен, ибо VirtualProtect принимает число байтов, а не число двойных слов.
     
  9. ArhY

    ArhY New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2010
    Сообщения:
    4
    Да К10. Ты прав. Так был увлечён проблемой, что как то не подумал. Конечно так быстрее и проще.
     
  10. ArhY

    ArhY New Member

    Публикаций:
    0
    Регистрация:
    13 июн 2010
    Сообщения:
    4
    Экспериментальным путём доказано, что google - прав. Спасибо за пост.
    Вывод: MSDN - это не Microsoft Developers Network, а MuSt Die Nihilism.
     
  11. baldr

    baldr New Member

    Публикаций:
    0
    Регистрация:
    29 апр 2010
    Сообщения:
    327
    На самом деле непонятно, откуда изначально взялась мысль об измерении размера региона для VirtualProtect() в единицах sizeof SIZE_T. Написано же (выделение моё):