Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version
Go to top

.NET Internals and Native Compiling

, 30 May 2008
An article about .NET internals and native compiling.
fxloader.zip
fxloader
detoured.lib
detours.lib
release
detoured.dll
fxloader.exe
rebtest.exe
native_msgbox.zip
nvcoree
#include "stdafx.h"
#include <CorHdr.h>
#include "corinfo.h"
#include "corjit.h"
#include <tchar.h>

extern "C" __declspec(dllexport) void HookJIT();

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  dwReason,
                       LPVOID lpReserved
					 )
{
	HookJIT();
	return TRUE;
}

BOOL bHooked = FALSE;
ULONG_PTR *(__stdcall *p_getJit)();

typedef int (__stdcall *compileMethod_def)(ULONG_PTR classthis, ICorJitInfo *comp, 
										   CORINFO_METHOD_INFO *info, unsigned flags,         
										   BYTE **nativeEntry, ULONG  *nativeSizeOfCode);
struct JIT
{
	compileMethod_def compileMethod;
};

compileMethod_def compileMethod;

//
// native code to inject
//

#define CODE_SIZE	15

BYTE Code[CODE_SIZE] = 
{
	0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00,	  // mov ecx, [addr]
	0xFF, 0x15, 0x00, 0x00, 0x00, 0x00,   // call [msgbox]
	0xC2, 0x04, 0x00					  // ret 4
};

int __stdcall my_compileMethod(ULONG_PTR classthis, ICorJitInfo *comp, CORINFO_METHOD_INFO *info, 
							   unsigned flags, BYTE **nativeEntry, ULONG  *nativeSizeOfCode)
{
	//
	// Very lazy way to identify the method to inject
	//

	const char *szMethodName = NULL;
	const char *szClassName = NULL;
	szMethodName = comp->getMethodName(info->ftn, &szClassName);

	if (strcmp(szMethodName, "button1_Click") == 0)
	{
		//
		// Retrieve string
		//

		unsigned int strToken = 0x70000063; // "Right password!"

		void* literalHnd = NULL;

		comp->constructStringLiteral(info->scope, strToken, &literalHnd);

		//
		// Retrieve method
		//

		/*
		* misused to activate the method's assembly
		* (we don't care about that)
		*
		CORINFO_CALL_INFO callInfo;

		comp->getCallInfo(info->ftn,
			info->scope,
			0x0A00001E,
			0, // constraintToken                                                            
			info->ftn,
			CORINFO_CALLINFO_KINDONLY,
			&callInfo);
		*/

		CORINFO_METHOD_HANDLE targetMethod = comp->findMethod(info->scope,
			0x0A00001E, info->ftn);

		CORINFO_CONST_LOOKUP addrInfo;

		comp->getFunctionEntryPoint(targetMethod, IAT_VALUE, &addrInfo);

		//
		// Set up native code
		//

		/*
		 * This is basically what we're doing
		 *
		__asm
		{ 
			mov ecx, [literalHnd]
			call [addrInfo.addr]
		} 
		*/

		BYTE *pCode = Code;

		pCode += 2;
		*((ULONG_PTR *) pCode) = (ULONG_PTR) literalHnd;
		pCode += 6;
		*((ULONG_PTR *) pCode) = (ULONG_PTR) addrInfo.addr;

		DWORD dwOldProtect;
		VirtualProtect(Code, CODE_SIZE, PAGE_EXECUTE_READWRITE, &dwOldProtect);

		*nativeEntry = Code;
		*nativeSizeOfCode = CODE_SIZE;

		return CORJIT_OK; // it's 0 as usual
	}

	int nRet = compileMethod(classthis, comp, info, flags, nativeEntry, nativeSizeOfCode);

	return nRet;
}

//
// Hooks compileMethod
//

extern "C" __declspec(dllexport)
void HookJIT()
{
	if (bHooked) return;

	LoadLibrary(_T("mscoree.dll"));

	HMODULE hJitMod = LoadLibrary(_T("mscorjit.dll"));

	if (!hJitMod)
		return;

	p_getJit = (ULONG_PTR *(__stdcall *)()) GetProcAddress(hJitMod, "getJit");

	if (p_getJit)
	{
		JIT *pJit = (JIT *) *((ULONG_PTR *) p_getJit());

		if (pJit)
		{
			DWORD OldProtect;
			VirtualProtect(pJit, sizeof (ULONG_PTR), PAGE_READWRITE, &OldProtect);
			compileMethod =  pJit->compileMethod;
			pJit->compileMethod = &my_compileMethod;
			VirtualProtect(pJit, sizeof (ULONG_PTR), OldProtect, &OldProtect);
			bHooked = TRUE;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Daniel Pistelli
Software Developer
Germany Germany
The languages I know best are: C, C++, C#, Assembly (x86, x64, ARM), MSIL, Python, Lua. The environments I frequently use are: Qt, Win32, MFC, .NET, WDK. I'm a developer and a reverse engineer and I like playing around with internals.
 
You can find most of my work at http://ntcore.com.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 30 May 2008
Article Copyright 2008 by Daniel Pistelli
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid