BSOne.SFC/Tocsg.Module/Bs1Flt/bs1flt/bs1flt_odd_hook.c

428 lines
10 KiB
C
Raw Blame History

#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;
}