977 lines
28 KiB
C
977 lines
28 KiB
C
#include "precomp.h"
|
||
|
||
|
||
|
||
enum
|
||
{
|
||
bluetooth_btkrnl = 0,
|
||
bluetooth_rfcomm,
|
||
bluetooth_btwusb,
|
||
bluetooth_bthusb,
|
||
bluetooth_bthenum, //Å×½ºÆ® ÇÊ¿ä..
|
||
bluetooth_maximum
|
||
};
|
||
|
||
static WCHAR* s_bthname[] =
|
||
{
|
||
L"\\Driver\\BTKRNL",
|
||
L"\\Driver\\RFCOMM",
|
||
L"\\Driver\\BTWUSB",
|
||
L"\\Driver\\BTHUSB",
|
||
L"\\Driver\\BTHENUM",
|
||
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);
|
||
NTSTATUS BthEnumHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp);
|
||
|
||
|
||
static PDRIVER_DISPATCH s_ProxyDispatchers[bluetooth_maximum] =
|
||
{
|
||
BtkrnHookDispatch,
|
||
RfcommHookDispatch,
|
||
BtwusbHookDispatch,
|
||
BthusbHookDispatch,
|
||
BthEnumHookDispatch //Å×½ºÆ® ÇÊ¿ä
|
||
};
|
||
|
||
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);
|
||
NTSTATUS BthEnumPnpControl(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 }, \
|
||
|
||
#define BTHENUM_COMMON_HOOK_HANDLERS \
|
||
[IRP_MJ_PNP] = { NULL, IRP_MJ_PNP, TRUE, BthEnumPnpControl }, \
|
||
|
||
static HOOK_CONTEXT g_BlueToothHookContexts[] =
|
||
{
|
||
{ 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 } }
|
||
//{ NULL, FALSE, 0, { BTHENUM_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 >= ARRAYSIZE(g_BlueToothHookContexts))
|
||
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 BthEnumHookDispatch(PDEVICE_OBJECT deviceObject, PIRP irp)
|
||
{
|
||
return BlueToothHookDispatch_Common(bluetooth_bthenum, deviceObject, irp);
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
// ¸ÅÇÎÀ» À§ÇÑ ±¸Á¶Ã¼ Á¤ÀÇ
|
||
typedef struct _BTH_UUID_MAPPING {
|
||
PWCHAR UuidLower; // ¼Ò¹®ÀÚ UUID
|
||
PWCHAR UuidUpper; // ´ë¹®ÀÚ UUID
|
||
PWCHAR ReadableName; // º¯È¯µÉ ÇѱÛ/¿µ¹® ¼³¸í
|
||
} BTH_UUID_MAPPING, * PBTH_UUID_MAPPING;
|
||
|
||
// ±âÁ¸ ¿Ï·á ·çƾÀÇ Á¤º¸¸¦ ¹é¾÷ÇØµÑ ±¸Á¶Ã¼ ¼±¾ð (Àü¿ª Çì´õ¿¡ ¼±¾ðÇϼ¼¿ä)
|
||
typedef struct _BTH_HOOK_CONTEXT {
|
||
PIO_COMPLETION_ROUTINE OldCompletionRoutine;
|
||
PVOID OldContext;
|
||
UCHAR OldControl;
|
||
char processName[50];
|
||
} BTH_HOOK_CONTEXT, * PBTH_HOOK_CONTEXT;
|
||
|
||
// ºí·çÅõ½º ÁÖ¿ä ÀåÄ¡ UUID ¸ÅÇÎ Å×À̺í (Àü¿ª ¹è¿)
|
||
BTH_UUID_MAPPING g_BthUuidTable[] = {
|
||
// --- [º¸¾È À§Çù / µ¥ÀÌÅÍ À¯Ãâ (Â÷´Ü ±ÇÀå)] ---
|
||
{ L"1105", L"1105", L"ÆÄÀÏ Àü¼Û (OBEX Object Push)" },
|
||
{ L"1101", L"1101", L"½Ã¸®¾ó Åë½Å (Serial Port)" },
|
||
{ L"1115", L"1115", L"ºí·çÅõ½º Å×´õ¸µ/°øÀ¯ (PANU)" },
|
||
{ L"1116", L"1116", L"ºí·çÅõ½º ÇÖ½ºÆÌ (NAP)" },
|
||
{ L"1132", L"1132", L"¹®ÀÚ ¸Þ½ÃÁö Á¢±Ù (MAP)" },
|
||
|
||
// --- [¹Ìµð¾î / ¿Àµð¿À (¼±ÅÃÀû Â÷´Ü)] ---
|
||
{ L"110b", L"110B", L"¿Àµð¿À/Çìµå¼Â ½ºÇÇÄ¿ (A2DP Sink)" },
|
||
{ L"110a", L"110A", L"¿Àµð¿À ¼Ò½º (A2DP Source)" },
|
||
{ L"1108", L"1108", L"±¸Çü ¸ð³ë Çìµå¼Â (Headset)" },
|
||
{ L"111e", L"111E", L"ÇÚÁîÇÁ¸® ÅëÈ (Handsfree)" },
|
||
{ L"110c", L"110C", L"¹Ìµð¾î ¸®¸ðÄÁ (AVRCP)" },
|
||
|
||
// --- [ÀÔ·Â ÀåÄ¡ (Çã¿ë ±ÇÀå)] ---
|
||
{ L"1124", L"1124", L"¸¶¿ì½º/Űº¸µå (HID)" },
|
||
{ L"1812", L"1812", L"ÀúÀü·Â ¸¶¿ì½º/Űº¸µå (BLE HID)" },
|
||
|
||
// ¹è¿ÀÇ ³¡À» ¾Ë¸®´Â ³Î(NULL) °ª
|
||
{ NULL, NULL, L"¾Ë ¼ö ¾ø´Â ºí·çÅõ½º ÀåÄ¡" }
|
||
};
|
||
|
||
/**
|
||
* Çϵå¿þ¾î ID ¹®ÀÚ¿ ³»¿¡¼ ƯÁ¤ UUID¸¦ ã¾Æ Àб⠽¬¿î À̸§À¸·Î ¹ÝȯÇÕ´Ï´Ù.
|
||
* @param HardwareIdString: °Ë»çÇÒ ¹®ÀÚ¿ (¿¹: L"BTHENUM\\{0000110b-0000...}")
|
||
* @return ¸ÅĪµÈ ÀåÄ¡ÀÇ ÇÑ±Û ¼³¸í Æ÷ÀÎÅÍ
|
||
*/
|
||
PWCHAR GetReadableBluetoothName(PWCHAR HardwareIdString) {
|
||
int i = 0;
|
||
|
||
if (HardwareIdString == NULL) {
|
||
return L"À߸øµÈ ÀåÄ¡ Á¤º¸";
|
||
}
|
||
|
||
// ¹è¿À» ¼øÈ¸ÇÏ¸ç ¸ÅĪµÇ´Â UUID°¡ ÀÖ´ÂÁö °Ë»ç
|
||
while (g_BthUuidTable[i].UuidLower != NULL) {
|
||
// ¼Ò¹®ÀÚ ¶Ç´Â ´ë¹®ÀÚ°¡ Æ÷ÇԵǾî ÀÖ´ÂÁö È®ÀÎ (wcsstr)
|
||
if (wcsstr(HardwareIdString, g_BthUuidTable[i].UuidLower) != NULL ||
|
||
wcsstr(HardwareIdString, g_BthUuidTable[i].UuidUpper) != NULL)
|
||
{
|
||
return g_BthUuidTable[i].ReadableName;
|
||
}
|
||
i++;
|
||
}
|
||
|
||
// ¸ÅĪµÇ´Â °ªÀÌ ¾øÀ¸¸é ±âº»°ª ¹Ýȯ
|
||
return L"¾Ë ¼ö ¾ø´Â ºí·çÅõ½º ÀåÄ¡ (±âŸ)";
|
||
}
|
||
|
||
#define TAG_LOG_STR 'goLB'
|
||
NTSTATUS GetAllHardwareIdsAsString(
|
||
_In_ PWCHAR MultiSzBuffer,
|
||
_Out_ PUNICODE_STRING CombinedString
|
||
)
|
||
{
|
||
PWCHAR currentString;
|
||
ULONG totalChars = 0;
|
||
USHORT maxLen = 0;
|
||
|
||
if (MultiSzBuffer == NULL || CombinedString == NULL)
|
||
{
|
||
return STATUS_INVALID_PARAMETER;
|
||
}
|
||
|
||
// 1. º´ÇÕ¿¡ ÇÊ¿äÇÑ Àüü ¹®ÀÚ¿ ±æÀÌ °è»ê
|
||
currentString = MultiSzBuffer;
|
||
while (*currentString != L'\0')
|
||
{
|
||
// ÇöÀç ¹®ÀÚ¿ ±æÀÌ + ±¸ºÐÀÚ("; ") 2±ÛÀÚ
|
||
totalChars += (ULONG)wcslen(currentString) + 2;
|
||
|
||
// ´ÙÀ½ ¹®ÀÚ¿·Î Æ÷ÀÎÅÍ À̵¿ (ÇöÀç±æÀÌ + NULL)
|
||
currentString += wcslen(currentString) + 1;
|
||
}
|
||
|
||
if (totalChars == 0)
|
||
{
|
||
RtlInitUnicodeString(CombinedString, L"");
|
||
return STATUS_NOT_FOUND;
|
||
}
|
||
|
||
// UNICODE_STRINGÀÇ ÃÖ´ë Å©±â´Â 65535 ¹ÙÀÌÆ®(USHORT)·Î Á¦ÇѵÊ
|
||
if ((totalChars * sizeof(WCHAR) + sizeof(WCHAR)) > 0xFFFF)
|
||
{
|
||
return STATUS_BUFFER_OVERFLOW;
|
||
}
|
||
|
||
// 2. ¸Þ¸ð¸® ÇÒ´ç (NonPagedPool »ç¿ë - ¿Ï·á ·çƾ(DISPATCH_LEVEL)¿¡¼ ¾ÈÀü)
|
||
maxLen = (USHORT)(totalChars * sizeof(WCHAR) + sizeof(WCHAR));
|
||
|
||
// ÃֽŠWDK¿¡¼´Â NonPagedPoolNx¸¦ ±ÇÀåÇϳª, ±¸¹öÀü ȣȯ¼ºÀ» À§ÇØ NonPagedPool »ç¿ë
|
||
CombinedString->Buffer = (PWCHAR)ExAllocatePoolWithTag(NonPagedPool, maxLen, TAG_LOG_STR);
|
||
|
||
if (CombinedString->Buffer == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
// UNICODE_STRING ±¸Á¶Ã¼ ÃʱâÈ
|
||
CombinedString->MaximumLength = maxLen;
|
||
CombinedString->Length = 0;
|
||
CombinedString->Buffer[0] = L'\0';
|
||
|
||
// 3. ¹®ÀÚ¿ °áÇÕ (Concatenation)
|
||
currentString = MultiSzBuffer;
|
||
while (*currentString != L'\0')
|
||
{
|
||
UNICODE_STRING tempStr;
|
||
RtlInitUnicodeString(&tempStr, currentString);
|
||
|
||
// ÇöÀç ¹®ÀÚ¿À» ºÙÀÓ
|
||
RtlAppendUnicodeStringToString(CombinedString, &tempStr);
|
||
|
||
currentString += (tempStr.Length / sizeof(WCHAR)) + 1;
|
||
|
||
// ´ÙÀ½ ¹®ÀÚ¿ÀÌ Á¸ÀçÇÏ¸é ±¸ºÐÀÚ("; ") »ðÀÔ
|
||
if (*currentString != L'\0') {
|
||
RtlAppendUnicodeToString(CombinedString, L"; ");
|
||
}
|
||
}
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
// -----------------------------------------------------------------------
|
||
// IRP_MN_QUERY_ID ¿Ï·á ·çƾ (¿©±â¼ ±â±â Á¾·ù¸¦ ÆÇº°Çϰí Â÷´ÜÇÕ´Ï´Ù)
|
||
// -----------------------------------------------------------------------
|
||
NTSTATUS PnpQueryIdCompletionRoutine(
|
||
PDEVICE_OBJECT DeviceObject,
|
||
PIRP Irp,
|
||
PVOID Context
|
||
) {
|
||
UNREFERENCED_PARAMETER(DeviceObject);
|
||
UNREFERENCED_PARAMETER(Context);
|
||
PBTH_HOOK_CONTEXT hookCtx = (PBTH_HOOK_CONTEXT)Context;
|
||
ULONG state = GetPolicyState(BDC_BLUETOOTH);
|
||
ULONG policyLog = IsPolicyLog(BDC_BLUETOOTH);
|
||
WCHAR processName[50] = { 0, };
|
||
WCHAR notice[MAX_PATH] = { 0, };
|
||
NTSTATUS status = Irp->IoStatus.Status;
|
||
BOOLEAN bBlock = FALSE;
|
||
//if (Irp->PendingReturned) {
|
||
// IoMarkIrpPending(Irp);
|
||
//}
|
||
|
||
//PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
|
||
// ÇÏÀ§ µå¶óÀ̹ö°¡ 󸮸¦ ¼º°øÇß°í, ¿ì¸®°¡ ¿øÇÏ´Â Hardware IDs ¿äûÀÎ °æ¿ì
|
||
if (NT_SUCCESS(Irp->IoStatus.Status) /*&&
|
||
irpSp->MinorFunction == IRP_MN_QUERY_ID &&
|
||
irpSp->Parameters.QueryId.IdType == BusQueryHardwareIDs*/)
|
||
{
|
||
if (Irp->IoStatus.Information != 0)
|
||
{
|
||
UNICODE_STRING allHwIdsStr;
|
||
PWCHAR hwIds = (PWCHAR)Irp->IoStatus.Information;
|
||
|
||
status = GetAllHardwareIdsAsString(hwIds, &allHwIdsStr);
|
||
if (NT_SUCCESS(status))
|
||
{
|
||
PWCHAR name = GetReadableBluetoothName(allHwIdsStr.Buffer); // ·Î±×¿¡ »ç¶÷ÀÌ ÀÐÀ» ¼ö ÀÖ´Â À̸§À¸·Î ³²±â±â À§ÇØ º¯È¯ ½Ãµµ
|
||
KLogEx(DEBUG_TRACE_INFO, "btheunm connect : %S, %S", name, allHwIdsStr.Buffer);
|
||
|
||
if (wcsstr(allHwIdsStr.Buffer, L"110b") != NULL ||
|
||
wcsstr(allHwIdsStr.Buffer, L"110B") != NULL ||
|
||
wcsstr(allHwIdsStr.Buffer, L"1105") != NULL)
|
||
{
|
||
bBlock = TRUE;
|
||
}
|
||
|
||
//'1124', '1812', '110B', '1108'
|
||
if (policyLog)
|
||
{
|
||
if(hookCtx->processName)
|
||
RtlStringCbPrintfW(processName, sizeof(processName), L"%S", hookCtx->processName);
|
||
|
||
if (/*state == DISABLE &&*/ bBlock)
|
||
RtlStringCbPrintfW(notice, sizeof(notice), L"btheunm blocked(%s)(%s)", name, allHwIdsStr.Buffer);
|
||
else
|
||
RtlStringCbPrintfW(notice, sizeof(notice), L"btheunm allow(%s)(%s)", name, allHwIdsStr.Buffer);
|
||
|
||
SetLog(NULL, NULL, LOG_POLICY, BDC_BLUETOOTH, state, 0, processName, notice);
|
||
}
|
||
|
||
if (/*state == DISABLE &&*/ bBlock)
|
||
{
|
||
KLogEx(DEBUG_TRACE_INFO, "btheunm connect STATUS_ACCESS_DENIED !!!");
|
||
ExFreePool(hwIds); // BthEnumÀÌ ¸¸µé¾îÁØ ¿ø·¡ ¹öÆÛµµ ÇØÁ¦
|
||
Irp->IoStatus.Information = 0;
|
||
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
|
||
}
|
||
else
|
||
{
|
||
|
||
}
|
||
|
||
if(allHwIdsStr.Buffer)
|
||
ExFreePoolWithTag(allHwIdsStr.Buffer, TAG_LOG_STR);
|
||
}
|
||
else
|
||
{
|
||
KLogEx(DEBUG_TRACE_ERROR, "GetAllHardwareIdsAsString Fail (%X)", status);
|
||
}
|
||
}
|
||
}
|
||
|
||
// »óÀ§ µå¶óÀ̹ö°¡ ¿ø·¡ µî·ÏÇØµÎ¾ú´ø ¿Ï·á ·çƾÀÌ ÀÖ´Ù¸é È£ÃâÇÏ¿© È帧 º¹¿ø
|
||
if (hookCtx->OldCompletionRoutine != NULL) {
|
||
BOOLEAN bInvoke = FALSE;
|
||
if (NT_SUCCESS(Irp->IoStatus.Status) && (hookCtx->OldControl & SL_INVOKE_ON_SUCCESS)) bInvoke = TRUE;
|
||
if (!NT_SUCCESS(Irp->IoStatus.Status) && (hookCtx->OldControl & SL_INVOKE_ON_ERROR)) bInvoke = TRUE;
|
||
if (Irp->Cancel && (hookCtx->OldControl & SL_INVOKE_ON_CANCEL)) bInvoke = TRUE;
|
||
|
||
if (bInvoke) {
|
||
status = hookCtx->OldCompletionRoutine(DeviceObject, Irp, hookCtx->OldContext);
|
||
}
|
||
else if (Irp->PendingReturned) {
|
||
IoMarkIrpPending(Irp);
|
||
}
|
||
}
|
||
else {
|
||
if (Irp->PendingReturned) {
|
||
IoMarkIrpPending(Irp);
|
||
}
|
||
}
|
||
|
||
// ÇÒ´çÇß´ø ÄÁÅØ½ºÆ® ¸Þ¸ð¸® ÇØÁ¦ (¸Þ¸ð¸® ¸¯ ¹æÁö)
|
||
ExFreePoolWithTag(hookCtx, 'kooH');
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS BthEnumPnpControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT deviceObject, PIRP irp)
|
||
{
|
||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(irp);
|
||
ULONG processId = 0;
|
||
char szProcessName[20] = { 0, };
|
||
|
||
if (!g_bs1Flt.IsAttached)
|
||
goto $BthEnumCleanup;
|
||
|
||
if (!enable_bluetoothhook)
|
||
goto $BthEnumCleanup;
|
||
|
||
processId = HandleToULong(PsGetCurrentProcessId());
|
||
UGetProcessName(szProcessName);
|
||
|
||
// IRP_MN_QUERY_ID (ÀåÄ¡ ½Äº°ÀÚ ¿äû) ÀÏ ¶§¸¸ ¿Ï·á ·çƾÀ» ´ä´Ï´Ù.
|
||
if (irpSp->MinorFunction == IRP_MN_QUERY_ID &&
|
||
irpSp->Parameters.QueryId.IdType == BusQueryHardwareIDs)
|
||
{
|
||
PBTH_HOOK_CONTEXT hookCtx = (PBTH_HOOK_CONTEXT)ExAllocatePoolWithTag(NonPagedPool, sizeof(BTH_HOOK_CONTEXT), 'kooH');
|
||
|
||
if (hookCtx != NULL) {
|
||
// ±âÁ¸ ½ºÅÃÀÇ ¿Ï·á ·çƾ ¹é¾÷
|
||
hookCtx->OldCompletionRoutine = irpSp->CompletionRoutine;
|
||
hookCtx->OldContext = irpSp->Context;
|
||
hookCtx->OldControl = irpSp->Control;
|
||
strcpy(hookCtx->processName, szProcessName);
|
||
|
||
// ¿ì¸®ÀÇ ¿Ï·á ·çƾÀ¸·Î ÇöÀç ½ºÅà À§Ä¡ µ¤¾î¾²±â (IoSetCompletionRoutine »ç¿ë ºÒ°¡)
|
||
irpSp->CompletionRoutine = PnpQueryIdCompletionRoutine;
|
||
irpSp->Context = hookCtx;
|
||
irpSp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL;
|
||
}
|
||
|
||
// ¿ø·¡ÀÇ BthEnum ÇÔ¼ö È£Ãâ
|
||
return dispath(deviceObject, irp);
|
||
}
|
||
$BthEnumCleanup:
|
||
// ±× ¿ÜÀÇ PnP ¿äûÀº ¿ø·¡ÀÇ BthEnum ÇÔ¼ö·Î ±×´ë·Î ³Ñ°Ü¹ö¸²
|
||
return dispath(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"rfcom 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;
|
||
}
|
||
|
||
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)
|
||
{
|
||
if (processId == 4)
|
||
return dispath(deviceObject, irp);
|
||
|
||
if (IsDefalutLocalDiskExceptProcess(szProcessName))
|
||
return dispath(deviceObject, irp);
|
||
|
||
if (_strnicmp(szProcessName, "SystemSettings", strlen(szProcessName)) == 0 ||
|
||
_strnicmp(szProcessName, "RuntimeBroker.", strlen(szProcessName)) == 0 )
|
||
return dispath(deviceObject, irp);
|
||
|
||
|
||
KLogEx(DEBUG_TRACE_INFO, " bthusb blocked(%s)(%X)", szProcessName, 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 < ARRAYSIZE(g_BlueToothHookContexts); 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 < ARRAYSIZE(g_BlueToothHookContexts); 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;
|
||
}
|