Gated code injection (yes it is not "destructive")*

Started by RawCode, March 01, 2017, 10:20:04 AM

Previous topic - Next topic

RawCode

All code can be found on git:
https://github.com/RawCode/yaCIL

*Non destructive code injection is not possible, you MUST change existing code to create entry point.
You can change call relative opcode inside specific methods to redirect flow, but this anyway destroys information about original call offsets.


1) Copy native function you need into RWX memory:

stored_ORIGINAL = new _FuncPtr32(typeof(Kagimono).GetMethod("ORIGINAL"));
stored_ORIGINAL.Rebase();
stored_ORIGINAL.Rebind();


After operation you have fully functional copy of provided function, you can invoke it with __CALL or _JMP methods provided with _FuncPtr32

2) Emit jmp into original method


_FuncPtr32 jmp = new _FuncPtr32(typeof(Kagimono).GetMethod("ORIGINAL"));
_FuncPtr32 gate = new _FuncPtr32(typeof(Kagimono).GetMethod("__GATE__ORIGINAL"));

jmp.Stream2Image();
jmp.Stream(__arglist((byte)0x68,(int)gate,(byte)0xC3));
jmp.Image2Raw();


It obviously destroys original method, but you already have copy.

Method "Stream" uses undocumented keyword __arglist.
You must specify type of each input, in other case, everything will be converted into integers and emit will fail hard due to zero opcodes appearing everywhere.
There is no way around, as developer have legitimate reasons to emit zero as integer and code can't read your mind (yet).

3) You still need managed method with proper signature, but you do not need to copy original method.


static _FuncPtr32 stored_ORIGINAL;
static public void __GATE__ORIGINAL(int _test_int)
{
_test_int+= 8;
stored_ORIGINAL.__HOST();
}


Gate code injection is about checking and altering arguments before they get into function.
Also you can yield to original method without any changes or cancel it's invocation completely and in case of methods with return - return some other value.