794 lines
21 KiB
C
794 lines
21 KiB
C
#include "precomp.h"
|
|
#include "usb.h"
|
|
#include "usbioctl.h"
|
|
#include "Usbdlib.h"
|
|
|
|
|
|
#pragma warning( disable : 4995 )
|
|
#pragma warning( disable : 4996 )
|
|
|
|
|
|
|
|
|
|
enum
|
|
{
|
|
usb_usbhub = 0,
|
|
usb_usbhub3 = 1,
|
|
usb_maximum = 2
|
|
};
|
|
|
|
static WCHAR* s_usbname[] =
|
|
{
|
|
L"\\Driver\\usbhub",
|
|
L"\\Driver\\usbhub3",
|
|
NULL
|
|
};
|
|
|
|
|
|
static BOOLEAN enable_usbhook = FALSE;
|
|
|
|
NTSTATUS USBPnpControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
|
NTSTATUS USBHookDispatch_0(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
|
NTSTATUS USBHookDispatch_3(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
|
|
|
|
|
static PDRIVER_DISPATCH s_ProxyDispatchers[usb_maximum] =
|
|
{
|
|
USBHookDispatch_0, // for usbhub
|
|
USBHookDispatch_3 // for usbhub3
|
|
};
|
|
|
|
|
|
//IRP_CORE USBIrpCore = { 0, };
|
|
|
|
|
|
|
|
#define USB_COMMON_HOOK_HANDLERS \
|
|
[IRP_MJ_PNP] = { NULL, IRP_MJ_PNP, TRUE, USBPnpControl }, \
|
|
/* 필요한 경우 아래처럼 추가하면 됩니다 */ \
|
|
/* [IRP_MJ_INTERNAL_DEVICE_CONTROL] = { NULL, IRP_MJ_INTERNAL_DEVICE_CONTROL, TRUE, MyInternalHandler }, */ \
|
|
/* [IRP_MJ_POWER] = { NULL, IRP_MJ_POWER, TRUE, MyPowerHandler }, */
|
|
|
|
/*
|
|
static IRP_HOOK_HANDLER USBIrpHookTemplate[] =
|
|
{
|
|
{NULL, IRP_MJ_CREATE, FALSE},
|
|
{NULL, IRP_MJ_CREATE_NAMED_PIPE, FALSE},
|
|
{NULL, IRP_MJ_CLOSE, FALSE},
|
|
{NULL, IRP_MJ_READ, FALSE},
|
|
{NULL, IRP_MJ_WRITE, FALSE},
|
|
{NULL, IRP_MJ_QUERY_INFORMATION, FALSE},
|
|
{NULL, IRP_MJ_SET_INFORMATION, FALSE},
|
|
{NULL, IRP_MJ_QUERY_EA, FALSE},
|
|
{NULL, IRP_MJ_SET_EA, FALSE},
|
|
{NULL, IRP_MJ_FLUSH_BUFFERS, FALSE},
|
|
{NULL, IRP_MJ_QUERY_VOLUME_INFORMATION, FALSE},
|
|
{NULL, IRP_MJ_SET_VOLUME_INFORMATION, FALSE},
|
|
{NULL, IRP_MJ_DIRECTORY_CONTROL, FALSE},
|
|
{NULL, IRP_MJ_FILE_SYSTEM_CONTROL, FALSE},
|
|
{NULL, IRP_MJ_DEVICE_CONTROL, FALSE},
|
|
{NULL, IRP_MJ_INTERNAL_DEVICE_CONTROL, FALSE},
|
|
{NULL, IRP_MJ_SHUTDOWN, FALSE},
|
|
{NULL, IRP_MJ_LOCK_CONTROL, FALSE},
|
|
{NULL, IRP_MJ_CLEANUP, FALSE},
|
|
{NULL, IRP_MJ_CREATE_MAILSLOT, FALSE},
|
|
{NULL, IRP_MJ_QUERY_SECURITY, FALSE},
|
|
{NULL, IRP_MJ_SET_SECURITY, FALSE},
|
|
{NULL, IRP_MJ_POWER, FALSE},
|
|
{NULL, IRP_MJ_SYSTEM_CONTROL, FALSE},
|
|
{NULL, IRP_MJ_DEVICE_CHANGE, FALSE},
|
|
{NULL, IRP_MJ_QUERY_QUOTA, FALSE},
|
|
{NULL, IRP_MJ_SET_QUOTA, FALSE},
|
|
{NULL, IRP_MJ_PNP, TRUE, USBPnpControl}
|
|
};
|
|
*/
|
|
|
|
|
|
//static USB_HOOK_CONTEXT g_HookContexts[usb_maximum];
|
|
|
|
static HOOK_CONTEXT g_HookContexts[usb_maximum] =
|
|
{
|
|
// Index 0: usbhub용 컨텍스트 초기화
|
|
{
|
|
NULL, // DriverObject (나중에 Init에서 채움)
|
|
FALSE, // IsHooked
|
|
0,
|
|
{ // HookHandlers 배열 (나머지는 자동으로 0/NULL 초기화됨)
|
|
USB_COMMON_HOOK_HANDLERS
|
|
}
|
|
},
|
|
|
|
// Index 1: usbhub3용 컨텍스트 초기화
|
|
{
|
|
NULL, // DriverObject
|
|
FALSE, // IsHooked
|
|
0,
|
|
{ // HookHandlers 배열
|
|
USB_COMMON_HOOK_HANDLERS
|
|
}
|
|
}
|
|
};
|
|
|
|
#define USBLock() InterlockedIncrement((volatile LONG *)&g_HookContexts[usb_usbhub].IrpEnterCount);
|
|
#define USBUnLock() InterlockedDecrement((volatile LONG *)&g_HookContexts[usb_usbhub].IrpEnterCount);
|
|
#define USBLock3() InterlockedIncrement((volatile LONG *)&g_HookContexts[usb_usbhub3].IrpEnterCount);
|
|
#define USBUnLock3() InterlockedDecrement((volatile LONG *)&g_HookContexts[usb_usbhub3].IrpEnterCount);
|
|
|
|
|
|
//static ULONG GetIrpHookHandlerCount()
|
|
//{
|
|
// return sizeof(USBIrpHookTemplate) / sizeof(IRP_HOOK_HANDLER);
|
|
//}
|
|
|
|
|
|
static BOOLEAN IsAdrIrpHookHandler(PIRP_HOOK_HANDLER pIrpH, ULONG id)
|
|
{
|
|
if (!pIrpH[id].IsHook)
|
|
return FALSE;
|
|
|
|
if (!MmIsAddressValid((PVOID)pIrpH[id].pOrgHandler))
|
|
return FALSE;
|
|
|
|
if (!pIrpH[id].pOrgHandler)
|
|
return FALSE;
|
|
|
|
if (!pIrpH[id].Work)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
static BOOLEAN IsOwnDeviceObject(PDEVICE_OBJECT DevcieObject)
|
|
{
|
|
if (DevcieObject == g_bs1Flt.DriverObject->DeviceObject)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
NTSTATUS UDF_CallUSBDI(IN PDEVICE_OBJECT pDevObj, IN PVOID UrbEtc)
|
|
{
|
|
IO_STATUS_BLOCK IoStatus;
|
|
KEVENT event;
|
|
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);
|
|
|
|
// 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");
|
|
status = KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
|
|
status = IoStatus.Status;
|
|
}
|
|
|
|
// return IRP completion status
|
|
KLogEx(DEBUG_TRACE_ERROR, "returned %x", status);
|
|
return status;
|
|
}
|
|
*/
|
|
|
|
BOOLEAN IsDefineDeviceClass(enum_usb_device_type deviceclass)
|
|
{
|
|
//BOOLEAN state = FALSE;
|
|
|
|
if (
|
|
//deviceclass == TUSB_CLASS_HID
|
|
//|| deviceclass == TUSB_CLASS_PRINTER
|
|
deviceclass == BDC_USB_CLASS_HUB
|
|
//|| deviceclass == TUSB_CLASS_AUDIO
|
|
//|| deviceclass == TUSB_CLASS_VIDEO
|
|
)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
NTSTATUS USBPnpControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION irpstack = IoGetCurrentIrpStackLocation(Irp);
|
|
ULONG minor = irpstack->MinorFunction;
|
|
ULONG state = 0;
|
|
UNICODE_STRING processImagePath = { 0, };
|
|
ULONG ProcessId = 0;
|
|
ULONG policyLog = 0;
|
|
//WCHAR* process_name = NULL;
|
|
//PURB urb = NULL;
|
|
//PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
|
|
//USB_STRING_DESCRIPTOR USD, * pFullUSD = NULL;
|
|
//ULONG size = 0;
|
|
char szProcessName[20] = { 0, };
|
|
PUSB_PARSED_INFO pUsbInfo = NULL;
|
|
|
|
if (!g_bs1Flt.IsAttached)
|
|
goto $USBCleanup;
|
|
|
|
if (!enable_usbhook)
|
|
goto $USBCleanup;
|
|
|
|
ProcessId = HandleToULong(PsGetCurrentProcessId());
|
|
UGetProcessName(szProcessName);
|
|
|
|
state = GetPolicyState(BDC_USB);
|
|
policyLog = IsPolicyLog(BDC_USB);
|
|
|
|
if (minor == IRP_MN_START_DEVICE)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, " IRP_MN_START_DEVICE (%d)(%s)\n", ProcessId, szProcessName);
|
|
|
|
status = CollectUsbDeviceInfo(DeviceObject, &pUsbInfo);
|
|
if (NT_SUCCESS(status) && pUsbInfo)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "USB Connected: DeviceClass(%d), DeviceSubClass(%d), bDeviceProtocol(%d), VID=0x%04X, PID=0x%04X\n",
|
|
pUsbInfo->DeviceDesc.bDeviceClass,
|
|
pUsbInfo->DeviceDesc.bDeviceSubClass,
|
|
pUsbInfo->DeviceDesc.bDeviceProtocol,
|
|
pUsbInfo->DeviceDesc.idVendor,
|
|
pUsbInfo->DeviceDesc.idProduct
|
|
);
|
|
|
|
if (IsDefineDeviceClass(pUsbInfo->DeviceDesc.bDeviceClass))
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "define deviceclass (%d)\n", pUsbInfo->DeviceDesc.bDeviceClass);
|
|
goto $USBCleanup;
|
|
}
|
|
|
|
//if (pUsbInfo->ProductStr)
|
|
//{
|
|
// KLogEx(DEBUG_TRACE_INFO, " Product: %S\n", pUsbInfo->ProductStr);
|
|
//}
|
|
|
|
if (pUsbInfo->SerialNumberStr)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, " Serial: %S\n", pUsbInfo->SerialNumberStr);
|
|
}
|
|
|
|
PrintUsbParsedInfo(pUsbInfo);
|
|
|
|
//if (pUsbInfo->ConfigDesc && pUsbInfo->ConfigDescSize > 0)
|
|
//{
|
|
// PUSB_CONFIGURATION_DESCRIPTOR pConfigDesc = pUsbInfo->ConfigDesc;
|
|
// PUCHAR pCurr = (PUCHAR)pConfigDesc;
|
|
// PUCHAR pEnd = pCurr + pConfigDesc->wTotalLength;
|
|
|
|
// 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;
|
|
|
|
// 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]");
|
|
// 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
|
|
// );
|
|
// }
|
|
|
|
// pCurr += pCommon->bLength;
|
|
// }
|
|
//}
|
|
|
|
//if (pUsbInfo->HidInterfaceCount > 0)
|
|
//{
|
|
// ULONG i;
|
|
// KLogEx(DEBUG_TRACE_INFO, " Total HID Interfaces Found: %d\n", pUsbInfo->HidInterfaceCount);
|
|
|
|
// for (i = 0; i < pUsbInfo->HidInterfaceCount; i++)
|
|
// {
|
|
// HID_INTERFACE_ENTRY* pEntry = &pUsbInfo->HidEntries[i];
|
|
// PUSB_HID_DESCRIPTOR pHid = pEntry->HidDesc;
|
|
|
|
// 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)
|
|
{
|
|
if(!IsUsbPolicyDisable(pUsbInfo->DeviceDesc.bDeviceClass))
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "usb policy disable\n");
|
|
state = ENABLE;
|
|
}
|
|
else if (IsUsbPortExceptionList(BDC_USB, pUsbInfo->DeviceDesc.idVendor, pUsbInfo->DeviceDesc.idProduct, pUsbInfo->DeviceDesc.bcdDevice, pUsbInfo->SerialNumberStr))
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "user usb policy exception\n");
|
|
state = ENABLE;
|
|
//goto $USBCleanup;
|
|
}
|
|
}
|
|
|
|
if (policyLog)
|
|
{
|
|
WCHAR notice[MAX_PATH] = { 0, };
|
|
WCHAR processName[50] = { 0, };
|
|
ULONG DeviceClass = 0;
|
|
|
|
if (pUsbInfo)
|
|
{
|
|
RtlStringCbPrintfW(notice, sizeof(notice), L"DeviceClass : %d, DeviceSubClass : %d, DeviceProtocol : %d, Vid: 0x%04X, Pid : 0x%04X, Serial : %s",
|
|
pUsbInfo->DeviceDesc.bDeviceClass,
|
|
pUsbInfo->DeviceDesc.bDeviceSubClass,
|
|
pUsbInfo->DeviceDesc.bDeviceProtocol,
|
|
pUsbInfo->DeviceDesc.idVendor,
|
|
pUsbInfo->DeviceDesc.idProduct,
|
|
pUsbInfo->SerialNumberStr
|
|
);
|
|
|
|
DeviceClass = pUsbInfo->DeviceDesc.bDeviceClass;
|
|
}
|
|
else
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "pUsbInfo invaild pointer\n");
|
|
RtlStringCbPrintfW(notice, sizeof(notice), L"pUsbInfo invaild pointer");
|
|
|
|
}
|
|
|
|
RtlStringCbPrintfW(processName, sizeof(processName), L"%S", szProcessName);
|
|
SetLog(NULL, NULL, LOG_POLICY, BDC_USB, state, DeviceClass, processName, notice);
|
|
|
|
}
|
|
|
|
if (state == DISABLE && pUsbInfo)
|
|
{
|
|
FreeUsbDeviceInfo(pUsbInfo);
|
|
pUsbInfo = NULL;
|
|
KLogEx(DEBUG_TRACE_INFO, "STATUS_ACCESS_DENIED!!!!!!\n");
|
|
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
FreeUsbDeviceInfo(pUsbInfo);
|
|
pUsbInfo = NULL;
|
|
}
|
|
else if (minor == IRP_MN_REMOVE_DEVICE)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, " IRP_MN_REMOVE_DEVICE\n");
|
|
goto $USBCleanup;
|
|
}
|
|
else
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, " minor(%0x)\n", minor);
|
|
goto $USBCleanup;
|
|
}
|
|
|
|
$USBCleanup:
|
|
FreeUsbDeviceInfo(pUsbInfo);
|
|
UStrFree(&processImagePath);
|
|
return dispath(DeviceObject, Irp);
|
|
|
|
}
|
|
|
|
NTSTATUS USBHookDispatch_Common(ULONG ContextIndex, PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION pCurrentIoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
ULONG Id = pCurrentIoStack->MajorFunction;
|
|
PHOOK_CONTEXT pCtx = NULL;
|
|
PDRIVER_DISPATCH pOrgHandler = NULL;
|
|
|
|
// 인덱스 유효성 검사 (방어 코드)
|
|
if (ContextIndex >= usb_maximum)
|
|
{
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
// 1. 인덱스로 바로 컨텍스트 접근
|
|
pCtx = &g_HookContexts[ContextIndex];
|
|
|
|
// 2. 후킹 유효성 검사
|
|
if (pCtx->IsHooked &&
|
|
pCtx->HookHandlers[Id].IsHook &&
|
|
pCtx->HookHandlers[Id].Work)
|
|
{
|
|
pOrgHandler = pCtx->HookHandlers[Id].pOrgHandler;
|
|
|
|
// 3. Work 함수 실행 (USBPnpControl 등)
|
|
NtStatus = pCtx->HookHandlers[Id].Work(
|
|
pOrgHandler,
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// 여기로 오면 안 되지만, 만약 오면 실패 처리 혹은 원본 호출 시도 불가
|
|
NtStatus = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
return NtStatus;
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// [별도 Dispatcher] 각 드라이버별 전용 함수
|
|
// ---------------------------------------------------------
|
|
|
|
// usbhub용 (Index 0)
|
|
NTSTATUS USBHookDispatch_0(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
USBLock();
|
|
status = USBHookDispatch_Common(usb_usbhub, DeviceObject, Irp);
|
|
USBUnLock();
|
|
return status;
|
|
}
|
|
|
|
// usbhub3용 (Index 1)
|
|
NTSTATUS USBHookDispatch_3(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
USBLock3();
|
|
status = USBHookDispatch_Common(usb_usbhub3, DeviceObject, Irp);
|
|
USBUnLock3();
|
|
return status;
|
|
}
|
|
|
|
|
|
//NTSTATUS USBHookDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
//{
|
|
//
|
|
// NTSTATUS NtStatus = STATUS_SUCCESS;
|
|
// PIO_STACK_LOCATION pCurrentIoStack = IoGetCurrentIrpStackLocation(Irp);
|
|
// ULONG Id = pCurrentIoStack->MajorFunction;
|
|
//
|
|
// USBLock();
|
|
//
|
|
// if (IsAdrIrpHookHandler(USBIrpHook, Id))
|
|
// {
|
|
// NtStatus = USBIrpHook[Id].Work(
|
|
// USBIrpHook[Id].pOrgHandler,
|
|
// DeviceObject,
|
|
// Irp
|
|
// );
|
|
// }
|
|
// USBUnLock();
|
|
//
|
|
// return NtStatus;
|
|
//
|
|
//}
|
|
|
|
|
|
//static PVOID GetHookDispatch()
|
|
//{
|
|
// return (PVOID)USBHookDispatch;
|
|
//}
|
|
//
|
|
//static PIRP_HOOK_HANDLER GetIrpHookHandler()
|
|
//{
|
|
// return USBIrpHook;
|
|
//}
|
|
|
|
//static PIRP_CORE GetIrpCore()
|
|
//{
|
|
// USBIrpCore.HookDispatch = GetHookDispatch();
|
|
// USBIrpCore.IrpHookHandler = GetIrpHookHandler();
|
|
// USBIrpCore.IrpHookHandlerCount = GetIrpHookHandlerCount();
|
|
// USBIrpCore.IrpEnterCount = 0;
|
|
// return &USBIrpCore;
|
|
//}
|
|
|
|
//NTSTATUS USBIrpHookCleanup()
|
|
//{
|
|
// ULONG cnt = 0;
|
|
// //ULONG OrSaveWP;
|
|
// LARGE_INTEGER WaitTime;
|
|
// PDRIVER_OBJECT DriverObject = USBIrpCore.HookDriverObject;
|
|
// ULONG IrpHookHandlerCount = USBIrpCore.IrpHookHandlerCount;
|
|
// PIRP_HOOK_HANDLER pIhh = USBIrpCore.IrpHookHandler;
|
|
//
|
|
// if (!DriverObject || !IrpHookHandlerCount || !pIhh)
|
|
// return STATUS_UNSUCCESSFUL;
|
|
//
|
|
// if (!pIhh)
|
|
// return STATUS_UNSUCCESSFUL;
|
|
//
|
|
// enable_usbhook = FALSE;
|
|
// for (cnt = 0; cnt < IrpHookHandlerCount; ++cnt)
|
|
// {
|
|
// if (!pIhh[cnt].IsHook)
|
|
// continue;
|
|
//
|
|
// if (pIhh[cnt].pOrgHandler == NULL)
|
|
// continue;
|
|
//
|
|
// InterlockedExchangePointer((PVOID)&DriverObject->MajorFunction[cnt], (PVOID)pIhh[cnt].pOrgHandler);
|
|
// //DbgPrint("unhook a %x %x\n",DriverObject->MajorFunction[cnt], pIhh[cnt].pOrgHandler);
|
|
// }
|
|
//
|
|
// WaitTime.QuadPart = -1 * 10 * 1000 * 1000;
|
|
//
|
|
// while (USBIrpCore.IrpEnterCount > 0)
|
|
// KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);
|
|
//
|
|
// KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);
|
|
// KLogEx(DEBUG_TRACE_INFO, "complete\n");
|
|
//
|
|
// return STATUS_SUCCESS;
|
|
//}
|
|
//
|
|
//NTSTATUS USBIrpHookInit()
|
|
//{
|
|
// WCHAR* name = NULL;
|
|
// ULONG cnt = 0;
|
|
// ULONG IrpHookHandlerCount = 0;
|
|
// PIRP_HOOK_HANDLER pIhh = NULL;
|
|
// PIRP_CORE irpcore = NULL;
|
|
// PDRIVER_OBJECT obj = NULL;
|
|
//
|
|
// //for (size_t i = 0; i < usb_maximum; i++)
|
|
// //{
|
|
// name = s_usbname[usb_usbhub3];
|
|
// KLogEx(DEBUG_TRACE_INFO, "driver(%S)\n", name);
|
|
// obj = SearchDriverObject(name);
|
|
// if (!obj)
|
|
// {
|
|
// KLogEx(DEBUG_TRACE_ERROR, "not find object (%S)\n", name);
|
|
// return STATUS_UNSUCCESSFUL;
|
|
// }
|
|
//
|
|
// irpcore = (PIRP_CORE)GetIrpCore();
|
|
// if (!irpcore)
|
|
// return STATUS_UNSUCCESSFUL;
|
|
//
|
|
// irpcore->HookDriverObject = obj;
|
|
// //KLog("hook init %p %p %p\n",irpcore->HookDriverObject,irpcore->HookDriverObject->DriverStart,irpcore->HookDriverObject->DriverSize);
|
|
//
|
|
// IrpHookHandlerCount = irpcore->IrpHookHandlerCount;
|
|
// pIhh = irpcore->IrpHookHandler;
|
|
// if (!pIhh)
|
|
// return STATUS_UNSUCCESSFUL;
|
|
//
|
|
// for (; cnt < IrpHookHandlerCount; ++cnt)
|
|
// {
|
|
// if (!pIhh[cnt].IsHook)
|
|
// continue;
|
|
//
|
|
// if (irpcore->HookDriverObject->MajorFunction[cnt] == irpcore->HookDispatch)
|
|
// continue;
|
|
//
|
|
// pIhh[cnt].pOrgHandler = irpcore->HookDriverObject->MajorFunction[cnt];
|
|
// if (pIhh[cnt].pOrgHandler == NULL)
|
|
// continue;
|
|
//
|
|
// if (pIhh[cnt].Work == NULL)
|
|
// continue;
|
|
//
|
|
// if (irpcore->HookDriverObject->DriverStart > (PVOID)irpcore->HookDriverObject->MajorFunction[cnt] ||
|
|
// GetPtr(irpcore->HookDriverObject->DriverStart, irpcore->HookDriverObject->DriverSize) < (PVOID)irpcore->HookDriverObject->MajorFunction[cnt])
|
|
// {
|
|
// KLogEx(DEBUG_TRACE_INFO, "exist hook c(%p)\n", irpcore->HookDriverObject->MajorFunction[cnt]);
|
|
// }
|
|
//
|
|
// InterlockedExchangePointer((PVOID)&irpcore->HookDriverObject->MajorFunction[cnt], (PVOID)irpcore->HookDispatch);
|
|
// KLogEx(DEBUG_TRACE_INFO, "hook c (%S), (%d), (%p), (%p)\n", name, cnt, (PVOID)pIhh[cnt].pOrgHandler, (PVOID)irpcore->HookDriverObject->MajorFunction[cnt]);
|
|
// enable_usbhook = TRUE;
|
|
// }
|
|
// //}
|
|
// KLogEx(DEBUG_TRACE_INFO, "complete\n");
|
|
// return STATUS_SUCCESS;
|
|
//}
|
|
|
|
|
|
NTSTATUS USBIrpHookInit()
|
|
{
|
|
WCHAR* name = NULL;
|
|
ULONG i, mi;
|
|
PDRIVER_OBJECT obj = NULL;
|
|
PHOOK_CONTEXT hook = NULL;
|
|
|
|
// g_HookContexts는 이미 컴파일 타임에 HookHandlers 정보가 채워져 있으므로
|
|
// memset 초기화나 템플릿 복사 루프가 필요 없습니다.
|
|
|
|
for (i = 0; i < usb_maximum; i++)
|
|
{
|
|
hook = &g_HookContexts[i];
|
|
|
|
// 이미 훅 상태면 패스
|
|
if (hook->IsHooked) continue;
|
|
|
|
name = s_usbname[i];
|
|
if (name == NULL) continue;
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "Target driver(%S)\n", name);
|
|
|
|
obj = SearchDriverObject(name);
|
|
if (!obj)
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "Not found object (%S)\n", name);
|
|
continue;
|
|
}
|
|
|
|
hook->DriverObject = obj;
|
|
|
|
for (mi = 0; mi < IRP_MJ_MAXIMUM_FUNCTION + 1; mi++)
|
|
{
|
|
// 컴파일 타임에 설정된 IsHook 값을 확인
|
|
if (!hook->HookHandlers[mi].IsHook)
|
|
continue;
|
|
|
|
// 이미 후킹되었는지 확인
|
|
if (obj->MajorFunction[mi] == s_ProxyDispatchers[i])
|
|
continue;
|
|
|
|
// 원본 백업
|
|
hook->HookHandlers[mi].pOrgHandler = obj->MajorFunction[mi];
|
|
|
|
if (hook->HookHandlers[mi].pOrgHandler == NULL)
|
|
continue;
|
|
|
|
// 주소 교체
|
|
InterlockedExchangePointer((PVOID)&obj->MajorFunction[mi],(PVOID)s_ProxyDispatchers[i]);
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "[Hook] %S MJ:%d Org:%p New:%p\n",
|
|
name, mi, hook->HookHandlers[mi].pOrgHandler, s_ProxyDispatchers[i]);
|
|
}
|
|
|
|
hook->IsHooked = TRUE;
|
|
enable_usbhook = TRUE;
|
|
}
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "complete\n");
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
NTSTATUS USBIrpHookCleanup()
|
|
{
|
|
ULONG i, mi;
|
|
LARGE_INTEGER WaitTime;
|
|
PHOOK_CONTEXT hook = NULL;
|
|
PDRIVER_DISPATCH pCurrentHandler = NULL;
|
|
|
|
// 1. 더 이상 새로운 훅 로직이 타지 않도록 플래그 비활성화
|
|
enable_usbhook = FALSE;
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "Started...\n");
|
|
|
|
for (i = 0; i < usb_maximum; i++)
|
|
{
|
|
hook = &g_HookContexts[i];
|
|
|
|
// 후킹된 적이 없거나 드라이버 객체가 없으면 스킵
|
|
if (!hook->IsHooked || !hook->DriverObject)
|
|
continue;
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "Unhooking Driver Index: %d\n", i);
|
|
|
|
// 3. IRP Major Function 테이블 복원
|
|
for (mi = 0; mi <= IRP_MJ_MAXIMUM_FUNCTION; mi++)
|
|
{
|
|
// 우리가 후킹하려고 했던 대상인지 확인
|
|
if (!hook->HookHandlers[mi].IsHook)
|
|
continue;
|
|
|
|
// 원본 함수 포인터가 유효한지 확인
|
|
if (hook->HookHandlers[mi].pOrgHandler == NULL)
|
|
continue;
|
|
|
|
// [중요] 현재 드라이버의 핸들러가 우리 프록시 함수(USBHookDispatch_X)인지 확인
|
|
// 만약 다른 드라이버가 그 위에 또 후킹했다면, 우리가 원본으로 되돌리면 안 될 수도 있음
|
|
// 하지만 보통 언로드 시점에는 강제로라도 원본으로 복구하는 것이 일반적임.
|
|
// 여기서는 무조건 복구하는 방식으로 진행 (InterlockedExchangePointer 사용)
|
|
|
|
pCurrentHandler = (PDRIVER_DISPATCH)InterlockedExchangePointer(
|
|
(PVOID)&hook->DriverObject->MajorFunction[mi],
|
|
(PVOID)hook->HookHandlers[mi].pOrgHandler
|
|
);
|
|
|
|
hook->HookHandlers[mi].pOrgHandler = NULL;
|
|
// 디버깅용: 교체된 주소가 우리 함수였는지 확인
|
|
/*
|
|
if (pCurrentHandler != s_ProxyDispatchers[i]) {
|
|
KLogEx(DEBUG_TRACE_WARNING, "Warning: Function pointer was modified by another driver! MJ:%d Curr:%p Our:%p\n",
|
|
mj_idx, pCurrentHandler, s_ProxyDispatchers[i]);
|
|
}
|
|
*/
|
|
}
|
|
|
|
// 4. [매우 중요] 실행 중인 IRP가 모두 빠져나갈 때까지 대기 (Rundown Protection)
|
|
// USBIrpCore.IrpEnterCount는 Hook 함수 진입 시 증가, 탈출 시 감소함.
|
|
// 이 값이 0이 될 때까지 기다려야 안전하게 드라이버를 언로드할 수 있음.
|
|
WaitTime.QuadPart = -50 * 1000 * 10; // 50ms 단위로 대기
|
|
while (hook->IrpEnterCount > 0)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "Waiting for active IRPs... Count: %d\n", hook->IrpEnterCount);
|
|
KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);
|
|
}
|
|
|
|
// 상태 초기화
|
|
hook->IsHooked = FALSE;
|
|
hook->DriverObject = NULL; // 드라이버 객체 참조 해제 (필요시 ObDereferenceObject 고려)
|
|
//RtlZeroMemory(pCtx->HookHandlers, sizeof(pCtx->HookHandlers));
|
|
}
|
|
|
|
// 혹시 모를 레이스 컨디션을 대비해 0.5초 정도 안전하게 추가 대기
|
|
WaitTime.QuadPart = -500 * 1000 * 10;
|
|
KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "Complete.\n");
|
|
|
|
return STATUS_SUCCESS;
|
|
} |