Magic of x86 assembly right inside your managed c# methods

Started by RawCode, February 27, 2017, 06:54:19 AM

Previous topic - Next topic

RawCode

Not useful by it's own, still, VERY useful in you know when and how.

How to use? look at this sample method:

[MethodImpl(MethodImplOptions.NoInlining)]
static public int RETURN_CALLER(int argx)
{
Console.WriteLine ("THIS IS RETURN CALLER PRE");
_ReJIT.__REPLACE
(
0x8B, 0x44, 0x24, 0x04, 0xD1, 0xE0, 0xC3
);
Console.WriteLine ("THIS IS RETURN CALLER POST");
return 0;
}


1)
[MethodImpl(MethodImplOptions.NoInlining)]
Mandatory flag, in other case your singleline placeholder methods will get inlined and modifications will have no effect.
It will not inline your methods in current version anyway, just in case.

2) Output left for reference, you will see first message once, second message won't show up ever.

3)

_ReJIT.__REPLACE
(
0x8B, 0x44, 0x24, 0x04, 0xD1, 0xE0, 0xC3
);

this is actual payload, it accept sequence of bytes that will be emitted directly into executable memory.

That all, first execution will invoke anything that method contains prior to __ReJIT line, then will invoke rejitter and then rejitter will return to already modified method, skipping original stackframes.

code itself can be found here
https://github.com/RawCode/yaCIL/tree/master

Few spotlights (code useful on it's own):


_FuncPtr32 RETIMM = new _FuncPtr32(typeof(_ReJIT).GetMethod("__TOPCALLER"));

RETIMM.Array2Image
(
0x8B, 0x45, 0x04, //mov    eax,DWORD PTR [esp+0x0]
0xC3 //ret
);
RETIMM.Image2Raw();

topcaller returns method that called method that called topcaller
this method used to determinate, what method contains _ReJIT instruction, it essential for gated hooks.


_FuncPtr32 DROPSPECIAL = new _FuncPtr32(typeof(_ReJIT).GetMethod("__DROPSPECIAL"));

DROPSPECIAL.Array2Image
(
0x8B, 0x44, 0x24, 0x04,
0xC9,
0xC9,
0x50,
0xC3
);
DROPSPECIAL.Image2Raw();

dropspecial discards two stack frames, frame holding __REPLACE and frame holding method, that called __REPLACE and jump into new address, in current implementation, it jumps into freshly rejitted method.
this allows to reuse memory of original method, it it can hold entire sequence of bytes provided.

Not yet completed method _X68.Update__CALLR() that can be used to copy and rebase method from one memory location to other memory location, without any overhead.
It already works well and fail only in case of unregistered opcodes.

Not yet finalized method _Funcptr.__CALL() that already works but need some love and support of __arglist.
Anyway, you can create rejitted method for each signature you may need and invoke function pointers directly, without delegates or reflection.
Same code will be reused for more user friendly access to private fields of objects.