1337 lines
40 KiB
C
1337 lines
40 KiB
C
#include "precomp.h"
|
|
|
|
|
|
NTSTATUS
|
|
Bs1FltFileInUserMode(
|
|
__in PCFLT_RELATED_OBJECTS FltObjects,
|
|
__in PUNICODE_STRING FilePath,
|
|
__out PBOOLEAN SafeToOpen
|
|
)
|
|
|
|
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
//PVOID buffer = NULL;
|
|
//ULONG bytesRead;
|
|
PFILE_OBJECT_DESC notification = NULL;
|
|
//FLT_VOLUME_PROPERTIES volumeProps;
|
|
//LARGE_INTEGER offset;
|
|
ULONG replyLength;
|
|
//ULONG length;
|
|
//PFLT_VOLUME volume = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
|
|
*SafeToOpen = TRUE;
|
|
|
|
if (g_bs1Flt.ClientPort == NULL)
|
|
{
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
try {
|
|
|
|
notification = ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_OBJECT_DESC), 'pbsn');
|
|
if (notification == NULL)
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
leave;
|
|
}
|
|
|
|
RtlZeroMemory(notification, sizeof(FILE_OBJECT_DESC));
|
|
notification->pid = HandleToULong(PsGetCurrentProcessId());
|
|
notification->size = min(FilePath->Length, PATH_SIZE - 2);
|
|
RtlCopyMemory(¬ification->path, FilePath->Buffer, notification->size);
|
|
|
|
/// 유저 클라이언트로 정보 전달 & Wait
|
|
KLogEx(DEBUG_TRACE_INFO, "notify path (%d)(%S)\n", notification->pid, FilePath->Buffer);
|
|
replyLength = sizeof(BS1FLT_REPLY);
|
|
status = FltSendMessage(g_bs1Flt.Filter,
|
|
&g_bs1Flt.ClientPort,
|
|
notification,
|
|
sizeof(FILE_OBJECT_DESC),
|
|
notification,
|
|
&replyLength,
|
|
NULL);
|
|
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
*SafeToOpen = ((PBS1FLT_REPLY)notification)->SafeToOpen;
|
|
KLogEx(DEBUG_TRACE_INFO, "FltSendMessage, Success %d size = %d\n", *SafeToOpen, sizeof(FILE_OBJECT_DESC));
|
|
}
|
|
else
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "couldn't send message to user-mode to, status 0x%X\n", status);
|
|
}
|
|
|
|
}
|
|
finally
|
|
{
|
|
if (NULL != notification)
|
|
{
|
|
ExFreePoolWithTag(notification, 'pbsn');
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
FLT_PREOP_CALLBACK_STATUS
|
|
Bs1FltNofity(PFLT_CALLBACK_DATA Data,
|
|
PCFLT_RELATED_OBJECTS FltObjects,
|
|
PUNICODE_STRING pUniFilePath,
|
|
ULONG ulPidType
|
|
)
|
|
{
|
|
BOOLEAN safeToOpen = FALSE;
|
|
FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
ULONG create_option = 0;
|
|
ULONG disposition = 0;
|
|
DWORD desiredaccess = 0;
|
|
USHORT fileattribute = 0;
|
|
|
|
create_option = Data->Iopb->Parameters.Create.Options;
|
|
disposition = (create_option >> 24) & 0xFF;
|
|
desiredaccess = Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
|
|
fileattribute = Data->Iopb->Parameters.Create.FileAttributes;
|
|
|
|
if (disposition != FILE_OPEN)
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
if (!(fileattribute & FILE_ATTRIBUTE_NORMAL))
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
/// 디렉토리면 예외
|
|
if (create_option & FILE_DIRECTORY_FILE)
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
if (!(create_option & FILE_NON_DIRECTORY_FILE))
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
//cretaeoption = 1000140, disposition = 1, desiredaccess = a1 예외 처리 정보
|
|
if (create_option & FILE_COMPLETE_IF_OPLOCKED)
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
if (ulPidType == PG_PID_WHITE)
|
|
{
|
|
Bs1FltFileInUserMode(FltObjects, pUniFilePath, &safeToOpen);
|
|
if (!safeToOpen)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "foul language detected in postcreate !!!\n");
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
Data->IoStatus.Information = 0;
|
|
returnStatus = FLT_PREOP_COMPLETE;;
|
|
}
|
|
|
|
//SetFileObjectList(0, FltObjects->FileObject, pUniFilePath->Buffer, pUniFilePath->Length);
|
|
}
|
|
|
|
return returnStatus;
|
|
}
|
|
|
|
BOOLEAN
|
|
Bs1FltIsFileName(PFLT_CALLBACK_DATA Data,
|
|
PCFLT_RELATED_OBJECTS FltObjects,
|
|
PUNICODE_STRING pUniFilePath,
|
|
ULONG ulPidType,
|
|
ULONG ulFileType
|
|
)
|
|
{
|
|
|
|
//WCHAR buf[260] = { 0, };
|
|
ULONG create_option = 0;
|
|
WCHAR* ptr = NULL;
|
|
UNICODE_STRING uniFileName = { 0, };
|
|
UCHAR major = Data->Iopb->MajorFunction;
|
|
|
|
UNREFERENCED_PARAMETER(ulPidType);
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(Data);
|
|
|
|
if (major == IRP_MJ_CREATE)
|
|
{
|
|
create_option = Data->Iopb->Parameters.Create.Options;
|
|
//KLogEx("PBShareLockIsFileName, CreateOption = %x\n", create_option);
|
|
if (create_option & FILE_DIRECTORY_FILE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// if(!(create_option & FILE_NON_DIRECTORY_FILE))
|
|
// {
|
|
// return TRUE;
|
|
// }
|
|
|
|
|
|
ptr = wcsrchr(pUniFilePath->Buffer, '\\');
|
|
if (ptr)
|
|
{
|
|
++ptr;
|
|
RtlInitUnicodeString(&uniFileName, ptr);
|
|
/// 2015.3.20 정책 파일 접근에 대한 문제로 인해 모든 프로세스에 읽기 전용으로 변경
|
|
if (IsFileName(ulFileType, uniFileName.Buffer, uniFileName.Length)/* && ulPidType == PG_PID_GREEN*/)
|
|
{
|
|
if (major == IRP_MJ_CREATE)
|
|
{
|
|
DWORD desiredaccess = Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
|
|
KLogEx(DEBUG_TRACE_ERROR, "desiredaccess(%x) name(%S) len(%d)\n", desiredaccess, uniFileName.Buffer, uniFileName.Length);
|
|
if (desiredaccess & ((WRITE_MODE | DELETE)))
|
|
return FALSE;
|
|
}
|
|
else if (major == IRP_MJ_SET_INFORMATION)
|
|
{
|
|
FILE_INFORMATION_CLASS fileinfoclass = Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
|
|
/// 이름 변경 & 삭제의 경우 차단
|
|
if (fileinfoclass == FileRenameInformation || fileinfoclass == FileDispositionInformation
|
|
|| fileinfoclass == FileRenameInformationEx || fileinfoclass == FileDispositionInformationEx)
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
BOOLEAN IsPolicyState(ULONG type, ULONG state, PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS fltobject)
|
|
{
|
|
ULONG disposition;
|
|
ULONG desired_access = 0;
|
|
ULONG create_option = 0;
|
|
// 쓰기 및 변경과 관련된 모든 권한 마스크 정의
|
|
ULONG WriteAccessMask = FILE_WRITE_DATA | FILE_APPEND_DATA |
|
|
FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |
|
|
FILE_DELETE_CHILD | DELETE |
|
|
WRITE_DAC | WRITE_OWNER |
|
|
MAXIMUM_ALLOWED |
|
|
GENERIC_WRITE | GENERIC_ALL;
|
|
|
|
UNREFERENCED_PARAMETER(type);
|
|
|
|
if (data->Iopb == NULL) return FALSE; // 방어 코드
|
|
|
|
desired_access = data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
|
|
create_option = data->Iopb->Parameters.Create.Options;
|
|
// Disposition 추출 (상위 8비트)
|
|
disposition = (data->Iopb->Parameters.Create.Options >> 24) & 0xFF;
|
|
|
|
if (state == DISABLE) return TRUE;
|
|
if (state == ENABLE) return FALSE;
|
|
|
|
// READONLY 정책 처리
|
|
if (state == READONLY)
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "READONLY, disposition[%x],create_option(%x), desired_access(%x)\n", disposition, create_option, desired_access);
|
|
// 1. [핵심] Disposition 별 처리
|
|
switch (disposition)
|
|
{
|
|
// [CASE A] 무조건 파일 내용을 변경하거나 새로 만드는 경우 -> 즉시 차단
|
|
case FILE_CREATE: // 없으면 생성, 있으면 실패 -> 생성 시도이므로 차단
|
|
case FILE_SUPERSEDE: // 있으면 덮어쓰기(삭제 후 생성) -> 차단
|
|
case FILE_OVERWRITE: // 있으면 덮어쓰기 -> 차단
|
|
case FILE_OVERWRITE_IF: // 없으면 생성, 있으면 덮어쓰기 -> 둘 다 변경이므로 차단
|
|
KLogEx(DEBUG_TRACE_ERROR, "Block(Destructive Action) disposition[%x]\n", disposition);
|
|
return TRUE;
|
|
|
|
// [CASE B] 파일이 있으면 열고, 없으면 만드는 경우
|
|
case FILE_OPEN_IF:
|
|
{
|
|
HANDLE hFileHandle = 0;
|
|
OBJECT_ATTRIBUTES objectAttributes; // 초기화 주의
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS ntStatus = 0;
|
|
|
|
InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
|
|
|
|
// 파일 존재 여부 확인 (읽기 권한으로 시도)
|
|
ntStatus = FltCreateFile(
|
|
fltobject->Filter,
|
|
fltobject->Instance,
|
|
&hFileHandle,
|
|
FILE_READ_ATTRIBUTES, // 최소 권한으로 확인
|
|
&objectAttributes,
|
|
&IoStatusBlock,
|
|
0,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE, // 옵션 주의
|
|
NULL,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
// 파일이 존재함 -> "파일 열기" 시도
|
|
FltClose(hFileHandle);
|
|
|
|
// [중요 수정] 파일이 있어도 '쓰기 권한'을 요청했다면 차단해야 함
|
|
if (desired_access & WriteAccessMask)
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "Block(OPEN_IF/Exist but Write) access(%x)\n", desired_access);
|
|
return TRUE;
|
|
}
|
|
// 쓰기 권한 없으면 허용 (읽기 전용 오픈)
|
|
}
|
|
else
|
|
{
|
|
// 파일이 없음 -> "파일 생성" 시도 -> 차단
|
|
KLogEx(DEBUG_TRACE_ERROR, "Block(OPEN_IF/Not Exist) -> Try Create\n");
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// [CASE C] 파일이 있을 때만 여는 경우 (기존 코드에서 가장 취약했던 부분)
|
|
case FILE_OPEN:
|
|
{
|
|
// [중요 수정] DELETE 뿐만 아니라 Write Data, Append Data 등도 체크해야 함
|
|
if (desired_access & WriteAccessMask)
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "Block(FILE_OPEN with Write) access(%x)\n", desired_access);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
*/
|
|
|
|
BOOLEAN IsPolicyState(ULONG type, ULONG state, PFLT_CALLBACK_DATA data, PCFLT_RELATED_OBJECTS fltobject)
|
|
{
|
|
ULONG disposition;
|
|
ULONG desired_access = 0;
|
|
ULONG create_option = 0;
|
|
USHORT create_fileattribute = 0;
|
|
//USHORT share_access = 0;
|
|
//ULONG devicetype = 0;
|
|
|
|
UNREFERENCED_PARAMETER(type);
|
|
desired_access = data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
|
|
create_option = data->Iopb->Parameters.Create.Options;
|
|
disposition = (create_option >> 24) & 0xFF;
|
|
create_fileattribute = data->Iopb->Parameters.Create.FileAttributes;
|
|
|
|
if (state == DISABLE)
|
|
return TRUE;
|
|
|
|
if (state == ENABLE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else if (state == READONLY)
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "READONLY, disposition[%x],create_option(%x), desired_access(%x)\n", disposition, create_option, desired_access);
|
|
|
|
switch (disposition)
|
|
{
|
|
case FILE_CREATE:
|
|
case FILE_SUPERSEDE:
|
|
{
|
|
/// 폴더 생성 차단
|
|
if (create_option & FILE_DIRECTORY_FILE)
|
|
{
|
|
if (desired_access & (FILE_WRITE_EA))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(1) create_option(%x), desired_access(%x)\n", create_option, desired_access);
|
|
return TRUE;
|
|
}
|
|
|
|
// sskim - 170207 Added.
|
|
if (desired_access & (FILE_LIST_DIRECTORY))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(2) create_option(%x), desired_access(%x)\n", create_option, desired_access);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if (desired_access & (FILE_WRITE_DATA))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(3) disposition(%x), desired_access(%x)\n", disposition, desired_access);
|
|
return TRUE;
|
|
}
|
|
// 삭제 차단
|
|
if (desired_access & (DELETE))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(4) disposition(%x), desired_access(%x)\n", disposition, desired_access);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
}
|
|
case FILE_OVERWRITE_IF:
|
|
case FILE_OPEN_IF:
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "FILE_OVERWRITE_IF , FILE_OPEN_IF disposition[%x]create_option(%x), desired_access(%x)\n", disposition, create_option, desired_access);
|
|
}
|
|
|
|
{
|
|
HANDLE hFileHandle = 0;
|
|
OBJECT_ATTRIBUTES objectAttributes = { 0, };
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
NTSTATUS ntStatus = 0;
|
|
|
|
ntStatus = FltCreateFile(
|
|
fltobject->Filter, fltobject->Instance, &hFileHandle,
|
|
GENERIC_READ,
|
|
&objectAttributes,
|
|
&IoStatusBlock,
|
|
0,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_DELETE | FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
FILE_OPEN,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
// 이미 파일이 있는 경우
|
|
FltClose(hFileHandle);
|
|
// 허용
|
|
KLogEx(DEBUG_TRACE_ERROR, "PERMIT(1) disposition(%x), desired_access(%x),create_option(%x)\n", disposition, desired_access, create_option);
|
|
|
|
}
|
|
else
|
|
{
|
|
//차단
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(5) disposition(%x), desired_access(%x)\n", disposition, desired_access);
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
if (desired_access & (DELETE))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(6) disposition(%x), desired_access(%x)\n", disposition, desired_access);
|
|
return TRUE;
|
|
}
|
|
|
|
{
|
|
if(desired_access & (FILE_WRITE_DATA))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(3) disposition(%x), desired_access(%x)\n", disposition, desired_access);
|
|
return TRUE;
|
|
}
|
|
// 삭제 차단
|
|
if(desired_access & (DELETE))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(4) disposition(%x), desired_access(%x)\n", disposition, desired_access);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
break;
|
|
case FILE_OPEN:
|
|
{
|
|
if (desired_access & (DELETE))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "block(7) disposition(%x), desired_access(%x)\n", disposition, desired_access);
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
break;
|
|
case FILE_OVERWRITE:
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "PERMIT(2) disposition(%x), desired_access(%x),create_option(%x)\n", disposition, desired_access, create_option);
|
|
//return TRUE;
|
|
}
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN IsNetworkDrive(LPWSTR path)
|
|
{
|
|
static LPCWSTR s_networkSignatures[] =
|
|
{
|
|
/// 네트워크 드라이브 사용
|
|
/// etc
|
|
/// win 7. \Device\Mup\;LanmanRedirector\;Z:00000000001cdd14\KMG-PC\share\allowpl - 복사본 (2).ini
|
|
/// xp sp3 \Device\LanmanRedirector\;Z:00000000000133ab\kmg-pc\share\
|
|
|
|
L"\\;LanmanRedirector\\;",
|
|
L"\\;lanmanredirector\\;",
|
|
L"\\LanmanRedirector\\;",
|
|
NULL
|
|
};
|
|
|
|
LPCWSTR* ep = s_networkSignatures;
|
|
while (*ep)
|
|
{
|
|
if (wcsstr(path, *ep) != NULL)
|
|
return TRUE;
|
|
|
|
++ep;
|
|
}
|
|
|
|
//드라이브 레터 패턴 확인(; Z: 또는; z: 형태)
|
|
LPCWSTR p = path;
|
|
while ((p = wcschr(p, L';')) != NULL)
|
|
{
|
|
// p[0]은 ';' 입니다.
|
|
// p[1]이 NULL이 아니고(문자열 끝 아님), p[2]가 ':' 인지 확인
|
|
if (p[1] != L'\0' && p[2] == L':')
|
|
{
|
|
WCHAR driveLetter = p[1];
|
|
// 영문자(A-Z, a-z)인지 확인
|
|
if ((driveLetter >= L'A' && driveLetter <= L'Z') ||
|
|
(driveLetter >= L'a' && driveLetter <= L'z'))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
p++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOLEAN once = FALSE;
|
|
BOOLEAN IsUsbException(PCFLT_RELATED_OBJECTS FltObjects, ULONG device_type)
|
|
{
|
|
PVOLUME_CONTEXT vctx = NULL;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
BOOLEAN state = FALSE;
|
|
|
|
UNREFERENCED_PARAMETER(device_type);
|
|
|
|
status = FltGetVolumeContext(FltObjects->Filter, FltObjects->Volume, &vctx);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "FltGetVolumeContext Failed (%x)\n", status);
|
|
return FALSE;
|
|
}
|
|
|
|
//KLogEx(DEBUG_TRACE_INFO, "Vendor ID(%s),productid(%s)(%s)\n", vctx->vendorid, vctx->productid, vctx->vendorspecific);
|
|
|
|
if (IsUsbDiskExceptionList((PCHAR)vctx->vendorid, (PCHAR)vctx->productid, (PCHAR)vctx->productrevisionlevel, (PCHAR)vctx->vendorspecific))
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "Vendor ID(%s),productid(%s)(%s)\n", vctx->vendorid, vctx->productid, vctx->vendorspecific);
|
|
state = TRUE;
|
|
}
|
|
|
|
FltReleaseContext(vctx);
|
|
return state;
|
|
|
|
}
|
|
// 기본 필터링 조건을 확인하여 패스 여부를 결정
|
|
BOOLEAN IsSkipCondition(PFLT_CALLBACK_DATA Data)
|
|
{
|
|
if (!g_bs1Flt.IsAttached)
|
|
return TRUE;
|
|
|
|
if (IoThreadToProcess(Data->Thread) == g_bs1Flt.UserProcess)
|
|
return TRUE;
|
|
|
|
if (!NT_SUCCESS(Data->IoStatus.Status) || (STATUS_REPARSE == Data->IoStatus.Status))
|
|
return TRUE;
|
|
|
|
if (Data->Iopb->MajorFunction == IRP_MJ_CLEANUP)
|
|
return TRUE;
|
|
|
|
// 관심있는 Major Function만 처리
|
|
if (Data->Iopb->MajorFunction != IRP_MJ_SET_INFORMATION &&
|
|
Data->Iopb->MajorFunction != IRP_MJ_CREATE &&
|
|
Data->Iopb->MajorFunction != IRP_MJ_READ &&
|
|
Data->Iopb->MajorFunction != IRP_MJ_WRITE) // READ/WRITE 추가 (코드 로직상 필요)
|
|
return TRUE;
|
|
|
|
if (KeGetCurrentIrql() > PASSIVE_LEVEL)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// 로컬 디스크 정책 처리
|
|
FLT_PREOP_CALLBACK_STATUS HandleLocalDiskPolicy(
|
|
PFLT_CALLBACK_DATA Data,
|
|
PCFLT_RELATED_OBJECTS FltObjects,
|
|
PUNICODE_STRING pUniFileName,
|
|
PUNICODE_STRING pProcessPath,
|
|
ULONG pid,
|
|
ULONG pidType
|
|
)
|
|
{
|
|
ULONG pathType = 0;
|
|
ULONG majorFunction = Data->Iopb->MajorFunction;
|
|
ULONG createOption = 0;
|
|
ULONG disposition = 0;
|
|
ULONG desiredAccess = 0;
|
|
|
|
UNREFERENCED_PARAMETER(pProcessPath);
|
|
|
|
if (!g_bs1Flt.IsFolderProtect)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
// 허용된 프로세스인 경우, Rename/Delete 차단 옵션 확인
|
|
if (pidType & PG_PID_ALLOW)
|
|
{
|
|
if ((pidType & PG_PID_BLOCK_RENAME) && (majorFunction == IRP_MJ_SET_INFORMATION))
|
|
{
|
|
FILE_INFORMATION_CLASS infoClass = Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
|
|
if (infoClass != FileRenameInformation && infoClass != FileRenameInformationEx)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
// Rename이면 아래 로직 계속 진행 (차단 검사)
|
|
}
|
|
else
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
}
|
|
|
|
pathType = IsProtectPath(PG_PATH_ALL, pUniFileName->Buffer, pUniFileName->Length);
|
|
if (pathType == PG_PATH_UNDEFINED)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (pathType == PG_PATH_GRAY) // GRAY: 읽기 허용, 쓰기/삭제/이름변경 차단
|
|
{
|
|
if (majorFunction == IRP_MJ_CREATE)
|
|
{
|
|
createOption = Data->Iopb->Parameters.Create.Options;
|
|
disposition = (createOption >> 24) & 0xFF;
|
|
desiredAccess = Data->Iopb->Parameters.Create.SecurityContext->DesiredAccess;
|
|
|
|
if (disposition == FILE_CREATE || (desiredAccess & (WRITE_MODE | DELETE)))
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "PG_PATH_GRAY BLOCK: CREATE/WRITE/DELETE Attempt. Path(%S)\n", pUniFileName->Buffer);
|
|
}
|
|
else
|
|
{
|
|
// 읽기 전용 접근 허용
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
}
|
|
else if (majorFunction == IRP_MJ_SET_INFORMATION)
|
|
{
|
|
FILE_INFORMATION_CLASS infoClass = Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
|
|
if (infoClass != FileRenameInformation && infoClass != FileDispositionInformation &&
|
|
infoClass != FileRenameInformationEx && infoClass != FileDispositionInformationEx)
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
else
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "PG_PATH_GRAY BLOCK: RENAME Attempt. Path(%S)\n", pUniFileName->Buffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pathType == PG_PATH_BLACK) // BLACK: 모든 접근 차단(단, 예외 파일은 허용)
|
|
{
|
|
if (Bs1FltIsFileName(Data, FltObjects, pUniFileName, pidType, PG_FILE_ALLOW))
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "PG_PATH_BLACK PERMIT FILENAME: Path(%S)\n", pUniFileName->Buffer);
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "ACCESS DENIED (Local Disk): Path(%S), Pid(%d)\n", pUniFileName->Buffer, pid);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
Data->IoStatus.Information = 0;
|
|
return FLT_PREOP_COMPLETE;
|
|
}
|
|
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
FLT_PREOP_CALLBACK_STATUS HandleNetWorkInDevicePolicy(
|
|
PFLT_CALLBACK_DATA Data,
|
|
PCFLT_RELATED_OBJECTS FltObjects,
|
|
ULONG deviceType,
|
|
ULONG policyState,
|
|
ULONG policyLog
|
|
)
|
|
{
|
|
char szProcessName[20] = { 0, };
|
|
WCHAR processName[50] = { 0, };
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
NTSTATUS status;
|
|
ULONG pid = HandleToULong(PsGetCurrentProcessId());
|
|
|
|
try
|
|
{
|
|
status = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "FltGetFileNameInformation Failed [%x]\n", status);
|
|
leave;
|
|
}
|
|
else
|
|
{
|
|
status = FltParseFileNameInformation(nameInfo);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "FltParseFileNameInformation Failed [%x]\n", status);
|
|
leave;
|
|
}
|
|
}
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "Network Drive In processName(%S), Path(%S)\n", processName, nameInfo->Name.Buffer);
|
|
|
|
if (policyLog)
|
|
{
|
|
UGetProcessName(szProcessName);
|
|
RtlStringCbPrintfW(processName, sizeof(processName), L"%S", szProcessName);
|
|
SetLog(Data, FltObjects, LOG_POLICY, deviceType, policyState, 0, processName, nameInfo->Name.Buffer);
|
|
}
|
|
|
|
if (policyState != ENABLE)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "ACCESS DENIED Pid(%d)\n", pid);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
Data->IoStatus.Information = 0;
|
|
return FLT_PREOP_COMPLETE;
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (nameInfo != NULL)
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
|
|
// USB, 네트워크 및 기타 장치(CD-ROM 등) 정책 처리
|
|
FLT_PREOP_CALLBACK_STATUS HandleExternalDevicePolicy(
|
|
PFLT_CALLBACK_DATA Data,
|
|
PCFLT_RELATED_OBJECTS FltObjects,
|
|
PUNICODE_STRING pUniFileName,
|
|
PUNICODE_STRING pProcessPath,
|
|
ULONG pid,
|
|
ULONG deviceType,
|
|
ULONG policyState,
|
|
ULONG policyLog
|
|
)
|
|
{
|
|
|
|
BOOLEAN isBlock = FALSE;
|
|
ULONG majorFunction = Data->Iopb->MajorFunction;
|
|
|
|
UNREFERENCED_PARAMETER(policyLog);
|
|
|
|
if (!g_bs1Flt.IsDeviceProtect)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
try
|
|
{
|
|
if (deviceType == BDC_USB_DISK || deviceType == BDC_EXTERNALHDD)
|
|
{
|
|
if (IsUsbException(FltObjects, deviceType))
|
|
leave;
|
|
}
|
|
|
|
// 네트워크 드라이브/공유 경로 재확인 및 정책 갱신
|
|
if (deviceType == BDC_NETWORKDRIVEOUT)
|
|
{
|
|
if (!IsNetworkDrive(pUniFileName->Buffer))
|
|
{
|
|
deviceType = BDC_NETWORKSHAREOUT;
|
|
policyState = GetPolicyState(deviceType);
|
|
}
|
|
}
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "Check External Policy: Pid(%d), Dev(%d), Path(%S)\n", pid, deviceType, pUniFileName->Buffer);
|
|
|
|
// Operation 별 차단 여부 결정
|
|
switch (majorFunction)
|
|
{
|
|
case IRP_MJ_CREATE:
|
|
if (IsPolicyState(deviceType, policyState, Data, FltObjects))
|
|
isBlock = TRUE;
|
|
|
|
break;
|
|
|
|
case IRP_MJ_SET_INFORMATION:
|
|
{
|
|
FILE_INFORMATION_CLASS infoClass = Data->Iopb->Parameters.SetFileInformation.FileInformationClass;
|
|
if (policyState == ENABLE)
|
|
{
|
|
// ENABLE 상태일 때 로그 처리 로직 (주석되어 있었음)
|
|
}
|
|
else
|
|
{
|
|
if (infoClass == FileRenameInformation || infoClass == FileDispositionInformation)
|
|
isBlock = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IRP_MJ_READ:
|
|
if (deviceType == BDC_CDROM)
|
|
{
|
|
// Windows Burning 관련 임시 파일 차단
|
|
if (wcsstr(pUniFileName->Buffer, L"\\AppData\\Local\\Microsoft\\Windows\\Burn\\Burn\\") != NULL)
|
|
isBlock = TRUE;
|
|
}
|
|
break;
|
|
|
|
case IRP_MJ_WRITE:
|
|
if (policyState != ENABLE)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "Check External Policy: Write !!!! Pid(%d), Dev(%d), Path(%S)\n", pid, deviceType, pUniFileName->Buffer);
|
|
isBlock = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// 네트워크 호스트 IP 허용 예외 처리
|
|
if ((deviceType == BDC_NETWORKDRIVEOUT || deviceType == BDC_NETWORKSHAREOUT) && isBlock)
|
|
{
|
|
if (IsAllowHostIp(pUniFileName->Buffer, pUniFileName->Length))
|
|
{
|
|
isBlock = FALSE; // IP 허용 목록에 있으면 차단 해제
|
|
}
|
|
}
|
|
|
|
// CD-ROM 예외 처리
|
|
if (deviceType == BDC_CDROM && isBlock)
|
|
{
|
|
PWCHAR pwszTemp = wcsstr(pUniFileName->Buffer, L"\\CdRom");
|
|
if (pwszTemp)
|
|
{
|
|
size_t len = wcslen(pwszTemp);
|
|
if (len == 7 || len == 8)
|
|
isBlock = FALSE;
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
// 로그 기록
|
|
if (policyLog)
|
|
{
|
|
if (policyState == READONLY && !isBlock)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
SetLog(Data, FltObjects, LOG_POLICY, deviceType, policyState, 0, pProcessPath->Buffer, pUniFileName->Buffer);
|
|
}
|
|
}
|
|
|
|
// 최종 차단 처리
|
|
if (policyState != ENABLE && isBlock == TRUE)
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "ACCESS DENIED Pid(%d), Path(%S)\n", pid, pUniFileName->Buffer);
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
Data->IoStatus.Information = 0;
|
|
return FLT_PREOP_COMPLETE;
|
|
}
|
|
}
|
|
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
/*************************************************************************
|
|
MiniFilter callback routines.
|
|
*************************************************************************/
|
|
FLT_PREOP_CALLBACK_STATUS
|
|
Bs1FltPreOperation(
|
|
_Inout_ PFLT_CALLBACK_DATA Data,
|
|
_In_ PCFLT_RELATED_OBJECTS FltObjects,
|
|
_Flt_CompletionContext_Outptr_ PVOID* CompletionContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is a pre-operation dispatch routine for this miniFilter.
|
|
|
|
This is non-pageable because it could be called on the paging path
|
|
|
|
Arguments:
|
|
|
|
Data - Pointer to the filter callbackData that is passed to us.
|
|
|
|
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
|
|
opaque handles to this filter, instance, its associated volume and
|
|
file object.
|
|
|
|
CompletionContext - The context for the completion routine for this
|
|
operation.
|
|
|
|
Return Value:
|
|
|
|
The return value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
|
|
FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
UNICODE_STRING filePath = { 0, };
|
|
UNICODE_STRING processPath = { 0, };
|
|
NTSTATUS status;
|
|
ULONG pid = 0;
|
|
ULONG pidType = 0;
|
|
ULONG processType = 0;
|
|
ULONG deviceType = 0;
|
|
ULONG policyState = 0;
|
|
ULONG policyLog = 0;
|
|
char szProcessName[20] = { 0, };
|
|
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
PAGED_CODE();
|
|
|
|
if (IsSkipCondition(Data))
|
|
{
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
deviceType = GetDeviceType(Data, FltObjects);
|
|
if (deviceType == BDC_UNKNOWN_DEV)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (Data->RequestorMode == KernelMode)
|
|
{
|
|
if (deviceType != BDC_NETWORKDRIVEIN)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
// 정책 상태 확인
|
|
policyState = GetPolicyState(deviceType);
|
|
policyLog = IsPolicyLog(deviceType);
|
|
|
|
if (deviceType != BDC_LOCAL_DISK)
|
|
{
|
|
if (policyState == ENABLE && policyLog == FALSE)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
if (deviceType == BDC_NETWORKDRIVEIN)
|
|
{
|
|
return HandleNetWorkInDevicePolicy(
|
|
Data,
|
|
FltObjects,
|
|
deviceType,
|
|
policyState,
|
|
policyLog
|
|
);
|
|
}
|
|
|
|
// 프로세스 ID 및 이름 확인
|
|
pid = HandleToULong(PsGetCurrentProcessId());
|
|
pidType = PgGetPidState(pid);
|
|
if ((pidType & PG_PID_ALLOW))
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
UGetProcessName(szProcessName);
|
|
|
|
if (deviceType == BDC_LOCAL_DISK)
|
|
{
|
|
if (IsDefalutLocalDiskExceptProcess(szProcessName))
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
else
|
|
{
|
|
if (IsDefalutExternalDiskExceptProcess(szProcessName))
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
|
|
// 파일 이름 정보 획득
|
|
status = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "FltGetFileNameInformation Failed (%x)\n", status);
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
try
|
|
{
|
|
FltParseFileNameInformation(nameInfo);
|
|
if (!NT_SUCCESS(UStrNew(&filePath, nameInfo->Name.MaximumLength + 10)))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "FltParseFileNameInformation Failed (%S)\n", nameInfo->Name.Buffer);
|
|
leave;
|
|
}
|
|
UStrCopy(&filePath, &nameInfo->Name);
|
|
|
|
status = UGetCurrentStackProcessImageName(pid, &processPath);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
KLogEx(DEBUG_TRACE_ERROR, "Get Process Name Info Failed. szProcessName(%s), pid(%d), status(%x)\n", szProcessName, pid, status);
|
|
leave;
|
|
}
|
|
|
|
// 정의되지 않은 프로세스 정책 업데이트
|
|
if (pidType == PG_PID_UNDEFINED)
|
|
{
|
|
if (!IsAllowProcessName(processPath.Buffer, processPath.Length, &processType))
|
|
{
|
|
pidType = PG_PID_BLACK;
|
|
}
|
|
else
|
|
{
|
|
KLogEx(DEBUG_TRACE_INFO, "Update Allow Process, Path(%S)(%d), Type(%d)\n", processPath.Buffer, pid, processType);
|
|
pidType = processType;
|
|
PgAddPid(pid, pidType);
|
|
}
|
|
}
|
|
|
|
// 디바이스 타입별 로직 분기
|
|
if (deviceType == BDC_LOCAL_DISK)
|
|
{
|
|
returnStatus = HandleLocalDiskPolicy(Data, FltObjects, &filePath, &processPath, pid, pidType);
|
|
}
|
|
else
|
|
{
|
|
if (pidType & PG_PID_ALLOW)
|
|
leave;
|
|
|
|
returnStatus = HandleExternalDevicePolicy(Data, FltObjects, &filePath, &processPath, pid, deviceType, policyState, policyLog);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
UStrFree(&processPath);
|
|
UStrFree(&filePath);
|
|
if (nameInfo != NULL)
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
|
|
return returnStatus;
|
|
}
|
|
|
|
|
|
|
|
FLT_PREOP_CALLBACK_STATUS
|
|
Bs1FltPreRead(
|
|
__inout PFLT_CALLBACK_DATA Data,
|
|
__in PCFLT_RELATED_OBJECTS FltObjects,
|
|
__deref_out_opt PVOID* CompletionContext
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
|
|
NTSTATUS status = FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (!g_bs1Flt.IsAttached)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (g_bs1Flt.UserProcess == PsGetCurrentProcess())
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if(!g_bs1Flt.IsDeviceProtect)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (Data == NULL)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
if (Data->RequestorMode == KernelMode)
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
// CDROM 정책 확인
|
|
|
|
if (GetPolicyState(BDC_CDROM) != ENABLE)
|
|
{
|
|
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
|
|
HANDLE processid = PsGetCurrentProcessId();
|
|
BOOLEAN isblock = FALSE;
|
|
UNICODE_STRING filepath = { 0, };
|
|
PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
|
|
ULONG readLen = iopb->Parameters.Read.Length;
|
|
ULONG uByteOffset = iopb->Parameters.Read.ByteOffset.LowPart;
|
|
|
|
try
|
|
{
|
|
if (readLen == 0 || (!FLT_IS_IRP_OPERATION(Data)) || uByteOffset != 0) {
|
|
leave;
|
|
}
|
|
/// 파일 경로 얻음
|
|
status = FltGetFileNameInformation(Data, FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
//KLogEx(DEBUG_TRACE_ERROR, "kdcmPreRead FltGetFileNameInformation fail(%x)\n", status);
|
|
leave;
|
|
}
|
|
|
|
status = FltParseFileNameInformation(nameInfo);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
//KLogEx(DEBUG_TRACE_ERROR, "kdcmPreRead FltParseFileNameInformation fail(%x)\n", status);
|
|
leave;
|
|
}
|
|
|
|
status = UStrNew(&filepath, nameInfo->Name.MaximumLength + 10);
|
|
if (!NT_SUCCESS(status))
|
|
leave;
|
|
|
|
status = UStrCopy(&filepath, &nameInfo->Name);
|
|
if (!NT_SUCCESS(status))
|
|
leave;
|
|
|
|
if (wcsrchr(filepath.Buffer, '\\') == NULL)
|
|
leave;
|
|
|
|
_wcslwr(filepath.Buffer);
|
|
if (wcsstr(filepath.Buffer, L"\\appdata\\local\\microsoft\\windows\\burn\\burn") != NULL
|
|
&& wcsstr(filepath.Buffer, L"\\desktop.ini") == NULL)
|
|
{
|
|
UNICODE_STRING processpath = { 0, };
|
|
ULONG state = 0;
|
|
|
|
status = UGetCurrentStackProcessImageName(HandleToULong(processid), &processpath);
|
|
state = GetPolicyState(BDC_CDROM);
|
|
|
|
isblock = TRUE;
|
|
SetLog(Data, FltObjects, LOG_POLICY, BDC_CDROM, state, 0, processpath.Buffer, filepath.Buffer);
|
|
|
|
KLogEx(DEBUG_TRACE_INFO, "READ BLOCK!!!!!!!!!!!!! pid(%d),processpath(%S)", processid, processpath.Buffer);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
UStrFree(&filepath);
|
|
|
|
if (nameInfo != NULL)
|
|
FltReleaseFileNameInformation(nameInfo);
|
|
}
|
|
|
|
if (isblock == TRUE)
|
|
{
|
|
Data->IoStatus.Status = STATUS_ACCESS_DENIED;
|
|
Data->IoStatus.Information = 0;
|
|
return FLT_PREOP_COMPLETE;
|
|
}
|
|
|
|
}
|
|
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
|
|
}
|
|
|
|
VOID
|
|
Bs1FltOperationStatusCallback(
|
|
_In_ PCFLT_RELATED_OBJECTS FltObjects,
|
|
_In_ PFLT_IO_PARAMETER_BLOCK ParameterSnapshot,
|
|
_In_ NTSTATUS OperationStatus,
|
|
_In_ PVOID RequesterContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when the given operation returns from the call
|
|
to IoCallDriver. This is useful for operations where STATUS_PENDING
|
|
means the operation was successfully queued. This is useful for OpLocks
|
|
and directory change notification operations.
|
|
|
|
This callback is called in the context of the originating thread and will
|
|
never be called at DPC level. The file object has been correctly
|
|
referenced so that you can access it. It will be automatically
|
|
dereferenced upon return.
|
|
|
|
This is non-pageable because it could be called on the paging path
|
|
|
|
Arguments:
|
|
|
|
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
|
|
opaque handles to this filter, instance, its associated volume and
|
|
file object.
|
|
|
|
RequesterContext - The context for the completion routine for this
|
|
operation.
|
|
|
|
OperationStatus -
|
|
|
|
Return Value:
|
|
|
|
The return value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(RequesterContext);
|
|
UNREFERENCED_PARAMETER(OperationStatus);
|
|
UNREFERENCED_PARAMETER(ParameterSnapshot);
|
|
|
|
//KLogEx(DEBUG_TRACE_INFO,
|
|
// ("cdsflt!cdsfltOperationStatusCallback: Entered\n"));
|
|
|
|
//KLogEx(DEBUG_TRACE_INFO,
|
|
// ("cdsflt!cdsfltOperationStatusCallback: Status=%08x ctx=%p IrpMj=%02x.%02x \"%s\"\n",
|
|
// OperationStatus,
|
|
// RequesterContext,
|
|
// ParameterSnapshot->MajorFunction,
|
|
// ParameterSnapshot->MinorFunction,
|
|
// FltGetIrpName(ParameterSnapshot->MajorFunction)));
|
|
}
|
|
|
|
|
|
FLT_POSTOP_CALLBACK_STATUS
|
|
Bs1FltPostOperation(
|
|
_Inout_ PFLT_CALLBACK_DATA Data,
|
|
_In_ PCFLT_RELATED_OBJECTS FltObjects,
|
|
_In_opt_ PVOID CompletionContext,
|
|
_In_ FLT_POST_OPERATION_FLAGS Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is the post-operation completion routine for this
|
|
miniFilter.
|
|
|
|
This is non-pageable because it may be called at DPC level.
|
|
|
|
Arguments:
|
|
|
|
Data - Pointer to the filter callbackData that is passed to us.
|
|
|
|
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
|
|
opaque handles to this filter, instance, its associated volume and
|
|
file object.
|
|
|
|
CompletionContext - The completion context set in the pre-operation routine.
|
|
|
|
Flags - Denotes whether the completion is successful or is being drained.
|
|
|
|
Return Value:
|
|
|
|
The return value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(Data);
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
UNREFERENCED_PARAMETER(Flags);
|
|
|
|
//PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
|
|
// ("cdsflt!cdsfltPostOperation: Entered\n"));
|
|
|
|
return FLT_POSTOP_FINISHED_PROCESSING;
|
|
}
|
|
|
|
|
|
FLT_PREOP_CALLBACK_STATUS
|
|
cdsfltPreOperationNoPostOperation(
|
|
_Inout_ PFLT_CALLBACK_DATA Data,
|
|
_In_ PCFLT_RELATED_OBJECTS FltObjects,
|
|
_Flt_CompletionContext_Outptr_ PVOID* CompletionContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is a pre-operation dispatch routine for this miniFilter.
|
|
|
|
This is non-pageable because it could be called on the paging path
|
|
|
|
Arguments:
|
|
|
|
Data - Pointer to the filter callbackData that is passed to us.
|
|
|
|
FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
|
|
opaque handles to this filter, instance, its associated volume and
|
|
file object.
|
|
|
|
CompletionContext - The context for the completion routine for this
|
|
operation.
|
|
|
|
Return Value:
|
|
|
|
The return value is the status of the operation.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER(Data);
|
|
UNREFERENCED_PARAMETER(FltObjects);
|
|
UNREFERENCED_PARAMETER(CompletionContext);
|
|
|
|
//PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
|
|
// ("cdsflt!cdsfltPreOperationNoPostOperation: Entered\n"));
|
|
|
|
// This template code does not do anything with the callbackData, but
|
|
// rather returns FLT_PREOP_SUCCESS_NO_CALLBACK.
|
|
// This passes the request down to the next miniFilter in the chain.
|
|
|
|
return FLT_PREOP_SUCCESS_NO_CALLBACK;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
Bs1FltDoRequestOperationStatus(
|
|
_In_ PFLT_CALLBACK_DATA Data
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This identifies those operations we want the operation status for. These
|
|
are typically operations that return STATUS_PENDING as a normal completion
|
|
status.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
TRUE - If we want the operation status
|
|
FALSE - If we don't
|
|
|
|
--*/
|
|
{
|
|
PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
|
|
|
|
//
|
|
// return boolean state based on which operations we are interested in
|
|
//
|
|
|
|
return (BOOLEAN)
|
|
|
|
//
|
|
// Check for oplock operations
|
|
//
|
|
|
|
(((iopb->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
|
|
((iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK) ||
|
|
(iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK) ||
|
|
(iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1) ||
|
|
(iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2)))
|
|
|
|
||
|
|
|
|
//
|
|
// Check for directy change notification
|
|
//
|
|
|
|
((iopb->MajorFunction == IRP_MJ_DIRECTORY_CONTROL) &&
|
|
(iopb->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY))
|
|
);
|
|
}
|