Quantcast
Channel: Casaba Security » Development
Viewing all articles
Browse latest Browse all 25

Microsoft “Roslyn” based REPL injection.

$
0
0

Microsoft recently released their new Compiler API codename “Roslyn”. If you haven’t checked it out yet you should. Here’s the link: http://msdn.microsoft.com/en-us/roslyn/.

I wanted to get my hands a little dirty and play with the new API. I’ve been meaning to look into Managed DLL injection for a while to get code execution for process interrogation. There are times when we’re testing that we want to interrogate a process for framework level information. For whatever reasons we sometimes can’t compile the target with hooks. So it would be nice to have a way to execute code. Roslyn’s CSX files look like a great way to accomplish this so that’s what I’m trying to expose.

Currently this only works on 32 bit processes.

Let’s start by describing the architecture as there are 3 things going on. The major components are the Injector, Unmanaged Injectee and Managed Injectee. The injector is the controller in this scenario; he’s responsible for the injection into the managed process and communication between the components. Communication is handled via named pipes.

The injector uses a well-documented dll injection technique via CreateRemoteThread and LoadLibrary. This loads the unmanaged dll into the Managed process. The unmanaged DLL actually handles the Managed DLL injection. I wont go into unmanaged dll injection as it’s pretty well document technique. I assume the reader understands these concepts.

From this point I assume the unmanaged DLL has been injected into the managed process.

After the unmanaged DLL is injected I need to make sure the correct version of the CLR is loaded. To accomplish this use the CLR hosting API’s to determine the version of the CLR that is loaded by the process (Provided there is one loaded). The host process must be running .Net 4.0 to support the Roslyn API. Because the early versions of the hosting API’s are deprecated I need to check to see if the .net 4.0 mscoree is loaded “msvcr100_clr0400.dll”. I check via a GetModuleHandle. If it exists we know we are running .Net 4.0 and know the CLR is already running. Two birds down with a single stone.

hMod = GetModuleHandle(L"msvcr100_clr0400.dll");

Once we know the CLR is loaded and it’s 4.0 we can get a handle to the CLSID_CLRMetaHost via:

hr = CLRCreateInstance( CLSID_CLRMetaHost,
IID_ICLRMetaHost,
(LPVOID*)&pMetaHost );

From the meta host we can get a handle to the running RunTimeHost via:

ICLRRuntimeHost *pClrHost = NULL;
runTimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (LPVOID *)&pClrHost);

This will return a handle to the current RuntimeHost (Or load the runtime if it isn’t running). The next call is to load my Managed DLL plus call the entry method.

pClrHost->ExecuteInDefaultAppDomain(L"InjectedManagedDll_Net_4.dll", L"InjectedManagedDll_Net_4.InjectedClass", L"Test", L"TestArg" , &ret);

This loads the Managed DLL into the process. Once the Managed DLL’s Test method is called I create a managed thread.

public static int Test(string param)
{
new Thread(new ThreadStart(ThreadFunc)).Start();
return 666;
}

This thread then generates a few more threads and sets up the NamedPipe communication pipe and reports to the server things are setup.

static void ThreadFunc()
{
try
{
PipeClient.Instance.Start("CNIPipe");
}
catch (Exception e)
{
PipeClient.Instance.LogMessageToServer(e.Message);
}
}

I then expose some simple messages back and forth between the injector and injectee and expose a simple REPL loosely based on this guy’s implementation: http://visualstudiomagazine.com/articles/2011/11/16/the-roslyn-scripting-api.aspx.

private ScriptHost()
{

HashSetassemblys = new HashSet();
assemblys.Add(Assembly.GetCallingAssembly());
assemblys.Add(Assembly.GetEntryAssembly());
assemblys.Add(Assembly.GetExecutingAssembly());

Listnamespaces = new List() { "System", "System.Collections", "System.Collections.Generic" };

ScriptEngine = new ScriptEngine(assemblys.ToList(), namespaces);

Session = Session.Create(this);
}

public object Execute(string code)
{
return ScriptEngine.Execute(code, Session);
}

This gets you a basic REPL inside another process. Next steps include making sure the communication API between the host and injectee are more well formed and able to handle both 32 and 64 bit processes. Stay tuned!


Viewing all articles
Browse latest Browse all 25

Trending Articles