можно ли программно изменить значение лексемы в сегменте констант

Тема в разделе "WASM.BEGINNERS", создана пользователем assch, 9 янв 2020.

  1. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Лексема это ассоциированное имя
    Компилятор masm32 по умолчанию
    сегменты глобальных данных распологает так:

    1 сегмент - .const (константные лексемы)
    2 сегмент - .data (инициализированные лексемы)
    3 сегмент - .data? (неинициализированные лексемы)

    Например в начале программы мы запустили функцию

    Код (ASM):
    1.  
    2. invoke GetModuleHandle,0
    3. mov hInstance,eax
    4.  
    лексему - hInstance
    соответственно заранее прописали в сегменте - .data?
    и в надежде что теперь можно весь кодинг пользоватся этим значением
    но вот если например мы в сегменте - .data
    объявили какой нибудь буфер под массив
    и в процессе выполнения программы данные которые мы будем
    записывать в этот буфер окажутся слишком большими
    то с определённой долей вероятности
    эти данные просто сотрут значение - hInstance

    Можно конечно для этой лексемы сделать такой ход
    сначала объявить её самую первую в сегменте - .data
    с каким нибудь например нулевым значением
    а потом изменить это значение функцией - GetModuleHandle

    Но интересно а можно ли
    как то это значение поместить в сегмент - .const
    чтобы сама программа оберегала это значение
    Вопрос кто в теме
    можно ли это как то сделать
    например пошаманить
    или это просто не возможно в принцыпи
     
  2. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.797
    assch,
    если это не dll, то GetModuleHandle(0) возвращает значение, с которым экзешник линковался
    link /BASE:0x400000
     
  3. ormoulu

    ormoulu Well-Known Member

    Публикаций:
    0
    Регистрация:
    24 янв 2011
    Сообщения:
    1.208
    Лексема (информатика) — последовательность допустимых символов языка программирования, имеющая смысл для транслятора.

    В данном случае вероятнее всего речь идет о переменных.
    Переменные и в самом деле могут быть инициализированными, неинициализированными и постоянными.
    Сегменты, в которых они располагаются, отличаются также первичной инициализацией при загрузке приложения в память, и атрибутами защиты.
    "Сама программа" ничего "оберегать" не будет, это вам не джава. Просто при выходе за границу доступных на запись страниц случится ошибка и вылет.
    Транслятор масм, насколько я помню, раньше располагал переменные в сегментах по желанию программиста, разве сейчас это уже не так? Даже если сейчас он раскидывает переменные автоматом, наверняка их расположение можно указать прямо.

    Что касается переполнения буфера - ну дык, не допускайте этого переполнения. Или используйте язык, который все сделает за вас. Зачем тогда вообще ассемблер?
    --- Сообщение объединено, 9 янв 2020 ---
    Разве вызов GetModuleHandle(0) проверяет, откуда он был сделан?
    --- Сообщение объединено, 9 янв 2020 ---
    Регистрация в 2011... Хмм...
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.330
    Я открою тебе секрет, только никому не говори. Переполнения буффера - это плохо вне зависимости от того, где ты этот буффер указал (на стеке, на куче, в статических данных, где угодно). С определенной очень большой долей вероятности программа после переполнения буффера будет работать некорректно. Поэтому тебе в процессе программирования стоит задуматься о том, как не переполнять буффер, а не о том, что буффер переполниться и что-либо там затрет.
     
    hiddy нравится это.
  5. ormoulu

    ormoulu Well-Known Member

    Публикаций:
    0
    Регистрация:
    24 янв 2011
    Сообщения:
    1.208
    Ну зачем так категорично... Переполнение буфера это не только плохо, но и, при некоторых обстоятельствах, хорошо.
     
  6. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.797
    ormoulu,
    я хотел сказать, что
    • если перед нами EXE, собранный masm и не использовался ключ /BASE тогда для 32-разрядного приложения GetModuleHandle(0)=0х400000, а для 64-разрядного GetModuleHandle(0)=0x140000000
    • для 32-разрядного DLL 0x10000000 и 0x180000000 для 64-разрядного
    https://docs.microsoft.com/en-us/cpp/build/reference/base-base-address?view=vs-2019
     
  7. ormoulu

    ormoulu Well-Known Member

    Публикаций:
    0
    Регистрация:
    24 янв 2011
    Сообщения:
    1.208
    Но GetModuleHandle это все-таки API, и насколько я помню, а также согласно документации
    Т.е. вызов GetModuleHandle(0) должен вернуть базу именно .exe, независимо от того, вызван он из кода .exe или .dll, разве нет?
     
  8. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.797
    ormoulu,
    то есть в случае с ехе вы со мной согласны ― при вызове GetModuleHandle(0) будет всегда возвращаться 400000h (32-bit) либо 140000000h (64-bit). А вот в случае с DLL вызов GetModuleHandle(0) не обязательно будет возвращать 10000000h (32-bit) либо 180000000h (64-bit) и это можно проверить, если в DLL встроить вывод значения hInstance. В зависимости от количества загруженных DLL, порядка их загрузки, значение, выдаваемое вызываемой из DLL функцией GetModuleHandle(0), каждый раз будет разным. Чтобы DLL не загрузилась поверх исполняемого приложения (конфликт базовых адресов), ее ImageBase обязательно должна быть перемещаемой (секция .reloc в помощь)
     
  9. ormoulu

    ormoulu Well-Known Member

    Публикаций:
    0
    Регистрация:
    24 янв 2011
    Сообщения:
    1.208
    Не обязательно 400000h (32-bit), вы хотели сказать? Потому, что .exe процесса не всегда будет иметь базовый адрес 400000h. Почему GetModuleHandle(0) должен возвращать 10000000h, как-то вообще непонятно.

    Разве там не принудительное перемещение будет? Или библиотека вообще не загрузится? Вы проверяли?
     
  10. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.797
    ormoulu,
    то есть запустить ехе, которое породит несколько процессов, каждый из которых вызовет GetModuleHandle(0)? А потом несколько раз вызвать DLL, которая вызовет GetModuleHandle(0)?
     
  11. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.330
    Она и не должна, в случае с DLL она вернет базовый адрес экзешника, который породил процесс, а никак не базовый адрес DLL. В DLL её базовый адрес передает загрузчик венды первым параметром DllMain.
     
  12. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    2.000
    Тема конечно бесценна.
    - можно ли программно менять содержимое секции?
    - можно сразу, если у секции есть атрибут MEM_WRITE, можно после установки PAGE_READWRITE для нужной страницы VirtualProtect()'ом, и можно потом вернуть все как было, чтобы программа "оберегала" свои "лексемы".

    ЗЫ: я вообще плохо представляю зачем в программе больше 3 секций. Секция кода (чтение-исполнение, код-релоки), секция статичных данных (чтение, ресурсы-экспорт-данные), секция данных (чтение-запись, импорт-инициализированные данные-неинициализированные данные, причем все неинициализированные в конце, а - аптимизация).
     
    Последнее редактирование: 10 янв 2020
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.330
    При желании это можно сделать скриптами/параметрами линкера. Я, когда делал шеллы на плюсах, сводил всё в одну RWX секцию, потом вырезал ее objdump'ом.
     
  14. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Уважаемые участники обсуждения темы
    предлагаю забыть об этом несчастном значении от - GetModuleHandle

    Прошу вас ответить на главный вопрос темы

    Можно ли программно изменить значение лексемы в сегменте констант

    Просто ответить да или нет
    и если да то как это сделать
     
  15. ormoulu

    ormoulu Well-Known Member

    Публикаций:
    0
    Регистрация:
    24 янв 2011
    Сообщения:
    1.208
    Выражение "значение лексемы" не имеет смысла.
    Можно изменить значение переменной в сегменте констант. Для этого нужно изменить доступ для страницы памяти, где эта константа находится. Сделать это можно, к примеру, при помощи VirtualProtect (см. ответ f13nd).
    Изменив значение, нужно поменять доступ снова на read-only.
     
  16. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    assch,

    > Можно ли программно изменить значение лексемы в сегменте констант

    Помесь понятий из скриптов и архитектуры, вы сошли с ума ?

    Есть область данных и её размер. Размер определяется в скрипте, при дефейне переменных. Что вам есчо нужно ?

    Вы хотите обмануть компилер и создать расширяемый буфер :sarcastic:

    Это не возможно, для этого есть лишь один механизм на нт - стек, причём он расширяется вниз, в отличие от расширения обычных буферов.

    Имхо полный бред. ТС пили менеджер памяти или используй динамические буфера.
     
  17. njeen

    njeen Active Member

    Публикаций:
    0
    Регистрация:
    26 мар 2017
    Сообщения:
    139
    Адрес:
    Ташлинск
    Что вам не понятно? Вам подробно ответили в #3 и #12 . 'Просто' ответить 'да или нет' на некоторые вопросы нельзя корректно , без оговорок, ибо в начальной постановке они бредовые, и ответ получится некорректным.
    Лексема, как вам написали, - это понятие компилятора на фазах прохода, программно вы можете менять только значение именованных ячеек памяти, т.е , переменных.

    Может, человек в запое был ..
     
  18. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    njeen,

    Ты туго соображаешь, он в статике пытается сделать то, что не позволяет система.
     
  19. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.330
    Да, можно, если сначала назначить странице виртуальной памяти права на запись, в противном случае при попытке записи будет эксепшн.
    --- Сообщение объединено, 10 янв 2020 ---
    куча, не?
     
  20. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Rel,

    Нет, механизм расширения памяти она не поддерживает. Там можно только переопределить размер резерв области. При этом должны быть запросы на аллокацию, а не прямые выборки как в задаче тс. Такое только ядро со стеком делает и вниз, что не подходит тс в любом случае, так как любой буфер растёт вверх по адресам.