1237 lines
39 KiB
Plaintext
1237 lines
39 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.Driver, Tocsg.Path,
|
||
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
|
||
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;
|
||
|
||
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);
|
||
|
||
|
||
property OnLog: TLogEvent read FOnLog write FOnLog;
|
||
property OnPopup: TLogEvent read FOnPopup write FOnPopup;
|
||
|
||
class function ReportCallback(Context: Pointer): DWORD; stdcall; static;
|
||
|
||
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 }
|
||
|
||
class function TDeviceGuardEngine.ReportCallback(Context: Pointer): DWORD; stdcall;
|
||
var
|
||
logMsg: string;
|
||
Instance: TDeviceGuardEngine;
|
||
begin
|
||
if Context = nil then Exit;
|
||
|
||
LogMsg := string(PWideChar(Context));
|
||
|
||
OutputDebugString(PWideChar(Context));
|
||
|
||
TThread.Queue(nil,
|
||
procedure
|
||
begin
|
||
if Assigned(gDeviceGuardEngine) then
|
||
begin
|
||
gDeviceGuardEngine.OnLog(LogMsg);
|
||
end;
|
||
end);
|
||
|
||
Result := 0;
|
||
end;
|
||
|
||
constructor TDeviceGuardEngine.Create;
|
||
begin
|
||
|
||
gDeviceGuardEngine:= self;
|
||
//FPolicies := TObjectList<TPolicyItem>.Create;
|
||
//FLock := TCriticalSection.Create;
|
||
FScanEvent := TEvent.Create(nil, False, False, '');
|
||
FThread := nil;
|
||
//FPolicyFilePath := ChangeFileExt(ParamStr(0), '.json');
|
||
end;
|
||
|
||
destructor TDeviceGuardEngine.Destroy;
|
||
begin
|
||
Stop;
|
||
FScanEvent.Free;
|
||
//FPolicies.Free;
|
||
//FLock.Free;
|
||
inherited;
|
||
end;
|
||
|
||
procedure TDeviceGuardEngine.Start;
|
||
var
|
||
path: string;
|
||
state: DWORD;
|
||
begin
|
||
path:= GetRunExePathDir;
|
||
gBs1fltControl:= TBs1fltControl.Create;
|
||
|
||
try
|
||
// Ä¿³Î µå¶óÀ̹öÀÇ À§Ä¡¸¦ Á¤ÇÑ´Ù.
|
||
state := gBs1fltControl.InitDriver(path, TDeviceGuardEngine.ReportCallback);
|
||
|
||
if state = 0 then
|
||
begin
|
||
OnLog('Bs1FltCtrl ÃʱâÈ ¼º°ø');
|
||
gBs1fltControl.BeginControl(1);
|
||
gBs1FltControl.SetDeviceProtect(1);
|
||
gBs1FltControl.Debug(3);
|
||
gBs1FltControl.SetHook(DWORD(BDC_USB), 1);
|
||
gBs1FltControl.SetHook(DWORD(BDC_BLUETOOTH), 1);
|
||
gBs1FltControl.SetHook(DWORD(BDC_MTP), 1);
|
||
|
||
end
|
||
else
|
||
begin
|
||
OnLog('Bs1FltCtrl ÃʱâÈ ½ÇÆÐ: ' + IntToStr(state));
|
||
end;
|
||
|
||
finally
|
||
|
||
end;
|
||
|
||
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;
|
||
|
||
if gBs1fltControl <> nil then
|
||
begin
|
||
gBs1fltControl.BeginControl(0);
|
||
gBs1fltControl.Cleanup;
|
||
FreeAndNil(gBs1fltControl);
|
||
end;
|
||
|
||
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
|
||
OnLog(Format('ScanForHardwareChanges, CM_Locate_DevNode failed: %x', [status]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
status := CM_Reenumerate_DevNode(LDevInst, 0);
|
||
|
||
if status <> CR_SUCCESS then
|
||
begin
|
||
OnLog(Format('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;
|
||
|
||
OnLog('RestartDevice.... 1');
|
||
|
||
if not SetupDiSetClassInstallParams(hDevInfo, @DevInfoData, @params.ClassInstallHeader, SizeOf(TSPPropChangeParams)) then
|
||
begin
|
||
OnLog(Format('restart_device, SetupDiSetClassInstallParams Fail(%d)', [GetLastError]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
OnLog('RestartDevice.... 2');
|
||
|
||
if not SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, @DevInfoData) then
|
||
begin
|
||
OnLog(Format('restart_device, SetupDiCallClassInstaller Fail(%d)', [GetLastError]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
|
||
OnLog('RestartDevice.... 3');
|
||
|
||
{
|
||
if not SetupDiCallClassInstaller(DIF_REMOVE, hDevInfo, pDevInfoData) then
|
||
begin
|
||
ShowDebug(Format('restart_device, SetupDiCallClassInstaller(DIF_REMOVE) Fail(%d)', [GetLastError]));
|
||
Result := False;
|
||
Exit;
|
||
end;
|
||
}
|
||
|
||
OnLog('restart_device, 4');
|
||
|
||
// ChangeState È£Ãâ
|
||
SetupDiChangeState(hDevInfo, @DevInfoData);
|
||
|
||
OnLog(Format('restart_device, 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
|
||
OnLog('SetupDiGetClassDevs Failed');
|
||
Exit;
|
||
end;
|
||
|
||
try
|
||
DeviceInfoData.cbSize := SizeOf(TSPDevInfoData);
|
||
devInfoListDetail.cbSize := SizeOf(TSPDevInfoListDetailData);
|
||
|
||
// ¸®½ºÆ® »ó¼¼ Á¤º¸ (C++ Äڵ忡 ÀÖ¾úÀ¸³ª ½ÇÁ¦ ·ÎÁ÷¿¡¼± »ç¿ë ¾ÈµÊ, È£Ã⸸ À¯Áö)
|
||
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);
|
||
OnLog(Format('SPDRP_SERVICE = [%s]', [sService]));
|
||
|
||
if (SameText(sService, 'USBSTOR')) or (SameText(sService, 'USBAAPL')) then
|
||
begin
|
||
// 2. Hardware ID È®ÀÎ
|
||
sHardwareID := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_HARDWAREID);
|
||
OnLog(Format('SPDRP_HARDWAREID = [%s]', [sHardwareID]));
|
||
|
||
// VID_05E3ÀÌ Æ÷ÇԵǾî ÀÖÁö ¾ÊÀ¸¸é Disable ó¸®
|
||
if Pos('VID_05E3', sHardwareID) = 0 then
|
||
begin
|
||
OnLog('PASS~!');
|
||
// ¿øº» ·ÎÁ÷: Disable ¼öÇà
|
||
SetDeviceState(hDevInfo, DeviceInfoData, True);
|
||
// restart_device(hDevInfo, @DeviceInfoData); // ¿øº» ÁÖ¼® 󸮵Ê
|
||
|
||
Inc(devIndex);
|
||
Continue;
|
||
end;
|
||
end;
|
||
|
||
// 3. Apple ÀåÄ¡ È®ÀÎ (SPDRP_SECURITY_SDS -> SPDRP_SECURITY)
|
||
sSecurity := GetDeviceStringProperty(hDevInfo, DeviceInfoData, SPDRP_SECURITY);
|
||
OnLog(Format('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
|
||
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
|
||
TGuardThread(FThread).DoLog(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;
|
||
if FThread <> nil then TGuardThread(FThread).DoLog(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;
|
||
if FThread <> nil then
|
||
begin
|
||
TGuardThread(FThread).DoLog(text + DevName);
|
||
TGuardThread(FThread).ShowPopup(DevName);
|
||
end;
|
||
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;
|
||
if FThread <> nil then TGuardThread(FThread).DoLog(text + DevName);
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
if Policy.isLog_ and IsLog then
|
||
begin
|
||
if FThread <> nil then
|
||
begin
|
||
TGuardThread(FThread).DoLog(Format('[ŽÁö](%s) %s (Rule: %s)', [text, DevName, Policy.Name]));
|
||
TGuardThread(FThread).DoLog(Format(
|
||
'Service:%s, DeviceClass:%s, friendlyName:%s, HardwareID:%s', [Service, DeviceClass, friendlyName, HardwareID]));
|
||
TGuardThread(FThread).DoLog(Format(
|
||
'ParentId:%s, DeviceDriveDesc:%s, Manufacturer:%s, RemovalPolicy:%d, InstatllState:%d',
|
||
[ParentId, DeviceDriveDesc, Manufacturer, DWORD(RemovalPolicy), DWORD(InstatllState)]));
|
||
TGuardThread(FThread).DoLog(Format('InstanceId:%s', [InstanceId]));
|
||
TGuardThread(FThread).DoLog('-----------------------------------------------------');
|
||
end;
|
||
end;
|
||
|
||
IsLog:= False;
|
||
end
|
||
else
|
||
begin
|
||
TGuardThread(FThread).DoLog(Format('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;
|
||
|
||
for var Match in Policy.Matches_ do
|
||
begin
|
||
TGuardThread(FThread).DoLog(Format('CheckAndApplyPolicy, Enumerator : (%s) MatchData : (%s)', [Match.Enumerator, Match.MatchData]));
|
||
ApplySingleMatch(Policy, Match);
|
||
end;
|
||
end;
|
||
|
||
|
||
|
||
procedure TDeviceGuardEngine.EnforceSystemPolicy;
|
||
var
|
||
Policies: TObjectList<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
|
||
gBs1FltControl.SetPolicy(DWORD(Policy.flag_), DWORD(Policy.state_), DWORD(Policy.isLog_));
|
||
// end;
|
||
|
||
if (Policy.flag_ = DWORD(BDC_BLUETOOTH_FILE)) then
|
||
begin
|
||
continue;
|
||
end
|
||
else if (Policy.flag_ = DWORD(BDC_MTP)) then
|
||
begin
|
||
|
||
end;
|
||
// 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
|
||
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
|
||
TGuardThread(FThread).DoLog(Format('[Ŭ·¡½º ¸í] : Name : %s, Class : %s', [Info.DeviceClass, DevInfoData.ClassGuid.ToString]));
|
||
TGuardThread(FThread).DoLog(
|
||
Format(' -> serviceName : %s || enumeratorName : %s || friendlyName: %s || HWID: %s || RemovalPolicy: %d || UniqueKey: %s',
|
||
[Info.Service, Info.Enumerator, Info.friendlyName, Info.HardwareID, Info.RemovalPolicy, UniqueKey]));
|
||
TGuardThread(FThread).DoLog(
|
||
Format(' -> 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
|
||
TGuardThread(FThread).DoLog('SetupDiChangeState Fail : ' + GetLastError.ToString);
|
||
Result:= False;
|
||
end;
|
||
|
||
end
|
||
else
|
||
begin
|
||
TGuardThread(FThread).DoLog('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
|
||
TGuardThread(FThread).DoLog('[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 DoLog('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.
|