1331 lines
42 KiB
Plaintext
1331 lines
42 KiB
Plaintext
unit DeviceGuard.Logic;
|
||
|
||
interface
|
||
|
||
uses
|
||
System.SysUtils, System.Classes, System.Generics.Collections, System.SyncObjs,
|
||
System.JSON, System.IOUtils, System.StrUtils,
|
||
Winapi.Windows, Winapi.Messages, Winapi.ActiveX,
|
||
Winapi.Bluetooth,
|
||
Tocsg.Obj, Tocsg.Driver, Tocsg.Path, Tocsg.Trace,
|
||
Bs1PolicyUnit,
|
||
Bs1FltCtrl;
|
||
|
||
const
|
||
|
||
// SetupAPI & CfgMgr »ó¼ö
|
||
DN_DRIVER_LOADED = $00000002;
|
||
DN_STARTED = $00000008;
|
||
DN_DISABLEABLE = $00002000;
|
||
DN_HAS_PROBLEM = $00000400;
|
||
CR_SUCCESS = $00000000;
|
||
|
||
// Property IDs
|
||
SPDRP_DEVICEDESC = $00000000;
|
||
SPDRP_HARDWAREID = $00000001;
|
||
SPDRP_COMPATIBLEIDS = $00000002;
|
||
SPDRP_SERVICE = $00000004;
|
||
SPDRP_CLASS = $00000007;
|
||
SPDRP_CLASSGUID = $00000008;
|
||
SPDRP_FRIENDLYNAME = $0000000C;
|
||
SPDRP_SECURITY = $00000017;
|
||
SPDRP_ENUMERATOR_NAME = $00000016; // ¿°ÅÀÚ À̸§ (USB, PCI µî)
|
||
SPDRP_REMOVAL_POLICY = $0000001F;
|
||
SPDRP_INSTALL_STATE = $00000022;
|
||
|
||
DICS_ENABLE = 1;
|
||
DICS_DISABLE = 2;
|
||
DICS_PROPCHANGE = 3;
|
||
DICS_START = 4;
|
||
DICS_STOP = 5;
|
||
|
||
DICS_FLAG_GLOBAL = 1;
|
||
DICS_FLAG_CONFIGSPECIFIC = 2;
|
||
|
||
DIF_REMOVE = $00000005;
|
||
DIF_PROPERTYCHANGE = $00000012;
|
||
|
||
// Bluetooth Classes
|
||
COD_MAJOR_AUDIO = 4;
|
||
COD_MAJOR_PHONE = 2;
|
||
COD_MAJOR_PERIPHERAL = 5;
|
||
COD_MAJOR_WEARABLE = 7;
|
||
|
||
GUID_DEVCLASS_USB = '{36fc9e60-c465-11cf-8056-444553540000}';
|
||
GUID_DEVCLASS_PORTS = '{4d36e978-e325-11ce-bfc1-08002be10318}';
|
||
GUID_DEVCLASS_MODEM = '{4d36e96d-e325-11ce-bfc1-08002be10318}';
|
||
GUID_DEVCLASS_BLUETOOTH = '{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}';
|
||
GUID_DEVCLASS_NET = '{4d36e972-e325-11ce-bfc1-08002be10318}';
|
||
GUID_DEVCLASS_INFRARED = '{6bdd1fc5-810f-11d0-bec7-08002be2092f}';
|
||
GUID_DEVCLASS_1394 = '{6bdd1fc1-810f-11d0-bec7-08002be2092f}';
|
||
GUID_DEVCLASS_PCMCIA = '{4d36e977-e325-11ce-bfc1-08002be10318}';
|
||
GUID_DEVCLASS_WPD = '{eec5ad98-8080-425f-922a-dabf3de3f69a}';
|
||
GUID_DEVCLASS_DISKDRIVE = '{4d36e967-e325-11ce-bfc1-08002be10318}';
|
||
|
||
CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL = 1;
|
||
CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL = 2;
|
||
CM_INSTALL_STATE_FAILED_INSTALL = 2;
|
||
|
||
DICLASSPROP_INSTALLER = $00000002;
|
||
|
||
type
|
||
HDEVINFO = THandle;
|
||
DEVINST = DWORD;
|
||
// TPolicyState = (
|
||
// psAllow = 0;
|
||
// psBlock,
|
||
// psLog,
|
||
// psLogNone
|
||
// );
|
||
DEVPROPKEY = record
|
||
fmtid: TGUID;
|
||
pid: DWORD;
|
||
end;
|
||
PDEVPROPKEY = ^DEVPROPKEY;
|
||
DEVPROPTYPE = DWORD;
|
||
|
||
PSPClassInstallHeader = ^TSPClassInstallHeader;
|
||
TSPClassInstallHeader = packed record
|
||
cbSize: DWORD;
|
||
InstallFunction: DWORD;
|
||
end;
|
||
|
||
PSPPropChangeParams = ^TSPPropChangeParams;
|
||
TSPPropChangeParams = packed record
|
||
ClassInstallHeader: TSPClassInstallHeader;
|
||
StateChange: DWORD;
|
||
Scope: DWORD;
|
||
HwProfile: DWORD;
|
||
end;
|
||
|
||
|
||
PSPDevInfoListDetailData = ^TSPDevInfoListDetailData;
|
||
TSPDevInfoListDetailData = packed record
|
||
cbSize: DWORD;
|
||
ClassGuid: TGUID;
|
||
RemoteMachineHandle: THandle;
|
||
RemoteMachineName: array [0..255] of Char; // SP_MAX_MACHINENAME_LENGTH
|
||
end;
|
||
|
||
TDeviceInfoDTO = record
|
||
Index: Integer;
|
||
DevInst: DWORD;
|
||
ClassGuid: TGUID;
|
||
Desc: string;
|
||
HardwareID: string;
|
||
Service: string;
|
||
DeviceClass: string;
|
||
Enumerator: string;
|
||
RemovalPolicy: DWORD;
|
||
IsStarted: Boolean;
|
||
FriendlyName: string;
|
||
ParentId: string;
|
||
function GetMainHardwareID: string;
|
||
end;
|
||
|
||
TLogEvent = procedure(const Msg: string) of object;
|
||
|
||
TGuardThread = class(TThread)
|
||
private
|
||
FOwnerEngine: TObject;
|
||
procedure DoLog(const Msg: string);
|
||
procedure ShowPopup(const Msg: string);
|
||
protected
|
||
procedure Execute; override;
|
||
public
|
||
constructor Create(AOwnerEngine: TObject);
|
||
end;
|
||
|
||
TDeviceGuardEngine = class(TTgObject)
|
||
private
|
||
FThread: TGuardThread;
|
||
FScanEvent: TEvent;
|
||
FPolicyFilePath: string;
|
||
|
||
FOnLog: TLogEvent;
|
||
FOnPopup: TLogEvent;
|
||
|
||
FUseRestart: Boolean;
|
||
// ÇïÆÛ ÇÔ¼ö
|
||
function GetDeviceStringProperty(DevInfoSet: HDEVINFO; var DevData: TSPDevInfoData; PropId: DWORD): string;
|
||
function GetDeviceStringPropertyDWORD(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; PropId: DWORD): DWORD;
|
||
function SetDeviceState(DevInfoSet: HDEVINFO; var DevData: TSPDevInfoData; Enable: Boolean): Boolean;
|
||
function GetDevicePropertyString(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA; const PropKey: DEVPROPKEY): string;
|
||
function GetClassPropertyString(const ClassGuid: TGUID; const PropKey: DEVPROPKEY): string;
|
||
function GetDeviceInstanceId(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA): string;
|
||
// [ÇÙ½É] ÀåÄ¡°¡ Á¤Ã¥°ú ÀÏÄ¡ÇÏ´ÂÁö °Ë»çÇÏ´Â ÇÔ¼ö
|
||
// function IsDeviceMatch(DevInfoSet: HDEVINFO; var DevData: TSPDevInfoData; Policy: TPolicyItem; out DevName: string): Boolean;
|
||
|
||
procedure EnforceBluetoothPolicy(PolicyItem: TPolicyItem);
|
||
|
||
procedure ApplySingleMatch(Policy: TPolicyItem; Match: TMatchCriteria);
|
||
|
||
|
||
public
|
||
constructor Create;
|
||
destructor Destroy; override;
|
||
|
||
procedure Start;
|
||
procedure Stop;
|
||
procedure CreateDefaultPolicies;
|
||
|
||
function IsVirtualMachineDevice(const Info: TDeviceInfoDTO): Boolean;
|
||
function IsGeneralHIDDevice(const Info: TDeviceInfoDTO): Boolean;
|
||
function IsSystemOrCriticalDevice(const Info: TDeviceInfoDTO): Boolean;
|
||
procedure AllEnumSystemDevice;
|
||
// Á¤Ã¥ °ü¸®
|
||
// Ãʱâ Á¤Ã¥ µî·Ï (¸Þ¸ð¸®)
|
||
//procedure AddDefaultPolicy(const Name, GuidStr: string; IsBT: Boolean = False);
|
||
|
||
// [ÇÙ½É ±â´É]
|
||
procedure TriggerScan; // À̺¥Æ® ½Ã±×³Î ¹ß»ý
|
||
//procedure SavePolicyToFile; // ÇöÀç »óŸ¦ JSONÀ¸·Î ÀúÀå
|
||
//procedure LoadPolicyFromFile; // JSON¿¡¼ ÀÐ¾î¼ »óÅ ¾÷µ¥ÀÌÆ® ÈÄ ½ºÄµ Æ®¸®°Å
|
||
procedure EnforceSystemPolicy;
|
||
procedure CheckAndApplyPolicy(Policy: TPolicyItem);
|
||
procedure UsbPortApplyPolicy(state: TDeviceState);
|
||
function AddUsbPortExcept(const Vendor, Product,
|
||
Serial: string): Boolean;
|
||
|
||
property OnLog: TLogEvent read FOnLog write FOnLog;
|
||
property OnPopup: TLogEvent read FOnPopup write FOnPopup;
|
||
|
||
procedure UsbReStart;
|
||
function RestartDevice(hDevInfo: HDEVINFO; DevInfoData: SP_DEVINFO_DATA): Boolean;
|
||
function ScanForHardwareChanges: Boolean;
|
||
end;
|
||
|
||
function CM_Get_DevNode_Status(out pulStatus: DWORD; out pulProblemNumber: DWORD;
|
||
dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external 'cfgmgr32.dll' name 'CM_Get_DevNode_Status';
|
||
function CM_Locate_DevNode(var pdnDevInst: DEVINST; pDeviceID: PChar; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Locate_DevNodeW';
|
||
function CM_Reenumerate_DevNode(dnDevInst: DEVINST; ulFlags: ULONG): CONFIGRET; stdcall; external 'cfgmgr32.dll' name 'CM_Reenumerate_DevNode';
|
||
|
||
function SetupDiGetDeviceInfoListDetail(DeviceInfoSet: HDEVINFO; DeviceInfoListDetailData: PSPDevInfoListDetailData): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiGetDeviceInfoListDetailW';
|
||
function SetupDiChangeState(DeviceInfoSet: HDEVINFO; DeviceInfoData: Pointer): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiChangeState';
|
||
|
||
var
|
||
gDeviceGuardEngine: TDeviceGuardEngine = nil;
|
||
|
||
DEVPKEY_Device_DeviceDesc: DEVPROPKEY = (fmtid: '{A45C254E-DF1C-4EFD-8020-67D146A850E0}'; pid: 2);
|
||
DEVPKEY_Device_HardwareIds: DEVPROPKEY = (fmtid: '{A45C254E-DF1C-4EFD-8020-67D146A850E0}'; pid: 3);
|
||
DEVPKEY_Device_Manufacturer: DEVPROPKEY = (fmtid: '{A45C254E-DF1C-4EFD-8020-67D146A850E0}'; pid: 13);
|
||
DEVPKEY_Device_Parent: DEVPROPKEY = (fmtid: '{4340A6C5-93FA-4706-972C-7B648008A5A7}'; pid: 8);
|
||
DEVPKEY_Device_DriverDesc: DEVPROPKEY = (fmtid: '{A8B865DD-2E3D-4094-AD97-E593A708E5D3}'; pid: 2);
|
||
DEVPKEY_Device_BusReportedDeviceDesc: DEVPROPKEY = (fmtid: '{540B947E-8B40-45BC-A8A2-6A0B894CBDA2}'; pid: 4);
|
||
DEVPKEY_DeviceClass_Name: DEVPROPKEY = (fmtid: '{259ABFFC-50A7-47CE-AF08-68C9A7D73366}'; pid: 2);
|
||
|
||
function SetupDiGetDevicePropertyW(
|
||
DeviceInfoSet: HDEVINFO;
|
||
const DeviceInfoData: SP_DEVINFO_DATA;
|
||
const PropertyKey: DEVPROPKEY;
|
||
var PropertyType: DEVPROPTYPE;
|
||
PropertyBuffer: PByte; // ¹öÆÛ´Â Æ÷ÀÎÅÍ·Î Àü´Þ
|
||
PropertyBufferSize: DWORD;
|
||
var RequiredSize: DWORD;
|
||
Flags: DWORD
|
||
): BOOL; stdcall; external 'setupapi.dll';
|
||
|
||
function SetupDiGetClassPropertyW(
|
||
const ClassGuid: TGUID;
|
||
const PropertyKey: DEVPROPKEY;
|
||
var PropertyType: DEVPROPTYPE;
|
||
PropertyBuffer: PByte;
|
||
PropertyBufferSize: DWORD;
|
||
var RequiredSize: DWORD;
|
||
Flags: DWORD;
|
||
Reserved: PVOID
|
||
): BOOL; stdcall; external 'setupapi.dll';
|
||
|
||
function SetupDiGetDeviceInstanceId(
|
||
DeviceInfoSet: HDEVINFO;
|
||
const DeviceInfoData: SP_DEVINFO_DATA;
|
||
DeviceInstanceId: PWideChar;
|
||
DeviceInstanceIdSize: DWORD;
|
||
var RequiredSize: DWORD
|
||
): BOOL; stdcall; external 'setupapi.dll' name 'SetupDiGetDeviceInstanceIdW';
|
||
|
||
implementation
|
||
|
||
{ TDeviceGuardEngine }
|
||
|
||
|
||
constructor TDeviceGuardEngine.Create;
|
||
var
|
||
path: string;
|
||
begin
|
||
|
||
gDeviceGuardEngine:= self;
|
||
FScanEvent := TEvent.Create(nil, False, False, '');
|
||
FThread := nil;
|
||
path:= GetRunExePathDir;
|
||
|
||
gBs1Policy:= TBs1Policy.Create;
|
||
gBs1Policy.LoadDataControlConfig;
|
||
|
||
if gBs1Policy.Policies.Count = 0 then
|
||
begin
|
||
//ShowMessage('ÀúÀåµÈ Á¤Ã¥ÀÌ ¾ø¾î ±âº» Á¤Ã¥À» »ý¼ºÇÕ´Ï´Ù.');
|
||
CreateDefaultPolicies;
|
||
end;
|
||
|
||
end;
|
||
|
||
destructor TDeviceGuardEngine.Destroy;
|
||
begin
|
||
Stop;
|
||
FScanEvent.Free;
|
||
gBs1Policy.Free;
|
||
|
||
inherited;
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.Start;
|
||
begin
|
||
|
||
|
||
|
||
if FThread <> nil then Exit;
|
||
FThread := TGuardThread.Create(Self);
|
||
FThread.Start;
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.Stop;
|
||
begin
|
||
if FThread <> nil then
|
||
begin
|
||
FThread.Terminate;
|
||
FScanEvent.SetEvent;
|
||
FThread.WaitFor;
|
||
FreeAndNil(FThread);
|
||
end;
|
||
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.CreateDefaultPolicies;
|
||
var
|
||
P: TPolicyItem;
|
||
begin
|
||
|
||
//µå¶óÀ̺ê Á¦¾î
|
||
P := gBs1Policy.CreatePolicy('BDC_CDROM', BDC_CDROM);
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('BDC_FLOOPY', BDC_FLOOPY);
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('BDC_USB_DISK', BDC_USB_DISK);
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('BDC_NETWORKDRIVEOUT', BDC_NETWORKDRIVEOUT);
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('BDC_NETWORKDRIVEIN', BDC_NETWORKDRIVEIN);
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('BDC_EXTERNALHDD', BDC_EXTERNALHDD);
|
||
gBs1Policy.AddPolicyObject(P);
|
||
///
|
||
///
|
||
|
||
//
|
||
// P := gBs1Policy.CreatePolicy('PCMCIA', BDC_PCMCIA);
|
||
// P.AddMatch(SPDRP_SERVICE, 'PCMCIA', 'PCI');
|
||
// gBs1Policy.AddPolicyObject(P);
|
||
//
|
||
// P := gBs1Policy.CreatePolicy('SERIAL', BDC_SERIAL);
|
||
// P.AddMatch(SPDRP_SERVICE, 'Serial', 'ACPI');
|
||
// gBs1Policy.AddPolicyObject(P);
|
||
//
|
||
// P := gBs1Policy.CreatePolicy('1394', BDC_1394);
|
||
// P.AddMatch(SPDRP_SERVICE, '1394', '1394');
|
||
// gBs1Policy.AddPolicyObject(P);
|
||
//
|
||
// P := gBs1Policy.CreatePolicy('IRDA', BDC_IRDA);
|
||
// P.AddMatch(SPDRP_SERVICE, 'IRDA', 'IRDA');
|
||
// gBs1Policy.AddPolicyObject(P);
|
||
//
|
||
// P := gBs1Policy.CreatePolicy('WIBRO', BDC_WIBRO);
|
||
// P.AddMatch(SPDRP_SERVICE, 'WIBRO', 'WIBRO');
|
||
// gBs1Policy.AddPolicyObject(P);
|
||
//
|
||
// P := gBs1Policy.CreatePolicy('PARALLEL', BDC_PARALLEL);
|
||
// P.AddMatch(SPDRP_SERVICE, 'parport', 'ACPI');
|
||
// gBs1Policy.AddPolicyObject(P);
|
||
//
|
||
// P := gBs1Policy.CreatePolicy('MODEM', BDC_MODEM);
|
||
// P.AddMatch(SPDRP_SERVICE, 'MODEM', 'MODEM');
|
||
// gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('USB', BDC_USB);
|
||
P.AddMatch(SPDRP_SERVICE, 'USBSTOR', 'USB');
|
||
P.AddMatch(SPDRP_SERVICE, 'USBAAPL', 'USB');
|
||
P.AddMatch(SPDRP_SECURITY, 'Apple', 'USB');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('MTP', BDC_MTP, GUID_DEVCLASS_WPD);
|
||
P.AddMatch(SPDRP_HARDWAREID, '_mtp', 'USB');
|
||
P.AddMatch(SPDRP_COMPATIBLEIDS, '_mtp', 'USB');
|
||
P.AddMatch(SPDRP_DEVICEDESC, 'apple', 'USB');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('TETHERING', BDC_TETHERING);
|
||
P.AddMatch(SPDRP_SERVICE, 'usb_rndisx', 'USB');
|
||
P.AddMatch(SPDRP_SERVICE, 'usb_rndisk', 'USB');
|
||
P.AddMatch(SPDRP_SERVICE, 'Netaapl', 'USB');
|
||
P.AddMatch(SPDRP_SERVICE, 'andnetndis', 'USB');
|
||
P.AddMatch(SPDRP_SERVICE, 'lgwqmindis', 'USB');
|
||
P.AddMatch(SPDRP_SERVICE, 'usbrndis6', 'USB');
|
||
P.AddMatch(SPDRP_SERVICE, 'BthPan', 'BTH');
|
||
P.AddMatch(SPDRP_SERVICE, 'RFCOMM', 'BTH');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('SDCARD', BDC_SDCARD);
|
||
P.AddMatch(SPDRP_SERVICE, 'risdxc', 'PCI');
|
||
P.AddMatch(SPDRP_SERVICE, 'disk', 'RISD');
|
||
P.AddMatch(SPDRP_SERVICE, 'sffdisk', 'SD');
|
||
P.AddMatch(SPDRP_SERVICE, 'sdbus', 'PCI');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('WIRELESS', BDC_WIRELESS);
|
||
P.AddMatch(SPDRP_SERVICE, 'mtkwlex', 'PCI');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('WEBCAM', BDC_WEBCAM);
|
||
P.AddMatch(SPDRP_SERVICE, 'usbvideo', 'USB');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
P := gBs1Policy.CreatePolicy('Bluetooth', BDC_BLUETOOTH, '');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
// P := gBs1Policy.CreatePolicy('Bluetooth File', BDC_BLUETOOTH_FILE, '');
|
||
// P.AddMatch(SPDRP_SERVICE, 'BTHUSB', 'USB');
|
||
// P.AddMatch(SPDRP_SERVICE, 'BTWUSB', 'USB');
|
||
// P.AddMatch(SPDRP_SERVICE, 'BTMUSB', 'USB');
|
||
gBs1Policy.AddPolicyObject(P);
|
||
|
||
end;
|
||
|
||
|
||
procedure TDeviceGuardEngine.TriggerScan;
|
||
begin
|
||
if FScanEvent <> nil then
|
||
FScanEvent.SetEvent;
|
||
end;
|
||
|
||
{
|
||
// -----------------------------------------------------------------------------
|
||
// [ÇÙ½É] ÀåÄ¡ ¸ÅĪ ·ÎÁ÷ (C++ SetStateControlDevNode ·ÎÁ÷ ±¸Çö)
|
||
// -----------------------------------------------------------------------------
|
||
function TDeviceGuardEngine.IsDeviceMatch(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; Policy: TPolicyItem; out DevName: string): Boolean;
|
||
var
|
||
DevEnum, DevPropVal: string;
|
||
begin
|
||
Result := False;
|
||
DevName := '';
|
||
|
||
// 1. Enumerator È®ÀÎ (¼³Á¤µÈ °æ¿ì¸¸)
|
||
// ¿¹: "PCI", "USB" µî
|
||
if Policy.targetEnumerator_ <> '' then
|
||
begin
|
||
DevEnum := GetDeviceStringProperty(DevInfoSet, DevData, SPDRP_ENUMERATOR_NAME).ToUpper;
|
||
// ºÎºÐ ÀÏÄ¡°¡ ¾Æ´Ï¶ó Á¤È®È÷ ÀÏÄ¡ÇØ¾ß ÇÔ (ÇÊ¿ä ½Ã Contains·Î º¯°æ °¡´É)
|
||
if DevEnum <> Policy.targetEnumerator_ then Exit;
|
||
end;
|
||
|
||
// 2. Property È®ÀÎ
|
||
// ¿¹: SPDRP_SERVICE °ªÀÌ "PCMCIA" ÀÎÁö È®ÀÎ
|
||
// ¿¹: SPDRP_CLASSGUID °ªÀÌ "..." ÀÎÁö È®ÀÎ
|
||
DevPropVal := GetDeviceStringProperty(DevInfoSet, DevData, Policy.matchPropType_).ToUpper;
|
||
|
||
// °ªÀÌ ºñ¾îÀÖÀ¸¸é ¸ÅĪ ½ÇÆÐ
|
||
if DevPropVal = '' then Exit;
|
||
|
||
// ºÎºÐ ¹®ÀÚ¿ ¸ÅĪ (Contains) Çã¿ë -> GUID´Â Á¤È®È÷, À̸§Àº Æ÷ÇÔ µî À¯¿¬ÇϰÔ
|
||
if Pos(Policy.matchData_, DevPropVal) > 0 then
|
||
begin
|
||
// ¸ÅĪ ¼º°ø!
|
||
Result := True;
|
||
|
||
// ·Î±×¿ë À̸§ ÃßÃâ
|
||
DevName := GetDeviceStringProperty(DevInfoSet, DevData, SPDRP_FRIENDLYNAME);
|
||
if DevName = '' then DevName := GetDeviceStringProperty(DevInfoSet, DevData, SPDRP_DEVICEDESC);
|
||
end;
|
||
end;
|
||
}
|
||
|
||
function TDeviceGuardEngine.ScanForHardwareChanges: Boolean;
|
||
var
|
||
LDevInst: DEVINST;
|
||
status: CONFIGRET;
|
||
begin
|
||
LDevInst := 0;
|
||
//CM_LOCATE_DEVNODE_NORMAL = $00000000;
|
||
status := CM_Locate_DevNode(LDevInst, nil, $00000000);
|
||
|
||
if status <> CR_SUCCESS then
|
||
begin
|
||
_Trace(Format('[BS1]ScanForHardwareChanges, CM_Locate_DevNode failed: %x', [status]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
status := CM_Reenumerate_DevNode(LDevInst, 0);
|
||
|
||
if status <> CR_SUCCESS then
|
||
begin
|
||
_Trace(Format('[BS1]ScanForHardwareChanges, CM_Reenumerate_DevNode failed: %x', [status]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
Result := True;
|
||
end;
|
||
|
||
function TDeviceGuardEngine.RestartDevice(hDevInfo: HDEVINFO; DevInfoData: SP_DEVINFO_DATA): Boolean;
|
||
var
|
||
params: TSPPropChangeParams;
|
||
begin
|
||
FillChar(params, SizeOf(TSPPropChangeParams), 0);
|
||
|
||
params.ClassInstallHeader.cbSize := SizeOf(TSPClassInstallHeader);
|
||
params.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
|
||
params.StateChange := DICS_PROPCHANGE; // Restart (Stop -> Start)
|
||
params.Scope := DICS_FLAG_CONFIGSPECIFIC;
|
||
params.HwProfile := 0;
|
||
|
||
_Trace('[BS1] .... 1');
|
||
|
||
if not SetupDiSetClassInstallParams(hDevInfo, @DevInfoData, @params.ClassInstallHeader, SizeOf(TSPPropChangeParams)) then
|
||
begin
|
||
_Trace(Format('[BS1] SetupDiSetClassInstallParams Fail(%d)', [GetLastError]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
_Trace('[BS1] .... 2');
|
||
|
||
if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DevInfoData) then
|
||
begin
|
||
_Trace(Format('[BS1] SetupDiCallClassInstaller Fail(%d)', [GetLastError]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
_Trace('[BS1] .... 3');
|
||
|
||
|
||
if not SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, @DevInfoData) then
|
||
begin
|
||
_Trace(Format('[BS1] SetupDiCallClassInstaller(DIF_REMOVE) Fail(%d)', [GetLastError]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
|
||
_Trace('[BS1] .... 4');
|
||
|
||
// ChangeState È£Ãâ
|
||
SetupDiChangeState(hDevInfo, @DevInfoData);
|
||
|
||
_Trace(Format('[BS1] SetupDiCallClassInstaller Succeed(%d)', [GetLastError]));
|
||
Result := True;
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.UsbReStart;
|
||
const
|
||
DIGCF_PRESENT = $00000002;
|
||
DIGCF_ALLCLASSES = $00000004;
|
||
var
|
||
hDevInfo: THandle;
|
||
DeviceInfoData: SP_DEVINFO_DATA;
|
||
devInfoListDetail: TSPDevInfoListDetailData;
|
||
devIndex: Integer;
|
||
|
||
sService: string;
|
||
sHardwareID: string;
|
||
sSecurity: string;
|
||
begin
|
||
// ÀåÄ¡ Á¤º¸ ¼¼Æ® °¡Á®¿À±â
|
||
hDevInfo := SetupDiGetClassDevs(nil, nil, 0, DIGCF_PRESENT or DIGCF_ALLCLASSES);
|
||
|
||
if hDevInfo = INVALID_HANDLE_VALUE then
|
||
begin
|
||
_Trace('[BS1] SetupDiGetClassDevs Failed');
|
||
Exit;
|
||
end;
|
||
|
||
try
|
||
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
|
||
devInfoListDetail.cbSize := SizeOf(TSPDevInfoListDetailData);
|
||
|
||
SetupDiGetDeviceInfoListDetail(hDevInfo, @devInfoListDetail);
|
||
|
||
devIndex := 0;
|
||
while SetupDiEnumDeviceInfo(hDevInfo, devIndex, DeviceInfoData) do
|
||
begin
|
||
// Class GUID ºñ±³ ({36FC9E60-C465-11CF-8056-444553540000})
|
||
if IsEqualGUID(DeviceInfoData.ClassGuid, StringToGUID(GUID_DEVCLASS_USB)) then
|
||
begin
|
||
// 1. Service ¸í È®ÀÎ (SPDRP_SERVICE)
|
||
sService := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_SERVICE);
|
||
_Trace(Format('[BS1] SPDRP_SERVICE = [%s]', [sService]));
|
||
|
||
if (SameText(sService, 'USBSTOR')) or (SameText(sService, 'USBAAPL')) then
|
||
begin
|
||
// 2. Hardware ID È®ÀÎ
|
||
sHardwareID := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_HARDWAREID);
|
||
_Trace(Format('[BS1] SPDRP_HARDWAREID = [%s]', [sHardwareID]));
|
||
|
||
// VID_05E3ÀÌ Æ÷ÇԵǾî ÀÖÁö ¾ÊÀ¸¸é Disable ó¸®
|
||
if Pos('VID_05E3', sHardwareID) = 0 then
|
||
begin
|
||
_Trace('[BS1] PASS~!');
|
||
// ¿øº» ·ÎÁ÷: Disable ¼öÇà
|
||
//SetDeviceState(hDevInfo, DeviceInfoData, True);
|
||
RestartDevice(hDevInfo, DeviceInfoData); // ¿øº» ÁÖ¼® 󸮵Ê
|
||
|
||
Inc(devIndex);
|
||
Continue;
|
||
end;
|
||
end;
|
||
|
||
// 3. Apple ÀåÄ¡ È®ÀÎ (SPDRP_SECURITY_SDS -> SPDRP_SECURITY)
|
||
sSecurity := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_SECURITY);
|
||
_Trace(Format('[BS1] SPDRP_SECURITY_SDS = [%s]', [sSecurity]));
|
||
|
||
// "Apple" ¹®ÀÚ¿ÀÌ Æ÷ÇԵǰųª °°À¸¸é Restart
|
||
// C++ ¿øº»: memcmp(devID, "Apple", ...) -> Á¤È®È÷ "Apple"·Î ½ÃÀÛÇÏ´ÂÁö üũ
|
||
if Pos('Apple', sSecurity) > 0 then
|
||
begin
|
||
RestartDevice(hDevInfo, DeviceInfoData);
|
||
// SetDeviceState(hDevInfo, DeviceInfoData, True);
|
||
Inc(devIndex);
|
||
Continue;
|
||
end;
|
||
end;
|
||
|
||
Inc(devIndex);
|
||
end;
|
||
|
||
// Çϵå¿þ¾î º¯°æ »çÇ× °Ë»ö
|
||
ScanForHardwareChanges();
|
||
|
||
finally
|
||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||
end;
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.ApplySingleMatch(Policy: TPolicyItem; Match: TMatchCriteria);
|
||
var
|
||
hDevInfo: THandle;
|
||
DevInfoData: SP_DEVINFO_DATA;
|
||
Idx: DWORD;
|
||
ClassGuid: TGUID;
|
||
PClassGuid: PGUID;
|
||
Flags: DWORD;
|
||
Enumerator: PChar;
|
||
CurrentPropVal: string;
|
||
DevName: string;
|
||
dwStatus, dwProblem: DWORD;
|
||
bIsMatch: Boolean;
|
||
text: string;
|
||
IsLog: Boolean;
|
||
begin
|
||
PClassGuid := nil;
|
||
Flags := DIGCF_PRESENT;
|
||
Enumerator := nil;
|
||
|
||
// 1. GUID ¼³Á¤ (Á¤Ã¥ ·¹º§)
|
||
if Policy.targetGUID_ <> '' then
|
||
begin
|
||
ClassGuid := StringToGUID(Policy.targetGUID_);
|
||
PClassGuid := @ClassGuid;
|
||
end
|
||
else
|
||
begin
|
||
Flags := Flags or DIGCF_ALLCLASSES;
|
||
end;
|
||
|
||
// 2. Enumerator ¼³Á¤ (Match ·¹º§)
|
||
if Match.Enumerator <> '' then
|
||
Enumerator := PChar(Match.Enumerator);
|
||
|
||
hDevInfo := SetupDiGetClassDevs(PClassGuid, Enumerator, 0, Flags);
|
||
if hDevInfo = INVALID_HANDLE_VALUE then Exit;
|
||
|
||
try
|
||
Idx := 0;
|
||
DevInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
|
||
|
||
while SetupDiEnumDeviceInfo(hDevInfo, Idx, DevInfoData) do
|
||
begin
|
||
bIsMatch := False;
|
||
|
||
// 3. MatchData ºñ±³
|
||
if Match.MatchData <> '' then
|
||
begin
|
||
CurrentPropVal := GetDeviceStringProperty(hDevInfo, DevInfoData, Match.PropType).ToUpper;
|
||
|
||
|
||
if (CurrentPropVal <> '') and (Pos(Match.MatchData.ToUpper, CurrentPropVal) > 0) then
|
||
bIsMatch := True;
|
||
end
|
||
else
|
||
bIsMatch := True; // µ¥ÀÌÅÍ ¾øÀ¸¸é ¹«Á¶°Ç ¸ÅĪ
|
||
|
||
//TGuardThread(FThread).DoLog(Format('(%s)(%d), Match.Enumerator : (%s) PropType : %x (PropVal: %s<>%s)', [Policy.name, DWORD(bIsMatch), Match.Enumerator, Match.PropType, Match.MatchData.ToUpper, CurrentPropVal]));
|
||
|
||
if bIsMatch then
|
||
begin
|
||
//USBSTOR\DISK&VEN_VENDORCO&PROD_PRODUCTCODE&REV_2.00\8328501217610604362&0
|
||
var friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
|
||
if friendlyName = '' then
|
||
friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_DEVICEDESC);
|
||
|
||
var HardwareID := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_HARDWAREID);
|
||
var DeviceClass := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_CLASS);
|
||
var Service := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_SERVICE);
|
||
var RemovalPolicy := GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_REMOVAL_POLICY);
|
||
var InstatllState:= GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_INSTALL_STATE);
|
||
|
||
var ParentId := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Parent);
|
||
var DeviceDriveDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DriverDesc);
|
||
var Manufacturer := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Manufacturer);
|
||
var DeviceDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DeviceDesc);
|
||
var InstanceId:= GetDeviceInstanceId(hDevInfo, DevInfoData);
|
||
|
||
//TGuardThread(FThread).DoLog(Format('InstanceId : %s', [InstanceId]));
|
||
|
||
// »óÅ Á¦¾î (Block/Allow)
|
||
if CM_Get_DevNode_Status(dwStatus, dwProblem, DevInfoData.DevInst, 0) = CR_SUCCESS then
|
||
begin
|
||
|
||
_Trace(Format('[BS1] CM_Get_DevNode_Status, dwStatus: %d' , [dwStatus]));
|
||
DevName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
|
||
if DevName = '' then DevName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_DEVICEDESC);
|
||
|
||
//TGuardThread(FThread).DoLog(Format('DevName : %s, state : %d', [DevName, DWORD(Policy.state_)]));
|
||
|
||
case Policy.state_ of
|
||
dsDisable:
|
||
begin
|
||
|
||
if (Policy.flag_ = DWORD(BDC_USB)) and gBs1Policy.IsUsbPortExcept(InstanceId) then
|
||
begin
|
||
_Trace('[BS1]' + text + '¿¹¿Ü' + ParentId);
|
||
|
||
text:= '------------------------> [Çã¿ë] ';
|
||
if ((dwStatus and DN_DISABLEABLE) <> 0) and ((dwStatus and DN_HAS_PROBLEM) <> 0) then
|
||
begin
|
||
if SetDeviceState(hDevInfo, DevInfoData, True) then
|
||
begin
|
||
IsLog:= True;
|
||
_Trace('[BS1]' + text + DevName);
|
||
end;
|
||
end;
|
||
|
||
break;
|
||
end
|
||
else
|
||
begin
|
||
text:= '------------------------> [Â÷´Ü] ';
|
||
if ((dwStatus and DN_DRIVER_LOADED) <> 0) and ((dwStatus and DN_STARTED) <> 0) then
|
||
begin
|
||
if SetDeviceState(hDevInfo, DevInfoData, False) then
|
||
begin
|
||
IsLog:= True;
|
||
|
||
_Trace(text + DevName);
|
||
// TGuardThread(FThread).ShowPopup(DevName);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
end;
|
||
dsReadOnly,
|
||
dsEnable:
|
||
begin
|
||
text:= '------------------------> [Çã¿ë] ';
|
||
if ((dwStatus and DN_DISABLEABLE) <> 0) and ((dwStatus and DN_HAS_PROBLEM) <> 0) then
|
||
begin
|
||
if SetDeviceState(hDevInfo, DevInfoData, True) then
|
||
begin
|
||
IsLog:= True;
|
||
_Trace('[BS1]' + text + DevName);
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
if Policy.isLog_ and IsLog then
|
||
begin
|
||
_Trace(Format('[BS1] [ŽÁö](%s) %s (Rule: %s)', [text, DevName, Policy.Name]));
|
||
_Trace(Format(
|
||
'[BS1] Service:%s, DeviceClass:%s, friendlyName:%s, HardwareID:%s', [Service, DeviceClass, friendlyName, HardwareID]));
|
||
_Trace(Format(
|
||
'[BS1] ParentId:%s, DeviceDriveDesc:%s, Manufacturer:%s, RemovalPolicy:%d, InstatllState:%d',
|
||
[ParentId, DeviceDriveDesc, Manufacturer, DWORD(RemovalPolicy), DWORD(InstatllState)]));
|
||
_Trace(Format('[BS1] InstanceId:%s', [InstanceId]));
|
||
_Trace('-----------------------------------------------------');
|
||
end;
|
||
|
||
IsLog:= False;
|
||
end
|
||
else
|
||
begin
|
||
_Trace(Format('[BS1] CM_Get_DevNode_Status Fail : %d', [GetLastError]));
|
||
end;
|
||
end;
|
||
Inc(Idx);
|
||
end;
|
||
finally
|
||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
procedure TDeviceGuardEngine.CheckAndApplyPolicy(Policy: TPolicyItem);
|
||
begin
|
||
// Match Ç׸ñÀÌ ¾øÀ¸¸é ½ÇÇàÇÏÁö ¾ÊÀ½ (´Ü, ºí·çÅõ½º µî ¿¹¿Ü Á¦¿Ü)
|
||
// ¶Ç´Â Match°¡ ¾øÀ¸¸é Â÷´Ü/Çã¿ëÀ» ¸øÇϹǷΠÆÐ½º
|
||
if Policy.Matches_.Count = 0 then Exit;
|
||
|
||
_Trace(Format('[BS1] Enumerator : state(%d)', [DWORD(Policy.state_)]));
|
||
for var Match in Policy.Matches_ do
|
||
begin
|
||
_Trace(Format('[BS1] Enumerator : (%s) MatchData : (%s)', [Match.Enumerator, Match.MatchData]));
|
||
ApplySingleMatch(Policy, Match);
|
||
end;
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.UsbPortApplyPolicy(state: TDeviceState);
|
||
var
|
||
tmp : TPolicyItem;
|
||
|
||
begin
|
||
tmp:= gBs1Policy.GetPolicyItem(DWORD(BDC_USB));
|
||
tmp.state_:= state;
|
||
CheckAndApplyPolicy(tmp);
|
||
end;
|
||
|
||
function TDeviceGuardEngine.AddUsbPortExcept(const Vendor, Product, Serial: string): Boolean;
|
||
begin
|
||
|
||
gBs1Policy.AddUsbPortExcept(Vendor, Product, Serial);
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.EnforceSystemPolicy;
|
||
var
|
||
Policies: TObjectList<TPolicyItem>;
|
||
tmp : TPolicyItem;
|
||
begin
|
||
|
||
Policies := TObjectList<TPolicyItem>.Create(True);
|
||
// µî·ÏµÈ ¸ðµç Á¤Ã¥¿¡ ´ëÇØ ¼øÈ¸
|
||
|
||
try
|
||
if gBs1Policy <> nil then
|
||
begin
|
||
gBs1Policy.CopyPoliciesTo(Policies);
|
||
end;
|
||
|
||
for var Policy in Policies do
|
||
begin
|
||
// ºí·çÅõ½º´Â º°µµ ·ÎÁ÷
|
||
// if Policy.isBluetooth_ then
|
||
// begin
|
||
// EnforceBluetoothPolicy(Policy);
|
||
// Continue;
|
||
// end;
|
||
|
||
case Policy.flag_ of
|
||
DWORD(BDC_CDROM),
|
||
DWORD(BDC_FLOOPY),
|
||
DWORD(BDC_USB_DISK),
|
||
DWORD(BDC_NETWORKDRIVEOUT),
|
||
DWORD(BDC_NETWORKDRIVEIN),
|
||
DWORD(BDC_EXTERNALHDD):
|
||
continue;
|
||
end;
|
||
|
||
// ÀÏ¹Ý ÀåÄ¡ Á¦¾î (SetupDiGetClassDevs -> Enum -> Match)
|
||
// gBs1fltControl.SetPolicy(Policy.flag_, DWORD(Policy.state_), DWORD(Policy.isLog_));
|
||
// if (Policy.flag_ <> DWORD(BDC_MTP)) then
|
||
// begin
|
||
|
||
|
||
// end;
|
||
_Trace(Format('[BS1] EnforceSystemPolicy, flag(%d), state(%d),log(%d)', [DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_)]));
|
||
|
||
if (Policy.flag_ = DWORD(BDC_BLUETOOTH_FILE)) then
|
||
begin
|
||
continue;
|
||
end
|
||
else if (Policy.flag_ = DWORD(BDC_MTP)) then
|
||
begin
|
||
var state: TDeviceState;
|
||
var log: Boolean;
|
||
|
||
gBs1Policy.GetPolicyState(DWORD(BDC_USB), state, log);
|
||
_Trace(Format('[BS1] EnforceSystemPolicy, BDC_USB, state(%d) log : (%d)', [DWORD(state), DWORD(log)]));
|
||
if (Policy.state_ = dsEnable) and (state = dsDisable) then
|
||
begin
|
||
// /CheckAndApplyPolicy(Policy);
|
||
_Trace(Format('[BS1] EnforceSystemPolicy, BDC_MTP, dsEnable', []));
|
||
gBs1FltControl.SetPolicy(DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_));
|
||
end
|
||
else
|
||
begin
|
||
_Trace(Format('[BS1] EnforceSystemPolicy, BDC_MTP, dsDisable', []));
|
||
gBs1FltControl.SetPolicy(DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_));
|
||
CheckAndApplyPolicy(Policy);
|
||
end;
|
||
|
||
|
||
continue;
|
||
end;
|
||
|
||
gBs1FltControl.SetPolicy(DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_));
|
||
// else if (Policy.flag_ = DWORD(BDC_USB)) then
|
||
// begin
|
||
// if (TDeviceState(Policy.state_) = dsDisable) then
|
||
// begin
|
||
// if not FUseRestart then
|
||
// begin
|
||
// UsbReStart;
|
||
// FUseRestart:= True;
|
||
// end;
|
||
// OnLog('UsbReStart Sucess...');
|
||
// end
|
||
// else
|
||
// begin
|
||
// FUseRestart:= False;
|
||
// end;
|
||
//
|
||
// continue;
|
||
// end;
|
||
|
||
CheckAndApplyPolicy(Policy);
|
||
|
||
end;
|
||
finally
|
||
Policies.Free;
|
||
|
||
end;
|
||
end;
|
||
|
||
function TDeviceGuardEngine.IsVirtualMachineDevice(const Info: TDeviceInfoDTO): Boolean;
|
||
begin
|
||
// Á¦°ÅÁ¤Ã¥ 2¹øÀÌ¸é¼ Æ¯Á¤ Ŭ·¡½ºÀÎ °æ¿ì (VMware, VirtualBox µî ¹æ¾î)
|
||
if Info.RemovalPolicy = CM_REMOVAL_POLICY_EXPECT_ORDERLY_REMOVAL then
|
||
begin
|
||
// if SameText(Info.DeviceClass, 'Net') or
|
||
if SameText(Info.DeviceClass, 'Monitor') or
|
||
SameText(Info.DeviceClass, 'System') or
|
||
SameText(Info.DeviceClass, 'HDC') or
|
||
SameText(Info.DeviceClass, 'DiskDrive') or
|
||
SameText(Info.DeviceClass, 'MEDIA') or
|
||
SameText(Info.DeviceClass, 'Display') then
|
||
|
||
begin
|
||
Exit(True); // °Ç³Ê¶Ù¾î¾ß ÇÔ
|
||
end;
|
||
end;
|
||
Result := False;
|
||
end;
|
||
|
||
function TDeviceGuardEngine.IsGeneralHIDDevice(const Info: TDeviceInfoDTO): Boolean;
|
||
begin
|
||
// Űº¸µå, ¸¶¿ì½º µîÀº Àý´ë Â÷´ÜÇÏ¸é ¾È µÊ
|
||
if (Pos('KEYBOARD', UpperCase(Info.DeviceClass)) > 0) or
|
||
(Pos('MOUSE', UpperCase(Info.DeviceClass)) > 0) or
|
||
(SameText(Info.DeviceClass, 'HIDClass')) then
|
||
begin
|
||
Result := True;
|
||
end
|
||
else
|
||
Result := False;
|
||
end;
|
||
|
||
function TDeviceGuardEngine.IsSystemOrCriticalDevice(const Info: TDeviceInfoDTO): Boolean;
|
||
begin
|
||
// °íÁ¤ ÀåÄ¡ (Removal Policy 1)
|
||
if Info.RemovalPolicy = CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL then
|
||
Exit(True);
|
||
|
||
// ¿°ÅÀÚ(Enumerator)¿Í ¼ºñ½º/Ŭ·¡½º Á¶ÇÕ È®ÀÎ
|
||
if (SameText(Info.Enumerator, 'SCSI') and SameText(Info.Service, 'DISK')) or
|
||
(SameText(Info.Enumerator, 'PCI') and SameText(Info.Service, 'nvlddmkm')) or // NVIDIA ±×·¡ÇÈ
|
||
(SameText(Info.Enumerator, 'SCSI') and SameText(Info.DeviceClass, 'DiskDrive')) or
|
||
(SameText(Info.Enumerator, 'PCI') and SameText(Info.DeviceClass, 'Display')) then
|
||
begin
|
||
Exit(True);
|
||
end;
|
||
|
||
// ƯÁ¤ Ŭ·¡½º À̸§ È®ÀÎ (¼ÒÇÁÆ®¿þ¾î ÀåÄ¡, ¿Àµð¿À, ÇÁ¸°ÅÍ µî)
|
||
// MatchText¸¦ ¾²¸é OR ¿¬»êÀ» ¹è¿·Î ±ò²ûÇÏ°Ô Ã³¸®ÇÒ ¼ö ÀÖ½À´Ï´Ù.
|
||
if MatchText(Info.DeviceClass, ['AudioEndpoint',
|
||
'PrintQueue',
|
||
'SoftwareDevice',
|
||
'WSDPrintDevice',
|
||
'Image']) then
|
||
begin
|
||
Exit(True);
|
||
end;
|
||
|
||
Result := False;
|
||
end;
|
||
|
||
function TDeviceInfoDTO.GetMainHardwareID: string;
|
||
begin
|
||
// HardwareID´Â ¸ÖƼ½ºÆ®¸µÀ̹ǷΠù ¹øÂ° ÁÙ¸¸ °¡Á®¿À°Å³ª ÆÄ½Ì
|
||
// ¿¹: USB\VID_1234&PID_5678...
|
||
Result := HardwareID.Split([#0], TStringSplitOptions.ExcludeEmpty)[0];
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.AllEnumSystemDevice;
|
||
var
|
||
hDevInfo: THandle;
|
||
DevInfoData: SP_DEVINFO_DATA;
|
||
Idx: DWORD;
|
||
MatchedItem: TPolicyItem;
|
||
IsMatchFound: Boolean;
|
||
DevName: string;
|
||
Info: TDeviceInfoDTO;
|
||
UniqueKey: string;
|
||
dwStatus, dwProblem: DWORD;
|
||
InstatllState: DWORD;
|
||
begin
|
||
|
||
hDevInfo := SetupDiGetClassDevs(nil, nil, 0, DIGCF_PRESENT or DIGCF_ALLCLASSES);
|
||
if hDevInfo = INVALID_HANDLE_VALUE then Exit;
|
||
|
||
try
|
||
Idx := 0;
|
||
|
||
DevInfoData.cbSize := SizeOf(SP_DEVINFO_DATA);
|
||
|
||
while SetupDiEnumDeviceInfo(hDevInfo, Idx, DevInfoData) do
|
||
begin
|
||
|
||
try
|
||
MatchedItem := nil;
|
||
IsMatchFound := False;
|
||
DevName := '';
|
||
|
||
Info.Index := Idx;
|
||
Info.friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
|
||
if Info.friendlyName = '' then
|
||
Info.friendlyName := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_DEVICEDESC);
|
||
|
||
Info.HardwareID := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_HARDWAREID);
|
||
Info.DeviceClass := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_CLASS);
|
||
Info.Service := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_SERVICE);
|
||
Info.Enumerator := GetDeviceStringProperty(hDevInfo, DevInfoData, SPDRP_ENUMERATOR_NAME);
|
||
Info.RemovalPolicy := GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_REMOVAL_POLICY);
|
||
InstatllState:= GetDeviceStringPropertyDWORD(hDevInfo, DevInfoData, SPDRP_INSTALL_STATE);
|
||
|
||
Info.ParentId := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Parent);
|
||
var DeviceDriveDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DriverDesc);
|
||
var Manufacturer := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_Manufacturer);
|
||
var DeviceDesc := GetDevicePropertyString(hDevInfo, DevInfoData, DEVPKEY_Device_DeviceDesc);
|
||
|
||
if Info.DeviceClass = '' then
|
||
Continue;
|
||
if InstatllState = CM_INSTALL_STATE_FAILED_INSTALL then
|
||
Continue;
|
||
|
||
if IsVirtualMachineDevice(Info) then Continue; // VM ¿¹¿Ü
|
||
if IsSystemOrCriticalDevice(Info) then Continue; // ½Ã½ºÅÛ ÀåÄ¡ ¿¹¿Ü
|
||
if IsGeneralHIDDevice(Info) then Continue; // Űº¸µå/¸¶¿ì½º ¿¹¿Ü
|
||
|
||
// ÀåÄ¡ ³ëµå »óÅ ȮÀÎ (Start ¿©ºÎ)
|
||
if CM_Get_DevNode_Status(dwStatus, dwProblem, DevInfoData.DevInst, 0) = CR_SUCCESS then
|
||
begin
|
||
Info.IsStarted := (dwStatus and DN_STARTED) <> 0;
|
||
end
|
||
else
|
||
Continue; // »óÅ ȮÀÎ ºÒ°¡ ÀåÄ¡´Â ÆÐ½º
|
||
|
||
UniqueKey := Info.GetMainHardwareID;
|
||
|
||
if FThread <> nil then
|
||
begin
|
||
_Trace(Format('[BS1] [Ŭ·¡½º ¸í] : Name : %s, Class : %s', [Info.DeviceClass, DevInfoData.ClassGuid.ToString]));
|
||
_Trace(
|
||
Format('[BS1] serviceName : %s || enumeratorName : %s || friendlyName: %s || HWID: %s || RemovalPolicy: %d || UniqueKey: %s',
|
||
[Info.Service, Info.Enumerator, Info.friendlyName, Info.HardwareID, Info.RemovalPolicy, UniqueKey]));
|
||
_Trace(
|
||
Format('[BS1] ParentId : %s || DeviceDriveDesc : %s || Manufacturer: %s || DeviceDesc: %s\n',
|
||
[Info.ParentId, DeviceDriveDesc, Manufacturer, DeviceDesc]));
|
||
|
||
end;
|
||
sleep(10);
|
||
finally
|
||
Inc(Idx);
|
||
end;
|
||
|
||
end;
|
||
finally
|
||
SetupDiDestroyDeviceInfoList(hDevInfo);
|
||
end;
|
||
end;
|
||
|
||
|
||
function TDeviceGuardEngine.GetDevicePropertyString(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA; const PropKey: DEVPROPKEY): string;
|
||
var
|
||
PropType: DEVPROPTYPE;
|
||
ReqSize: DWORD;
|
||
Buffer: array of Byte;
|
||
begin
|
||
Result := '';
|
||
ReqSize := 0;
|
||
|
||
// 1. Å©±â Á¶È¸
|
||
if not SetupDiGetDevicePropertyW(hDevInfo, DevData, PropKey, PropType, nil, 0, ReqSize, 0) then
|
||
begin
|
||
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then Exit;
|
||
end;
|
||
|
||
if ReqSize = 0 then Exit;
|
||
|
||
// 2. µ¥ÀÌÅÍ Á¶È¸
|
||
SetLength(Buffer, ReqSize);
|
||
if SetupDiGetDevicePropertyW(hDevInfo, DevData, PropKey, PropType, @Buffer[0], ReqSize, ReqSize, 0) then
|
||
begin
|
||
// DEVPROP_TYPE_STRING È®ÀÎ ·ÎÁ÷ÀÌ ÇÊ¿äÇÒ ¼ö ÀÖÀ¸³ª, ¿©±â¼± ¹®ÀÚ¿ÀÌ¶ó °¡Á¤ÇÏ°í º¯È¯
|
||
Result := TEncoding.Unicode.GetString(Buffer);
|
||
Result := Result.TrimRight([#0]); // NULL Á¾·á ¹®ÀÚ Á¦°Å
|
||
end;
|
||
end;
|
||
|
||
|
||
function TDeviceGuardEngine.GetClassPropertyString(const ClassGuid: TGUID; const PropKey: DEVPROPKEY): string;
|
||
var
|
||
PropType: DEVPROPTYPE;
|
||
ReqSize: DWORD;
|
||
Buffer: array of Byte;
|
||
begin
|
||
Result := '';
|
||
ReqSize := 0;
|
||
|
||
// 1. Å©±â Á¶È¸
|
||
if not SetupDiGetClassPropertyW(ClassGuid, PropKey, PropType, nil, 0, ReqSize, DICLASSPROP_INSTALLER, 0) then
|
||
begin
|
||
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then Exit;
|
||
end;
|
||
|
||
if ReqSize = 0 then Exit;
|
||
|
||
// 2. µ¥ÀÌÅÍ Á¶È¸
|
||
SetLength(Buffer, ReqSize);
|
||
if SetupDiGetClassPropertyW(ClassGuid, PropKey, PropType, @Buffer[0], ReqSize, ReqSize, DICLASSPROP_INSTALLER, 0) then
|
||
begin
|
||
Result := TEncoding.Unicode.GetString(Buffer);
|
||
Result := Result.TrimRight([#0]);
|
||
end;
|
||
end;
|
||
|
||
function TDeviceGuardEngine.GetDeviceStringProperty(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; PropId: DWORD): string;
|
||
var
|
||
Buffer: TBytes;
|
||
Size, ReqSize: DWORD;
|
||
DataType: DWORD;
|
||
dwPropertyRegDataType: DWORD;
|
||
begin
|
||
Result := '';
|
||
ReqSize := 0;
|
||
SetupDiGetDeviceRegistryProperty(DevInfoSet, DevData, PropId, dwPropertyRegDataType, nil, 0, ReqSize);
|
||
if (GetLastError = ERROR_INSUFFICIENT_BUFFER) and (ReqSize > 0) then
|
||
begin
|
||
SetLength(Buffer, ReqSize);
|
||
if SetupDiGetDeviceRegistryProperty(DevInfoSet, DevData, PropId, DataType, @Buffer[0], ReqSize, Size) then
|
||
if (DataType = REG_SZ) or (DataType = REG_MULTI_SZ) then
|
||
Result := TEncoding.Unicode.GetString(Buffer).Trim([#0]);
|
||
end;
|
||
end;
|
||
|
||
function TDeviceGuardEngine.GetDeviceStringPropertyDWORD(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; PropId: DWORD): DWORD;
|
||
var
|
||
ReqSize, DataType: DWORD;
|
||
begin
|
||
Result := 0;
|
||
SetupDiGetDeviceRegistryProperty(DevInfoSet, DevData, PropId, DataType, @Result, SizeOf(DWORD), ReqSize);
|
||
end;
|
||
|
||
function TDeviceGuardEngine.GetDeviceInstanceId(hDevInfo: HDEVINFO; var DevData: SP_DEVINFO_DATA): string;
|
||
var
|
||
ReqSize: DWORD;
|
||
Buffer: array of Char; // µ¿Àû ¹è¿ »ç¿ë
|
||
begin
|
||
Result := '';
|
||
ReqSize := 0;
|
||
|
||
// 1. ÇÊ¿äÇÑ ¹öÆÛ Å©±â ±¸Çϱâ
|
||
// ÇÔ¼ö°¡ False¸¦ ¸®ÅÏÇϰí GetLastError°¡ ERROR_INSUFFICIENT_BUFFERÀÏ ¶§ Á¤»ó
|
||
if not SetupDiGetDeviceInstanceId(hDevInfo, DevData, nil, 0, ReqSize) then
|
||
begin
|
||
if GetLastError <> ERROR_INSUFFICIENT_BUFFER then Exit;
|
||
end;
|
||
|
||
if ReqSize = 0 then Exit;
|
||
|
||
// 2. ¹öÆÛ ¸Þ¸ð¸® ÇÒ´ç
|
||
SetLength(Buffer, ReqSize);
|
||
|
||
// 3. ½ÇÁ¦ µ¥ÀÌÅÍ °¡Á®¿À±â
|
||
if SetupDiGetDeviceInstanceId(hDevInfo, DevData, @Buffer[0], ReqSize, ReqSize) then
|
||
begin
|
||
// PChar·Î º¯È¯ÇÏ¿© µ¨ÆÄÀÌ ½ºÆ®¸µ¿¡ ´ã±â
|
||
Result := PChar(@Buffer[0]);
|
||
Result := Trim(Result); // Ȥ½Ã ¸ð¸¦ °ø¹é Á¦°Å
|
||
end;
|
||
end;
|
||
|
||
function TDeviceGuardEngine.SetDeviceState(DevInfoSet: HDEVINFO; var DevData: SP_DEVINFO_DATA; Enable: Boolean): Boolean;
|
||
var
|
||
PCP: SP_PROPCHANGE_PARAMS;
|
||
state : DWORD;
|
||
|
||
begin
|
||
FillChar(PCP, SizeOf(PCP), 0);
|
||
PCP.ClassInstallHeader.cbSize := SizeOf(PCP.ClassInstallHeader);
|
||
PCP.ClassInstallHeader.InstallFunction := DIF_PROPERTYCHANGE;
|
||
|
||
if Enable then
|
||
PCP.StateChange := DICS_ENABLE
|
||
else
|
||
PCP.StateChange := DICS_DISABLE;
|
||
|
||
PCP.Scope := DICS_FLAG_GLOBAL;
|
||
PCP.HwProfile := 0;
|
||
|
||
if not SetupDiSetClassInstallParams(DevInfoSet, @DevData, @PCP, SizeOf(PCP)) then
|
||
Exit(False);
|
||
|
||
Result := SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DevInfoSet, @DevData);
|
||
if Result then
|
||
begin
|
||
state:= DWORD(SetupDiChangeState(DevInfoSet, @DevData));
|
||
if state = 0 then
|
||
begin
|
||
_Trace('[BS1] SetupDiChangeState Fail : ' + GetLastError.ToString);
|
||
Result:= False;
|
||
end;
|
||
|
||
end
|
||
else
|
||
begin
|
||
_Trace('[BS1] SetupDiCallClassInstaller Fail : ' + GetLastError.ToString);
|
||
end;
|
||
|
||
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.EnforceBluetoothPolicy(PolicyItem: TPolicyItem);
|
||
var
|
||
SearchParams: BLUETOOTH_DEVICE_SEARCH_PARAMS;
|
||
DeviceInfo: BLUETOOTH_DEVICE_INFO;
|
||
DeviceHandle: HBLUETOOTH_DEVICE_FIND;
|
||
MajorClass: Cardinal;
|
||
IsTarget: Boolean;
|
||
begin
|
||
if PolicyItem.state_ = dsEnable then Exit;
|
||
|
||
FillChar(SearchParams, SizeOf(SearchParams), 0);
|
||
SearchParams.dwSize := SizeOf(SearchParams);
|
||
SearchParams.fReturnAuthenticated := True;
|
||
SearchParams.fReturnConnected := True;
|
||
SearchParams.fReturnRemembered := True;
|
||
SearchParams.fReturnUnknown := True;
|
||
SearchParams.fIssueInquiry := False;
|
||
|
||
FillChar(DeviceInfo, SizeOf(DeviceInfo), 0);
|
||
DeviceInfo.dwSize := SizeOf(DeviceInfo);
|
||
|
||
DeviceHandle := BluetoothFindFirstDevice(SearchParams, DeviceInfo);
|
||
if DeviceHandle = 0 then Exit;
|
||
|
||
try
|
||
repeat
|
||
MajorClass := (DeviceInfo.ulClassofDevice and $1F00) shr 8;
|
||
IsTarget := False;
|
||
|
||
// KCD_BLUETOOTH(Àüü) ¶Ç´Â KCD_BLUETOOTH_FILE(ÀϺÎ) µî¿¡ µû¶ó ·ÎÁ÷ ºÐ±â °¡´É
|
||
// ¿©±â¼± ±âÁ¸ ·ÎÁ÷´ë·Î ¿Àµð¿À/Æù/¿þ¾î·¯ºí Â÷´Ü
|
||
if (MajorClass = COD_MAJOR_AUDIO) or (MajorClass = COD_MAJOR_PHONE) or (MajorClass = COD_MAJOR_WEARABLE) then
|
||
IsTarget := True;
|
||
|
||
if MajorClass = COD_MAJOR_PERIPHERAL then IsTarget := False;
|
||
|
||
if IsTarget and (PolicyItem.state_ = dsDisable) then
|
||
begin
|
||
if BluetoothRemoveDevice(DeviceInfo.Address) = ERROR_SUCCESS then
|
||
begin
|
||
if FThread <> nil then
|
||
begin
|
||
_Trace('[BS1] [BT Â÷´Ü] ' + DeviceInfo.szName);
|
||
//TGuardThread(FThread).ShowPopup('BT: ' + DeviceInfo.szName);
|
||
end;
|
||
end;
|
||
end;
|
||
until not BluetoothFindNextDevice(DeviceHandle, DeviceInfo);
|
||
finally
|
||
BluetoothFindDeviceClose(DeviceHandle);
|
||
end;
|
||
end;
|
||
|
||
{ TGuardThread }
|
||
constructor TGuardThread.Create(AOwnerEngine: TObject);
|
||
begin
|
||
inherited Create(True);
|
||
FOwnerEngine := AOwnerEngine;
|
||
FreeOnTerminate := False;
|
||
end;
|
||
|
||
procedure TGuardThread.Execute;
|
||
var
|
||
Engine: TDeviceGuardEngine;
|
||
WaitResult: TWaitResult;
|
||
begin
|
||
Engine := TDeviceGuardEngine(FOwnerEngine);
|
||
|
||
while not Terminated do
|
||
begin
|
||
WaitResult := Engine.FScanEvent.WaitFor(INFINITE);
|
||
|
||
if Terminated then Break;
|
||
|
||
if WaitResult = wrSignaled then
|
||
begin
|
||
try
|
||
Engine.EnforceSystemPolicy;
|
||
except
|
||
on E: Exception do OutPutDebugStringW(PChar('[BS1] Scan Error: ' + E.Message));
|
||
end;
|
||
// ÀÚµ¿ ¸®¼Â À̺¥Æ®°¡ ¾Æ´Ï¸é ResetEvent È£Ãâ ÇÊ¿ä, ¿©±â¼± Create½Ã ÀÚµ¿ ¸®¼ÂÀ¸·Î ¼³Á¤ÇÔ
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
procedure TGuardThread.DoLog(const Msg: string);
|
||
begin
|
||
if Terminated then Exit;
|
||
Queue(procedure begin
|
||
if Assigned(TDeviceGuardEngine(FOwnerEngine).OnLog) then
|
||
TDeviceGuardEngine(FOwnerEngine).OnLog(Msg);
|
||
end);
|
||
end;
|
||
|
||
procedure TGuardThread.ShowPopup(const Msg: string);
|
||
begin
|
||
if Terminated then Exit;
|
||
Queue(procedure begin
|
||
if Assigned(TDeviceGuardEngine(FOwnerEngine).OnPopup) then
|
||
TDeviceGuardEngine(FOwnerEngine).OnPopup(Msg);
|
||
end);
|
||
end;
|
||
|
||
end.
|