Сообщение Re[39]: 32/64/AnyCPU - что за @$^%$? от 03.11.2016 10:48
Изменено 03.11.2016 10:59 Serginio1
Так для общего развития
https://msdn.microsoft.com/ru-ru/library/system.runtimemethodhandle.getfunctionpointer(v=vs.110).aspx
Метод RuntimeMethodHandle.GetFunctionPointer () Получает указатель на метод, представленный этим экземпляром
https://habrahabr.ru/post/307088/
Перехват функций .NET/CLR
1. Способ вызова методов в CLR
В CLR каждая функция (метод) представляет собой набор IL-команд и вся информация о ней хранится в метаданных модуля. При загрузке модуля для каждого его класса система CLR создает таблицу MethodTable, содержащую информацию о методах класса. Каждый метод класса описывается структурой MethodDesc, одно из полей которой содержит адрес скомпилированного метода в памяти (при выполненной JIT-компиляции метода), а другое содержит индекс в таблице MethodTable, по которому указан адрес переходника (thunk), содержимое которого изменяется в процессе выполнения в зависимости от того, скомпилирован метод или нет.
Первоначально (до выполнения JIT-компиляции) в качестве переходника выступает один из четырех т.н. precode переходников CLR: StubPrecode, FixupPrecode, RemotingPrecode или NDirectImportPrecode. Поскольку последний переходник используется только для вызова API-функций Windows, которые можно перехватить и напрямую, то его мы рассматривать не будем.
Основной задачей каждого из precode-переходников является передача адреса структуры MethodDesc,
определяющей используемый метод, внутренней функции ThePreStub (ThePreStubAMD64 для платформы x64, на рисунке отмечена как Stub), которая выполняет следующие задачи:
1.JIT-компиляция метода, идентифицируемого структурой MethodDesc;
2.установка указателя в структуре MethodDesc на сгенерированный native-код;
3.перезапись переходника таким образом, чтобы он осуществлял безусловный переход (jmp) на сгенерированный native-код;
4.выполнение сгенерированного native-кода.
Таким образом, в результате первоначального вызова целевого метода не только сгенерируется и выполнится код метода, но и изменится содержимое переходника, что приведет к прямому вызову сгенерированного native-кода при последующих вызовах метода.
Любой метод .NET, вызываемый из среды CLR, проходит через адрес в таблице MethodTable методов класса. Однако среда CLR предоставляет возможность вызова метода из неуправляемой среды С/С++. Для этого служат следующие функции: GetFunctionPointer класса RuntimeMethodHandle и GetFunctionPointerForDelegate класса Marshal. Адреса, возвращаемые указанными функциями, также являются адресами переходников, среди которых могут быть уже упомянутые StubPrecode, FixupPrecode и RemotingPrecode. В результате первоначального вызова метода происходит его компиляция и выполнение, при последующем вызове – прямой переход на сгенерированный код. При этом важным для нас является то, что для некомпилированного метода при вызове его как через таблицу методов, так и через возвращаемые упомянутыми функциями указатели, происходит вызов внутренней функции ThePreStub.
Так для общего развития
https://msdn.microsoft.com/ru-ru/library/system.runtimemethodhandle.getfunctionpointer(v=vs.110).aspx
Метод RuntimeMethodHandle.GetFunctionPointer () Получает указатель на метод, представленный этим экземпляром
https://habrahabr.ru/post/307088/
Перехват функций .NET/CLR
1. Способ вызова методов в CLR
В CLR каждая функция (метод) представляет собой набор IL-команд и вся информация о ней хранится в метаданных модуля. При загрузке модуля для каждого его класса система CLR создает таблицу MethodTable, содержащую информацию о методах класса. Каждый метод класса описывается структурой MethodDesc, одно из полей которой содержит адрес скомпилированного метода в памяти (при выполненной JIT-компиляции метода), а другое содержит индекс в таблице MethodTable, по которому указан адрес переходника (thunk), содержимое которого изменяется в процессе выполнения в зависимости от того, скомпилирован метод или нет.
Первоначально (до выполнения JIT-компиляции) в качестве переходника выступает один из четырех т.н. precode переходников CLR: StubPrecode, FixupPrecode, RemotingPrecode или NDirectImportPrecode. Поскольку последний переходник используется только для вызова API-функций Windows, которые можно перехватить и напрямую, то его мы рассматривать не будем.
Основной задачей каждого из precode-переходников является передача адреса структуры MethodDesc,
определяющей используемый метод, внутренней функции ThePreStub (ThePreStubAMD64 для платформы x64, на рисунке отмечена как Stub), которая выполняет следующие задачи:
1.JIT-компиляция метода, идентифицируемого структурой MethodDesc;
2.установка указателя в структуре MethodDesc на сгенерированный native-код;
3.перезапись переходника таким образом, чтобы он осуществлял безусловный переход (jmp) на сгенерированный native-код;
4.выполнение сгенерированного native-кода.
Таким образом, в результате первоначального вызова целевого метода не только сгенерируется и выполнится код метода, но и изменится содержимое переходника, что приведет к прямому вызову сгенерированного native-кода при последующих вызовах метода.
Любой метод .NET, вызываемый из среды CLR, проходит через адрес в таблице MethodTable методов класса. Однако среда CLR предоставляет возможность вызова метода из неуправляемой среды С/С++. Для этого служат следующие функции: GetFunctionPointer класса RuntimeMethodHandle и GetFunctionPointerForDelegate класса Marshal. Адреса, возвращаемые указанными функциями, также являются адресами переходников, среди которых могут быть уже упомянутые StubPrecode, FixupPrecode и RemotingPrecode. В результате первоначального вызова метода происходит его компиляция и выполнение, при последующем вызове – прямой переход на сгенерированный код. При этом важным для нас является то, что для некомпилированного метода при вызове его как через таблицу методов, так и через возвращаемые упомянутыми функциями указатели, происходит вызов внутренней функции ThePreStub.
https://ludeon.com/forums/index.php?topic=13813.0
unsafe public sealed override void ResolveReferences()
{
Log.Warning("x86 override test 1");
Log.Warning(TEST().ToString());
byte* mpx_1 = (byte*)typeof(Redefine).GetMethod ("TEST", BindingFlags.Static | BindingFlags.Public).MethodHandle.GetFunctionPointer ().ToPointer();
*(mpx_1 + 0) = 0xB8; //mov eax,0x0
*(mpx_1 + 1) = 7;
*(mpx_1 + 2) = 2;
*(mpx_1 + 3) = 2;
*(mpx_1 + 4) = 1;
*(mpx_1 + 5) = 0xC3; //ret
Log.Warning("x86 override test 2");
Log.Warning(TEST().ToString());
Log.Warning("have a nice day!");
//StageA();
}