views:

223

answers:

4

I am working on a project to prevent applications from being launched from removable devices. Does anyone out there know how i can do this? Preferrably in C++ on the Windows platform.

My aim is to prevent execution of the exe file even if the user double clicks it or even if he tries to launch it from the command line.

A: 

You can write snippet that returns from Main method if the current disk type is removable device.
Call GetCurrentDirectory split disk name and use WMI(this can help) or even better GetDriveType(this can help here) method to know is it on removable disk or not

ArsenMkrt
An easy solution. You just test it on startup and exit if its not from the hard drive.
Goz
he need just that, isn't it?
ArsenMkrt
A: 

Seems to me you are looking for a generic way to stop any app being launched off the device from an application that is already running. So essentially three issues: 1. Detecting the new application has started 2. Checking what type of device it is running off 3. Forcing the app to die if you don't want it

Part 1: This is the difficult party I think you need to either poll on a regular basis using EnumProcess which isn't great or just check applications which generate a WM_ACTIVATEAPP

Part 2: ArsenMkrt's Solution seems appropriate for this

Part 3: TerminateProcess should do it for you

Elemental
+3  A: 

Assuming that you wish to stop ANY process launching from a removable drive, this seems to be an application for a shell hook. I wrote the following code over the last half-hour, and it seems to test out OK. Bear in mind that writing a hook is a non-trivial process, and a global hook requires that a DLL be written. This is the relevant guts of the hook DLL:

BOOL __declspec(dllexport) __stdcall InstallShellHook ()
{
   lpfnHookProc = (HOOKPROC) ShellFunc ;
   BOOL bRetVal = FALSE;

   if (hShellHook == NULL)
   {
      hShellHook = SetWindowsHookEx (WH_SHELL, 
                                     lpfnHookProc, 
                                     hInstance, 
                                     NULL);
      return TRUE;
   }
   return FALSE;
}

LRESULT CALLBACK ShellFunc(int nCode, WPARAM wParam, LPARAM lParam)
{
   HWND hWndNew;
   char szBuff  [_MAX_PATH];
   char szDrive [_MAX_DRIVE];

   switch (nCode)
   {
      case HSHELL_WINDOWCREATED:
         hWndNew = (HWND)wParam;
         GetWindowModuleFileName (hWndNew, szBuff, _MAX_PATH);
         _splitpath (szBuff, szDrive, NULL, NULL, NULL);
         if (GetDriveType (szDrive) ==  DRIVE_REMOVABLE)
         {
            PostMessage (hWndNew, WM_CLOSE, 0, 0);
         }
         break;

      default:
         break;
   }
   return 0;
}

I have tested this code, installed from a simple dialog testbed, and it allows me to launch any windowed application from my hard drive, but immediately closes any I launch from a USB key.

Note that this solution works for all GUI processes (i.e. non-console), but requires that they respond to WM_CLOSE on a top-level window. A more aggressive general solution would probably require you to resolve the hwnd into a hprocess and call TerminateProcess: the solution I have provided is "kinder" (linked DLLs will get unloaded etc), but less general.

If you want to know the basics of writing a system-wide hook, you can find them on my website here. Note that the above isn't production-quality code, I hacked it into an old ANSI dll I had laying around, hence the lack of support for Unicode, or anything approaching decent debug capability. It shows the basic idea though.

Bob Moore
Even after modifying this code to use TerminateProcess, I'm pretty sure (from past experience) that this won't work for console applications. That is because console apps are handled differently from windowed apps by csrss.exe (some sort of "console server") who also handles their message loops. I couldn't fully understand from your answer if this solution would be appropriate in this case.
Idan K
A console app is not a GUI process, so no, the code I posted isn't appropriate for console apps. My comment about TerminateProcess relates to apps which ignore WM_CLOSE, not console apps. I think the OP needs to be a bit clearer about the precise requirement: getting some thing that works for all cases is quite tricky. It may be that this code is enough, but only he can clarify the precise intent.
Bob Moore
+1  A: 

Your network admin can take care of that without you needing to write any code. We implemented exactly that same thing here to prevent the possibility of employees copying customers private information to removable devices and the network admin implemented it himself without us here in the dev dept needing to do anything. I don't know if that would work in your situation but it's worth considering.

ChadNC
Try: Start->Run->"secpo.msc"->Security Settings->Software Restriction Policies->Additional Rules, Right Click->New Path Rule. It should be possible to write an application to set this up.
Skizz