428 lines
10 KiB
C
428 lines
10 KiB
C
#include "precomp.h"
|
||
#include "ntddscsi.h"
|
||
#include "srb.h"
|
||
|
||
enum
|
||
{
|
||
odd_imapi = 0,
|
||
odd_atapi,
|
||
odd_cdrom,
|
||
};
|
||
|
||
|
||
static WCHAR* s_oddname[] =
|
||
{
|
||
L"\\driver\\imapi",
|
||
L"\\driver\\atapi",
|
||
L"\\driver\\Cdrom",
|
||
NULL
|
||
};
|
||
|
||
static ULONG s_oddtype = 0;
|
||
|
||
NTSTATUS ODDControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||
|
||
|
||
IRP_CORE ODDIrpCore = { 0, };
|
||
|
||
#define ODDLock() InterlockedIncrement((volatile LONG *)&ODDIrpCore.IrpEnterCount);
|
||
#define ODDUnLock() InterlockedDecrement((volatile LONG *)&ODDIrpCore.IrpEnterCount);
|
||
|
||
|
||
static IRP_HOOK_HANDLER ODDIrpHook[] =
|
||
{
|
||
{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, TRUE, ODDControl},
|
||
{NULL, IRP_MJ_INTERNAL_DEVICE_CONTROL, TRUE, ODDControl},
|
||
{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, FALSE}
|
||
};
|
||
|
||
static PROCESS_MANAGER s_oddallowprocess[] =
|
||
{
|
||
{PG_PID_ALLOW, L"fph.exe", 7},
|
||
{PG_PID_ALLOW, L"fclient.exe", 11},
|
||
{PG_PID_ALLOW, L"iexplore.exe",13},
|
||
{PG_PID_ALLOW, L"kcdsaclt.exe",13},
|
||
{PG_PID_ALLOW, L"services.exe",13},
|
||
{PG_PID_ALLOW, L"AYAgent.aye", 11}
|
||
};
|
||
|
||
|
||
static ULONG GetIrpHookHandlerCount()
|
||
{
|
||
return sizeof(ODDIrpHook) / 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;
|
||
}
|
||
|
||
|
||
#pragma warning( disable : 4995 )
|
||
#pragma warning( disable : 4996 )
|
||
|
||
BOOLEAN IsODDReadOnly(PIRP irp)
|
||
{
|
||
PIO_STACK_LOCATION irpstack = IoGetCurrentIrpStackLocation(irp);
|
||
ULONG id = irpstack->MajorFunction;
|
||
ULONG code = irpstack->Parameters.DeviceIoControl.IoControlCode;
|
||
PSCSI_REQUEST_BLOCK scsi = NULL;
|
||
PSCSI_PASS_THROUGH_DIRECT scsi_through = NULL;
|
||
|
||
try
|
||
{
|
||
if (id == IRP_MJ_INTERNAL_DEVICE_CONTROL && s_oddtype == odd_atapi)
|
||
{
|
||
scsi = (PSCSI_REQUEST_BLOCK)irpstack->Parameters.Scsi.Srb;
|
||
if (scsi->Function == SRB_FUNCTION_EXECUTE_SCSI)
|
||
{
|
||
if (scsi->DataBuffer == NULL)
|
||
return FALSE;
|
||
|
||
if (scsi->SrbFlags & SRB_FLAGS_DATA_OUT)
|
||
return TRUE;
|
||
}
|
||
}
|
||
else if (id == IRP_MJ_DEVICE_CONTROL && s_oddtype == odd_cdrom)
|
||
{
|
||
if (code == IOCTL_SCSI_PASS_THROUGH_DIRECT)
|
||
{
|
||
scsi_through = (PSCSI_PASS_THROUGH_DIRECT)irp->AssociatedIrp.SystemBuffer;
|
||
if (scsi_through->DataIn == SCSI_IOCTL_DATA_OUT)
|
||
return TRUE;
|
||
}
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
NTSTATUS ODDControl(PDRIVER_DISPATCH dispath, PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PIO_STACK_LOCATION irpstack = IoGetCurrentIrpStackLocation(Irp);
|
||
//ULONG id = irpstack->MajorFunction;
|
||
ULONG ControlCode = irpstack->Parameters.DeviceIoControl.IoControlCode;
|
||
ULONG state = 0;
|
||
UNICODE_STRING processImagePath = { 0, };
|
||
ULONG ProcessId;
|
||
WCHAR* process_name = NULL;
|
||
|
||
if (!g_bs1Flt.IsAttached)
|
||
goto $ODDCleanup;
|
||
|
||
if (IsOwnDeviceObject(DeviceObject))
|
||
goto $ODDCleanup;
|
||
|
||
if (g_bs1Flt.UserProcess == PsGetCurrentProcess())
|
||
goto $ODDCleanup;
|
||
|
||
if (IOCTL_SCSI_PASS_THROUGH != ControlCode && IOCTL_SCSI_PASS_THROUGH_DIRECT != ControlCode)
|
||
{
|
||
goto $ODDCleanup;
|
||
}
|
||
|
||
ProcessId = HandleToULong(PsGetCurrentProcessId());
|
||
status = UGetCurrentStackProcessImageName(ProcessId, &processImagePath);
|
||
if (!NT_SUCCESS(status))
|
||
goto $ODDCleanup;
|
||
|
||
// if( IOCTL_SCSI_PASS_THROUGH != ControlCode && IOCTL_SCSI_PASS_THROUGH_DIRECT != ControlCode)
|
||
// {
|
||
// KLog("ODDControl, ioctrl except s_oddtype(%d), id(%x) ControlCode(%x)\n", s_oddtype, id, ControlCode);
|
||
// goto $ODDCleanup;
|
||
// }
|
||
|
||
|
||
process_name = wcsrchr(processImagePath.Buffer, '\\');
|
||
if (!process_name)
|
||
process_name = processImagePath.Buffer;
|
||
else
|
||
++process_name;
|
||
|
||
if (IsExceptionProcess(s_oddallowprocess, ARRAYSIZE(s_oddallowprocess), process_name) == PG_PID_ALLOW)
|
||
goto $ODDCleanup;
|
||
|
||
state = GetPolicyState(BDC_CDROM);
|
||
if (state == READONLY)
|
||
{
|
||
if (!IsODDReadOnly(Irp))
|
||
goto $ODDCleanup;
|
||
}
|
||
//IOCTL_STORAGE_CHECK_VERIFY2
|
||
if (state != ENABLE)
|
||
{
|
||
/*
|
||
/// <20><><EFBFBD><EFBFBD> ó<><C3B3>
|
||
PSCSI_REQUEST_BLOCK scsi = NULL;
|
||
PSCSI_PASS_THROUGH_DIRECT scsi_through = NULL;
|
||
|
||
if(id == IRP_MJ_INTERNAL_DEVICE_CONTROL && s_oddtype == odd_atapi)
|
||
{
|
||
scsi = (PSCSI_REQUEST_BLOCK)irpstack->Parameters.Scsi.Srb;
|
||
if(scsi)
|
||
{
|
||
KLog("ODDControl, inter Function(%x) DataTransferLength(%d) SrbFlags(%x)\n", scsi->Function, scsi->DataTransferLength, scsi->SrbFlags);
|
||
}
|
||
|
||
// if(scsi->Function == SRB_FUNCTION_EXECUTE_SCSI)
|
||
// {
|
||
// if(scsi->DataBuffer == NULL)
|
||
// return FALSE;
|
||
//
|
||
// if(scsi->SrbFlags & SRB_FLAGS_DATA_OUT)
|
||
// return TRUE;
|
||
}
|
||
else if(id == IRP_MJ_DEVICE_CONTROL && s_oddtype == odd_cdrom)
|
||
{
|
||
if(ControlCode == IOCTL_SCSI_PASS_THROUGH_DIRECT)
|
||
{
|
||
scsi_through = (PSCSI_PASS_THROUGH_DIRECT)Irp->AssociatedIrp.SystemBuffer;
|
||
// if(scsi_through->DataIn == SCSI_IOCTL_DATA_OUT)
|
||
// return TRUE;
|
||
if(scsi_through)
|
||
{
|
||
KLog("ODDControl, device DataIn(%x) DataTransferLength(%d) TargetId(%x)\n", scsi_through->DataIn, scsi_through->DataTransferLength, scsi_through->TargetId);
|
||
}
|
||
}
|
||
}
|
||
|
||
KLog("ODDControl, processname(%S) ControlCode(%x)\n", processImagePath.Buffer, ControlCode);
|
||
*/
|
||
|
||
SetLog(NULL, NULL, LOG_POLICY, BDC_CDROM, state, 0, (PWCHAR)processImagePath.Buffer, NULL);
|
||
|
||
|
||
UStrFree(&processImagePath);
|
||
|
||
//UserNotifyMessage(DEVICE_CDROM, NULL, NULL);
|
||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
return STATUS_INVALID_DEVICE_REQUEST;
|
||
}
|
||
|
||
$ODDCleanup:
|
||
UStrFree(&processImagePath);
|
||
return dispath(DeviceObject, Irp);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
NTSTATUS ODDHookDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||
{
|
||
|
||
NTSTATUS NtStatus = STATUS_SUCCESS;
|
||
PIO_STACK_LOCATION pCurrentIoStack = IoGetCurrentIrpStackLocation(Irp);
|
||
ULONG Id = pCurrentIoStack->MajorFunction;
|
||
|
||
ODDLock();
|
||
|
||
if (IsAdrIrpHookHandler(ODDIrpHook, Id))
|
||
{
|
||
NtStatus = ODDIrpHook[Id].Work(
|
||
ODDIrpHook[Id].pOrgHandler,
|
||
DeviceObject,
|
||
Irp
|
||
);
|
||
}
|
||
ODDUnLock();
|
||
|
||
return NtStatus;
|
||
|
||
}
|
||
|
||
|
||
static PVOID GetHookDispatch()
|
||
{
|
||
return (PVOID)ODDHookDispatch;
|
||
}
|
||
|
||
static PIRP_HOOK_HANDLER GetIrpHookHandler()
|
||
{
|
||
return ODDIrpHook;
|
||
}
|
||
|
||
static PIRP_CORE GetIrpCore()
|
||
{
|
||
|
||
ODDIrpCore.HookDispatch = GetHookDispatch();
|
||
ODDIrpCore.IrpHookHandler = GetIrpHookHandler();
|
||
ODDIrpCore.IrpHookHandlerCount = GetIrpHookHandlerCount();
|
||
ODDIrpCore.IrpEnterCount = 0;
|
||
return &ODDIrpCore;
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS ODDIrpHookCleanup()
|
||
{
|
||
ULONG cnt = 0;
|
||
//ULONG OrSaveWP;
|
||
LARGE_INTEGER WaitTime;
|
||
PDRIVER_OBJECT DriverObject = ODDIrpCore.HookDriverObject;
|
||
ULONG IrpHookHandlerCount = ODDIrpCore.IrpHookHandlerCount;
|
||
PIRP_HOOK_HANDLER pIhh = ODDIrpCore.IrpHookHandler;
|
||
|
||
if (!DriverObject || !IrpHookHandlerCount || !pIhh)
|
||
return STATUS_UNSUCCESSFUL;
|
||
|
||
if (!pIhh)
|
||
return STATUS_UNSUCCESSFUL;
|
||
|
||
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 (ODDIrpCore.IrpEnterCount > 0)
|
||
KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);
|
||
|
||
KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);
|
||
KLogEx(DEBUG_TRACE_INFO, "complete\n");
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
NTSTATUS ODDIrpHookInit()
|
||
{
|
||
// WCHAR * xpname = L"\\driver\\imapi";
|
||
// WCHAR * win7name = L"\\driver\\atapi";
|
||
// WCHAR * etcname = L"\\driver\\Cdrom";
|
||
WCHAR* name = NULL;
|
||
//ULONG type = 0;
|
||
ULONG cnt = 0;
|
||
//PVOID TargetPoint = NULL;
|
||
|
||
ULONG IrpHookHandlerCount = 0;
|
||
PIRP_HOOK_HANDLER pIhh = NULL;
|
||
|
||
PIRP_CORE irpcore = NULL;
|
||
PDRIVER_OBJECT obj = NULL;
|
||
|
||
if (g_bs1Flt.OsVersion >= WinVista)
|
||
{
|
||
s_oddtype = odd_atapi;
|
||
}
|
||
else
|
||
{
|
||
s_oddtype = odd_imapi;
|
||
}
|
||
|
||
name = s_oddname[s_oddtype];
|
||
KLogEx(DEBUG_TRACE_INFO, "driver(%S)\n", name);
|
||
obj = SearchDriverObject(name);
|
||
if (!obj)
|
||
{
|
||
|
||
s_oddtype = odd_cdrom;
|
||
name = s_oddname[s_oddtype];
|
||
KLogEx(DEBUG_TRACE_INFO, "driver(%S)\n", name);
|
||
obj = SearchDriverObject(name);
|
||
if (!obj)
|
||
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(%08p)\n", irpcore->HookDriverObject->MajorFunction[cnt]);
|
||
}
|
||
|
||
InterlockedExchangePointer((PVOID)&irpcore->HookDriverObject->MajorFunction[cnt], (PVOID)irpcore->HookDispatch);
|
||
KLogEx(DEBUG_TRACE_INFO, "hook c (%S), (%d), (%08x), (%08x)\n", name, cnt, pIhh[cnt].pOrgHandler, irpcore->HookDriverObject->MajorFunction[cnt]);
|
||
}
|
||
|
||
KLogEx(DEBUG_TRACE_INFO, "complete\n");
|
||
return STATUS_SUCCESS;
|
||
} |