bug : bs1flt

- 특정 window 10에서 load 되지 않는 현상 수정
 - 디버그 옵션이 정상 적용되지 않는 현상 수정
 - 프로세스 종료 방지 기능이 정상동작 안하는 현상 수정

feat : agent start 로그 시작 추가
bug : RecoverService 시작 위치 변경 → ManagerService 시
 - 복구 파일시 목록 누락된 파일 추가

feat : 설치시 서버 주소 검증 기능 추가
 - 설치정보(si.dat)는 설치 위치에 암호화 하여 저장하고, 복원을 위한 백업 리스스 압축파일에 추가

feat : UsbToUsb  파일 전송 차단시 해당 프로그램에서 반복적으로 차단되는 현상 수정

bug  : 블루투스 파일 전송시 간혈적으로 블루투스 프로세스가 죽는현상
feat : 파일 관리(bluetooth, usb, usbtousb, mtp, cd-rom)
 - 예외 확장자, 예외 경로 기능 추가
This commit is contained in:
mgkim 2026-03-25 21:27:21 +09:00
parent def1b99ef7
commit 826810ca06
466 changed files with 342739 additions and 142380 deletions

View File

@ -11,7 +11,7 @@ unit ApiHookExplorer;
interface
uses
Winapi.Windows, System.SysUtils, Winapi.ActiveX, Tocsg.Thread, Winapi.ShlObj;
Winapi.Windows, System.SysUtils, Winapi.ActiveX, Tocsg.Thread, Winapi.ShlObj, StrUtils;
type
TFileOpProgressSink = class(TInterfacedObject, IFileOperationProgressSink)
@ -296,6 +296,59 @@ var
FileUseBlock: TFileUseBlock;
resultMsg: string;
curAppType: TCurAppType;
function IsExceptionExtenstion(const APath: string; var AtExt : string): Boolean;
var
sExt: string;
ExceptionExt: TArray<string>;
Ext: string;
begin
Result:= False;
if AtExt <> '' then
begin
ExceptionExt := AtExt.Split(['|']);
for Ext in ExceptionExt do
begin
if Trim(Ext) = '' then
Continue;
if SameText(sExt, Ext) then
begin
Result := True;
exit;
end;
end;
end;
end;
function IsExceptionPath(const APath: string; var AtPath : string): Boolean;
var
ExceptionPaths: TArray<string>;
ExPath: string;
begin
Result:= False;
if AtPath <> '' then
begin
ExceptionPaths := AtPath.Split(['|']);
for ExPath in ExceptionPaths do
begin
if Trim(ExPath) = '' then
Continue;
if ContainsText(APath, ExPath) then
begin
Result := True;
exit;
end;
end;
end;
end;
begin
Result := S_OK;
resultMsg := '';
@ -380,6 +433,12 @@ begin
else
FileUseBlock := fubMonitor;
if IsExceptionExtenstion(sSrcPath, IntBlockNewFile.extList) then
exit;
if IsExceptionPath(sSrcPath, IntBlockNewFile.excList) then
exit;
DVLOG('ProcMon: mode(%d), blockByFilename(%s), contentsFilter(%s)',
[DWORD(IntBlockNewFile.mode), IntBlockNewFile.blockByFilename_list, IntBlockNewFile.contentsFilter_list]);

View File

@ -48,6 +48,8 @@ type
PSCSI_PASS_THROUGH_DIRECT = ^SCSI_PASS_THROUGH_DIRECT;
TApiHookContents = class
private
function IsExceptionExtenstion(const APath: string ; var AtExt : string): Boolean;
public
fileHandleList_: TFileHandleList;
appType_: TCurAppType;
@ -66,7 +68,7 @@ type
function GetDriveBusType(DriveLetter: WideChar): STORAGE_BUS_TYPE;
function GetOffLineType(dwType: DWORD; dwBusType: DWORD; pwszPath: PWideChar): string;
function GetFileReadBuffer(const path: string; pbuffer: PByte; buffersize: DWORD): Boolean; stdcall;
function IsExceptionPath(const APath: string): Boolean;
function IsExceptionPath(const APath: string; var AtPath : string): Boolean;
end;
@ -157,7 +159,7 @@ var
implementation
uses
BS1Hook, Tocsg.Packet, Tocsg.Files, DefineHelper, ApiHookFile, superobject;
BS1Hook, Tocsg.Packet, Tocsg.Safe, Tocsg.Files, DefineHelper, ApiHookFile, superobject;
@ -659,7 +661,45 @@ begin
end;
end;
function TApiHookContents.IsExceptionPath(const APath: string): Boolean;
function TApiHookContents.IsExceptionExtenstion(const APath: string; var AtExt : string): Boolean;
var
sExt: string;
ExceptionExt: TArray<string>;
Ext: string;
begin
Result:= False;
sExt := ExtractFileExt(APath);
if SameText(sExt, '.dll') or SameText(sExt, '.exe') or SameText(sExt, '.ico') then
begin
Result:= True;
Exit;
end;
if AtExt <> '' then
begin
ExceptionExt := AtExt.Split(['|']);
for Ext in ExceptionExt do
begin
if Trim(Ext) = '' then
Continue;
if SameText(sExt, Ext) then
begin
Result := True;
exit;
end;
end;
end;
end;
function TApiHookContents.IsExceptionPath(const APath: string; var AtPath : string): Boolean;
var
ExceptionPaths: TArray<string>;
ExPath: string;
begin
Result:= True;
@ -682,12 +722,31 @@ begin
Exit;
Result:= False;
if AtPath <> '' then
begin
ExceptionPaths := AtPath.Split(['|']);
for ExPath in ExceptionPaths do
begin
if Trim(ExPath) = '' then
Continue;
if ContainsText(APath, ExPath) then
begin
Result := True;
exit;
end;
end;
end;
end;
function TApiHookContents.CreateFileProc(hFile: THandle; lpFileName: LPCWSTR; dwDesiredAccess, dwShareMode: DWORD; lpSecurityAttributes: PSecurityAttributes; dwCreationDisposition, dwFlagsAndAttributes: DWORD; hTemplateFile: THandle): Boolean stdcall;
var
sPath: string;
IntBlockNewFile: TIntBlockNewFile;
begin
Result:= False;
if (hFile = 0) or (hFile = INVALID_HANDLE_VALUE) then
@ -725,20 +784,27 @@ begin
end;
sPath:= lpFileName;
sPath := Trim(PChar(sPath));
if (Length(sPath) >= 2) and (sPath[1] = '.') and (sPath[2] = '\') then
Exit;
if StartsText(sPath, 'C:\WINDOWS\') then
Exit;
if EndsText('.dll', sPath) or EndsText('.exe', sPath) then
Exit;
if ContainsText(sPath, '\bs1dc.json') then
Exit;
if IsExceptionPath(sPath) then
if (appType_ = catFquirt) then
begin
IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntBtBlockNewFile;
end
else if (appType_ = catLINKENGKM) then
begin
IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntUsbToUsbBlockNewFile;
end;
if IsExceptionExtenstion(sPath, IntBlockNewFile.extList) then
Exit;
if IsExceptionPath(sPath, IntBlockNewFile.excList) then
Exit;
if (appType_ = catExplorer) then //or (gbsHook_.processType_ = ptExplore)
@ -852,11 +918,11 @@ begin
if dwBytesRead = 0 then Exit;
// DVLOG('ReadFileProc: hFile(%p), nNumberOfBytesToRead(%d)', [Pointer(hFile), nNumberOfBytesToRead]);
if fileHandleList_.IsHandle(hFile, handleInfo) then
// var
if fileHandleList_.IsHandleOutPath(hFile, sPath) then
begin
sPath := handleInfo.path;
handleInfo.Free;
// sPath := handleInfo.path;
// handleInfo.Free;
fileHandleList_.InsertBufferForHandle(hFile, sPath, lpBuffer, dwBytesRead);
@ -1043,6 +1109,9 @@ begin
begin
if appType_ = catLINKENGKM then
begin
//2026-03-24 해당 어플리케이션에서 차단시 오류코드로 반환시
//지속적으로 시도하는 것으로 확인되어.. 정상으로 처리하고 원본함수
//호출 하지 않는 방법으로 변경
// SetLastError(ERROR_DEV_NOT_EXIST);
if (lpOutBuffer <> nil) and (nOutBufferSize >= 3) then
begin
@ -1055,7 +1124,7 @@ begin
end;
SetLastError(ERROR_SUCCESS);
Result := True;
Result := False;
end
else
SetLastError(ERROR_ACCESS_DENIED);
@ -1090,17 +1159,22 @@ var
FileSizeLow: DWORD;
pMem: Pointer;
ViewSize: SIZE_T;
sExt: string;
IntBlockNewFile: TIntBlockNewFile;
begin
Result:= False;
if not (flProtect in [PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY]) then
Exit;
if (appType_ = catFquirt) then
Exit;
sPath:= '';
if fileHandleList_.IsHandle(hFile, handleInfo) then
if fileHandleList_.IsHandleOutPath(hFile, sPath) then
begin
sPath:= handleInfo.path;
handleInfo.Free;
// sPath:= handleInfo.path;
// handleInfo.Free;
end
else if GetPathFromHandle(hFile, sPath) then
begin
@ -1114,12 +1188,24 @@ begin
if sPath = '' then
Exit;
if EndsText('.dll', sPath) or EndsText('.exe', sPath) then
sPath := Trim(PChar(sPath));
if (appType_ = catFquirt) then
begin
IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntBtBlockNewFile;
end
else if (appType_ = catLINKENGKM) then
begin
IntBlockNewFile:= gAppHook.Helper.CtrlOpt.IntUsbToUsbBlockNewFile;
end;
if IsExceptionExtenstion(sPath, IntBlockNewFile.extList) then
Exit;
if IsExceptionPath(sPath) then
if IsExceptionPath(sPath, IntBlockNewFile.excList) then
Exit;
CheckSize := (Int64(dwMaximumSizeHigh) shl 32) or dwMaximumSizeLow;
if CheckSize = 0 then
begin
@ -1374,7 +1460,11 @@ begin
begin
Result:= gApiHookContents_.DeviceIoControlProc(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
if not result then
begin
if gApiHookContents_.appType_ = catLINKENGKM then
result:= True;
Exit;
end;
end;
Result:= ozDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);

View File

@ -40,6 +40,8 @@ type
end;
TFileHandleList = class
private
public
lFile: TObjectList<TFileHandle>;
lHisFile: TObjectList<TFileHandle>;
@ -52,7 +54,7 @@ type
procedure Lock(var ACS: TRTLCriticalSection);
procedure UnLock(var ACS: TRTLCriticalSection);
function IsHandleOutPath(h: THandle; out sPath: string): BOOL;
function FindHandle(h: THandle): TFileHandle;
function ChangeHandle(h: THandle; const path: string; dwDesiredAccess: DWORD = 0;
dwShareMode: DWORD = 0; dwCreationDisposition: DWORD = 0;
@ -486,6 +488,33 @@ begin
end;
function TFileHandleList.IsHandleOutPath(h: THandle; out sPath: string): BOOL;
var
fh: TFileHandle;
begin
Result := FALSE;
if not state then Exit;
if lFile.Count = 0 then Exit;
Lock(cs);
try
for fh in lFile do
begin
if fh.h = h then
begin
sPath:= fh.path;
Result := TRUE;
Break;
end;
end;
finally
UnLock(cs);
end;
end;
function TFileHandleList.IsHistoryFileBufferCompare(const path: string; lpBuffer: PByte; size: DWORD;
out fileHandle: TFileHandle): BOOL;

View File

@ -10,7 +10,7 @@ ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2} ;This value is determine
;Class = "ActivityMonitor"
;ClassGuid = {AE71EC8D-C1FD-4564-8AA9-D56ADE722321}
Provider = %ManufacturerName%
DriverVer = 03/20/2026,17.0.19.906
DriverVer = 03/25/2026,17.39.11.270
CatalogFile = bs1flt.cat
PnpLockdown = 1

View File

@ -10,7 +10,7 @@ ClassGuid = {b86dff51-a31e-4bac-b3cf-e8cfe75c9fc2} ;This value is determine
;Class = "ActivityMonitor"
;ClassGuid = {AE71EC8D-C1FD-4564-8AA9-D56ADE722321}
Provider = %ManufacturerName%
DriverVer = 03/20/2026,17.0.19.906
DriverVer = 03/25/2026,17.39.11.270
CatalogFile = bs1flt.cat
PnpLockdown = 1

View File

@ -1104,10 +1104,8 @@ Return Value:
UNREFERENCED_PARAMETER(RegistryPath);
g_DebugLevel = DEBUG_TRACE_INFO;
KLogEx(DEBUG_TRACE_INFO, "Entered\n");
KLogEx(DEBUG_TRACE_INFO, "RegPath(%S)(%d)\n", RegistryPath->Buffer, RegistryPath->Length);
g_DebugLevel = DEBUG_TRACE_INFO;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%s:%s : Entered RegPath(%S)(%d)", DRIVERNAMEA, __FUNCTION__, RegistryPath->Buffer, RegistryPath->Length);
RtlZeroMemory(&g_bs1Flt, sizeof(g_bs1Flt));
@ -1115,8 +1113,8 @@ Return Value:
{
g_DebugLevel = 0;
}
g_DebugLevel = DEBUG_TRACE_ALL;
//g_DebugLevel = DEBUG_TRACE_ALL;
//
// Register with FltMgr to tell it our callback routines
//
@ -1276,7 +1274,7 @@ $Success:
CleanupPathlist();
CleanupProcesslist();
CleanupProcessProtectList();
Cleanuplog();
PgReset();
CleanupUsbDiskExceptionList();
@ -1296,6 +1294,7 @@ $Success:
FltUnregisterFilter(g_bs1Flt.Filter);
g_bs1Flt.Filter = NULL;
}
Cleanuplog();
return STATUS_SUCCESS;
}

View File

@ -439,7 +439,6 @@ NTSTATUS InstallProcessProtect() {
return STATUS_SUCCESS;
}
g_bs1Flt.IsProcessProtect = TRUE;
s_operationRegistrations[0].ObjectType = PsProcessType;
s_operationRegistrations[0].Operations |= OB_OPERATION_HANDLE_CREATE;
s_operationRegistrations[0].Operations |= OB_OPERATION_HANDLE_DUPLICATE;
@ -467,6 +466,7 @@ NTSTATUS InstallProcessProtect() {
return status;
}
g_bs1Flt.IsProcessProtect = TRUE;
s_callbacksInstalled = TRUE;
KLogEx(DEBUG_TRACE_INFO, "Sucess\n");
return STATUS_SUCCESS;
@ -483,5 +483,7 @@ VOID UnInstallProcessProtect()
g_bs1Flt.IsProcessProtect = FALSE;
ObUnRegisterCallbacks(s_registrationHandle);
s_registrationHandle = NULL;
s_callbacksInstalled = FALSE;
KLogEx(DEBUG_TRACE_ERROR, "Sucess\n");
}

View File

@ -28,8 +28,8 @@ typedef struct _LOG_LIST
static LIST_ENTRY s_log_list;
static KSPIN_LOCK s_log_list_lock;
static ULONG s_log_cnt;
static NPAGED_LOOKASIDE_LIST s_log_PoolList;
//static NPAGED_LOOKASIDE_LIST s_log_PoolList;
static LOOKASIDE_LIST_EX s_log_PoolList;
#define LOG_POOL_TAG 'kdrp'
@ -67,13 +67,23 @@ VOID Initlog()
s_log_cnt = 0;
InitializeListHead(&s_log_list);
KeInitializeSpinLock(&s_log_list_lock);
ExInitializeNPagedLookasideList(&s_log_PoolList
, NULL
, NULL
, 0
, sizeof(LOG_LIST)
, LOG_POOL_TAG
, 0);
//ExInitializeNPagedLookasideList(&s_log_PoolList
// , NULL
// , NULL
// , 0
// , sizeof(LOG_LIST)
// , LOG_POOL_TAG
// , 0);
ExInitializeLookasideListEx(
&s_log_PoolList,
NULL,
NULL,
NonPagedPoolNx, // 기존 NonPagedPool 대신 NX 풀 사용
0,
sizeof(LOG_LIST), // 실제 할당할 구조체 크기
LOG_POOL_TAG,
0
);
}
@ -479,13 +489,15 @@ NTSTATUS SetLog(
code, a0, a1, desc.ProcessName, desc.path);
}
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
//log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
log = (PLOG_LIST)ExAllocateFromLookasideListEx(&s_log_PoolList);
if (!log)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(log, s_log_PoolList.L.Size);
//RtlZeroMemory(log, s_log_PoolList.L.Size);
RtlZeroMemory(log, sizeof(LOG_LIST));
memcpy(&log->a, &desc, sizeof(REPORT_DESC));
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
@ -523,13 +535,15 @@ NTSTATUS SetConnectLog(
if (!(g_bs1Flt.LogType & LOG_CONNECT))
return STATUS_INSUFFICIENT_RESOURCES;
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
//log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
log = (PLOG_LIST)ExAllocateFromLookasideListEx(&s_log_PoolList);
if (!log)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(log, s_log_PoolList.L.Size);
//RtlZeroMemory(log, s_log_PoolList.L.Size);
RtlZeroMemory(log, sizeof(LOG_LIST));
KeQuerySystemTime(&current_time);
log->a.time = (LONGLONG)current_time.QuadPart;
@ -608,13 +622,15 @@ NTSTATUS SetProcessLog(
if (!(g_bs1Flt.LogType & code))
return STATUS_INSUFFICIENT_RESOURCES;
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
//log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
log = (PLOG_LIST)ExAllocateFromLookasideListEx(&s_log_PoolList);
if (!log)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(log, s_log_PoolList.L.Size);
//RtlZeroMemory(log, s_log_PoolList.L.Size);
RtlZeroMemory(log, sizeof(LOG_LIST));
KeQuerySystemTime(&current_time);
log->a.time = (LONGLONG)current_time.QuadPart;
@ -739,7 +755,8 @@ NTSTATUS SetENLog(PFLT_CALLBACK_DATA data, ULONG code, ULONG devicetype, ULONG u
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
//log = (PLOG_LIST)ExAllocateFromNPagedLookasideList(&s_log_PoolList);
log = (PLOG_LIST)ExAllocateFromLookasideListEx(&s_log_PoolList);
if (!log)
{
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
@ -760,22 +777,61 @@ NTSTATUS SetENLog(PFLT_CALLBACK_DATA data, ULONG code, ULONG devicetype, ULONG u
//VOID Cleanuplog()
//{
// //PLIST_ENTRY pList = NULL;
// //PLOG_LIST plog = NULL;
// KIRQL oldIrql;
//
// KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
// InitializeListHead(&s_log_list);
// ExDeleteNPagedLookasideList(&s_log_PoolList);
// //ExDeleteLookasideListEx(&s_log_PoolList);
// s_log_cnt = 0;
//
// KeReleaseSpinLock(&s_log_list_lock, oldIrql);
//
// KLogEx(DEBUG_TRACE_INFO, "success\n");
//}
VOID Cleanuplog()
{
//PLIST_ENTRY pList = NULL;
//PLOG_LIST plog = NULL;
KIRQL oldIrql;
PLIST_ENTRY pList = NULL;
PLOG_LIST plog = NULL;
KIRQL oldIrql;
LIST_ENTRY tempList;
// 1. 임시 리스트 초기화
InitializeListHead(&tempList);
// 2. 락을 걸고 기존 리스트의 항목들을 임시 리스트로 빠르게 옮깁니다.
KeAcquireSpinLock(&s_log_list_lock, &oldIrql);
InitializeListHead(&s_log_list);
ExDeleteNPagedLookasideList(&s_log_PoolList);
s_log_cnt = 0;
if (!IsListEmpty(&s_log_list))
{
tempList.Flink = s_log_list.Flink;
tempList.Blink = s_log_list.Blink;
s_log_list.Flink->Blink = &tempList;
s_log_list.Blink->Flink = &tempList;
InitializeListHead(&s_log_list); // 원본 리스트 비우기
}
s_log_cnt = 0;
// ★ 여기서 반드시 락을 먼저 풀어야 합니다! (IRQL 강하)
KeReleaseSpinLock(&s_log_list_lock, oldIrql);
KLogEx(DEBUG_TRACE_INFO, "success\n");
}
// 3. 락이 풀린 안전한 상태(PASSIVE_LEVEL)에서 남은 메모리들을 모두 해제합니다.
while (!IsListEmpty(&tempList))
{
pList = RemoveHeadList(&tempList);
plog = CONTAINING_RECORD(pList, LOG_LIST, list);
ExFreeToLookasideListEx(&s_log_PoolList, plog);
}
// 4. 리스트 메모리를 모두 비운 후, 마지막으로 Lookaside 풀을 삭제합니다.
ExDeleteLookasideListEx(&s_log_PoolList);
KLogEx(DEBUG_TRACE_INFO, "Cleanuplog success\n");
}
NTSTATUS GetLog(PVOID buf, ULONG size, ULONG* req)
{
@ -854,7 +910,8 @@ NTSTATUS GetLog(PVOID buf, ULONG size, ULONG* req)
RtlCopyMemory(r, &plog->a, sizeof(REPORT_DESC));
RemoveEntryList(&plog->list);
ExFreeToNPagedLookasideList(&s_log_PoolList, plog);
//ExFreeToNPagedLookasideList(&s_log_PoolList, plog);
ExFreeToLookasideListEx(&s_log_PoolList, plog);
--s_log_cnt;
--ulReminCnt;

View File

@ -1,7 +1,8 @@
#include "precomp.h"
// ---------------------------------------------------------------------------
// [헬퍼 함수] URB 전송 및 메모리 해제 로직 (기존 코드 유지)
// ---------------------------------------------------------------------------
NTSTATUS UDF_CallUSBDI(IN PDEVICE_OBJECT pDevObj, IN PVOID UrbEtc)
{
IO_STATUS_BLOCK IoStatus;
@ -9,37 +10,23 @@ NTSTATUS UDF_CallUSBDI(IN PDEVICE_OBJECT pDevObj, IN PVOID UrbEtc)
NTSTATUS status;
PIRP Irp = NULL;
PIO_STACK_LOCATION NextIrpStack = NULL;
//g_Temp = pDevObj;
//g_Temp2 = UrbEtc;
// Initialise IRP completion event
KeInitializeEvent(&event, NotificationEvent, FALSE);
// Build Internal IOCTL IRP
Irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB, pDevObj,
NULL, 0, // Input buffer
NULL, 0, // Output buffer
TRUE, &event, &IoStatus);
NULL, 0, NULL, 0, TRUE, &event, &IoStatus);
// Get IRP stack location for next driver down (already set up)
NextIrpStack = IoGetNextIrpStackLocation(Irp);
// Store pointer to the URB etc
NextIrpStack->Parameters.Others.Argument1 = UrbEtc;
NextIrpStack->Parameters.Others.Argument2 = (PVOID)0;
// Call the driver and wait for completion if necessary
status = IoCallDriver(pDevObj, Irp);
if (status == STATUS_PENDING)
{
KLogEx(DEBUG_TRACE_ERROR, "waiting for URB completion\n");
status = KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
status = IoStatus.Status;
}
// return IRP completion status
KLogEx(DEBUG_TRACE_ERROR, "returned %x\n", status);
return status;
}
@ -52,310 +39,109 @@ PURB AllocUrb(USHORT Size)
VOID FreeUsbDeviceInfo(IN PUSB_PARSED_INFO pInfo)
{
if (!pInfo) return;
if (!pInfo)
return;
// 문자열 메모리 해제
if (pInfo->ManufacturerStr) ExFreePool(pInfo->ManufacturerStr);
if (pInfo->ProductStr) ExFreePool(pInfo->ProductStr);
if (pInfo->SerialNumberStr) ExFreePool(pInfo->SerialNumberStr);
if (pInfo->ManufacturerStr)
ExFreePool(pInfo->ManufacturerStr);
// Configuration Descriptor 해제
if (pInfo->ConfigDesc) ExFreePool(pInfo->ConfigDesc);
if (pInfo->ProductStr)
ExFreePool(pInfo->ProductStr);
if (pInfo->SerialNumberStr)
ExFreePool(pInfo->SerialNumberStr);
if (pInfo->ConfigDesc)
ExFreePool(pInfo->ConfigDesc);
// 구조체 자체 해제
ExFreePool(pInfo);
}
// ---------------------------------------------------------------------------
// 1. Device Descriptor 가져오기
// ---------------------------------------------------------------------------
NTSTATUS GetUsbDeviceDescriptor(
IN PDEVICE_OBJECT DeviceObject,
OUT PUSB_DEVICE_DESCRIPTOR* ppDescriptor
)
NTSTATUS GetUsbDeviceDescriptor(IN PDEVICE_OBJECT DeviceObject, OUT PUSB_DEVICE_DESCRIPTOR* ppDescriptor)
{
PURB urb = NULL;
PUSB_DEVICE_DESCRIPTOR descriptor = NULL;
NTSTATUS status;
urb = AllocUrb(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
PURB urb = AllocUrb(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (!urb) return STATUS_INSUFFICIENT_RESOURCES;
descriptor = ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEVICE_DESCRIPTOR), 'DST');
if (!descriptor) {
ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
PUSB_DEVICE_DESCRIPTOR descriptor = ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_DEVICE_DESCRIPTOR), 'DST');
if (!descriptor) { ExFreePool(urb); return STATUS_INSUFFICIENT_RESOURCES; }
RtlZeroMemory(descriptor, sizeof(USB_DEVICE_DESCRIPTOR));
UsbBuildGetDescriptorRequest(urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, descriptor, NULL, sizeof(USB_DEVICE_DESCRIPTOR), NULL);
UsbBuildGetDescriptorRequest(
urb,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_DEVICE_DESCRIPTOR_TYPE,
0, 0,
descriptor, NULL,
sizeof(USB_DEVICE_DESCRIPTOR), NULL
);
status = UDF_CallUSBDI(DeviceObject, urb);
if (!NT_SUCCESS(status)) {
ExFreePool(descriptor);
*ppDescriptor = NULL;
}
else {
*ppDescriptor = descriptor;
}
NTSTATUS status = UDF_CallUSBDI(DeviceObject, urb);
if (!NT_SUCCESS(status)) { ExFreePool(descriptor); *ppDescriptor = NULL; }
else { *ppDescriptor = descriptor; }
ExFreePool(urb);
return status;
}
// ---------------------------------------------------------------------------
// 2. String Descriptor 가져오기 (특정 Index, Language ID)
// ---------------------------------------------------------------------------
NTSTATUS GetUsbStringDescriptor(
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Index,
IN USHORT LangId,
OUT PWCHAR* ppStringData
)
NTSTATUS GetUsbStringDescriptor(IN PDEVICE_OBJECT DeviceObject, IN UCHAR Index, IN USHORT LangId, OUT PWCHAR* ppStringData)
{
PURB urb = NULL;
PUSB_STRING_DESCRIPTOR pStrDesc = NULL;
NTSTATUS status;
ULONG size = 256; // 넉넉하게 잡음
if (Index == 0) return STATUS_INVALID_PARAMETER;
urb = AllocUrb(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
PURB urb = AllocUrb(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (!urb) return STATUS_INSUFFICIENT_RESOURCES;
pStrDesc = ExAllocatePoolWithTag(NonPagedPool, size, 'STR');
if (!pStrDesc) {
ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
ULONG size = 256;
PUSB_STRING_DESCRIPTOR pStrDesc = ExAllocatePoolWithTag(NonPagedPool, size, 'STR');
if (!pStrDesc) { ExFreePool(urb); return STATUS_INSUFFICIENT_RESOURCES; }
RtlZeroMemory(pStrDesc, size);
UsbBuildGetDescriptorRequest(
urb,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_STRING_DESCRIPTOR_TYPE,
Index,
LangId,
pStrDesc, NULL,
size, NULL
);
status = UDF_CallUSBDI(DeviceObject, urb);
UsbBuildGetDescriptorRequest(urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_STRING_DESCRIPTOR_TYPE, Index, LangId, pStrDesc, NULL, size, NULL);
NTSTATUS status = UDF_CallUSBDI(DeviceObject, urb);
if (NT_SUCCESS(status) && pStrDesc->bLength > 2) {
// bString은 WCHAR 배열입니다. NULL Termination을 위해 별도 버퍼에 복사
ULONG strLenBytes = pStrDesc->bLength - 2;
PWCHAR outBuf = ExAllocatePoolWithTag(NonPagedPool, strLenBytes + sizeof(WCHAR), 'STR2');
if (outBuf) {
RtlZeroMemory(outBuf, strLenBytes + sizeof(WCHAR));
RtlCopyMemory(outBuf, pStrDesc->bString, strLenBytes);
*ppStringData = outBuf;
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
else { status = STATUS_INSUFFICIENT_RESOURCES; }
}
else {
*ppStringData = NULL;
status = STATUS_UNSUCCESSFUL;
}
ExFreePool(pStrDesc);
ExFreePool(urb);
return status;
}
// ---------------------------------------------------------------------------
// 3. Configuration Descriptor 전체 가져오기 (Interface, Endpoint 포함)
// ---------------------------------------------------------------------------
NTSTATUS GetUsbFullConfigDescriptor(
IN PDEVICE_OBJECT DeviceObject,
OUT PUSB_CONFIGURATION_DESCRIPTOR* ppConfigDesc
)
NTSTATUS GetUsbFullConfigDescriptor(IN PDEVICE_OBJECT DeviceObject, OUT PUSB_CONFIGURATION_DESCRIPTOR* ppConfigDesc)
{
PURB urb = NULL;
PUSB_CONFIGURATION_DESCRIPTOR pHeader = NULL;
PUSB_CONFIGURATION_DESCRIPTOR pFullDesc = NULL;
NTSTATUS status;
ULONG fullSize = 0;
// 1단계: 헤더(9바이트)만 먼저 읽어서 전체 크기(wTotalLength) 파악
urb = AllocUrb(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
PURB urb = AllocUrb(sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (!urb) return STATUS_INSUFFICIENT_RESOURCES;
pHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_CONFIGURATION_DESCRIPTOR), 'CFG');
if (!pHeader) {
ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
PUSB_CONFIGURATION_DESCRIPTOR pHeader = ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_CONFIGURATION_DESCRIPTOR), 'CFG');
if (!pHeader) { ExFreePool(urb); return STATUS_INSUFFICIENT_RESOURCES; }
UsbBuildGetDescriptorRequest(
urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0,
pHeader, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR), NULL
);
UsbBuildGetDescriptorRequest(urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, pHeader, NULL, sizeof(USB_CONFIGURATION_DESCRIPTOR), NULL);
status = UDF_CallUSBDI(DeviceObject, urb);
if (!NT_SUCCESS(status)) {
ExFreePool(pHeader);
ExFreePool(urb);
return status;
}
NTSTATUS status = UDF_CallUSBDI(DeviceObject, urb);
if (!NT_SUCCESS(status)) { ExFreePool(pHeader); ExFreePool(urb); return status; }
fullSize = pHeader->wTotalLength;
ExFreePool(pHeader); // 헤더는 이제 필요 없음 (크기 알았으므로)
ULONG fullSize = pHeader->wTotalLength;
ExFreePool(pHeader);
// 2단계: 전체 크기만큼 할당 후 다시 요청
pFullDesc = ExAllocatePoolWithTag(NonPagedPool, fullSize, 'CFG');
if (!pFullDesc) {
ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
PUSB_CONFIGURATION_DESCRIPTOR pFullDesc = ExAllocatePoolWithTag(NonPagedPool, fullSize, 'CFG');
if (!pFullDesc) { ExFreePool(urb); return STATUS_INSUFFICIENT_RESOURCES; }
// URB 재사용을 위해 ZeroMemory (버퍼 포인터 등이 바뀌므로)
RtlZeroMemory(urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
UsbBuildGetDescriptorRequest(
urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0,
pFullDesc, NULL, fullSize, NULL
);
UsbBuildGetDescriptorRequest(urb, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, pFullDesc, NULL, fullSize, NULL);
status = UDF_CallUSBDI(DeviceObject, urb);
if (NT_SUCCESS(status)) {
*ppConfigDesc = pFullDesc;
}
else {
ExFreePool(pFullDesc);
*ppConfigDesc = NULL;
}
if (NT_SUCCESS(status)) { *ppConfigDesc = pFullDesc; }
else { ExFreePool(pFullDesc); *ppConfigDesc = NULL; }
ExFreePool(urb);
return status;
}
// ---------------------------------------------------------------------------
// Main Logic: 모든 정보를 수집하고 출력(Logging)하는 함수
// ---------------------------------------------------------------------------
VOID GetAllUsbDeviceInfo(PDEVICE_OBJECT DeviceObject)
{
NTSTATUS status;
PUSB_DEVICE_DESCRIPTOR pDevDesc = NULL;
PUSB_CONFIGURATION_DESCRIPTOR pConfigDesc = NULL;
USHORT LangId = 0x0409; // Default English
KLogEx(DEBUG_TRACE_INFO, "===== START USB INFO COLLECTION =====\n");
// 1. Device Descriptor 수집
status = GetUsbDeviceDescriptor(DeviceObject, &pDevDesc);
if (NT_SUCCESS(status) && pDevDesc)
{
KLogEx(DEBUG_TRACE_INFO, "[Device Descriptor]\n");
KLogEx(DEBUG_TRACE_INFO, " bLength: 0x%X\n", pDevDesc->bLength);
KLogEx(DEBUG_TRACE_INFO, " bDescriptorType: 0x%X\n", pDevDesc->bDescriptorType);
KLogEx(DEBUG_TRACE_INFO, " bcdUSB: 0x%X\n", pDevDesc->bcdUSB);
KLogEx(DEBUG_TRACE_INFO, " idVendor: 0x%04X\n", pDevDesc->idVendor);
KLogEx(DEBUG_TRACE_INFO, " idProduct: 0x%04X\n", pDevDesc->idProduct);
KLogEx(DEBUG_TRACE_INFO, " bcdDevice: 0x%X\n", pDevDesc->bcdDevice);
KLogEx(DEBUG_TRACE_INFO, " bNumConfigurations: 0x%X\n", pDevDesc->bNumConfigurations);
// String Descriptor 수집 (Manufacturer, Product, Serial)
// 실제로는 String Index 0을 먼저 호출하여 지원 언어를 확인해야 하지만,
// 여기서는 편의상 0x0409(English)를 시도합니다.
if (pDevDesc->iManufacturer)
{
PWCHAR pStr = NULL;
if (NT_SUCCESS(GetUsbStringDescriptor(DeviceObject, pDevDesc->iManufacturer, LangId, &pStr)) && pStr) {
KLogEx(DEBUG_TRACE_INFO, " Manufacturer: %ws\n", pStr);
ExFreePool(pStr);
}
}
if (pDevDesc->iProduct)
{
PWCHAR pStr = NULL;
if (NT_SUCCESS(GetUsbStringDescriptor(DeviceObject, pDevDesc->iProduct, LangId, &pStr)) && pStr) {
KLogEx(DEBUG_TRACE_INFO, " Product: %ws\n", pStr);
ExFreePool(pStr);
}
}
if (pDevDesc->iSerialNumber)
{
PWCHAR pStr = NULL;
if (NT_SUCCESS(GetUsbStringDescriptor(DeviceObject, pDevDesc->iSerialNumber, LangId, &pStr)) && pStr) {
KLogEx(DEBUG_TRACE_INFO, " SerialNumber: %ws\n", pStr);
ExFreePool(pStr);
}
}
}
// 2. Configuration Descriptor (Full) 수집 및 파싱
status = GetUsbFullConfigDescriptor(DeviceObject, &pConfigDesc);
if (NT_SUCCESS(status) && pConfigDesc)
{
PUCHAR pCurr = (PUCHAR)pConfigDesc;
PUCHAR pEnd = pCurr + pConfigDesc->wTotalLength;
KLogEx(DEBUG_TRACE_INFO, "[Configuration Descriptor]\n");
KLogEx(DEBUG_TRACE_INFO, " wTotalLength: 0x%X\n", pConfigDesc->wTotalLength);
KLogEx(DEBUG_TRACE_INFO, " bNumInterfaces: 0x%X\n", pConfigDesc->bNumInterfaces);
KLogEx(DEBUG_TRACE_INFO, " bConfigurationValue: 0x%X\n", pConfigDesc->bConfigurationValue);
KLogEx(DEBUG_TRACE_INFO, " MaxPower: 0x%X", pConfigDesc->MaxPower);
// Loop를 돌면서 Interface 및 Endpoint 파싱
// 첫 번째 Descriptor는 Configuration이므로 건너뜀
pCurr += pConfigDesc->bLength;
while (pCurr < pEnd)
{
PUSB_COMMON_DESCRIPTOR pCommon = (PUSB_COMMON_DESCRIPTOR)pCurr;
if (pCommon->bLength == 0) break; // 에러 방지
if (pCommon->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
{
PUSB_INTERFACE_DESCRIPTOR pIntf = (PUSB_INTERFACE_DESCRIPTOR)pCommon;
KLogEx(DEBUG_TRACE_INFO, "[Interface Descriptor]\n");
KLogEx(DEBUG_TRACE_INFO, " bInterfaceNumber: 0x%X\n", pIntf->bInterfaceNumber);
KLogEx(DEBUG_TRACE_INFO, " bAlternateSetting: 0x%X\n", pIntf->bAlternateSetting);
KLogEx(DEBUG_TRACE_INFO, " bNumEndpoints: 0x%X\n", pIntf->bNumEndpoints);
KLogEx(DEBUG_TRACE_INFO, " bInterfaceClass: 0x%X\n", pIntf->bInterfaceClass);
KLogEx(DEBUG_TRACE_INFO, " bInterfaceSubClass: 0x%X\n", pIntf->bInterfaceSubClass);
KLogEx(DEBUG_TRACE_INFO, " bInterfaceProtocol: 0x%X\n", pIntf->bInterfaceProtocol);
}
else if (pCommon->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
{
PUSB_ENDPOINT_DESCRIPTOR pEp = (PUSB_ENDPOINT_DESCRIPTOR)pCommon;
KLogEx(DEBUG_TRACE_INFO, "[Endpoint Descriptor]\n");
KLogEx(DEBUG_TRACE_INFO, " bEndpointAddress: 0x%X\n", pEp->bEndpointAddress);
KLogEx(DEBUG_TRACE_INFO, " bmAttributes: 0x%X\n", pEp->bmAttributes);
KLogEx(DEBUG_TRACE_INFO, " wMaxPacketSize: 0x%X\n", pEp->wMaxPacketSize);
KLogEx(DEBUG_TRACE_INFO, " bInterval: 0x%X\n", pEp->bInterval);
}
pCurr += pCommon->bLength;
}
}
// 메모리 정리
if (pDevDesc) ExFreePool(pDevDesc);
if (pConfigDesc) ExFreePool(pConfigDesc);
KLogEx(DEBUG_TRACE_INFO, "===== END USB INFO COLLECTION =====\n");
}
NTSTATUS CollectUsbDeviceInfo(
IN PDEVICE_OBJECT DeviceObject,
OUT PUSB_PARSED_INFO* ppInfo
@ -368,96 +154,230 @@ NTSTATUS CollectUsbDeviceInfo(
*ppInfo = NULL;
if (KeGetCurrentIrql() > APC_LEVEL)
{
KLogEx(DEBUG_TRACE_ERROR, "not APC_LEVEL\n");
if (KeGetCurrentIrql() > APC_LEVEL)
return STATUS_INVALID_DEVICE_STATE;
}
// 1. 구조체 할당
pInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(USB_PARSED_INFO), 'INFO');
if (!pInfo) return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(pInfo, sizeof(USB_PARSED_INFO));
// 2. Device Descriptor 수집
status = GetUsbDeviceDescriptor(DeviceObject, &pDevDesc);
if (!NT_SUCCESS(status) || !pDevDesc) {
FreeUsbDeviceInfo(pInfo);
return status;
if (!NT_SUCCESS(status) || !pDevDesc)
{
FreeUsbDeviceInfo(pInfo);
return status;
}
// 구조체에 복사 후 임시 버퍼 해제
RtlCopyMemory(&pInfo->DeviceDesc, pDevDesc, sizeof(USB_DEVICE_DESCRIPTOR));
ExFreePool(pDevDesc);
// 3. String Descriptor 수집 (Manufacturer, Product, Serial)
if (pInfo->DeviceDesc.iManufacturer) {
// String Descriptor 수집
if (pInfo->DeviceDesc.iManufacturer)
GetUsbStringDescriptor(DeviceObject, pInfo->DeviceDesc.iManufacturer, LangId, &pInfo->ManufacturerStr);
}
if (pInfo->DeviceDesc.iProduct) {
if (pInfo->DeviceDesc.iProduct)
GetUsbStringDescriptor(DeviceObject, pInfo->DeviceDesc.iProduct, LangId, &pInfo->ProductStr);
}
if (pInfo->DeviceDesc.iSerialNumber) {
if (pInfo->DeviceDesc.iSerialNumber)
GetUsbStringDescriptor(DeviceObject, pInfo->DeviceDesc.iSerialNumber, LangId, &pInfo->SerialNumberStr);
}
// 4. Configuration Descriptor (Full) 수집
// ConfigDesc는 내부적으로 할당된 메모리를 그대로 포인터로 연결
// Configuration Descriptor (Full) 수집 및 원-패스 파싱
status = GetUsbFullConfigDescriptor(DeviceObject, &pInfo->ConfigDesc);
if (NT_SUCCESS(status) && pInfo->ConfigDesc)
if (NT_SUCCESS(status) && pInfo->ConfigDesc)
{
pInfo->ConfigDescSize = pInfo->ConfigDesc->wTotalLength;
PUCHAR pCurr = (PUCHAR)pInfo->ConfigDesc;
PUCHAR pEnd = pCurr + pInfo->ConfigDescSize;
LONG currentInterfaceIndex = -1; // 현재 파싱 중인 인터페이스 번호
LONG currentInterfaceIndex = -1;
if (pCurr + sizeof(USB_CONFIGURATION_DESCRIPTOR) < pEnd)
pCurr += ((PUSB_COMMON_DESCRIPTOR)pCurr)->bLength;
KLogEx(DEBUG_TRACE_INFO, "[Configuration Descriptor] bNumInterfaces: 0x%X", pInfo->ConfigDesc->bNumInterfaces);
while (pCurr < pEnd)
{
PUSB_COMMON_DESCRIPTOR pCommon = (PUSB_COMMON_DESCRIPTOR)pCurr;
// 유효성 체크
if (pCommon->bLength == 0 || pCurr + pCommon->bLength > pEnd)
break;
// Interface Descriptor 확인
if (pCommon->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE) {
PUSB_INTERFACE_DESCRIPTOR pIntf = (PUSB_INTERFACE_DESCRIPTOR)pCommon;
// =================================================================
// Interface Descriptor 파싱
// =================================================================
if (pCommon->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
{
PUSB_INTERFACE_DESCRIPTOR pIntf = (PUSB_INTERFACE_DESCRIPTOR)pCommon;
UCHAR cls = pIntf->bInterfaceClass;
UCHAR subCls = pIntf->bInterfaceSubClass;
UCHAR proto = pIntf->bInterfaceProtocol;
KLogEx(DEBUG_TRACE_INFO, "[Interface Descriptor] bInterfaceNumber: 0x%X, bAlternateSetting: 0x%X, bNumEndpoints: 0x%X, bInterfaceClass: 0x%X, bInterfaceSubClass: 0x%X, bInterfaceProtocol: 0x%X",
pIntf->bInterfaceNumber,
pIntf->bAlternateSetting,
pIntf->bNumEndpoints,
pIntf->bInterfaceClass,
pIntf->bInterfaceSubClass,
pIntf->bInterfaceProtocol
);
currentInterfaceIndex = pIntf->bInterfaceNumber;
pInfo->FoundClassCount++;
if (pInfo->FoundClassCount > 1)
pInfo->IsCompositeDevice = TRUE;
switch (cls)
{
case 0x01: pInfo->IsAudio = TRUE; break;
case 0x02: pInfo->IsCDC = TRUE; break;
case 0x06:
case 0x0E: pInfo->IsImageOrVideo = TRUE; break;
case 0x07: pInfo->IsPrinter = TRUE; break;
case 0x08: pInfo->IsMassStorage = TRUE; break;
case 0x09: pInfo->IsHub = TRUE; break;
case 0x03: // HID (키보드, 마우스, 기타)
if (subCls == 0x01)
{
if (proto == 0x01) pInfo->IsBootKeyboard = TRUE;
else if (proto == 0x02) pInfo->IsBootMouse = TRUE;
else pInfo->IsAbnormalHID = TRUE;
}
else if (subCls == 0x00)
{
pInfo->IsCustomHID = TRUE;
}
else
{
pInfo->IsAbnormalHID = TRUE;
}
if (!pInfo->IsBootKeyboard && !pInfo->IsBootMouse)
{
pInfo->OtherHidSubClass = subCls;
pInfo->OtherHidProtocol = proto;
}
break;
}
}
// [B] HID Descriptor 발견 (0x21)
else if (pCommon->bDescriptorType == USB_DESCRIPTOR_TYPE_HID)
// =================================================================
// Endpoint Descriptor 파싱 (BadUSB 위협 분석용)
// =================================================================
else if (pCommon->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
{
PUSB_ENDPOINT_DESCRIPTOR pEp = (PUSB_ENDPOINT_DESCRIPTOR)pCommon;
UCHAR epType = pEp->bmAttributes & 0x03; // USB_ENDPOINT_TYPE_MASK
KLogEx(DEBUG_TRACE_INFO, "[Endpoint Descriptor] bEndpointAddress: 0x%X, bmAttributes: 0x%X, wMaxPacketSize: 0x%X, bInterval: 0x%X\n",
pEp->bEndpointAddress,
pEp->bmAttributes,
pEp->wMaxPacketSize,
pEp->bInterval
);
pInfo->TotalEndpoints++;
if (epType == USB_ENDPOINT_TYPE_INTERRUPT)
{
pInfo->InterruptEndpoints++;
}
else if (epType == USB_ENDPOINT_TYPE_BULK)
{
pInfo->BulkEndpoints++;
}
}
// =================================================================
// [C] HID Descriptor 별도 보관 (필요 시 Report 분석용)
// =================================================================
else if (pCommon->bDescriptorType == USB_DESCRIPTOR_TYPE_HID)
{
PUSB_HID_DESCRIPTOR pHid = (PUSB_HID_DESCRIPTOR)pCommon;
// 저장 공간이 있고, 유효한 인터페이스 내부에 있는 경우
if (pInfo->HidInterfaceCount < MAX_HID_INTERFACES && currentInterfaceIndex >= 0)
if (pInfo->HidInterfaceCount < MAX_HID_INTERFACES && currentInterfaceIndex >= 0)
{
ULONG idx = pInfo->HidInterfaceCount;
pInfo->HidEntries[idx].InterfaceNumber = (UCHAR)currentInterfaceIndex;
pInfo->HidEntries[idx].HidDesc = pHid;
pInfo->HidInterfaceCount++;
KLogEx(DEBUG_TRACE_INFO, " Found HID Desc at Interface %d (Count: %d)\n",
currentInterfaceIndex, pInfo->HidInterfaceCount);
}
}
pCurr += pCommon->bLength;
}
// =================================================================
// [결론] 최종 BadUSB 휴리스틱 판별 (루프 종료 후)
// =================================================================
// 1. Bulk와 Interrupt가 혼용되었는지 (아이폰, 프린터 등 복합장치 특성)
if (pInfo->InterruptEndpoints > 0 && pInfo->BulkEndpoints > 0)
{
pInfo->HasMixedEndpoints = TRUE;
}
BOOLEAN hasHID = pInfo->IsBootKeyboard || pInfo->IsBootMouse;
BOOLEAN hasBothHID = pInfo->IsBootKeyboard && pInfo->IsBootMouse;
// 2. 최종 판별 로직 (안전한 신형 로직 적용)
// 조건: 자기가 키보드나 마우스라고 주장하는데, 아래 중 하나라도 해당하면 BadUSB로 차단!
// - 키보드와 마우스가 동시에 존재 (해커들이 자주 씀)
// - 인터럽트 엔드포인트가 3개 이상으로 비정상적으로 많음
// - 엔드포인트가 전혀 없음 (가짜 장치)
// - 키보드라면서 대용량 전송용 BULK 엔드포인트가 섞여 있음
if (hasBothHID || (hasHID && (pInfo->InterruptEndpoints >= 3 || pInfo->TotalEndpoints == 0 || pInfo->HasMixedEndpoints)))
{
pInfo->IsBadUSB = TRUE;
KLogEx(DEBUG_TRACE_ERROR, "[!!!] MALICIOUS BAD-USB DETECTED! (IntEps: %d, BulkEps: %d)\n",
pInfo->InterruptEndpoints, pInfo->BulkEndpoints);
}
}
else
else
{
pInfo->ConfigDesc = NULL;
pInfo->ConfigDescSize = 0;
}
// 성공 시 포인터 반환
*ppInfo = pInfo;
return STATUS_SUCCESS;
}
VOID PrintUsbParsedInfo(IN PUSB_PARSED_INFO pInfo)
{
if (!pInfo)
{
KLogEx(DEBUG_TRACE_ERROR, "[-] PrintUsbParsedInfo: pInfo is NULL\n");
return;
}
// HID 정보 출력
if (pInfo->IsBootKeyboard) KLogEx(DEBUG_TRACE_INFO, " - IsBootKeyboard : TRUE\n");
if (pInfo->IsBootMouse) KLogEx(DEBUG_TRACE_INFO, " - IsBootMouse : TRUE\n");
if (pInfo->IsCustomHID) KLogEx(DEBUG_TRACE_INFO, " - IsCustomHID : TRUE\n");
if (pInfo->IsAbnormalHID) KLogEx(DEBUG_TRACE_INFO, " - IsAbnormalHID : TRUE\n");
// 기타 HID일 경우에만 서브클래스와 프로토콜 값을 출력
if (pInfo->IsCustomHID || pInfo->IsAbnormalHID) {
KLogEx(DEBUG_TRACE_INFO, " > OtherHidSubClass : 0x%02X\n", pInfo->OtherHidSubClass);
KLogEx(DEBUG_TRACE_INFO, " > OtherHidProtocol : 0x%02X\n", pInfo->OtherHidProtocol);
}
// 디바이스 클래스 정보 출력
if (pInfo->IsMassStorage) KLogEx(DEBUG_TRACE_INFO, " - IsMassStorage : TRUE\n");
if (pInfo->IsAudio) KLogEx(DEBUG_TRACE_INFO, " - IsAudio : TRUE\n");
if (pInfo->IsPrinter) KLogEx(DEBUG_TRACE_INFO, " - IsPrinter : TRUE\n");
if (pInfo->IsImageOrVideo) KLogEx(DEBUG_TRACE_INFO, " - IsImageOrVideo : TRUE\n");
if (pInfo->IsHub) KLogEx(DEBUG_TRACE_INFO, " - IsHub : TRUE\n");
if (pInfo->IsCDC) KLogEx(DEBUG_TRACE_INFO, " - IsCDC : TRUE\n");
if (pInfo->IsCompositeDevice) KLogEx(DEBUG_TRACE_INFO, " - IsCompositeDevice : TRUE\n");
KLogEx(DEBUG_TRACE_INFO, " - FoundClassCount : %lu\n", pInfo->FoundClassCount);
// 3. BadUSB 및 엔드포인트 정보 출력
KLogEx(DEBUG_TRACE_INFO, "\n[BadUSB & Endpoint Information]\n");
KLogEx(DEBUG_TRACE_INFO, " - TotalEndpoints : %lu\n", pInfo->TotalEndpoints);
KLogEx(DEBUG_TRACE_INFO, " - InterruptEndpoints : %lu\n", pInfo->InterruptEndpoints);
KLogEx(DEBUG_TRACE_INFO, " - BulkEndpoints : %lu\n", pInfo->BulkEndpoints);
if (pInfo->HasMixedEndpoints)
KLogEx(DEBUG_TRACE_INFO, " - HasMixedEndpoints : TRUE\n");
// BadUSB 탐지 여부는 눈에 잘 띄게 출력
if (pInfo->IsBadUSB) {
KLogEx(DEBUG_TRACE_INFO, " - IsBadUSB : *** TRUE (MALICIOUS DEVICE DETECTED!) ***\n");
}
}

View File

@ -28,21 +28,51 @@ typedef struct _HID_INTERFACE_ENTRY {
PUSB_HID_DESCRIPTOR HidDesc; // HID Descriptor 포인터 (ConfigDesc 내부 위치)
} HID_INTERFACE_ENTRY, * PHID_INTERFACE_ENTRY;
// USB 정보를 담을 구조체 정의
typedef struct _USB_PARSED_INFO {
// 1. Device Descriptor (VendorID, ProductID 등)
USB_DEVICE_DESCRIPTOR DeviceDesc;
// 2. String Descriptors (사람이 읽을 수 있는 문자열)
PWCHAR ManufacturerStr; // 제조사 (NULL일 수 있음)
PWCHAR ProductStr; // 제품명 (NULL일 수 있음)
PWCHAR SerialNumberStr; // 시리얼 번호 (NULL일 수 있음)
PWCHAR ManufacturerStr;
PWCHAR ProductStr;
PWCHAR SerialNumberStr;
// 3. Configuration Descriptor (Interface, Endpoint 포함된 전체 Blob)
PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc;
ULONG ConfigDescSize;
ULONG HidInterfaceCount;
// -----------------------------------------
// 1. [CC 인증 요구사항] HID 상세 분류 플래그
// -----------------------------------------
BOOLEAN IsBootKeyboard; // 완벽한 표준 키보드 (SubClass 1, Protocol 1)
BOOLEAN IsBootMouse; // 완벽한 표준 마우스 (SubClass 1, Protocol 2)
BOOLEAN IsCustomHID; // 기타 커스텀 HID (SubClass 0, Protocol 0 - 바코드, 터치 등)
BOOLEAN IsAbnormalHID; // 스펙에 맞지 않는 비정상 HID
UCHAR OtherHidSubClass;
UCHAR OtherHidProtocol;
// -----------------------------------------
// 2. [매체 제어 요구사항] 주요 디바이스 클래스
// -----------------------------------------
BOOLEAN IsMassStorage; // 0x08: USB 메모리, 외장하드
BOOLEAN IsAudio; // 0x01: USB 스피커, 헤드셋
BOOLEAN IsPrinter; // 0x07: USB 프린터
BOOLEAN IsImageOrVideo; // 0x06 (Image), 0x0E (Video): 웹캠, 스마트폰 MTP 일부
BOOLEAN IsHub; // 0x09: USB 허브
BOOLEAN IsCDC; // 0x02: 통신 장치 (스마트폰 테더링, 가상 시리얼)
BOOLEAN IsCompositeDevice; // 복합 장치 여부
ULONG FoundClassCount; // 발견된 고유 인터페이스 개수
// -----------------------------------------
// 3. [안티 해킹] BadUSB 탐지용 카운터 및 플래그
// -----------------------------------------
ULONG TotalEndpoints; // 전체 엔드포인트 개수
ULONG InterruptEndpoints; // 인터럽트 엔드포인트 개수
ULONG BulkEndpoints; // 대용량 전송 엔드포인트 개수
BOOLEAN HasMixedEndpoints; // Bulk와 Interrupt가 섞여 있는지 여부 (구형 CheckBADUSB 아이디어)
BOOLEAN IsBadUSB; // 최종 BadUSB 확정 플래그 (TRUE면 차단)
// HID 부가 정보 보관용
ULONG HidInterfaceCount;
HID_INTERFACE_ENTRY HidEntries[MAX_HID_INTERFACES];
} USB_PARSED_INFO, * PUSB_PARSED_INFO;
@ -50,4 +80,4 @@ typedef struct _USB_PARSED_INFO {
// 함수 원형 선언
NTSTATUS CollectUsbDeviceInfo(IN PDEVICE_OBJECT DeviceObject, OUT PUSB_PARSED_INFO* ppInfo);
VOID FreeUsbDeviceInfo(IN PUSB_PARSED_INFO pInfo);
VOID PrintUsbParsedInfo(IN PUSB_PARSED_INFO pInfo);

View File

@ -261,105 +261,107 @@ NTSTATUS USBPnpControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT DeviceObject, PI
goto $USBCleanup;
}
if (pUsbInfo->ProductStr)
{
KLogEx(DEBUG_TRACE_INFO, " Product: %S\n", pUsbInfo->ProductStr);
}
//if (pUsbInfo->ProductStr)
//{
// KLogEx(DEBUG_TRACE_INFO, " Product: %S\n", pUsbInfo->ProductStr);
//}
if (pUsbInfo->SerialNumberStr)
{
KLogEx(DEBUG_TRACE_INFO, " Serial: %S\n", pUsbInfo->SerialNumberStr);
}
if (pUsbInfo->ConfigDesc && pUsbInfo->ConfigDescSize > 0)
{
PUSB_CONFIGURATION_DESCRIPTOR pConfigDesc = pUsbInfo->ConfigDesc;
PUCHAR pCurr = (PUCHAR)pConfigDesc;
PUCHAR pEnd = pCurr + pConfigDesc->wTotalLength;
PrintUsbParsedInfo(pUsbInfo);
KLogEx(DEBUG_TRACE_INFO, "[Configuration Descriptor]");
KLogEx(DEBUG_TRACE_INFO, " wTotalLength: 0x%X, bNumInterfaces: 0x%X, bConfigurationValue: 0x%X, MaxPower: 0x%X\n",
pConfigDesc->wTotalLength,
pConfigDesc->bNumInterfaces,
pConfigDesc->bConfigurationValue,
pConfigDesc->MaxPower
);
// Loop를 돌면서 Interface 및 Endpoint 파싱
// 첫 번째 Descriptor는 Configuration이므로 건너뜀
pCurr += pConfigDesc->bLength;
//if (pUsbInfo->ConfigDesc && pUsbInfo->ConfigDescSize > 0)
//{
// PUSB_CONFIGURATION_DESCRIPTOR pConfigDesc = pUsbInfo->ConfigDesc;
// PUCHAR pCurr = (PUCHAR)pConfigDesc;
// PUCHAR pEnd = pCurr + pConfigDesc->wTotalLength;
while (pCurr < pEnd)
{
PUSB_COMMON_DESCRIPTOR pCommon = (PUSB_COMMON_DESCRIPTOR)pCurr;
// KLogEx(DEBUG_TRACE_INFO, "[Configuration Descriptor]");
// KLogEx(DEBUG_TRACE_INFO, " wTotalLength: 0x%X, bNumInterfaces: 0x%X, bConfigurationValue: 0x%X, MaxPower: 0x%X\n",
// pConfigDesc->wTotalLength,
// pConfigDesc->bNumInterfaces,
// pConfigDesc->bConfigurationValue,
// pConfigDesc->MaxPower
// );
//
// // Loop를 돌면서 Interface 및 Endpoint 파싱
// // 첫 번째 Descriptor는 Configuration이므로 건너뜀
// pCurr += pConfigDesc->bLength;
if (pCommon->bLength == 0)
break; // 에러 방지
// while (pCurr < pEnd)
// {
// PUSB_COMMON_DESCRIPTOR pCommon = (PUSB_COMMON_DESCRIPTOR)pCurr;
if (pCommon->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
{
PUSB_INTERFACE_DESCRIPTOR pIntf = (PUSB_INTERFACE_DESCRIPTOR)pCommon;
KLogEx(DEBUG_TRACE_INFO, "[Interface Descriptor]");
KLogEx(DEBUG_TRACE_INFO, " bInterfaceNumber: 0x%X, bAlternateSetting: 0x%X, bNumEndpoints: 0x%X, bInterfaceClass: 0x%X, bInterfaceSubClass: 0x%X, bInterfaceProtocol: 0x%X",
pIntf->bInterfaceNumber,
pIntf->bAlternateSetting,
pIntf->bNumEndpoints,
pIntf->bInterfaceClass,
pIntf->bInterfaceSubClass,
pIntf->bInterfaceProtocol
);
}
else if (pCommon->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
{
PUSB_ENDPOINT_DESCRIPTOR pEp = (PUSB_ENDPOINT_DESCRIPTOR)pCommon;
KLogEx(DEBUG_TRACE_INFO, "[Endpoint Descriptor]\n");
KLogEx(DEBUG_TRACE_INFO, " bEndpointAddress: 0x%X, bmAttributes: 0x%X, wMaxPacketSize: 0x%X, bInterval: 0x%X\n",
pEp->bEndpointAddress,
pEp->bmAttributes,
pEp->wMaxPacketSize,
pEp->bInterval
);
}
// if (pCommon->bLength == 0)
// break; // 에러 방지
pCurr += pCommon->bLength;
}
}
// if (pCommon->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE)
// {
// PUSB_INTERFACE_DESCRIPTOR pIntf = (PUSB_INTERFACE_DESCRIPTOR)pCommon;
// KLogEx(DEBUG_TRACE_INFO, "[Interface Descriptor]");
// KLogEx(DEBUG_TRACE_INFO, " bInterfaceNumber: 0x%X, bAlternateSetting: 0x%X, bNumEndpoints: 0x%X, bInterfaceClass: 0x%X, bInterfaceSubClass: 0x%X, bInterfaceProtocol: 0x%X",
// pIntf->bInterfaceNumber,
// pIntf->bAlternateSetting,
// pIntf->bNumEndpoints,
// pIntf->bInterfaceClass,
// pIntf->bInterfaceSubClass,
// pIntf->bInterfaceProtocol
// );
// }
// else if (pCommon->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE)
// {
// PUSB_ENDPOINT_DESCRIPTOR pEp = (PUSB_ENDPOINT_DESCRIPTOR)pCommon;
// KLogEx(DEBUG_TRACE_INFO, "[Endpoint Descriptor]\n");
// KLogEx(DEBUG_TRACE_INFO, " bEndpointAddress: 0x%X, bmAttributes: 0x%X, wMaxPacketSize: 0x%X, bInterval: 0x%X\n",
// pEp->bEndpointAddress,
// pEp->bmAttributes,
// pEp->wMaxPacketSize,
// pEp->bInterval
// );
// }
if (pUsbInfo->HidInterfaceCount > 0)
{
ULONG i;
KLogEx(DEBUG_TRACE_INFO, " Total HID Interfaces Found: %d\n", pUsbInfo->HidInterfaceCount);
// pCurr += pCommon->bLength;
// }
//}
for (i = 0; i < pUsbInfo->HidInterfaceCount; i++)
{
HID_INTERFACE_ENTRY* pEntry = &pUsbInfo->HidEntries[i];
PUSB_HID_DESCRIPTOR pHid = pEntry->HidDesc;
//if (pUsbInfo->HidInterfaceCount > 0)
//{
// ULONG i;
// KLogEx(DEBUG_TRACE_INFO, " Total HID Interfaces Found: %d\n", pUsbInfo->HidInterfaceCount);
KLogEx(DEBUG_TRACE_INFO, " [HID Interface #%d]\n", pEntry->InterfaceNumber);
if (pHid)
{
KLogEx(DEBUG_TRACE_INFO, " bcdHID: 0x%04X\n", pHid->bcdHID);
KLogEx(DEBUG_TRACE_INFO, " Report Descs: %d\n", pHid->bNumDescriptors);
if (pHid->bNumDescriptors > 0)
{
KLogEx(DEBUG_TRACE_INFO, " Desc Length: %d\n", pHid->DescriptorList[0].wDescriptorLength);
}
}
}
// for (i = 0; i < pUsbInfo->HidInterfaceCount; i++)
// {
// HID_INTERFACE_ENTRY* pEntry = &pUsbInfo->HidEntries[i];
// PUSB_HID_DESCRIPTOR pHid = pEntry->HidDesc;
// 예시: 1번 인터페이스가 HID라면 차단?
/*
for (i = 0; i < pUsbInfo->HidInterfaceCount; i++) {
if (pUsbInfo->HidEntries[i].InterfaceNumber == 1) {
bBlock = TRUE;
}
}
*/
}
else
{
KLogEx(DEBUG_TRACE_INFO, " No HID Interfaces found.\n");
}
// KLogEx(DEBUG_TRACE_INFO, " [HID Interface #%d]\n", pEntry->InterfaceNumber);
// if (pHid)
// {
// KLogEx(DEBUG_TRACE_INFO, " bcdHID: 0x%04X\n", pHid->bcdHID);
// KLogEx(DEBUG_TRACE_INFO, " Report Descs: %d\n", pHid->bNumDescriptors);
// if (pHid->bNumDescriptors > 0)
// {
// KLogEx(DEBUG_TRACE_INFO, " Desc Length: %d\n", pHid->DescriptorList[0].wDescriptorLength);
// }
// }
// }
// // 예시: 1번 인터페이스가 HID라면 차단?
// /*
// for (i = 0; i < pUsbInfo->HidInterfaceCount; i++) {
// if (pUsbInfo->HidEntries[i].InterfaceNumber == 1) {
// bBlock = TRUE;
// }
// }
// */
//}
//else
//{
// KLogEx(DEBUG_TRACE_INFO, " No HID Interfaces found.\n");
//}
}
if (state == DISABLE && pUsbInfo)

View File

@ -723,6 +723,103 @@ UGetIoOpenDriverRegistryKey(
return pIoOpenDriverRegistryKey;
}
//NTSTATUS
//UOpenServiceParametersKey(
// _In_ PUNICODE_STRING RegistryPath,
// _Out_ PHANDLE ServiceParametersKey
//)
//{
// NTSTATUS Status;
// HANDLE ServiceKey = NULL;
// HANDLE ParametersKey = NULL;
// OBJECT_ATTRIBUTES Attributes;
// UNICODE_STRING SubKeyName;
//
// // 1. 서비스 루트 키 열기 (\Registry\...\bs1flt)
// InitializeObjectAttributes(&Attributes,
// RegistryPath,
// OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
// NULL,
// NULL);
//
// Status = ZwOpenKey(&ServiceKey, KEY_READ, &Attributes);
// if (!NT_SUCCESS(Status)) {
// return Status;
// }
//
// // 2. "Parameters" 서브 키 열기
// RtlInitUnicodeString(&SubKeyName, L"Parameters");
// InitializeObjectAttributes(&Attributes,
// &SubKeyName,
// OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
// ServiceKey,
// NULL);
//
// Status = ZwOpenKey(&ParametersKey, KEY_READ, &Attributes);
//
// // 3. 서비스 루트 키는 이제 필요 없으므로 닫음
// ZwClose(ServiceKey);
//
// if (NT_SUCCESS(Status)) {
// *ServiceParametersKey = ParametersKey;
// }
//
// return Status;
//}
/////NTSTATUS USetConfiguration(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath);
//NTSTATUS
//USetConfiguration(
// _In_ PUNICODE_STRING RegistryPath // DriverObject는 필요 없음
//)
//{
// NTSTATUS status;
// HANDLE settingsKey = NULL;
// UNICODE_STRING valueName;
//
// // 버퍼 크기를 넉넉하게 잡음 (데이터가 ULONG이 아닐 수도 있으므로)
// UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
// PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
// ULONG resultLength;
//
// // 1. Parameters 키 열기
// status = UOpenServiceParametersKey(RegistryPath, &settingsKey);
// if (!NT_SUCCESS(status)) {
// return STATUS_SUCCESS;
// }
//
// // 2. DebugLevel 값 읽기
// RtlInitUnicodeString(&valueName, L"DebugLevel");
// status = ZwQueryValueKey(settingsKey,
// &valueName,
// KeyValuePartialInformation,
// value,
// sizeof(buffer),
// &resultLength);
//
// if (NT_SUCCESS(status) && value->Type == REG_DWORD) {
// // 전역 변수 설정 (extern 선언 필요)
// g_DebugLevel = *(PULONG)value->Data;
// }
//
// // 3. ProcessCreate 값 읽기
// RtlInitUnicodeString(&valueName, L"ProcessCreate");
// status = ZwQueryValueKey(settingsKey,
// &valueName,
// KeyValuePartialInformation,
// value,
// sizeof(buffer),
// &resultLength);
//
// if (NT_SUCCESS(status) && value->Type == REG_DWORD) {
// g_bs1Flt.IsProcessCreate = *(PULONG)value->Data;
// }
//
// // 4. 핸들 닫기 (필수)
// ZwClose(settingsKey);
//
// return STATUS_SUCCESS;
//}
NTSTATUS
UOpenServiceParametersKey(
_In_ PUNICODE_STRING RegistryPath,
@ -735,7 +832,7 @@ UOpenServiceParametersKey(
OBJECT_ATTRIBUTES Attributes;
UNICODE_STRING SubKeyName;
// 1. 서비스 루트 키 열기 (\Registry\...\bs1flt)
// 1. 서비스 루트 키 열기
InitializeObjectAttributes(&Attributes,
RegistryPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
@ -744,6 +841,7 @@ UOpenServiceParametersKey(
Status = ZwOpenKey(&ServiceKey, KEY_READ, &Attributes);
if (!NT_SUCCESS(Status)) {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[MGKIM] Failed to open Service Root Key (0x%X)\n", Status);
return Status;
}
@ -757,37 +855,40 @@ UOpenServiceParametersKey(
Status = ZwOpenKey(&ParametersKey, KEY_READ, &Attributes);
// 3. 서비스 루트 키는 이제 필요 없으므로 닫음
// 3. 서비스 루트 키 닫기
ZwClose(ServiceKey);
if (NT_SUCCESS(Status)) {
*ServiceParametersKey = ParametersKey;
}
else {
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[MGKIM] Failed to open 'Parameters' SubKey (0x%X)\n", Status);
}
return Status;
}
///NTSTATUS USetConfiguration(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath);
NTSTATUS
USetConfiguration(
_In_ PUNICODE_STRING RegistryPath // DriverObject는 필요 없음
_In_ PUNICODE_STRING RegistryPath
)
{
NTSTATUS status;
HANDLE settingsKey = NULL;
UNICODE_STRING valueName;
// 버퍼 크기를 넉넉하게 잡음 (데이터가 ULONG이 아닐 수도 있으므로)
UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
ULONG buffer[32] = { 0 };
PKEY_VALUE_PARTIAL_INFORMATION value = (PKEY_VALUE_PARTIAL_INFORMATION)buffer;
ULONG resultLength;
// 1. Parameters 키 열기
// Parameters 키 열기
status = UOpenServiceParametersKey(RegistryPath, &settingsKey);
if (!NT_SUCCESS(status)) {
return STATUS_SUCCESS;
if (!NT_SUCCESS(status))
{
return status;
}
// 2. DebugLevel 값 읽기
// DebugLevel 값 읽기
RtlInitUnicodeString(&valueName, L"DebugLevel");
status = ZwQueryValueKey(settingsKey,
&valueName,
@ -796,12 +897,17 @@ USetConfiguration(
sizeof(buffer),
&resultLength);
if (NT_SUCCESS(status) && value->Type == REG_DWORD) {
// 전역 변수 설정 (extern 선언 필요)
g_DebugLevel = *(PULONG)value->Data;
if (NT_SUCCESS(status) && value->Type == REG_DWORD)
{
g_DebugLevel = *((PULONG)value->Data);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%s:%s: DebugLevel loaded: %d\n", DRIVERNAMEA, __FUNCTION__, g_DebugLevel);
}
else
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "%s:%s: ZwQueryValueKey failed for DebugLevel (0x%X)\n", DRIVERNAMEA, __FUNCTION__, status);
}
// 3. ProcessCreate 값 읽기
// ProcessCreate 값 읽기
RtlInitUnicodeString(&valueName, L"ProcessCreate");
status = ZwQueryValueKey(settingsKey,
&valueName,
@ -810,11 +916,17 @@ USetConfiguration(
sizeof(buffer),
&resultLength);
if (NT_SUCCESS(status) && value->Type == REG_DWORD) {
g_bs1Flt.IsProcessCreate = *(PULONG)value->Data;
if (NT_SUCCESS(status) && value->Type == REG_DWORD)
{
g_bs1Flt.IsProcessCreate = *((PULONG)value->Data);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "%s:%s: ProcessCreate loaded: %d\n", DRIVERNAMEA, __FUNCTION__, g_bs1Flt.IsProcessCreate);
}
else
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "%s:%s: ZwQueryValueKey failed for ProcessCreate (0x%X)\n", DRIVERNAMEA, __FUNCTION__, status);
}
// 4. 핸들 닫기 (필수)
// 핸들 닫기
ZwClose(settingsKey);
return STATUS_SUCCESS;

View File

@ -6,7 +6,8 @@
#pragma warning(disable : 4995)
#undef NTDDI_VERSION
#define NTDDI_VERSION 0x0A00000A
#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
@ -95,7 +96,7 @@ do { \
{ \
DbgPrintEx( \
DPFLTR_IHVDRIVER_ID, \
DPFLTR_ERROR_LEVEL, \
DPFLTR_INFO_LEVEL, \
"%s:%s: " Format, \
DRIVERNAMEA, \
__FUNCTION__, \

View File

@ -93,9 +93,9 @@ int CLocalConf::GetConfig(const char* filename, DWORD pid)
debug_type = GetJsonUint32("bs1flt", debug);
bs1fltkernel = GetJsonUint32("bs1fltkernel", debug);
/*char debugporint[100] = { 0, };
sprintf_s(debugporint, sizeof(debugporint), "debug_type(%d), bs1fltkernel(%d)", debug_type, bs1fltkernel);
OutputDebugStringA(debugporint);*/
char debugporint[100] = { 0, };
sprintf_s(debugporint, sizeof(debugporint), "[BS1] debug_type(%d), bs1fltkernel(%d)", debug_type, bs1fltkernel);
OutputDebugStringA(debugporint);
stream.close();
}
else

View File

@ -637,16 +637,16 @@ void CtoolDlg::OnBnClickedButtonSetPolicy()
if ((DWORD)policy[i].device_type == BDC_USB && policy[i].state == DISABLE)
{
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_UNSPECIFIED, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_CDC, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_HID, ENABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_AUDIO, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_PHYSICAL, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_IMAGE, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_PRINTER, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_MSC, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_CDC_DATA, DISABLE);
bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_SMART_CARD, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_UNSPECIFIED, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_CDC, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_HID, ENABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_AUDIO, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_PHYSICAL, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_IMAGE, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_PRINTER, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_MSC, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_CDC_DATA, DISABLE);
//bs1flt_.Bs1fltSetUsbPolicy((DWORD)BDC_USB_CLASS_SMART_CARD, DISABLE);
debug.Format(L"SetPolicy : ReStartUsb");
CloseHandle(CreateThread(NULL, 0, ReStartUsb, NULL, 0, NULL));

View File

@ -5,7 +5,7 @@
<FrameworkType>VCL</FrameworkType>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Release</Config>
<Platform Condition="'$(Platform)'==''">Win64</Platform>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>3</TargetedPlatforms>
<AppType>Library</AppType>
<MainSource>eCrmHeHelper.dpr</MainSource>
@ -135,10 +135,12 @@
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_MapFile>3</DCC_MapFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_MapFile>3</DCC_MapFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
@ -156,6 +158,8 @@ $(PostBuildEvent)]]></PostBuildEvent>
<DCC_MapFile>3</DCC_MapFile>
<DCC_DebugInformation>2</DCC_DebugInformation>
<DCC_LocalDebugSymbols>true</DCC_LocalDebugSymbols>
<VerInfo_Build>1</VerInfo_Build>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.1;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.1;Comments=</VerInfo_Keys>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
<PostBuildEvent><![CDATA[copy "$(OUTPUTPATH)" "$(OUTPUTDIR)\conf\$(OUTPUTFILENAME)"

View File

@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
<Transactions>
<Transaction>1899-12-30 00:00:00.000.581,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\ObexParserUnit.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.934,C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\ObexParserUnit.pas=</Transaction>
<Transaction>1899-12-30 00:00:00.000.033,=C:\mgkim\8.bsone\BSOne.SFC\eCrmHE\DLL_eCrmHeHelper\WindowFinderThread.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.361,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\ObexParserUnit.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.033,=C:\mgkim\8.bsone\BSOne.SFC\eCrmHE\DLL_eCrmHeHelper\WindowFinderThread.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.581,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\ObexParserUnit.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.546,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\FileHandleListUnit.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.894,C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\FileHandleListUnit.pas=</Transaction>
<Transaction>1899-12-30 00:00:00.000.318,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\FileHandleListUnit.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.246,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneDebug.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.796,C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneDebug.pas=</Transaction>
<Transaction>1899-12-30 00:00:00.000.508,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneUtil.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.853,C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneUtil.pas=</Transaction>
<Transaction>1899-12-30 00:00:00.000.283,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneUtil.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.691,=C:\mgkim\8.bsone\BSOne.SFC\eCrmHE\DLL_eCrmHeHelper\Unit1.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.246,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneDebug.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.471,=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneDebug.pas</Transaction>
<Transaction>1899-12-30 00:00:00.000.796,C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\BsoneDebug.pas=</Transaction>
<Transaction>1899-12-30 00:00:00.000.713,C:\mgkim\8.bsone\BSOne.SFC\eCrmHE\DLL_eCrmHeHelper\Unit1.pas=C:\mgkim\8.bsone\BSOne.SFC\Tocsg.Module\Bs1Flt\MTPMon\MTPControl\ApiHookContents.pas</Transaction>
</Transactions>
</BorlandProject>

View File

@ -2186,25 +2186,31 @@ object DlgeCrmHeInstMain: TDlgeCrmHeInstMain
OnClick = btnInfoClick
end
object Label20: TLabel
Left = 48
Top = 122
Width = 70
Left = 46
Top = 130
Width = 72
Height = 17
Alignment = taRightJustify
Caption = 'IP '#51221#48372' '#51077#47141
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Charset = ANSI_CHARSET
Font.Color = clBlack
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = []
Font.Style = [fsBold]
ParentFont = False
end
object Label21: TLabel
Left = 321
Top = 124
Width = 33
Height = 15
Caption = #54252#53944' : '
Left = 317
Top = 132
Width = 26
Height = 17
Caption = #54252#53944
Font.Charset = ANSI_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI Semibold'
Font.Style = [fsBold]
ParentFont = False
end
object edEmpNo: TEdit
Left = 150
@ -2238,26 +2244,32 @@ object DlgeCrmHeInstMain: TDlgeCrmHeInstMain
end
object edtIPAddress: TEdit
Left = 150
Top = 120
Top = 128
Width = 155
Height = 23
TabOrder = 3
Text = '192.168.15.197'
end
object edtPort: TEdit
Left = 360
Top = 120
Width = 63
Left = 349
Top = 128
Width = 74
Height = 23
TabOrder = 4
Text = '8443'
end
object chkIPCheck: TCheckBox
Left = 429
Top = 120
Left = 430
Top = 131
Width = 97
Height = 17
Caption = 'IP '#51217#49549' '#52404#53356
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = []
ParentFont = False
TabOrder = 5
OnClick = ClickiPCheck
end

View File

@ -7,7 +7,7 @@ uses
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls,
Vcl.Imaging.pngimage, PngImageList, System.ImageList, Vcl.ImgList,
Vcl.WinXPanels, Vcl.ComCtrls, VirtualTrees, Vcl.Buttons,
IdHTTP, IdSSLOpenSSL, IdIOHandler, System.Actions, Vcl.ActnList, AbArcTyp,
IdHTTP, IdSSLOpenSSL, IdIOHandler, System.Actions, Vcl.ActnList, AbZipper, AbArcTyp,
AbUtils, Tocsg.Obj, superobject, System.Net.HttpClient, System.Net.URLClient;
//{$DEFINE _MOTRAS_}
@ -409,6 +409,32 @@ var
// end;
end;
function AddFileToZip(const sZipFilePath, sFileToAdd: string): Boolean;
var
zip: TAbZipper;
begin
Result := False;
if not FileExists(sFileToAdd) then
Exit;
try
zip := TAbZipper.Create(nil);
try
zip.FileName := sZipFilePath;
zip.StoreOptions := [soStripPath];
zip.AddFiles(sFileToAdd, 0);
zip.Save;
Result := True;
finally
zip.Free;
end;
except
on E: Exception do
ETgException.TraceException(E, Format('Fail .. AddFileToZip(), Zip="%s", File="%s"', [sZipFilePath, sFileToAdd]));
end;
end;
var
ProcInfo: TProcessInformation;
begin
@ -918,6 +944,7 @@ begin
OutputDebugString(PChar(Format('[MGKIM] si dat ok : %s, %s',[PChar(sInstDir + 'si.dat'), DlgeCrmHeInstMain.serverInfo_])));
InstFileInfo.FileList_.Add(PChar(sInstDir + 'si.dat'));
AddFileToZip(sBackDir + 'rst.01', sInstDir + 'si.dat');
InstFileInfo.SaveFileInfo(sBackDir + 'rst.00');
end;
@ -1438,7 +1465,28 @@ end;
procedure TCertValidator.DoValidateServerCertificate(const Sender: TObject; const ARequest: TURLRequest;
const Certificate: TCertificate; var Accepted: Boolean);
begin
// 핵심: 인증서가 만료되었거나 IP 주소라서 안 맞거나, 사설 인증서라도 무조건 통과(True) 시킴!
// 인증서가 만료되었거나 IP 주소라서 안 맞거나, 사설 인증서라도 무조건 통과(True) 시킴!
// 1. 인증서 상세 정보 출력
OutputDebugString(PChar('[MGKIM] 인증서 정보 시작 ---'));
// 발급 대상 (도메인, 소유자 정보 등)
OutputDebugString(PChar('[MGKIM] 발급 대상(Subject): ' + Certificate.Subject));
// 발급자 (인증 기관 - CA)
OutputDebugString(PChar('[MGKIM] 발급자(Issuer): ' + Certificate.Issuer));
// 유효 기간
OutputDebugString(PChar('[MGKIM] 유효기간 시작: ' + DateTimeToStr(Certificate.Start)));
OutputDebugString(PChar('[MGKIM] 유효기간 만료: ' + DateTimeToStr(Certificate.Expiry)));
// 보안 및 암호화 정보 (수정된 정확한 속성명)
OutputDebugString(PChar('[MGKIM] 서명 알고리즘: ' + Certificate.AlgSignature));
OutputDebugString(PChar('[MGKIM] 암호화 알고리즘: ' + Certificate.AlgEncryption));
OutputDebugString(PChar('[MGKIM] 키 크기(Key Size): ' + IntToStr(Certificate.KeySize) + ' bits'));
OutputDebugString(PChar('[MGKIM] 일련번호(SerialNum): ' + Certificate.SerialNum));
OutputDebugString(PChar('[MGKIM] 인증서 정보 끝 ---'));
Accepted := True;
end;
@ -1446,45 +1494,40 @@ function CheckServerConnection(const AUrl: string): Boolean;
var
Client: THTTPClient;
Response: IHTTPResponse;
Validator: TCertValidator; // 더미 클래스 변수 추가
Validator: TCertValidator;
begin
Result := False;
Validator := TCertValidator.Create; // 이벤트 처리용 객체 생성
// HTTP 클라이언트 객체 생성
Client := THTTPClient.Create;
try
// [핵심] 연결 시도 중 UI가 영원히 멈추는 것을 방지하기 위한 타임아웃 설정 (밀리초)
Client.ConnectionTimeout := 3000; // 3초 내에 연결 안 되면 포기
Client.ResponseTimeout := 3000; // 연결 후 3초 내에 응답 없으면 포기
Validator := TCertValidator.Create;
try // Validator 보호용 try 추가
Client := THTTPClient.Create;
try
Client.ConnectionTimeout := 3000;
Client.ResponseTimeout := 3000;
Client.OnValidateServerCertificate := Validator.DoValidateServerCertificate;
Client.OnValidateServerCertificate := Validator.DoValidateServerCertificate;
try
// GET 방식 요청
Response := Client.Get(AUrl);
// GET 방식 요청
Response := Client.Get(AUrl);
// 서버가 정상적으로 응답했는지 상태 코드 확인 (200 = OK)
// *참고: 웹 서버가 켜져있다는 것 자체만 확인하려면 Response가 돌아온 것만으로도 True를 줄 수 있습니다.
if Response.StatusCode = 200 then
Result := True
else
begin
// 404(Not Found)나 500(Server Error) 등이 발생했을 때의 처리
// _Trace(Format('서버 응답 오류: %d', [Response.StatusCode]));
OutputDebugString(PChar(Format('[MGKIM] 서버 응답 오류: %d', [Response.StatusCode])));
Result := False;
end;
except
on E: Exception do
begin
// 타임아웃, 네트워크 단절, 서버 다운 등의 경우 이곳으로 빠집니다.
// _Trace('접속 실패: ' + E.Message);
OutputDebugString(PChar('[MGKIM] 접속 실패: ' + E.Message));
Result := False;
if Response.StatusCode = 200 then
Result := True
else
begin
OutputDebugString(PChar(Format('[MGKIM] 서버 응답 오류: %d', [Response.StatusCode])));
end;
except
on E: Exception do
begin
OutputDebugString(PChar('[MGKIM] 접속 실패: ' + E.Message));
end;
end;
finally
Client.Free;
end;
finally
Client.Free;
Validator.Free;
end;
end;
@ -1990,17 +2033,21 @@ begin
if not chkIPCheck.Checked then
begin
MessageBox(Handle, '서버 접속 확인을 해주세요.', PChar(Caption), MB_ICONWARNING or MB_OK);
chkIPCheck.SetFocus;
exit;
end;
if edtIPAddress.Text = '' then
begin
MessageBox(Handle, 'IP 정보를 입력해주세요', PChar(Caption), MB_ICONWARNING or MB_OK);
edtIPAddress.SetFocus;
exit;
end;
if edtPort.Text = '' then
begin
MessageBox(Handle, '포트 정보를 입력해주세요', PChar(Caption), MB_ICONWARNING or MB_OK);
edtPort.SetFocus;
exit;
end;

View File

@ -455,22 +455,22 @@ begin
var ExitCode: DWORD;
if GetExitCodeProcess(processHandle, ExitCode) then
begin
if ExitCode = 0 then
begin
// [상황 A] 정상적으로 스스로 종료됨
// 재실행하지 않고 루프를 끝내거나 대기할 수 있습니다.
end
else if ExitCode = 1 then
begin
// [상황 B] 누군가 강제 종료(1)했거나 크래시(비정상 코드)로 죽음
// 강제 종료로 간주하고 즉시 재실행 또는 시스템 재부팅!
ForceRebootSystem;
end;
OutputDebugString(PChar(Format('[MGKIM] ServiceExecute() .. Terminate Process ExitCode : %x',[ExitCode])));
if ExitCode = 0 then
begin
// [상황 A] 정상적으로 스스로 종료됨
// 재실행하지 않고 루프를 끝내거나 대기할 수 있습니다.
end
else if ExitCode = 1 then
begin
// [상황 B] 누군가 강제 종료(1)했거나 크래시(비정상 코드)로 죽음
// 강제 종료로 간주하고 즉시 재실행 또는 시스템 재부팅!
ForceRebootSystem;
end;
Sleep(3000);
{$IFDEF DEBUG} TTgTrace.T(Format('ServiceExecute() .. Terminate Process ExitCode : %x',[ExitCode])); {$ENDIF}
CloseHandle(ProcessInfo.hProcess);
processHandle := 0;
end;

View File

@ -4,7 +4,7 @@
<ProjectVersion>20.3</ProjectVersion>
<FrameworkType>VCL</FrameworkType>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Config Condition="'$(Config)'==''">Release</Config>
<Platform Condition="'$(Platform)'==''">Win64</Platform>
<TargetedPlatforms>3</TargetedPlatforms>
<AppType>Library</AppType>
@ -67,6 +67,12 @@
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win64)'!=''">
<Cfg_2_Win64>true</Cfg_2_Win64>
<CfgParent>Cfg_2</CfgParent>
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\_OUT_Object\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>..\OUT_$(Config) - $(Platform)</DCC_ExeOutput>
@ -143,6 +149,14 @@
<Manifest_File>(None)</Manifest_File>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Build>1</VerInfo_Build>
<VerInfo_Locale>1033</VerInfo_Locale>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.1;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.1;Comments=</VerInfo_Keys>
<Manifest_File>(None)</Manifest_File>
<AppDPIAwarenessMode>none</AppDPIAwarenessMode>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>

View File

@ -3,7 +3,7 @@
interface
const
BUILD_DT = '2026-03-24 16:04:51';
BUILD_DT = '2026-03-25 18:24:05';
implementation

View File

@ -2476,6 +2476,7 @@ begin
ETgException.TraceException(Self, E, 'Fail .. tInitTimer() .. ProcIni');
end;
TTgTrace.T('[MGKIM] tInitTimer()', 1);
MgSvc_ := TManagerService.Create(Handle);
// if GetProcessPidByName(EXE_MG) <> 0 then
begin

View File

@ -206,7 +206,7 @@ resourcestring
RS_UsbToUsbToothFIleNew = 'USB To Usb 파일 차단';
RS_CdromToothFIleNew = 'Cdrom 파일 차단';
RS_MtpToothFIleNew = 'MTP 파일 차단';
RS_UsbDevBlock = 'USB 장치 차단';
{$R *.dfm}
@ -774,6 +774,12 @@ begin
// pkWater : AddEnt(pNode, RS_PrinterCut, RS_UseFWater);
end;
AddEnt(pNode, RS_PrinterWater, BooleanToStr(PO.Print.PrintWater = pwActive, 'ON', 'OFF'));
if PO.IntUsbDevBlock.use then
AddEnt(pNode, RS_UsbDevBlock, 'ON')
else
AddEnt(pNode, RS_UsbDevBlock, 'OFF');
case PO.UsbBlockKind of
ubkNone : AddEnt(pNode, RS_USBCut, 'OFF');
ubkBlock : AddEnt(pNode, RS_USBCut, 'ON');
@ -944,6 +950,7 @@ begin
abkLog : AddEnt(pNode, RS_MtpToothFIleNew, '로그 수집');
end;
// 화면 및 클립보드 설정
pNode := AddEnt(nil, RS_ScreenLogoSet, '');
case PO.ClipBlockKind of

View File

@ -1543,6 +1543,11 @@ begin
if not LoadInjectionDriver(BS1HOOK_DRIVERTAG, BS1HOOK_DRIVERNAME32, BS1HOOK_DRIVERNAME64) then
begin
_Trace(Format('[BS1HOOK] loading driver failed error....(%d)', [GetLastError]));
DVLOG('loading driver failed error....(%d)', [GetLastError]);
end
else
begin
DVLOG(' %s loading driver success', [BS1HOOK_DRIVERTAG]);
end;
sConfDir := GetRunExePathDir + DIR_CONF;
@ -1561,7 +1566,12 @@ begin
if not CopyFile(PChar(sConfDir + DLL_HOOK32), PChar(sDataDir + DLL_HOOK32), false) then
begin
_Trace('[BS1HOOK] Fail .. copyFile(1)');
DVLOG('Fail .. copyFile(1)....(%d)', [GetLastError]);
exit;
end
else
begin
DVLOG('copyFile(1)....ok', []);
end;
end;
@ -1570,7 +1580,12 @@ begin
if not CopyFile(PChar(sConfDir + DLL_HOOK), PChar(sDataDir + DLL_HOOK), false) then
begin
_Trace('[BS1HOOK] Fail .. copyFile(2)');
DVLOG('Fail .. copyFile(2)....(%d)', [GetLastError]);
exit;
end
else
begin
DVLOG('copyFile(2)....ok', []);
end;
end;

View File

@ -622,6 +622,8 @@ type
IntCdromBlockNewFile,
IntMtpBlockNewFile: TIntBlockNewFile;
IntUsbDevBlock: TIntUsbDevBlock;
IgnoreDriverLoad: Boolean;
Constructor Create(sPoName: String; bLoad: Boolean = true; bSaveAble: Boolean = true);
@ -1699,7 +1701,7 @@ begin
if ForceDirectories(sDir) then
plainText.SaveToFile(sDir + Format('%s-%s_painText%s', [NAME_PREF, sPoFName_, EXT_PROP]));
_Trace('정책 저장 : %s' ,[sDir + Format('%s-%s%s', [NAME_PREF, sPoFName_, EXT_PROP])], 1);
// _Trace('정책 저장 : %s' ,[sDir + Format('%s-%s%s', [NAME_PREF, sPoFName_, EXT_PROP])], 1);
end else
if ORecent_ <> nil then
@ -2216,6 +2218,52 @@ function TPrefModel.LoadFromJsonObj(aO: ISuperObject; CP: Boolean): Boolean;
end;
end;
function GetIniUsbDevBlock(const sKeyName: string): TIntUsbDevBlock;
var
i: Integer;
O, OItem: ISuperObject;
sTemp, sVendor, sProduct, sSerial, sDevData: string;
begin
Result.use := False;
Result.noti := False;
Result.execList := '';
O := GetJsonObj(sKeyName);
if O = nil then Exit;
Result.use := O.B['use'];
Result.noti := O.B['noti'];
if (O.O['execList'] <> nil) and (O.O['execList'].DataType = stArray) then
begin
sTemp := '';
for i := 0 to O.A['execList'].Length - 1 do
begin
OItem := O.A['execList'].O[i];
if OItem <> nil then
begin
// 1. 값 읽어오기 및 양쪽 공백 제거
sVendor := Trim(OItem.S['vendor']);
sProduct := Trim(OItem.S['product']);
sSerial := Trim(OItem.S['serial']);
// 2. 빈 값이면 '*' (와일드카드)로 치환!
if sVendor = '' then sVendor := '*';
if sProduct = '' then sProduct := '*';
if sSerial = '' then sSerial := '*';
// 3. 벤더^제품명^시리얼 형태로 조립
sDevData := sVendor + '^' + sProduct + '^' + sSerial;
// 4. 파이프(|)로 기기들을 연결
SumString(sTemp, sDevData, '|');
end;
end;
Result.execList := sTemp;
end;
end;
var
sTemp: String;
i: Integer;
@ -3174,6 +3222,31 @@ begin
IntMtpBlockNewFile:= GetIniBlockFileNew('int_mtpBlockNewFile');
_Trace('Mtp 파일 차단 정책 시작 : mode : %d, content : %s',[Integer(IntMtpBlockNewFile.mode), IntMtpBlockNewFile.contentsFilter_list], 1);
// { int_usbDevBlock
// "use": true, // USB 차단 기능 사용 여부 (true | false)
// "noti": true, // 사용자 알림 수행 여부 (true | false)
// "execList": [
// {
// "vendor": "Kingston", // USB 장치 벤더명
// "product": "DataTraveler Exodia", // USB 장치 제품명
// "serial": "DTX-583920" // USB 장치 시리얼넘버
// },
// {
// "vendor": "Western Digital",
// "product": "My Passport",
// "serial": "WDP-102884"
// },
// {
// "vendor": "Sony",
// "product": "USM16GR",
// "serial": "SNY-441275"
// }
// ]
// }
IntUsbDevBlock:= GetIniUsbDevBlock('int_usbDevBlock');
bLoaded_ := true;
IsOldPolicy := false;
ProcessAfterSetPolicy;
@ -4632,7 +4705,7 @@ begin
Result.B['IsTempGroup'] := IsTempGroup;
// 블루투스 차단, USB, 파일 차단 기능 추가
_Trace('IntBtBlockNewFile mode :%d', [Integer(IntBtBlockNewFile.mode)], 1);
// _Trace('IntBtBlockNewFile mode :%d', [Integer(IntBtBlockNewFile.mode)], 1);
Result.O['IntBtBlockNewFile'] := TTgJson.ValueToJsonObject<TIntBlockNewFile>(IntBtBlockNewFile);
Result.O['IntUsbBlockNewFile'] := TTgJson.ValueToJsonObject<TIntBlockNewFile>(IntUsbBlockNewFile);
Result.O['IntUsbToUsbBlockNewFile'] := TTgJson.ValueToJsonObject<TIntBlockNewFile>(IntUsbToUsbBlockNewFile);
@ -5247,23 +5320,25 @@ begin
//mgkim 프로세스 시작 시 정책 읽어ㅏ야함..
IntBtBlockNewFile:= TTgJson.GetDataAsType<TIntBlockNewFile>(O['IntBtBlockNewFile']);
// IntBtBlockNewFile := GetBlockFileNew(O['int_btBlockNewFile']);
_Trace('블루 투스 파일 차단 정책 끝 : mode : %d',[Integer(IntBtBlockNewFile.mode)], 1);
// _Trace('블루 투스 파일 차단 정책 끝 : mode : %d',[Integer(IntBtBlockNewFile.mode)], 1);
IntUsbBlockNewFile:= TTgJson.GetDataAsType<TIntBlockNewFile>(O['IntUsbBlockNewFile']);
// IntUsbBlockNewFile := GetBlockFileNew(O['int_usbBlockNewFile']);
_Trace('Usb 차단 정책 끝 : mode : %d',[Integer(IntUsbBlockNewFile.mode)], 1);
// _Trace('Usb 차단 정책 끝 : mode : %d',[Integer(IntUsbBlockNewFile.mode)], 1);
IntUsbToUsbBlockNewFile:= TTgJson.GetDataAsType<TIntBlockNewFile>(O['IntUsbToUsbBlockNewFile']);
// IntUsbToUsbBlockNewFile := GetBlockFileNew(O['int_usbToUsbBlockNewFile']);
_Trace('Usb TO Usb 차단 정책 끝 : mode : %d',[Integer(IntUsbToUsbBlockNewFile.mode)], 1);
// _Trace('Usb TO Usb 차단 정책 끝 : mode : %d',[Integer(IntUsbToUsbBlockNewFile.mode)], 1);
IntCdromBlockNewFile:= TTgJson.GetDataAsType<TIntBlockNewFile>(O['IntCdromBlockNewFile']);
// IntCdromBlockNewFile := GetBlockFileNew(O['int_cdBlockNewFile']);
_Trace('Cdrom 차단 정책 끝 : mode : %d',[Integer(IntCdromBlockNewFile.mode)], 1);
// _Trace('Cdrom 차단 정책 끝 : mode : %d',[Integer(IntCdromBlockNewFile.mode)], 1);
IntMtpBlockNewFile:= TTgJson.GetDataAsType<TIntBlockNewFile>(O['IntMtpUsbBlockNewFile']);
// IntMtpBlockNewFile := GetBlockFileNew(O['int_mtpBlockNewFile']);
_Trace('Mtp 차단 정책 끝 : mode : %d',[Integer(IntMtpBlockNewFile.mode)], 1);
IntUsbDevBlock:= TTgJson.GetDataAsType<TIntUsbDevBlock>(O['IntUsbDevBlock']);
_Trace('SetPolicyFromJsonObj...ok (%s)', [PolicyName], 1);
SetOldDefault;
end;

View File

@ -229,7 +229,8 @@ type
ThdTaskTimer_,
ThdDevTaskTimer_, // 장치 차단이 오래 걸리는 경우가 있어서 별도 스레드 추가 25_1113 11:05:53 kku
ThdStatusTimer_: TThdTaskTimer;
ThdStatusTimer_,
ThdUsbDevTaskTimer_ : TThdTaskTimer; //mgkim USB Dev 차단 타이머 추가
sRecentUserSid_,
sAgentPatchVersion_: String;
@ -510,6 +511,7 @@ type
procedure SetModeName(sModeName: String);
function GetModeName: String;
procedure SendStartAgentAuditLog;
procedure TimerProcessUsbDevTask(aSender: TObject);
public
RecoverSvc_: TRecoverService;
AgentInfo: TCheckAgentInfo;
@ -779,6 +781,8 @@ function EmfToPng(const sEmfPath, sPngPath: string;
nDPI: Integer = 96; aBackColor: TColor = clWhite): Boolean;
function GetFileToSha1Str_BS1(sPath: String): String;
procedure DVLOG(const AFormat: string; const AArgs: array of const);
var
gMgSvc: TManagerService = nil;
@ -830,6 +834,34 @@ var
_CheckVpnProcs: String = '';
_CheckVpnList: TStringList = nil;
procedure DVLOG(const AFormat: string; const AArgs: array of const);
var
Header: string;
TimeStamp: string;
LogMessage: string;
FinalLog: string;
FinalLogAnsi: AnsiString;
begin
// if not gdebug_ then
// Exit;
Header:= '[MGKIM]';
try
LogMessage := Format(AFormat, AArgs);
except
on E: Exception do
LogMessage := '*** LOG FORMATTING ERROR: ' + E.Message + ' ***';
end;
FinalLog := Header + TimeStamp + LogMessage;
OutputDebugStringW(PChar(FinalLog));
end;
function GetDefAipLabelId(bEncCamp: Boolean = false): String;
begin
case CUSTOMER_TYPE of
@ -1134,12 +1166,13 @@ Constructor TManagerService.Create(hRcvHwnd: HWND);
var
LoginForm: TAuthForm;
begin
LoginForm := TAuthForm.Create(nil);
LoginForm.OnSuccess := ChangeLoginMode; // 성공했을때 호출할 함수 등록
LoginForm.sAgentId := sAgentId_;
LoginForm.sDestIPort := sDestIPort_;
LoginForm.Show;
LoginForm := TAuthForm.Create(nil);
LoginForm.OnSuccess := ChangeLoginMode; // 성공했을때 호출할 함수 등록
LoginForm.sAgentId := sAgentId_;
LoginForm.sDestIPort := sDestIPort_;
LoginForm.Show;
end;
procedure InitAgentInfo;
@ -1208,9 +1241,6 @@ Constructor TManagerService.Create(hRcvHwnd: HWND);
// AgentModel_.Save; 아래에서 함 22_0721 15:24:12 kku
end;
//[yhkim]
ExecuteLogin();
if CUSTOMER_TYPE = CUSTOMER_LOTTEMART then
begin
// 실행마다 NAC에서 유저 ID값 가져오기
@ -1297,7 +1327,8 @@ begin
SetRegValueInteger(HKEY_USERS, RecentUserSid + '\' + REG_HE, 'CT', CUSTOMER_TYPE, true);
SetRegValueString(HKEY_USERS, RecentUserSid + '\' + REG_HE, 'RW', IntToStr(hRcvHwnd), true);
agentStatTime_:= FormatDateTime('yyyy-mm-dd"T"hh:nn:ss"+09:00"', Now);
_Trace('에이전트 시작 시간: %s',[agentStatTime_], 1);
sTmpAcc_ := '';
FormatSettings.ShortDateFormat := 'YYYY-MM-DD';
FormatSettings.LongDateFormat := 'YYYY-MM-DD';
@ -1410,7 +1441,7 @@ begin
FileExpEntList_ := TFileExpEntList.Create;
FileExpEntList_.OnNotify := OnFileExpNotify;
LoadFileExpEnt;
_Trace('Create.. 0 step', 0);
sRecentLabel_ := '';
sScreenLogoChkApps_ := '';
sScreenLogoChkUrls_ := '';
@ -1452,6 +1483,7 @@ begin
ThdAppMon_ := nil;
xPrintLogService_ := nil;
sUtcOffset_ := '+00:00';
try
var TS: TTimeSpan := TTimeZone.Local.GetUtcOffset(Now);
@ -1515,6 +1547,7 @@ begin
MgPwe_ := TManagerPrtWaterExcept.Create;
// MgPwe_.AddFileHash('C:\Users\kku\Desktop\BSOne_OutTest.docx');
// MgCltFld_ := TManagerCltFld.Create;
_Trace('Create.. 1 step', 0);
sComName_ := GetComName;
@ -1551,7 +1584,7 @@ begin
bIsPatchUptoDate_ := true;
// bIsPatchUptoDate_ := false; // OS 패치 취약 테스트
bIsServiceAvailable_ := false;
_Trace('Create.. 2 step', 0);
HandleConfig_ := THandleConfig.Create;
HandleSecurity_ := THandleSecurity.Create(HandleConfig_.OsVersion);
@ -1676,6 +1709,7 @@ begin
end;
end;
_Trace('Create.. 3 step', 0);
InitAgentInfo;
bSchRstVul_ := false;
LoadSchRstVul;
@ -1712,8 +1746,7 @@ begin
DcFltCtrlEnt_ := TDictionary<String,String>.Create;
// IgnoreDriverLoad
agentStatTime_:= FormatDateTime('yyyy-mm-dd"T"hh:nn:ss"+09:00"', Now);
_Trace('에이전트 시작 시간: %s',[agentStatTime_], 1);
SendStartAgentAuditLog;
if UseFltCtrl then
@ -1808,6 +1841,11 @@ begin
ThdDevTaskTimer_.AddTask(TimerProcessDevTask, 500, true);
ThdDevTaskTimer_.StartTimerThread;
ThdUsbDevTaskTimer_ := TThdTaskTimer.Create(1000, true);
ThdUsbDevTaskTimer_.AddTask(TimerProcessUsbDevTask, 1000, true);
ThdUsbDevTaskTimer_.StartTimerThread;
ThdStatusTimer_ := TThdTaskTimer.Create(1000, true);
dwStatusInterval_ := 2000;
case CUSTOMER_TYPE of
@ -1921,20 +1959,25 @@ begin
var ini: TIniFile;
var bExeRecover: Boolean;
var sPath := GetProgramFilesDir + DIR_TG + INI_FORCEHE;
bExeRecover:= True;
if FileExists(sPath) then
begin
Guard(ini, TIniFile.Create(sPath));
bExeRecover := ini.ReadBool('Force', 'RecoverFile', true);
if bExeRecover then
begin
RecoverSvc_ := TRecoverService.Create;
RecoverSvc_.StartService;
TTgTrace.T('[MGKIM] RecoverSvc.. start', 2);
end;
end;
if bExeRecover then
begin
RecoverSvc_ := TRecoverService.Create;
RecoverSvc_.StartService;
TTgTrace.T('[MGKIM] RecoverSvc.. start', 2);
end;
//[yhkim]
_Trace('InitAgentInfo.. ExecuteLogin in', 0);
ExecuteLogin();
_Trace('InitAgentInfo.. ExecuteLogin out', 0);
end;
@ -5515,6 +5558,23 @@ begin
end;
end;
procedure TManagerService.TimerProcessUsbDevTask(aSender: TObject);
var
PO: TPrefModel;
begin
try
PO := GetModePolicy;
_Trace('[MGKIM] TimerProcessUsbDevTask .. use(%d), (%s)',[DWORD(PO.IntUsbDevBlock.use), PO.IntUsbDevBlock.execList]);
except
on E: Exception do
ETgException.TraceException(Self, E, 'Fail .. TimerProcessUsbDevTask()');
end;
end;
// BS1OutlookAddInClient.pas에서도 사용, 중요한 수정 시 함께 수정하도록.
procedure TManagerService.SetPatternList(sPatternOpt: String; var aList: TPatternEntList);
var

Some files were not shown because too many files have changed in this diff Show More