Example #1
0
        static void writeOriginalCode(NativeCodeGenerator code, byte[] origCode, IntPtr origAddr)
        {
            for (int i = 0; i < origCode.Length; i++)
            {
                byte b = origCode[i];
                if (b != 0xE8 || i + 5 >= origCode.Length)
                {
                    code.writeByte(b);
                    continue;
                }

                IntPtr dest = new IntPtr(origAddr.ToInt64() + i + 5 + BitConverter.ToInt32(origCode, i + 1));
                code.writeCall(dest);
                i += 4;
            }
        }
Example #2
0
        unsafe byte[] createOurCode(IntPtr compileMethod)
        {
            var code = new NativeCodeGenerator();

            var origCode = new byte[0x60];

            Marshal.Copy(compileMethod, origCode, 0, origCode.Length);

            // our compileMethod() func
            int compileMethodOffset = code.Size;

            code.writeByte(0xE9);
            code.writeDword((uint)origCode.Length);
            writeOriginalCode(code, origCode, compileMethod);

            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));

            IntPtr baseAddr = new IntPtr((byte *)jitterTextFreeMem - code.Size);

            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);
            return(code.getCode(baseAddr));
        }
        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);
        }