// Writes push dword ptr [esp+displ] static void WritePushDwordPtrEspDispl(NativeCodeGenerator code, sbyte displ) { code.WriteBytes(0xFF, 0x74); code.WriteBytes(0x24, (byte)displ); }
unsafe void CreateOurCode() { var code = new NativeCodeGenerator(); // our compileMethod() func int compileMethodOffset = code.Size; int numPushedArgs = compileMethodIsThisCall ? 5 : 6; code.WriteByte(0x51); // push ecx code.WriteByte(0x50); // push eax code.WriteByte(0x54); // push esp for (int i = 0; i < 5; i++) { WritePushDwordPtrEspDispl(code, (sbyte)(0xC + numPushedArgs * 4)); // push dword ptr [esp+XXh] } if (!compileMethodIsThisCall) { WritePushDwordPtrEspDispl(code, (sbyte)(0xC + numPushedArgs * 4)); // push dword ptr [esp+XXh] } else { code.WriteByte(0x51); // push ecx } code.WriteCall(ourCompileMethodInfo.ptr); code.WriteByte(0x5A); // pop edx code.WriteByte(0x59); // pop ecx code.WriteBytes(0x84, 0xD2); // test dl, dl code.WriteBytes(0x74, 0x03); // jz $+5 code.WriteBytes(0xC2, (ushort)(numPushedArgs * 4)); // retn 14h/18h for (int i = 0; i < numPushedArgs; i++) { WritePushDwordPtrEspDispl(code, (sbyte)(numPushedArgs * 4)); // push dword ptr [esp+XXh] } code.WriteCall(origCompileMethod); code.WriteBytes(0xC2, (ushort)(numPushedArgs * 4)); // retn 14h/18h // Our callMethod() code. 1st arg is the method to call. stdcall calling convention. int callMethodOffset = code.Size; code.WriteByte(0x58); // pop eax (ret addr) code.WriteByte(0x5A); // pop edx (method to call) if (compileMethodIsThisCall) { code.WriteByte(0x59); // pop ecx (this ptr) } code.WriteByte(0x50); // push eax (ret addr) code.WriteBytes(0xFF, 0xE2); // jmp edx // Returns token of method int getMethodTokenOffset = code.Size; code.WriteCall(returnMethodTokenInfo.ptr); code.WriteBytes(0xC2, (ushort)(IntPtr.Size * 2)); // Returns name of method int getMethodNameOffset = code.Size; code.WriteCall(returnNameOfMethodInfo.ptr); code.WriteBytes(0xC2, (ushort)(IntPtr.Size * 3)); ourCodeAddr = VirtualAlloc(IntPtr.Zero, new UIntPtr((ulong)code.Size), 0x00001000, PAGE_EXECUTE_READWRITE); IntPtr baseAddr = ourCodeAddr; ourCompileMethodInfo.ptrInDll = new IntPtr((byte *)baseAddr + compileMethodOffset); callMethod = new IntPtr((byte *)baseAddr + callMethodOffset); returnMethodTokenInfo.ptrInDll = new IntPtr((byte *)baseAddr + getMethodTokenOffset); returnNameOfMethodInfo.ptrInDll = new IntPtr((byte *)baseAddr + getMethodNameOffset); byte[] theCode = code.GetCode(baseAddr); Marshal.Copy(theCode, 0, baseAddr, theCode.Length); }