Click here to Skip to main content
Click here to Skip to main content

RmThread - Code execution in Another Process Context.

By , 17 Aug 2006
Rate this:
Please Sign up or sign in to vote.

Sample Image - rmthread.gif

Introduction

RmThread is a project that I made based on one of three ideas from the Robert Kuster article, "Three Ways to Inject Your Code into Another Process". However, I didn't use any code. I wanted to learn about it, searched over the net, and got influenced by the CreateRemoteThread & LoadLibrary technique. The rest was a prescription of "quite right function calls" and MSDN.

The project is useful for someone who need to run some code in a neighbor process, but doesn't want to worry about remote thread technique development. He wants just to write the code to run remotely. The demo project, RmThread.exe, works precisely to do the dirty thing. You say what process to run and the DLL to load, and it starts the process and loads the DLL in the process context. The rest remains in the DLL code.

To write your DLL, there's a demo project that uses a technique that I created to run some code starting from the DllMain execution (apart from another DLL function calling) and doesn't be a slave of its limitations (like: you can safely call only kernel32.dll functions).

Using the code

There're three useful functions that could be called from your program:

/** Run process and get rights for running remote threads. */ 
HANDLE CreateAndGetProcessGodHandle(LPCTSTR lpApplicationName, 
                                            LPTSTR lpCommandLine);

/** Load DLL in another process. */
HMODULE RemoteLoadLibrary(HANDLE hProcess, LPCTSTR lpFileName);

/** Free DLL in another process. */
BOOL RemoteFreeLibrary(HANDLE hProcess, HMODULE hModule);

Here's a simplified main routine showing how simple it is to use the functions:

//...
   // Start process and get handle with powers.
   hProc = CreateAndGetProcessGodHandle(tzProgPath, tzProgArgs);

   if( hProc != NULL )
   {
      // Load DLL in the create process context.
      HMODULE hDll = RemoteLoadLibrary(hProc, tzDllPath);

      if( hDll != NULL )
         RemoteFreeLibrary(hProc, hDll);

      CloseHandle(hProc);
   }
//...

The most complicated thing maybe what to do when your DLL is loaded. Considering that when it is called in your entry point, the DLL code has to follow some boring rules to avoid boring things like access violations (for more, read the DllMain help at MSDN). I made an "alternative execution", creating a thread in the DllMain function:

BOOL APIENTRY DllMain(HANDLE hModule, 
        DWORD ul_reason_for_call, LPVOID lpReserved) {
   switch( ul_reason_for_call )
   {
      case DLL_PROCESS_ATTACH:
      {
         DWORD dwThrId;

         // Fill global variable with handle copy of this thread.
         BOOL bRes =
         DuplicateHandle(GetCurrentProcess(),
                         GetCurrentThread(),
                         GetCurrentProcess(),
                         &g_hThrDllMain,
                         0, 
                         FALSE, 
                         0);
         if( bRes == FALSE ) break;

         // Call function that do the useful stuff with its DLL handle.
         CloseHandle(CreateThread(NULL, 
                                  0,
                                  RmThread,
                                  (LPVOID) LoadLibrary(g_tzModuleName),
                                  0, 
                                  &dwThrId));
      }
      break;
//...

The tasks for our newly created thread, by its turn are, to wait for the DllMain finalization (we'd have its handle stored in g_hThrDllMain), to do what it must to do (the all this stuff purpose), and to get back, releasing at the same time the DLL handle allocated for itself:

/**
 * Sample function, called remotely for RmThread.exe.
 */
DWORD WINAPI RmThread(LPVOID lpParameter) {
   HMODULE hDll = (HMODULE) lpParameter;
   LPCTSTR ptzMsg = 
           _T("Congratulations! Did you call RmThread.dll successfully!");

   // Wait DllMain termination.
   WaitForSingleObject(g_hThrDllMain, INFINITE);

   //TODO: Put your remote code here.
   MessageBox(NULL,
              ptzMsg,
              g_tzModuleName,
              MB_OK | MB_ICONINFORMATION);
 
   // Do what the function name says.
   FreeLibraryAndExitThread(hDll, 0);
}

The TODO mark is where your code must be written (you can pull out the MessageBox, if you want). Like DllMain code was previously executed, this part of the code is free to do what it wants to do in the neighbor process context.

An interesting detail is the requirement to call FreeLibraryAndExitThread. In another way, if you call FreeLibrary and then return, the code to be executed after that (a simple ret assembly instruction) would be in an invalid memory address (the DLL code is no more loaded at the address space). So, the result could not be so delightful like the final solution.

Points of Interest

A boring problem that you can find is: if the DLL couldn't be loaded successfully, how can I get the error code? Unfortunately, there's no trivial way to get the error code returned from LoadLibrary call. In order for the thread to start and finish in this API function, the LastError code is lost (there's a LastError for each thread in the process). Any idea?

History

  • 2004.06.11 - 1.0.0.1 version released.
  • 2004.06.13 - Support to VC6 project.
  • 2006.08.17 - Support for VS2005.

License

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

About the Author

Wanderley Caloni
Web Developer Caloni Tecnology
Brazil Brazil
Capacitation
Ten years experience in Windows operating systems developing in information security companies;
great team relationship; problem solving using systemic vision, knowledge bases maintenance,
chronograms and people coordination.
 
Technical historic
Software and hardware inventory
Clipboard and PrintScreen protection using windows hooks and global messages manipulation
Driver writing system event log
DeviceIoControl user/kernel communication
Desktop remote control using VNC technique
Remote execution tool PsExec (SysInternals) like
Print control using regex (Boost) and shell hook
Access policies management during user logon/logoff (register and hooks)
Datgabase migration CTree -> SQL (OLE classes)
Windows authentication using custom GINA and DCOM; Credential Provider (Vista)
CTree database synchronism using custom DCOM service
Bootable Linux CD with bash scripts and disk cryptography tools using C language
Hard disk encryption and PenDrive (USB) storage control
Blue Screen analysis using memory dumps and WinDbg live (Gflags)
System account execution using custom COM service
MBR (Master Boot Record) customization library
Blowfish/SHA-1 encryption library using C++ and 16 bits Assembly
Log access driver using shared memory between user and kernel mode
Kernel mode API hook for 9X and NT platforms
16 bits Assembly loader; debugging using debug.com tool
Executable protection using embedded domain authentication recorded inside files resources
Internet Explorer 6/7 and Firefox 1/2 browsing protection using Assembly 32 bits code injection
Code, strings and execution protection library (using Win32 interruptions)
Centralized log generation library using shared memory and global events
Internet Explorer 6/7 BHO (Broser Helper Object) and ActiveX; Mozilla/Firefox XPI plugin
Projects management using Source Safe, Bazaar and Batch (Win) scripts
Kernel mode debugging using SoftIce and WinDbg for NT
etc
Follow on   Twitter   Google+

Comments and Discussions

 
GeneralApplication Pinmembersomen_shaw22-Jul-08 0:26 
GeneralRe: Application PinmemberWanderley Caloni22-Jul-08 2:11 
GeneralDelete the dll file after loading PinmemberDavidi21-Jul-04 4:54 
GeneralRe: Delete the dll file after loading PinmemberWanderley Caloni Jr21-Jul-04 14:58 
GeneralHeavy footprint. PinmemberWREY13-Jun-04 19:02 
GeneralRe: Heavy footprint. PinmemberWanderley Caloni Jr14-Jun-04 6:19 
QuestionVC6 sample? PinmemberWREY13-Jun-04 3:30 
AnswerRe: VC6 sample? PinmemberWanderley Caloni Jr13-Jun-04 8:23 
GeneralMissing files. PinmemberWREY13-Jun-04 9:02 
GeneralRe: Missing files. PinmemberWanderley Caloni Jr13-Jun-04 12:11 
GeneralRe: Missing files. PinmemberWREY13-Jun-04 17:40 
GeneralRe: Missing files. PinmemberWanderley Caloni Jr14-Jun-04 2:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140415.2 | Last Updated 17 Aug 2006
Article Copyright 2004 by Wanderley Caloni
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid