-
May 19th, 2009, 11:35 AM
#1
Force stop/kill/eject usb mass storage device
Hi,
I am writing a security app that would disable or stop or eject a usb mass storage device if its detected. But so far I can only disable or eject it successfully if its not being used, if a file is opened on that storage device, calling the api to eject or disable the device do not work. I know that windows does this to prevent data corruption but what if its more important for security to kill the device than to prevent data corruption. How do i force stop/kill/eject a usb mass storage device ?
Also in vista, you dont event have to have a file opened on the USB mass storage device, you just need to have it opened in your file explorer and it wont allow you to eject/disable the device.
thanks,
Elman
-
May 19th, 2009, 02:26 PM
#2
Re: Force stop/kill/eject usb mass storage device
I'm pretty certain windows has built in security features in the policies to prevent the use of removable media.
Simplest case... Give them a zero write quota except for their home drive.
-
May 19th, 2009, 06:38 PM
#3
Re: Force stop/kill/eject usb mass storage device
How do I implement this zero write quota ? Would this effectively prevent access both read/write on the USB mass storage device ?
as I understand it, this will only limit write access to the mass storage device but still allows read access. Which could be bad especially if you dont want malicious software/virus copied from the removable device and installed on your system.
-
May 19th, 2009, 06:57 PM
#4
Re: Force stop/kill/eject usb mass storage device
Also would this affect already opened devices ?
I know that setting the group policy to prevent the use of mass storage devices works only as long as the device was not in used when the policy was enforced. But if a device was being used when the policy was applied, a reboot will be necessary or the device will need to be unplugged and replugged for the group policy to be applied.
So I was wondering if there is a way to force stop/kill/eject a usb mass storage device when its in use. I know when I reboot/shutdown the computer, windows seems to know how to shut down the device and eject it, there must be a way to kill the device short of rebooting windows ?
-
May 20th, 2009, 03:35 PM
#5
Re: Force stop/kill/eject usb mass storage device
Discussing how to set up and organise security policies in windows isn't really the topic for a programmers forum
You may want to go check out forums dealing with this very subject... I'd be highly surprised if features to block external devices aren't built into the OS. But I'm not that up to spec with the latest in security
-
May 21st, 2009, 11:34 AM
#6
Re: Force stop/kill/eject usb mass storage device
Sorry, I guess I was misunderstood, I do not want to set up and organize windows policy on blocking usb mass storage devices.
My question is how to programmatically force kill/stop/eject a usb mass storage thats in use in VC++.
what I have tried:
- I programmatically disabled the device by changing its state to disabled, unfortunately, if the device is in use, it will change the device state to disabled and return that the change state to disable was successful in the api, however the device will still be functional, a reboot is required for it to be disabled.
- I programmatically eject the device, the api returns fail if the device is in use
- I programmatically change the registry to how the group policy OReubens was talking about in order to disallow usb mass storage device. again If the device is in used when I made the change, it will not kill/eject/stop the device. A reboot is required for it to get blocked.
- I have tried all 3 above together and differing combinations, but no luck
if anyone has any insight, I just want to force kill a USB mass storage device so that it wont be accessible. The app I have right now only works at blocking USB devices if it hasn't been plugged in yet but if a device is being used, there is no way I can force kill it Any help would be kindly appreciated.
-
May 23rd, 2009, 07:40 PM
#7
Re: Force stop/kill/eject usb mass storage device
Well... things aren't as easy. There's the whole "sharing" thing going on afterall...
If your VC program is the one and only programm accessing the USB... then ejecting it should be easy enough and you can do that with this.
If however the USB is accessed by other programs... you cannot safely remove it and windows will not allow you to eject it programmatically. you can manuall yank the usb device out of the port, but that could very well leave the data corrupt, and may crash the other applications.
-
May 25th, 2009, 12:10 PM
#8
Re: Force stop/kill/eject usb mass storage device
Thanks for your thoughts OReubens.
However I am already using that eject api and another eject api not for scsi devices. Both returns that it could not eject the device since its in used.
Anyone else have a solution to my problem ?
how to programmatically force kill/stop/eject a usb mass storage thats in use by other apps ?
any usb mass storage device guru out there ?
if not in xp maybe in vista ?
-
May 26th, 2009, 08:18 AM
#9
Re: Force stop/kill/eject usb mass storage device
If you can't find a direct way of doing this you can try the same approach used by unlocker i.e finding which processes have locked the drive and unlocking/killing them.
Or if you're into reverse engineering try reversing Starforce Nightmare. That program can even disconnect your main hard drive while windows is running Almost screwed my HDD once.
-
June 10th, 2009, 03:57 PM
#10
Re: Force stop/kill/eject usb mass storage device
try this code
you'll have to use WinDDK
and link to setupapi.lib
worked for me
if you want i can send you a link to the project
USBFixedDiskSafeRemoval.h
Code:
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the USBFIXEDDISKSAFEREMOVAL_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// USBFIXEDDISKSAFEREMOVAL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef USBFIXEDDISKSAFEREMOVAL_EXPORTS
#define USBFIXEDDISKSAFEREMOVAL_API __declspec(dllexport)
#else
#define USBFIXEDDISKSAFEREMOVAL_API __declspec(dllimport)
#endif
// This class is exported from the USBFixedDiskSafeRemoval.dll
class USBFIXEDDISKSAFEREMOVAL_API CUSBFixedDiskSafeRemoval {
public:
CUSBFixedDiskSafeRemoval(void);
// TODO: add your methods here.
};
extern USBFIXEDDISKSAFEREMOVAL_API int nUSBFixedDiskSafeRemoval;
USBFIXEDDISKSAFEREMOVAL_API int fnUSBFixedDiskSafeRemoval(char cDriveLetter);
USBFixedDiskSafeRemoval.cpp
Code:
// USBFixedDiskSafeRemoval.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "USBFixedDiskSafeRemoval.h"
#include <winioctl.h>
#include <Setupapi.h>
#include <stdio.h>
#include <cfgmgr32.h>
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// This is an example of an exported variable
USBFIXEDDISKSAFEREMOVAL_API int nUSBFixedDiskSafeRemoval=0;
DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber, UINT DriveType, char* szDosDeviceName)
{
bool IsFloppy = (strstr(szDosDeviceName, "\\Floppy") != NULL); // who knows a better way?
GUID* guid;
switch (DriveType) {
case DRIVE_REMOVABLE:
if ( IsFloppy ) {
guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
} else {
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
}
break;
case DRIVE_FIXED:
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_CDROM:
guid = (GUID*)&GUID_DEVINTERFACE_CDROM;
break;
default:
return 0;
}
// Get device interface info set handle for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) {
return 0;
}
// Retrieve a context structure for a device interface of a device information set
DWORD dwIndex = 0;
long res;
BYTE Buf[1024];
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
spdid.cbSize = sizeof(spdid);
while ( true ) {
res = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &spdid);
if ( !res ) {
break;
}
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL); // check the buffer size
if ( dwSize!=0 && dwSize<=sizeof(Buf) ) {
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory(&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd, dwSize, &dwSize, &spdd);
if ( res ) {
// in case you are interested in the USB serial number:
// the device id string contains the serial number if the device has one,
// otherwise a generated id that contains the '&' char...
/*
DEVINST DevInstParent = 0;
CM_Get_Parent(&DevInstParent, spdd.DevInst, 0);
char szDeviceIdString[MAX_PATH];
CM_Get_Device_ID(DevInstParent, szDeviceIdString, MAX_PATH, 0);
printf("DeviceId=%s\n", szDeviceIdString);
*/
// open the disk or cdrom or floppy
HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if ( hDrive != INVALID_HANDLE_VALUE ) {
// get its device number
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if ( res ) {
if ( DeviceNumber == (long)sdn.DeviceNumber ) { // match the given device number with the one of the current device
CloseHandle(hDrive);
SetupDiDestroyDeviceInfoList(hDevInfo);
return spdd.DevInst;
}
}
CloseHandle(hDrive);
}
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return 0;
}
// This is an example of an exported function.
USBFIXEDDISKSAFEREMOVAL_API int fnUSBFixedDiskSafeRemoval(char cDriveLetter)
{
cDriveLetter &= ~0x20; // uppercase
if ( cDriveLetter < 'A' || cDriveLetter > 'Z' ) {
return 1;
}
char szRootPath[] = "X:\\"; // "X:\" -> for GetDriveType
szRootPath[0] = cDriveLetter;
char szDevicePath[] = "X:"; // "X:" -> for QueryDosDevice
szDevicePath[0] = cDriveLetter;
char szVolumeAccessPath[] = "\\\\.\\X:"; // "\\.\X:" -> to open the volume
szVolumeAccessPath[4] = cDriveLetter;
long DeviceNumber = -1;
// open the storage volume
HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hVolume == INVALID_HANDLE_VALUE) {
return 1;
}
// get the volume's device number
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if ( res ) {
DeviceNumber = sdn.DeviceNumber;
}
CloseHandle(hVolume);
if ( DeviceNumber == -1 ) {
return 1;
}
// get the drive type which is required to match the device numbers correctely
UINT DriveType = GetDriveType(szRootPath);
// get the dos device name (like \device\floppy0) to decide if it's a floppy or not - who knows a better way?
char szDosDeviceName[MAX_PATH];
res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH);
if ( !res ) {
return 1;
}
// get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number
DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName);
if ( DevInst == 0 ) {
return 1;
}
PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
WCHAR VetoNameW[MAX_PATH];
VetoNameW[0] = 0;
bool bSuccess = false;
// get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives!
DEVINST DevInstParent = 0;
res = CM_Get_Parent(&DevInstParent, DevInst, 0);
for ( long tries=1; tries<=3; tries++ ) { // sometimes we need some tries...
VetoNameW[0] = 0;
// CM_Query_And_Remove_SubTree doesn't work for restricted users
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART); // with messagebox (W2K, Vista) or balloon (XP)
res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0);
//res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP)
bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown);
if ( bSuccess ) {
break;
}
Sleep(500); // required to give the next tries a chance!
}
if ( bSuccess ) {
printf("Success\n\n");
return 1;
}
printf("failed\n");
printf("Result=0x%2X\n", res);
if ( VetoNameW[0] ) {
printf("VetoName=%ws)\n\n", VetoNameW);
}
return 0;
}
// This is the constructor of a class that has been exported.
// see USBFixedDiskSafeRemoval.h for the class definition
CUSBFixedDiskSafeRemoval::CUSBFixedDiskSafeRemoval()
{
return;
}
"Use The source Luke"
-
June 11th, 2009, 04:07 AM
#11
Re: Force stop/kill/eject usb mass storage device
Thanks Karpatuz,
I executed the code but it does not seem to work. The USB is rejected if no process are running.
If you open a txt file in notepad from the USB then this will code fail. But I want it to eject even if any file open.
Regards,
Vipin
-
June 15th, 2009, 05:41 PM
#12
Re: Force stop/kill/eject usb mass storage device
Karpatuz,
Sorry been busy with another project.
From a quick code review I noticed I am using the same api as you, but just in case your code has an option that I missed, I tried it out anyway. Your code only stops a usb device that is not being used ie no file is opened in the usb or no file transfer happening between usb and internal storage.
As vipink85 pointed out, the code you posted does not work to block/stop/kill/eject a usb mass storage device that is currently being used.
-
June 16th, 2009, 06:42 AM
#13
Re: Force stop/kill/eject usb mass storage device
I'm working at a similar project.
I need to block usb devices .. therefore i have to eject them first.
I combined a few ideas so far:
- close open file handles to the devices i want 2 remove.
- close open processes with a processimagepath pointing to any of the devices. (when running applications directly from the usb device)
- eject the device with cm_request_device_eject
it works quite okay so far. but i still have a few problems:
- excel for example loads a ddl with filemapping structure, so i can't eject with just closing the file handle
- while copying or deleting files closing the file handle results in a crash
how did u block usb devices after ejecting them? with the registry value?
-
June 16th, 2009, 11:54 AM
#14
Re: Force stop/kill/eject usb mass storage device
christian_k1984,
There is a windows group policy that allows you to block USB devices. However it will only block usb devices that are not already inserted or being used. For it to work on usb devices already connected, you will need to reboot
How did you know which file handles and processes belong to the USB device ?
-
June 17th, 2009, 02:01 AM
#15
Re: Force stop/kill/eject usb mass storage device
You can get the handles by inspecting the handle names, but you have to do a few things therefor.
First of all you have to find out witch of your disks are attached via usb. There are a few examples how to get this done. I use SetupDiEnumDeviceInterfaces. You should get drive names like:
\Device\Harddisk1\DP(1)0-0+3b
If you have the drives, you can enumerate all openhandles. (http://forum.sysinternals.com/forum_posts.asp?TID=18892)
Just compare the handlenames with the list of drives you have. If you find any matching paths, you can get the the process id with handle.ProcessId. At the moment I'm trying to just close the handles. This works for most applications and I'm able to eject the device. But I have problems with explorer (copying / deleting) and excel.
I think this is by far the best solution for open files.
I also implemented a function that inspects all running processes and compares the ImagePath of the process with the usb devices to find processes running directly from the usb drives (firefox portable for example)
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|