Есть ли способ обмануть JIT-компилятор.net для запуска другого метода?
Хорошо, скажите, что мое приложение отправляет (x86) инструкции в память, делает страницу исполняемой и т. Д. Есть ли способ изменить заглушку метода un-JITted, чтобы он указывал на мой поток испущенных команд?
Например:
Предположим, я создал поток инструкций x86 в памяти, который делает что-то произвольное. Теперь предположим, что у меня есть метод int Target(). Я еще не звонил, поэтому он не был скомпилирован. Есть ли способ:
- Получить указатель на заглушку цели
- Сделайте так, чтобы он указывал на мой поток инструкций.
Я понимаю, что практически каждая функция безопасности.Net разработана таким образом, чтобы предотвратить угон. Но возможно ли это, скажем, через API хостинга?
5 ответов
Да, вы можете сделать!
Крючок getJit методом mscorjit. И вас будут спрашивать каждый раз, когда любой метод требует джитинга. Вы можете передать все, что вы хотите. Некоторые защитники.net работают следующим образом.
Это возможно через Profiling API. Я никогда не использовал его, но он используется для подобных целей в TypeMock.
Редактировать: Я думаю, что было хорошее сообщение в блогах MSDN, будет охотиться за ним.
Изменить 2: Doh, первый удар!
Как вы говорите, это нелегко, и это может быть даже невозможно. Если я правильно помню, код будет включать в себя адрес JIT-компилятора для метода, который не был скомпилирован. Поэтому, когда вы пытаетесь вызвать этот метод, JIT-компилятор выполнит свою работу и вставит адрес во вновь скомпилированный метод. Если вы можете изменить этот адрес, вы сможете вставить вызов в свой собственный код. Как бы вы сделали это незамеченным, вне меня. Я, конечно, надеюсь, что CLR обнаружит этот вид вмешательства.
Я не думаю, что Profiling API поможет вам в этом случае (как предлагает Леппи), так как вы не пытаетесь изменить MSIL. Если вы думаете иначе, эта статья может быть полезна, поскольку она описывает, что вы должны сделать, чтобы реализовать то, что делает TypeMock.
Я не стал бы пытаться связываться напрямую с памятью, и я не уверен, что это даже возможно, вместо этого вы можете использовать API профилировщика - есть несколько примеров, но нет реальной документации. Взгляните на статью в журнале MSDN - Перепишите код MSIL на лету с помощью.NET Framework Profiling API
В дополнение к возможности использовать ICorProfiler и переписывать ваш метод до его соединения, вы можете использовать ICorDebug (MDBG управляет интерфейсом). Установите точку останова, когда точка останова достигнет, установите следующий оператор для вашего перехватываемого кода. Весь этот процесс может быть выполнен из кода, но он действительно навязчив, и вам понадобится процесс "наблюдателя", чтобы координировать это.
Еще одна вещь, на которую стоит обратить внимание, это проект PostSharp, который дает вам методы входа и выхода, если вы применяете атрибуты.