Эта задачка - в некотором смысле, продолжение предыдущей.
Предположим, у нас есть такой очень простой код:
procedure DoSomething; begin end; procedure Work; begin ... DoSomething; // <- ... end;При некоторых условиях в отмеченной строке возбуждается исключение Access Violation.
Ваша задача - объяснить, как такое может быть.
При этом:
- Код присутствует в памяти и имеет правильные атрибуты защиты (PAGE_EXECUTEREAD).
- Это простая функция, не метод объекта.
- Функция вызывается напрямую (нет полиморфизма/опосредованного вызова, т.е. там просто "asm call DoSomething end").
- Код вызывающего и вызываемого находится в одном модуле, в вопросе нет DLL.
- Это не аппаратная проблема.
- Нет никаких внешних воздействий (отладчик, другие потоки, системный код).
Ответ.
Рискну предположить что причиной может быть зацикленная рекурсия, в следствие чего - переполнение стека и попытка вписать данные за его пределы.
ОтветитьУдалитьммм... а ответ на предыдущую будет ?
ОтветитьУдалитьХотя это крючкотворство, но в контексте функции Work DoSomething может быть переменно процедурного типа. Это вписывается в "asm call DoSomething end", хотя и будет опосредованным вызовом :-)))
ОтветитьУдалитьМожет DoSomething быть функцией с ring 0, а Work - функцией Ring 3 ? Хотя это бы не относилось к VirtualProtect из прошлой задачи.
ОтветитьУдалитьА посты про сериализацию уже закончились?
ОтветитьУдалитьПланирую закончить, но после серии о плагинах. Про плагины ещё две статьи осталось.
ОтветитьУдалитьИз всего возможного могу представить себе только проезд по памяти... Неужели может быть что-то кроме?..
ОтветитьУдалитьИнструкция CALL сохраняет в стек адрес возврата. На мой взгляд, это единственное место, в котором она может сломаться с Access Violation - нет места в стеке и регистр SP испортился.
ОтветитьУдалитьСтраницы под стек выделяются по мере надобности, поэтому Access Violation может быть и нормальным поведением, ОС перехватит и выделит новую страницу.
Нормальный компилятор этот вызов-пустышку вообще должен выкидывать в release.
ОтветитьУдалитьВ одной из статей у автора (или в переводах) довольно чётко обозначена одна из особенностей архитектуры x86: инструкции процессора имеют переменный размер.
ОтветитьУдалитьЯ в ассемблере не силён, но мне кажется, что проблема в следующем.
Если процедура DoSomething; пуста, то она содержит всего одну команду - ret, которая занимает 1 байт.
В предыдущей задачке: по адресу, где расположена эта процедура, делается попытка вставить команду jmp XX, которая уже будет занимать как минимум два байта: сама команда + смещение.
Соответственно мы затираем какую-то другую инструкцию и получаем AV.
Исправить это можно, наверное, так:
procedure DoSomething;
asm
nop;nop;nop;
end;
Возможно nop-операций надо больше, помнится там есть разновидности jmp near и jmp far..
В целом и общем, согласен с предыдущим постом. Не делился своим мнением ранее по причине сомнений, ибо в асме также не силен (сорри за офтоп). ИМХО, nop-операций нужно 4, не могу объяснить, почему.
ОтветитьУдалитьЭто отличные две задачки. Вроде и простая проблема, и даже наводку дали второй задачкой, но даже не подумал о том что функция может быть меньше JMP.
ОтветитьУдалитьНиколай Зверев, вы где ответы "подсматриваете"? 13-ую раскусили, 15 и 16 тоже :)
MrShoor, я ответы не подсматриваю :)
ОтветитьУдалитьЭто, скорее, знания + смекалка:
а) несколько лет назад я "подсмотрел" как работает библиотека FastCode - там как раз JMP и используется при замещении функций типа FillChar, Pos, CompareStr... уже тогда у меня была мысль, что в общем случае такое делать не безопасно;
б) как раз на днях читал о разных архитектурах, подсказка об особенности x86 подтверждает догадку;
в) отладчик IDE Delphi в помощь.
> 13-ую раскусили, 15 и 16 тоже :)
эээ... 15ю я не кусал, не успел, а к 13й я там и так подробно расписал ход мыслей. Кстати, привычку вчитываться в каждый символ кода (не важно какого языка программирования) очень полезно иметь программисту.
хмм ответ про длину JMP показался слишком ожидаемым, тем более, что не было сказано про хак из предыдущего примера, было сказано об особенности x86...
ОтветитьУдалитьЕсли это таки верный ответ, то задача поставлена коайне неточно :(