#include "precomp.h" enum { bluetooth_btkrnl = 0, bluetooth_rfcomm, bluetooth_btwusb, bluetooth_bthusb, bluetooth_maximum }; static WCHAR* s_bthname[] = { L"\\Driver\\BTKRNL", L"\\Driver\\RFCOMM", L"\\Driver\\BTWUSB", L"\\Driver\\BTHUSB", NULL }; static BOOLEAN enable_bluetoothhook = FALSE; NTSTATUS BtkrnHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp); NTSTATUS RfcommHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp); NTSTATUS BtwusbHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp); NTSTATUS BthusbHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp); static PDRIVER_DISPATCH s_ProxyDispatchers[bluetooth_maximum] = { BtkrnHookDispatch, RfcommHookDispatch, BtwusbHookDispatch, BthusbHookDispatch }; NTSTATUS BtkrnlDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp); NTSTATUS RfcommInternalDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp); NTSTATUS BtwusbDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp); NTSTATUS BthusbDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp); #define BTKRNL_COMMON_HOOK_HANDLERS \ [IRP_MJ_DEVICE_CONTROL] = { NULL, IRP_MJ_DEVICE_CONTROL, TRUE, BtkrnlDeviceIoControl }, \ #define RFCOMM_COMMON_HOOK_HANDLERS \ [IRP_MJ_INTERNAL_DEVICE_CONTROL] = { NULL, IRP_MJ_INTERNAL_DEVICE_CONTROL, TRUE, RfcommInternalDeviceIoControl }, \ #define BTWUSB_COMMON_HOOK_HANDLERS \ [IRP_MJ_DEVICE_CONTROL] = { NULL, IRP_MJ_DEVICE_CONTROL, TRUE, BtwusbDeviceIoControl }, \ #define BTHUSB_COMMON_HOOK_HANDLERS \ [IRP_MJ_DEVICE_CONTROL] = { NULL, IRP_MJ_DEVICE_CONTROL, TRUE, BthusbDeviceIoControl }, \ static HOOK_CONTEXT g_BlueToothHookContexts[bluetooth_maximum] = { { NULL, FALSE, 0, { BTKRNL_COMMON_HOOK_HANDLERS } }, { NULL, FALSE, 0, { RFCOMM_COMMON_HOOK_HANDLERS } }, { NULL, FALSE, 0, { BTWUSB_COMMON_HOOK_HANDLERS } }, { NULL, FALSE, 0, { BTHUSB_COMMON_HOOK_HANDLERS } } }; NTSTATUS BlueToothHookDispatch_Common(ULONG ContextIndex, PDEVICE_OBJECT deviceObject, PIRP irp) { NTSTATUS NtStatus = STATUS_SUCCESS; PIO_STACK_LOCATION pCurrentIoStack = IoGetCurrentIrpStackLocation(irp); ULONG id = pCurrentIoStack->MajorFunction; PHOOK_CONTEXT hook = NULL; PDRIVER_DISPATCH pOrgHandler = NULL; if (ContextIndex >= bluetooth_maximum) return STATUS_UNSUCCESSFUL; InterlockedIncrement((volatile LONG*)&g_BlueToothHookContexts[ContextIndex].IrpEnterCount); hook = &g_BlueToothHookContexts[ContextIndex]; // 2. ÈÄÅ· À¯È¿¼º °Ë»ç if (hook->IsHooked && hook->HookHandlers[id].IsHook && hook->HookHandlers[id].Work) { pOrgHandler = hook->HookHandlers[id].pOrgHandler; NtStatus = hook->HookHandlers[id].Work( pOrgHandler, deviceObject, irp ); } else { NtStatus = STATUS_UNSUCCESSFUL; } InterlockedDecrement((volatile LONG*)&g_BlueToothHookContexts[ContextIndex].IrpEnterCount); return NtStatus; } NTSTATUS BtkrnHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp) { return BlueToothHookDispatch_Common(bluetooth_btkrnl, deviceObject, irp); } NTSTATUS RfcommHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp) { return BlueToothHookDispatch_Common(bluetooth_rfcomm, deviceObject, irp); } NTSTATUS BtwusbHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp) { return BlueToothHookDispatch_Common(bluetooth_btwusb, deviceObject, irp); } NTSTATUS BthusbHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp) { return BlueToothHookDispatch_Common(bluetooth_bthusb, deviceObject, irp); } /** @brief ºí·çÅõ½º µ¿±Û ÈÄÅ·ÇÔ¼ö */ NTSTATUS BtkrnlDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpstack = IoGetCurrentIrpStackLocation(irp); ULONG buffSize = irpstack->Parameters.DeviceIoControl.InputBufferLength; ULONG controlCode = irpstack->Parameters.DeviceIoControl.IoControlCode; ULONG state = 0; WCHAR processName[50] = { 0, }; ULONG processId = 0; ULONG policyLog = 0; char szProcessName[20] = { 0, }; if (!g_bs1Flt.IsAttached) goto $BtkrnlCleanup; if (!enable_bluetoothhook) goto $BtkrnlCleanup; processId = HandleToULong(PsGetCurrentProcessId()); UGetProcessName(szProcessName); state = GetPolicyState(BDC_BLUETOOTH); policyLog = IsPolicyLog(BDC_BLUETOOTH); if (state == DISABLE) { // ¹öÆÛ Å©±â üũ µîÀº Çʿ信 µû¶ó ¼öÇà if (buffSize > 4) { WCHAR notice[MAX_PATH] = { 0, }; KLogEx(DEBUG_TRACE_INFO, "btkrnl blocked(%X)(%d)", controlCode, buffSize); if (policyLog) { RtlStringCbPrintfW(processName, sizeof(processName), L"%S", szProcessName); RtlStringCbPrintfW(notice, sizeof(notice), L"btkrnl blocked(%X)(%d)", controlCode, buffSize); SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, state, 0, processName, notice); } irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; // ¶Ç´Â STATUS_ACCESS_DENIED irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } } $BtkrnlCleanup: return dispath(deviceObject, irp); } /** @brief ³»Àå ºí·çÅõ½º ÀåÄ¡ ÈÄÅ· ÇÔ¼ö (RfComm / Microsoft Stack) */ PFILE_OBJECT gFileObject = NULL; NTSTATUS RfcommInternalDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpstack = IoGetCurrentIrpStackLocation(irp); NTSTATUS status = STATUS_SUCCESS; PCHAR pBuffer = NULL; PFILE_OBJECT pFileObject = irpstack->FileObject; ULONG controlCode = irpstack->Parameters.DeviceIoControl.IoControlCode; ULONG blueToothState = 0; ULONG blueToothFileState = 0; WCHAR processName[50] = { 0, }; ULONG processId = 0; ULONG blueToothlog = 0; ULONG blueToothFilelog = 0; char szProcessName[20] = { 0, }; WCHAR notice[MAX_PATH] = { 0, }; if (!g_bs1Flt.IsAttached) return dispath(deviceObject, irp); if (!enable_bluetoothhook) return dispath(deviceObject, irp); processId = HandleToULong(PsGetCurrentProcessId()); UGetProcessName(szProcessName); blueToothState = GetPolicyState(BDC_BLUETOOTH); blueToothlog = IsPolicyLog(BDC_BLUETOOTH); if (blueToothState == DISABLE) { KLogEx(DEBUG_TRACE_INFO, " blocked(%X)", controlCode); if (blueToothlog) { RtlStringCbPrintfW(processName, sizeof(processName), L"%S", szProcessName); RtlStringCbPrintfW(notice, sizeof(notice), L"controlCode(%X)", controlCode); SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, blueToothState, 0, processName, notice); } irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } if (!irp->MdlAddress || !irp->MdlAddress->ByteCount ||!irpstack->FileObject) return dispath(deviceObject, irp); pBuffer = MmGetSystemAddressForMdl(irp->MdlAddress); if (!pBuffer) return dispath(deviceObject, irp); __try { blueToothFileState = GetPolicyState(BDC_BLUETOOTH_FILE); blueToothFilelog = IsPolicyLog(BDC_BLUETOOTH_FILE); RtlStringCbPrintfW(processName, sizeof(processName), L"%S", szProcessName); POBEX_COMMON_HEADER pCommon = (POBEX_COMMON_HEADER)pBuffer; KLogEx(DEBUG_TRACE_INFO, "Opcode(%X)", pCommon->Opcode); switch (pCommon->Opcode) { case OBEX_OPCODE_CONNECT: { KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_CONNECT(%p)", pFileObject); POBEX_CONNECT_PACKET pConn = (POBEX_CONNECT_PACKET)pBuffer; USHORT hostPacketLen = 0; USHORT hostMaxPktSize = 0; if (blueToothFilelog || blueToothlog) { if (irp->MdlAddress->ByteCount < sizeof(OBEX_CONNECT_PACKET)) { KLogEx(DEBUG_TRACE_INFO, "Data too short for OBEX Connect"); break; } hostPacketLen = SWAP_USHORT(pConn->PacketLength); hostMaxPktSize = SWAP_USHORT(pConn->MaxPacketSize); RtlStringCbPrintfW(notice, sizeof(notice), L"OBEX_OPCODE_CONNECT, hostPacketLen(%d), version(0x%x), flag(%d), hostMaxPktSize(%d)", hostPacketLen, pConn->Version, pConn->Flags, hostMaxPktSize); KLogEx(DEBUG_TRACE_INFO, "file blocked(%X), (%S)", controlCode, notice); SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, blueToothFileState, 0, processName, notice); } gFileObject = pFileObject; if (blueToothFileState == DISABLE) { KLogEx(DEBUG_TRACE_INFO, "Blocked OBEX Connect"); irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } } break; case OBEX_OPCODE_DISCONNECT: // Disconnect { KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_DISCONNECT(%p)", pFileObject); gFileObject = NULL; if (blueToothFilelog || blueToothlog) { RtlStringCbPrintfW(notice, sizeof(notice), L"OBEX_OPCODE_DISCONNECT, ByteCount(%d)", irp->MdlAddress->ByteCount); KLogEx(DEBUG_TRACE_INFO, "(%S)", notice); SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, blueToothFileState, 0, processName, notice); } } break; case OBEX_OPCODE_PUT: // Put case OBEX_OPCODE_PUT_FINAL: // Put Final { KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_PUT,OBEX_OPCODE_PUT_FINAL(%p)", pFileObject); if (gFileObject != pFileObject) { break; } ULONG currentOffset = 3; WCHAR szFileName[260] = { 0 }; ULONG packetLen = irp->MdlAddress->ByteCount; PUCHAR pData = (PUCHAR)pBuffer; if (blueToothFilelog || blueToothlog) { while (currentOffset < packetLen) { UCHAR headerId = pData[currentOffset]; if (currentOffset + 3 > packetLen) break; // OBEX Çì´õ´Â »óÀ§ 2ºñÆ®¿¡ µû¶ó ÀÎÄÚµù ¹æ½ÄÀÌ ´Ù¸§ // 00xxxxxx: Unicode String (Length Æ÷ÇÔ) -> Name Çì´õ°¡ ¿©±â ¼ÓÇÔ // 01xxxxxx: Byte Sequence (Length Æ÷ÇÔ) // 10xxxxxx: 1 Byte Value (Length ÇÊµå ¾øÀ½) // 11xxxxxx: 4 Byte Value (Length ÇÊµå ¾øÀ½) if (headerId == OBEX_OPCODE_NAME) // 0x01: ÆÄÀÏ¸í ¹ß°ß! { USHORT headerLen = 0; // Length Çʵå´Â Big Endian (2 bytes) ((PUCHAR)&headerLen)[1] = pData[currentOffset + 1]; ((PUCHAR)&headerLen)[0] = pData[currentOffset + 2]; // ½ÇÁ¦ À̸§ ±æÀÌ = Çì´õ±æÀÌ - (ID 1byte + Length 2bytes) // OBEX NameÀº Null-terminated UnicodeÀÓ (¸¶Áö¸· 2¹ÙÀÌÆ® 0x00 0x00 Æ÷ÇÔ) if (headerLen > 5 && (currentOffset + headerLen <= packetLen)) { ULONG nameByteLen = headerLen - 3; // ¼ø¼ö ¹®ÀÚ¿­ ¹ÙÀÌÆ® ¼ö (Çì´õ ¿À¹öÇìµå 3¹ÙÀÌÆ® Á¦¿Ü) if (nameByteLen >= sizeof(szFileName)) nameByteLen = sizeof(szFileName) - 2; // ÆÄÀÏ¸í º¹»ç (pData + offset + 3) RtlCopyMemory(szFileName, &pData[currentOffset + 3], nameByteLen); for (ULONG k = 0; k < nameByteLen / 2; k++) szFileName[k] = SWAP_USHORT(szFileName[k]); szFileName[nameByteLen/2] = 0; KLogEx(DEBUG_TRACE_INFO, "File Name Found: %ws", szFileName); RtlStringCbPrintfW(notice, sizeof(notice), L"File Transfer: %s, packetLen: %d", szFileName, packetLen); } break; // À̸§À» ã¾ÒÀ¸¸é ·çÇÁ Á¾·á (ÃÖÀûÈ­) } // ´ÙÀ½ Çì´õ·Î À̵¿Çϱâ À§ÇÑ ¿ÀÇÁ¼Â °è»ê if ((headerId & 0xC0) == 0x00 || (headerId & 0xC0) == 0x40) { // Length Çʵ尡 Àִ ŸÀÔ (String, Sequence) USHORT chunkLen = 0; ((PUCHAR)&chunkLen)[1] = pData[currentOffset + 1]; ((PUCHAR)&chunkLen)[0] = pData[currentOffset + 2]; if (chunkLen == 0) break; // ¹«ÇÑ·çÇÁ ¹æÁö currentOffset += chunkLen; } else if ((headerId & 0xC0) == 0x80) { // 1 Byte Value (ÃÑ 2¹ÙÀÌÆ®: ID + Value) currentOffset += 2; } else if ((headerId & 0xC0) == 0xC0) { // 4 Byte Value (ÃÑ 5¹ÙÀÌÆ®: ID + Value 4bytes) currentOffset += 5; } } if(notice[0] == 0) RtlStringCbPrintfW(notice, sizeof(notice), L"File Transfer: unknown, packetLen: %d", packetLen); SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, blueToothFileState, 0, processName, notice); } if (blueToothFileState == DISABLE || blueToothFileState == READONLY) { KLogEx(DEBUG_TRACE_INFO, "Blocked File Transfer: %ws", szFileName); irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } } break; case OBEX_OPCODE_OK: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_OK"); break; case OBEX_OPCODE_CONTINUE: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_CONTINUE"); break; case OBEX_OPCODE_BODY: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_BODY"); break; case OBEX_OPCODE_END_BODY: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_END_BODY"); break; case OBEX_OPCODE_VERSION: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_VERSION"); break; case OBEX_OPCODE_CONN_FLAGS: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_CONN_FLAGS"); break; case OBEX_OPCODE_NAME: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_NAME"); break; case OBEX_OPCODE_LENGTH: KLogEx(DEBUG_TRACE_INFO, "OBEX_OPCODE_LENGTH"); break; default: KLogEx(DEBUG_TRACE_INFO, "default OBEX_OPCODE"); break; } } __except (EXCEPTION_EXECUTE_HANDLER) { NTSTATUS exceptStatus = GetExceptionCode(); KLogEx(DEBUG_TRACE_ERROR, "Exception accessing buffer: 0x%X", exceptStatus); } status = dispath(deviceObject, irp); return status; } /** @brief ºí·çÅõ½º USB ÀåÄ¡ ÈÄÅ· ÇÔ¼ö (BTWUSB) */ NTSTATUS BtwusbDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpstack = IoGetCurrentIrpStackLocation(irp); ULONG controlCode = irpstack->Parameters.DeviceIoControl.IoControlCode; NTSTATUS ntStatus = STATUS_SUCCESS; ULONG blueToothState = 0; WCHAR processName[50] = { 0, }; ULONG processId = 0; ULONG blueToothlog = 0; char szProcessName[20] = { 0, }; WCHAR notice[MAX_PATH] = { 0, }; if (!g_bs1Flt.IsAttached) return dispath(deviceObject, irp); if (!enable_bluetoothhook) return dispath(deviceObject, irp); processId = HandleToULong(PsGetCurrentProcessId()); UGetProcessName(szProcessName); blueToothState = GetPolicyState(BDC_BLUETOOTH); blueToothlog = IsPolicyLog(BDC_BLUETOOTH); if (blueToothState == DISABLE) { KLogEx(DEBUG_TRACE_INFO, " btwusb blocked(%X)", controlCode); if (blueToothlog) { RtlStringCbPrintfW(processName, sizeof(processName), L"%S", szProcessName); RtlStringCbPrintfW(notice, sizeof(notice), L"btwusb blocked(%X)", controlCode); SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, blueToothState, 0, processName, notice); } irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } ntStatus = dispath(deviceObject, irp); if (blueToothlog == TRUE) { } return ntStatus; } /** @brief ºí·çÅõ½º USB ÀåÄ¡ ÈÄÅ· ÇÔ¼ö (BTHUSB) */ NTSTATUS BthusbDeviceIoControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpstack = IoGetCurrentIrpStackLocation(irp); ULONG controlCode = irpstack->Parameters.DeviceIoControl.IoControlCode; NTSTATUS ntStatus = STATUS_SUCCESS; ULONG blueToothState = 0; WCHAR processName[50] = { 0, }; ULONG processId = 0; ULONG blueToothlog = 0; char szProcessName[20] = { 0, }; WCHAR notice[MAX_PATH] = { 0, }; if (!g_bs1Flt.IsAttached) return dispath(deviceObject, irp); if (!enable_bluetoothhook) return dispath(deviceObject, irp); processId = HandleToULong(PsGetCurrentProcessId()); UGetProcessName(szProcessName); blueToothState = GetPolicyState(BDC_BLUETOOTH); blueToothlog = IsPolicyLog(BDC_BLUETOOTH); if (blueToothState == DISABLE) { KLogEx(DEBUG_TRACE_INFO, " bthusb blocked(%X)", controlCode); if (blueToothlog) { RtlStringCbPrintfW(processName, sizeof(processName), L"%S", szProcessName); RtlStringCbPrintfW(notice, sizeof(notice), L"bthusb blocked(%X)", controlCode); SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, blueToothState, 0, processName, notice); } irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; irp->IoStatus.Information = 0; IoCompleteRequest(irp, IO_NO_INCREMENT); return STATUS_INVALID_DEVICE_REQUEST; } ntStatus = dispath(deviceObject, irp); if (blueToothlog == TRUE) { } return ntStatus; } NTSTATUS BlueToothIrpHookInit() { WCHAR* name = NULL; ULONG i, mi; PDRIVER_OBJECT obj = NULL; PHOOK_CONTEXT hook = NULL; for (i = 0; i < bluetooth_maximum; i++) { hook = &g_BlueToothHookContexts[i]; if (hook->IsHooked) continue; name = s_bthname[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++) { 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_bluetoothhook = TRUE; } KLogEx(DEBUG_TRACE_INFO, "complete\n"); return STATUS_SUCCESS; } NTSTATUS BlueToothIrpHookCleanup() { ULONG i, mi; LARGE_INTEGER WaitTime; PHOOK_CONTEXT hook = NULL; PDRIVER_DISPATCH pCurrentHandler = NULL; enable_bluetoothhook = FALSE; KLogEx(DEBUG_TRACE_INFO, "Started...\n"); for (i = 0; i < bluetooth_maximum; i++) { hook = &g_BlueToothHookContexts[i]; if (!hook->IsHooked || !hook->DriverObject) continue; KLogEx(DEBUG_TRACE_INFO, "Unhooking Driver Index: %d\n", i); for (mi = 0; mi <= IRP_MJ_MAXIMUM_FUNCTION; mi++) { if (!hook->HookHandlers[mi].IsHook) continue; if (hook->HookHandlers[mi].pOrgHandler == NULL) continue; pCurrentHandler = (PDRIVER_DISPATCH)InterlockedExchangePointer( (PVOID)&hook->DriverObject->MajorFunction[mi], (PVOID)hook->HookHandlers[mi].pOrgHandler ); hook->HookHandlers[mi].pOrgHandler = NULL; } WaitTime.QuadPart = -50 * 1000 * 10; // 50ms ´ÜÀ§·Î ´ë±â while (hook->IrpEnterCount > 0) { KLogEx(DEBUG_TRACE_INFO, "(%d), Waiting for active IRPs... Count: %d\n", i, hook->IrpEnterCount); KeDelayExecutionThread(KernelMode, FALSE, &WaitTime); } hook->IsHooked = FALSE; hook->DriverObject = NULL; //RtlZeroMemory(hook->HookHandlers, sizeof(hook->HookHandlers)); } WaitTime.QuadPart = -500 * 1000 * 10; KeDelayExecutionThread(KernelMode, FALSE, &WaitTime); KLogEx(DEBUG_TRACE_INFO, "Complete.\n"); return STATUS_SUCCESS; }