NTSTATUS CreateDllSection(IN IN PUNICODE_STRING pDllName, OUT PHANDLE pSection, OUT PPVOID pBaseAddress) { HANDLE hFile; OBJECT_ATTRIBUTES oa = {sizeof oa, 0, pDllName, OBJ_CASE_INSENSITIVE}; IO_STATUS_BLOCK iosb; SIZE_T size=0; NTSTATUS status; PAGED_CODE(); ASSERT(pSection&&pBaseAddress); *pBaseAddress = NULL; status = ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(status)) { oa.ObjectName = 0; status = ZwCreateSection(pSection, SECTION_ALL_ACCESS, &oa, 0,PAGE_EXECUTE, SEC_IMAGE, hFile); if (NT_SUCCESS(status)) { status = ZwMapViewOfSection(*pSection, ZwCurrentProcess(), pBaseAddress, 0, 1000, 0, &size, (SECTION_INHERIT)1, MEM_TOP_DOWN, PAGE_READWRITE); if (!NT_SUCCESS(status)) { ZwClose(*pSection); } } ZwClose(hFile); } return status; }
/** * 检查文件是否为PE文件 * @param filename 文件路径。 * return 如果文件是PE文件的话否回true,否则返回false。 * 注:现在的方法比较简单,只检查了文件的前两个字节,最好再检查几步。 */ bool IsPEFile(const PUNICODE_STRING filename) { HANDLE hFile; bool bIsPEFile = true; OBJECT_ATTRIBUTES oaFile; InitializeObjectAttributes(&oaFile, filename, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); IO_STATUS_BLOCK ioStatus; NTSTATUS status = ZwOpenFile(&hFile, GENERIC_READ, &oaFile, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); if(!NT_SUCCESS(status)) { KdPrint(("IsPEFile: ZwOpenFile: %ws %08x\n", filename->Buffer, status)); return true; } USHORT PESig; LARGE_INTEGER offset; offset.QuadPart = 0; ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, &PESig, 2, &offset, NULL); if(PESig != 'ZM') bIsPEFile = false; ZwClose(hFile); return bIsPEFile; }
/* * OpenInputDevice * * Opens input device for asynchronous access */ static NTSTATUS NTAPI OpenInputDevice(PHANDLE pHandle, PFILE_OBJECT *ppObject, CONST WCHAR *pszDeviceName) { UNICODE_STRING DeviceName; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; IO_STATUS_BLOCK Iosb; RtlInitUnicodeString(&DeviceName, pszDeviceName); InitializeObjectAttributes(&ObjectAttributes, &DeviceName, 0, NULL, NULL); Status = ZwOpenFile(pHandle, FILE_ALL_ACCESS, &ObjectAttributes, &Iosb, 0, 0); if (NT_SUCCESS(Status) && ppObject) { Status = ObReferenceObjectByHandle(*pHandle, SYNCHRONIZE, NULL, KernelMode, (PVOID*)ppObject, NULL); ASSERT(NT_SUCCESS(Status)); } return Status; }
// // Reads or writes specified number of sectors from/to the specified buffer. // NTSTATUS _stdcall BkSectorIo( PUNICODE_STRING DriveName, // drive name to read/write sectors from/to PCHAR Buffer, // bufer to store the data ULONG Length, // size of the buffer ULONGLONG StartSector, // starting LBA sector ULONG Count, // number of sectors to read/write ULONG Flags // variouse operation flags ) { HANDLE hDrive; NTSTATUS ntStatus = STATUS_BUFFER_TOO_SMALL; OBJECT_ATTRIBUTES oa = {0}; IO_STATUS_BLOCK IoStatus = {0}; LARGE_INTEGER FilePos = {0}; ULONG ObjectFlags = OBJ_CASE_INSENSITIVE; #ifdef _M_AMD64 if ((ULONG_PTR)&ObjectFlags & 0x8000000000000000) #else if ((ULONG_PTR)&ObjectFlags & 0x80000000) #endif ObjectFlags |= OBJ_KERNEL_HANDLE; InitializeObjectAttributes(&oa, DriveName, ObjectFlags, NULL, NULL); if ((Count * BIOS_DEFAULT_SECTOR_SIZE) <= Length) { // ntStatus = ZwCreateFile(&hDrive, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &oa, &IoStatus, NULL, 0, // FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); ntStatus = ZwOpenFile(&hDrive, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &oa, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(ntStatus)) { FilePos.QuadPart = (StartSector * BIOS_DEFAULT_SECTOR_SIZE); if (Flags & BK_IO_WRITE) ntStatus = ZwWriteFile(hDrive, 0, NULL, NULL, &IoStatus, Buffer, (Count*BIOS_DEFAULT_SECTOR_SIZE), &FilePos, NULL); else ntStatus = ZwReadFile(hDrive, 0, NULL, NULL, &IoStatus, Buffer, (Count*BIOS_DEFAULT_SECTOR_SIZE), &FilePos, NULL); ZwClose(hDrive); } // if (hDrive != INVALID_HANDLE_VALUE) } // if ((Count * BIOS_DEFAULT_SECTOR_SIZE) <= Length) return(ntStatus); }
NTSTATUS NTAPI RtlpMapFile(PUNICODE_STRING ImageFileName, ULONG Attributes, PHANDLE Section) { OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE hFile = NULL; IO_STATUS_BLOCK IoStatusBlock; /* Open the Image File */ InitializeObjectAttributes(&ObjectAttributes, ImageFileName, Attributes & (OBJ_CASE_INSENSITIVE | OBJ_INHERIT), NULL, NULL); Status = ZwOpenFile(&hFile, SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to read image file from disk, Status = 0x%08X\n", Status); return Status; } /* Now create a section for this image */ Status = ZwCreateSection(Section, SECTION_ALL_ACCESS, NULL, NULL, PAGE_EXECUTE, SEC_IMAGE, hFile); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to create section for image file, Status = 0x%08X\n", Status); } ZwClose(hFile); return Status; }
NTSTATUS RtlpOpenImageFile( IN PUNICODE_STRING ImagePathName, IN ULONG Attributes, OUT PHANDLE FileHandle, IN BOOLEAN ReportErrors ) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE File; IO_STATUS_BLOCK IoStatus; *FileHandle = NULL; InitializeObjectAttributes( &ObjectAttributes, ImagePathName, Attributes, NULL, NULL ); Status = ZwOpenFile( &File, SYNCHRONIZE | FILE_EXECUTE, &ObjectAttributes, &IoStatus, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE ); if (!NT_SUCCESS( Status )) { #if DBG if (ReportErrors) { DbgPrint( "NTRTL: RtlpOpenImageFile - NtCreateFile( %wZ ) failed. Status == %X\n", ImagePathName, Status ); } #endif // DBG return( Status ); } *FileHandle = File; return( STATUS_SUCCESS ); }
NTSTATUS getFileIdOA(POBJECT_ATTRIBUTES OA, PLARGE_INTEGER result) { WCHAR buf[1024]; NTSTATUS status; HANDLE hfile; IO_STATUS_BLOCK iostatus; UNICODE_STRING t1, t2, t3, obj; int ok=0; if (!getFullPath(buf, sizeof(buf), OA)) { uwcscpy(buf, OA->ObjectName); } debugOutput(L"getFileIdOA object="); debugOutput(buf); debugOutput(L"\n"); RtlInitUnicodeString(&obj, buf); RtlInitUnicodeString(&t1, L"\\device\\harddisk"); RtlInitUnicodeString(&t2, L"\\??\\"); RtlInitUnicodeString(&t3, L"\\device\\lanmanredirector"); if (RtlPrefixUnicodeString(&t1, &obj, TRUE)) ok = 1; else if (RtlPrefixUnicodeString(&t2, &obj, TRUE)) { if (obj.Length > 5*sizeof(WCHAR) && obj.Buffer[5]==L':') ok=1; } else if (RtlPrefixUnicodeString(&t3, &obj, TRUE)) { ok=1; } if (!ok) return STATUS_OBJECT_NAME_INVALID; status = ZwOpenFile(&hfile, 0, OA, &iostatus, 0, 0); if (status == STATUS_SUCCESS) { status = getFileIdHandle(hfile, result); ZwClose(hfile); } return status; }
NTSTATUS CWdfDevice::CreateUserModeHandle(HANDLE RequestorProcess, PHANDLE ObjectHandle) { IO_STATUS_BLOCK IoStatusBlock; PCUNICODE_STRING UniName = m_CachedName; OBJECT_ATTRIBUTES ObjectAttributes; InitializeObjectAttributes(&ObjectAttributes, const_cast<PUNICODE_STRING>(UniName), OBJ_KERNEL_HANDLE, nullptr, nullptr); HANDLE KernelHandle; auto status = ZwOpenFile(&KernelHandle, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, &IoStatusBlock, 0, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS); if (!NT_SUCCESS(status)) { return status; } status = ZwDuplicateObject(ZwCurrentProcess(), KernelHandle, RequestorProcess, ObjectHandle, 0, 0, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_CLOSE_SOURCE); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, TRACE_WDFDEVICE, "%!FUNC! ZwDuplicateObject failed. %!STATUS!", status); ZwClose(KernelHandle); } return status; }
/* * @implemented */ NTSTATUS NTAPI RtlLockBootStatusData(OUT PHANDLE FileHandle) { OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; UNICODE_STRING FileName; HANDLE LocalFileHandle; NTSTATUS Status; /* Intialize the file handle */ *FileHandle = NULL; /* Initialize the file name */ RtlInitUnicodeString(&FileName, L"\\SystemRoot\\bootstat.dat"); /* Initialize the object attributes */ InitializeObjectAttributes(&ObjectAttributes, &FileName, 0, NULL, NULL); /* Open the boot status data file */ Status = ZwOpenFile(&LocalFileHandle, FILE_ALL_ACCESS, &ObjectAttributes, &IoStatusBlock, 0, FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(Status)) { /* Return the file handle */ *FileHandle = LocalFileHandle; } return Status; }
// // Searches for free disk space to allocate FS area there. // NTSTATUS FsLibGetFsArea( IN OUT PBK_FS_AREA pFsArea ) { PVOID WorkBuffer = NULL; NTSTATUS ntStatus; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK IoStatus; pFsArea->pDeviceName = &g_FsVolumeDevice; InitializeObjectAttributes(&oa, pFsArea->pDeviceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ntStatus = ZwOpenFile(&pFsArea->hDevice, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &oa, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(ntStatus)) { if (WorkBuffer = MyAllocatePool(PagedPool, PAGE_SIZE)) { // Searching for FS area. ntStatus = BkAllocateFsArea(pFsArea, WorkBuffer); MyFreePool(WorkBuffer); } // if (WorkBuffer = MyAllocatePool(PagedPool, PAGE_SIZE)) else ntStatus = STATUS_INSUFFICIENT_RESOURCES; ZwClose(pFsArea->hDevice); } // if (NT_SUCCESS(ntStatus)) if (!NT_SUCCESS(ntStatus)) { KdPrint(("VFS: Unable to allocate FS area, status 0x%x\n", ntStatus)); } return(ntStatus); }
/*! \brief Loads a symbol file. * * \param FileName Filename of the symbol file to load. * \param RosSymInfo Pointer to a ROSSYM_INFO which gets filled. * * \sa KdbpSymUnloadModuleSymbols */ VOID KdbpSymLoadModuleSymbols( IN PUNICODE_STRING FileName, OUT PROSSYM_INFO *RosSymInfo) { OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandle; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; PFILE_OBJECT FileObject; PROSSYM_KM_OWN_CONTEXT FileContext; /* Allow KDB to break on module load */ KdbModuleLoaded(FileName); if (!LoadSymbols) { *RosSymInfo = NULL; return; } /* Try to find cached (already loaded) symbol file */ *RosSymInfo = KdbpSymFindCachedFile(FileName); if (*RosSymInfo) { DPRINT("Found cached symbol file %wZ\n", FileName); return; } /* Open the file */ InitializeObjectAttributes(&ObjectAttributes, FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); DPRINT("Attempting to open image: %wZ\n", FileName); Status = ZwOpenFile(&FileHandle, FILE_READ_ACCESS | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { DPRINT("Could not open image file(%x): %wZ\n", Status, FileName); return; } DPRINT("Loading symbols from %wZ...\n", FileName); Status = ObReferenceObjectByHandle (FileHandle, FILE_READ_DATA | SYNCHRONIZE, NULL, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { DPRINT("Could not get the file object\n"); ZwClose(FileHandle); return; } if ((FileContext = KdbpCaptureFileForSymbols(FileObject))) { if (RosSymCreateFromFile(FileContext, RosSymInfo)) { /* add file to cache */ int i; UNICODE_STRING TruncatedName = *FileName; for (i = (TruncatedName.Length / sizeof(WCHAR)) - 1; i >= 0; i--) if (TruncatedName.Buffer[i] == '\\') { TruncatedName.Buffer += i+1; TruncatedName.Length -= (i+1)*sizeof(WCHAR); TruncatedName.MaximumLength -= (i+1)*sizeof(WCHAR); break; } KdbpSymAddCachedFile(&TruncatedName, *RosSymInfo); DPRINT("Installed symbols: %wZ %p\n", &TruncatedName, *RosSymInfo); } KdbpReleaseFileForSymbols(FileContext); } ObDereferenceObject(FileObject); ZwClose(FileHandle); }
NTSTATUS MuInitializeUserModeHelper ( PMU_GLOBAL_DATA GlobalData ) { NTSTATUS status; HANDLE file, proc, dllsec; SIZE_T imgsize = 0; PVOID secobj, dllbase = NULL; LARGE_INTEGER secofs; UNICODE_STRING fp; IO_STATUS_BLOCK iosb; OBJECT_ATTRIBUTES oa; WCHAR path[MAX_PATH]; wcscpy(path, MU_ROOTDIR_SYSTEM32); wcscat(path, MU_FILENAME_HELPER_DLL); RtlInitUnicodeString(&fp, path); InitializeObjectAttributes(&oa, &fp, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); status = ZwOpenFile(&file, GENERIC_READ, &oa, &iosb, FILE_SHARE_READ, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(status)) { status = ZwCreateSection(&dllsec, SECTION_ALL_ACCESS, NULL, NULL, PAGE_EXECUTE_READWRITE, SEC_IMAGE, file); ZwClose(file); if (!NT_SUCCESS(status)) return status; status = ObReferenceObjectByHandle(dllsec, SECTION_ALL_ACCESS, *MmSectionObjectType, KernelMode, &secobj, NULL); ZwClose(dllsec); if (NT_SUCCESS(status)) { secofs.QuadPart = 0; status = MmMapViewOfSection(secobj, PsGetCurrentProcess(), &dllbase, 0, 0, &secofs, &imgsize, ViewShare, 0, PAGE_EXECUTE_READWRITE); if (NT_SUCCESS(status)) { status = MuLinkDll(GlobalData, dllbase); MmUnmapViewOfSection(PsGetCurrentProcess(), dllbase); } if (!NT_SUCCESS(status)) { ObDereferenceObject(secobj); secobj = NULL; } GlobalData->DllSection = secobj; GlobalData->DllImageSize = imgsize; GlobalData->DllImageBase = dllbase; } } return status; }
static NTSTATUS RtlpSysVolTakeOwnership(IN PUNICODE_STRING DirectoryPath, IN PSECURITY_DESCRIPTOR SecurityDescriptor) { TOKEN_PRIVILEGES TokenPrivileges; OBJECT_ATTRIBUTES ObjectAttributes; SECURITY_DESCRIPTOR AbsSD; PSID AdminSid = NULL; IO_STATUS_BLOCK IoStatusBlock; BOOLEAN TokenEnabled = FALSE; HANDLE hToken = NULL; HANDLE hDirectory = NULL; NTSTATUS Status; ULONG ReturnLength; Status = ZwOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* attempt to enable the SE_TAKE_OWNERSHIP_PRIVILEGE privilege */ TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges[0].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE; TokenPrivileges.Privileges[0].Luid.HighPart = 0; TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; Status = ZwAdjustPrivilegesToken(hToken, FALSE, &TokenPrivileges, sizeof(TokenPrivileges), &TokenPrivileges, &ReturnLength); if (!NT_SUCCESS(Status)) { goto Cleanup; } TokenEnabled = (TokenPrivileges.PrivilegeCount != 0); /* open the directory */ InitializeObjectAttributes(&ObjectAttributes, DirectoryPath, 0, NULL, SecurityDescriptor); Status = ZwOpenFile(&hDirectory, SYNCHRONIZE | WRITE_OWNER, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the Administrators SID */ Status = RtlAllocateAndInitializeSid(&LocalSystemAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the security descriptor */ Status = RtlCreateSecurityDescriptor(&AbsSD, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlSetOwnerSecurityDescriptor(&AbsSD, AdminSid, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* attempt to take ownership */ Status = ZwSetSecurityObject(hDirectory, OWNER_SECURITY_INFORMATION, &AbsSD); Cleanup: if (TokenEnabled) { ZwAdjustPrivilegesToken(hToken, FALSE, &TokenPrivileges, 0, NULL, NULL); } if (AdminSid != NULL) { RtlFreeSid(AdminSid); } if (hDirectory != NULL) { ZwClose(hDirectory); } if (hToken != NULL) { ZwClose(hToken); } return Status; }
NTSTATUS GetNextReparseVolumePath( IN HANDLE Handle, OUT PUNICODE_STRING Path ) /*++ Routine Description: This routine queries the reparse index for the next volume mount point. Arguments: Handle - Supplies the handle. Path - Returns the path. Return Value: NTSTATUS --*/ { NTSTATUS status; IO_STATUS_BLOCK ioStatus; FILE_REPARSE_POINT_INFORMATION reparseInfo; UNICODE_STRING fileId; OBJECT_ATTRIBUTES oa; HANDLE h; PREPARSE_DATA_BUFFER reparse; UNICODE_STRING volumeName; ULONG nameInfoSize; PFILE_NAME_INFORMATION nameInfo; for (;;) { status = ZwQueryDirectoryFile(Handle, NULL, NULL, NULL, &ioStatus, &reparseInfo, sizeof(reparseInfo), FileReparsePointInformation, TRUE, NULL, FALSE); if (!NT_SUCCESS(status)) { return status; } if (reparseInfo.Tag != IO_REPARSE_TAG_MOUNT_POINT) { continue; } fileId.Length = sizeof(reparseInfo.FileReference); fileId.MaximumLength = fileId.Length; fileId.Buffer = (PWSTR) &reparseInfo.FileReference; InitializeObjectAttributes(&oa, &fileId, 0, Handle, NULL); status = ZwOpenFile(&h, SYNCHRONIZE | FILE_GENERIC_READ, &oa, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(status)) { continue; } reparse = ExAllocatePool(PagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!reparse) { ZwClose(h); return STATUS_INSUFFICIENT_RESOURCES; } status = ZwFsControlFile(h, NULL, NULL, NULL, &ioStatus, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!NT_SUCCESS(status)) { ExFreePool(reparse); ZwClose(h); continue; } volumeName.Length = reparse->MountPointReparseBuffer.SubstituteNameLength - sizeof(WCHAR); volumeName.MaximumLength = volumeName.Length + sizeof(WCHAR); volumeName.Buffer = (PWCHAR) ((PCHAR) reparse->MountPointReparseBuffer.PathBuffer + reparse->MountPointReparseBuffer.SubstituteNameOffset); volumeName.Buffer[volumeName.Length/sizeof(WCHAR)] = 0; if (!IsVolumeName(&volumeName)) { ExFreePool(reparse); ZwClose(h); continue; } ExFreePool(reparse); nameInfoSize = 1024; nameInfo = ExAllocatePool(PagedPool, nameInfoSize); if (!nameInfo) { ZwClose(h); continue; } status = ZwQueryInformationFile(h, &ioStatus, nameInfo, nameInfoSize, FileNameInformation); ZwClose(h); if (!NT_SUCCESS(status)) { continue; } Path->Length = (USHORT) nameInfo->FileNameLength; Path->MaximumLength = Path->Length + sizeof(WCHAR); Path->Buffer = ExAllocatePool(PagedPool, Path->MaximumLength); if (!Path->Buffer) { ExFreePool(nameInfo); continue; } RtlCopyMemory(Path->Buffer, nameInfo->FileName, Path->Length); Path->Buffer[Path->Length/sizeof(WCHAR)] = 0; ExFreePool(nameInfo); break; } return status; }
NTSTATUS OpenDeviceReparseIndex( IN PUNICODE_STRING DeviceName, OUT PHANDLE Handle ) /*++ Routine Description: This routine opens the reparse index on the given device. Arguments: DeviceName - Supplies the device name. Handle - Returns the handle. Return Value: NTSTATUS --*/ { NTSTATUS status; PFILE_OBJECT fileObject; PDEVICE_OBJECT deviceObject; UNICODE_STRING reparseSuffix, reparseName; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK ioStatus; status = IoGetDeviceObjectPointer(DeviceName, FILE_READ_ATTRIBUTES, &fileObject, &deviceObject); if (!NT_SUCCESS(status)) { return status; } deviceObject = fileObject->DeviceObject; if (!deviceObject->Vpb || !(deviceObject->Vpb->Flags&VPB_MOUNTED)) { ObDereferenceObject(fileObject); return STATUS_UNSUCCESSFUL; } ObDereferenceObject(fileObject); RtlInitUnicodeString(&reparseSuffix, L"\\$Extend\\$Reparse:$R:$INDEX_ALLOCATION"); reparseName.Length = DeviceName->Length + reparseSuffix.Length; reparseName.MaximumLength = reparseName.Length + sizeof(WCHAR); reparseName.Buffer = ExAllocatePool(PagedPool, reparseName.MaximumLength); if (!reparseName.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(reparseName.Buffer, DeviceName->Buffer, DeviceName->Length); RtlCopyMemory((PCHAR) reparseName.Buffer + DeviceName->Length, reparseSuffix.Buffer, reparseSuffix.Length); reparseName.Buffer[reparseName.Length/sizeof(WCHAR)] = 0; InitializeObjectAttributes(&oa, &reparseName, OBJ_CASE_INSENSITIVE, 0, 0); status = ZwOpenFile(Handle, SYNCHRONIZE | FILE_LIST_DIRECTORY, &oa, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT | FILE_OPEN_FOR_BACKUP_INTENT); ExFreePool(reparseName.Buffer); return status; }
NTSTATUS QueryDeviceNameForPath( IN PUNICODE_STRING Path, OUT PUNICODE_STRING DeviceName ) /*++ Routine Description: This routine returns the device name for the given path. It first checks to see if the path is a symbolic link and then checks to see if it is a volume reparse point. Arguments: Path - Supplies the path. DeviceName - Returns the device name. Return Value: NTSTATUS --*/ { NTSTATUS status; OBJECT_ATTRIBUTES oa; HANDLE h; IO_STATUS_BLOCK ioStatus; PREPARSE_DATA_BUFFER reparse; UNICODE_STRING volumeName; status = QuerySymbolicLink(Path, DeviceName); if (NT_SUCCESS(status)) { return status; } InitializeObjectAttributes(&oa, Path, OBJ_CASE_INSENSITIVE, 0, 0); status = ZwOpenFile(&h, SYNCHRONIZE | FILE_GENERIC_READ, &oa, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(status)) { return status; } reparse = ExAllocatePool(PagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!reparse) { ZwClose(h); return STATUS_INSUFFICIENT_RESOURCES; } status = ZwFsControlFile(h, NULL, NULL, NULL, &ioStatus, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); ZwClose(h); if (!NT_SUCCESS(status)) { ExFreePool(reparse); return status; } volumeName.Length = reparse->MountPointReparseBuffer.SubstituteNameLength - sizeof(WCHAR); volumeName.MaximumLength = volumeName.Length + sizeof(WCHAR); volumeName.Buffer = (PWCHAR) ((PCHAR) reparse->MountPointReparseBuffer.PathBuffer + reparse->MountPointReparseBuffer.SubstituteNameOffset); volumeName.Buffer[volumeName.Length/sizeof(WCHAR)] = 0; status = QuerySymbolicLink(&volumeName, DeviceName); ExFreePool(reparse); return status; }
NTSTATUS Log_Rotate() { NTSTATUS Status = STATUS_SUCCESS; HANDLE hFile = NULL; OBJECT_ATTRIBUTES fAttrs; UNICODE_STRING FileName; IO_STATUS_BLOCK StatusBlock = { 0 }; ULONG RotateIndex = 0; FILE_RENAME_INFORMATION *RenameBuffer = NULL; LPCWSTR BaseFileName = LogFileName; ULONG BaseFileNameLength = 0; if (!LogFileName || !LogFile) return STATUS_INVALID_DEVICE_STATE; LPWSTR End1 = wcsrchr(LogFileName, L'\\'), End2 = wcsrchr(LogFileName, L'/'); if ((SIZE_T)End1 > (SIZE_T)End2 > 0) BaseFileName = End1 ? End1 + 1 : LogFileName; else BaseFileName = End2 ? End2 + 1 : LogFileName; BaseFileNameLength = (ULONG)(wcslen(BaseFileName) + 4) * sizeof(WCHAR); ULONG FileNameLength = (ULONG)(wcslen(LogFileName) + 5) * sizeof(WCHAR); RenameBuffer = ExAllocatePoolWithTag(PagedPool, FileNameLength + FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName), LogAllocationTag); if (!RenameBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } RenameBuffer->FileNameLength = BaseFileNameLength; RenameBuffer->ReplaceIfExists = FALSE; RenameBuffer->RootDirectory = NULL; // Rename already rotated files first Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", LogFileName, LogSettings.MaxKeptRotatedFiles); if (!SUCCEEDED(Status)) goto Cleanup; RtlInitUnicodeString(&FileName, RenameBuffer->FileName); InitializeObjectAttributes(&fAttrs, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ZwDeleteFile(&fAttrs); for (RotateIndex = LogSettings.MaxKeptRotatedFiles - 1; RotateIndex > 0; RotateIndex--) { Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", LogFileName, RotateIndex); if (!SUCCEEDED(Status)) goto Cleanup; RtlInitUnicodeString(&FileName, RenameBuffer->FileName); InitializeObjectAttributes(&fAttrs, &FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&hFile, DELETE, &fAttrs, &StatusBlock, 0, 0); if (!NT_SUCCESS(Status)) continue; Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", BaseFileName, RotateIndex + 1); if (!SUCCEEDED(Status)) goto Cleanup; Status = ZwSetInformationFile(hFile, &StatusBlock, RenameBuffer, FileNameLength + FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName), FileRenameInformation); if (!NT_SUCCESS(Status)) goto Cleanup; ZwClose(hFile); hFile = NULL; } // Rename it Status = StringCbPrintf(RenameBuffer->FileName, FileNameLength, L"%ws.%03d", BaseFileName, 1); if (!SUCCEEDED(Status)) goto Cleanup; // Compress Status = Log_CompressFile(LogFile); Status = ZwSetInformationFile(LogFile, &StatusBlock, RenameBuffer, FileNameLength + FIELD_OFFSET(FILE_RENAME_INFORMATION, FileName), FileRenameInformation); if (!NT_SUCCESS(Status)) goto Cleanup; // And start logging into the new file ZwClose(LogFile); LogFile = NULL; Status = Log_StartFileLogging(LogFileName); Cleanup: if (hFile) ZwClose(hFile); if (RenameBuffer) ExFreePoolWithTag(RenameBuffer, LogAllocationTag); return Status; }
PPROVIDER_DEF ReplLookupProvider( ULONG ProviderId ) { NTSTATUS Status; PPROVIDER_DEF pProv; HANDLE hProvider = NULL; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; OBJECT_HANDLE_INFORMATION handleInformation; PFILE_OBJECT fileObject; int i; DfsDbgTrace(+1, Dbg, "ReplLookupProvider Entered: id = %x\n", ProviderId); for (pProv = DfsData.pProvider, i=0; i<DfsData.cProvider; pProv++, i++) { if (ProviderId == pProv->eProviderId) { if (pProv->FileObject == NULL) { DfsDbgTrace(0, Dbg, "Provider device not been referenced yet\n", 0); // // We haven't opened a handle to the provider yet - so // lets try to. // if (pProv->DeviceName.Buffer) { // // Get a handle to the provider. // DfsDbgTrace(0, Dbg, "About to open %wZ\n", &pProv->DeviceName); InitializeObjectAttributes( &objectAttributes, &pProv->DeviceName, OBJ_CASE_INSENSITIVE, // Attributes 0, // Root Directory NULL // Security ); Status = ZwOpenFile( &hProvider, FILE_TRAVERSE, &objectAttributes, &ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE ); if ( NT_SUCCESS( Status ) ) { Status = ioStatusBlock.Status; } DfsDbgTrace(0, Dbg, "Open returned %08lx\n", Status); if ( NT_SUCCESS( Status ) ) { // // Increment ref count on objects // Status = ObReferenceObjectByHandle( hProvider, 0, NULL, KernelMode, (PVOID *)&fileObject, &handleInformation ); // // We have to do this because the pProv structure is in paged // pool, and ObReferenceObjectByHandle requires the fileObject // argument in NonPaged memory. So, we pass in a stack variable // to ObReferenceObjectByHandle, then copy it to pProv->FileObject // pProv->FileObject = fileObject; ASSERT( NT_SUCCESS( Status ) ); pProv->DeviceObject = IoGetRelatedDeviceObject( pProv->FileObject ); Status = ObReferenceObjectByPointer( pProv->DeviceObject, 0, NULL, KernelMode ); ASSERT( pProv->DeviceObject->StackSize < 6 ); // see dsinit.c ZwClose(hProvider); DfsDbgTrace(-1, Dbg, "ReplLookupProvider Exited: " "Provider Def @ %08lx\n", pProv); return pProv; } else { return NULL; } } } else { DfsDbgTrace(-1, Dbg, "ReplLookupProvider Exited: " "Provider Def @ %08lx\n", pProv); return pProv; } // If pProv->FileObject == NULL } // If ProviderId == pProv->eProviderId } // For all provider defs DfsDbgTrace(-1, Dbg, "ReplLookupProvider Exited: Failed!", 0); return NULL; }
/** * 先检测黑名单,如果在黑名单内,直接拒,否则放行。 如果不在黑名单,则检查白名单,在白名单内,无操作。 如果不在白名单内,则将文件全路径及hash值传递到上层 * @param filename 文件全路径。 * return 如果文件安全则返回true,否则返回false。 */ bool CheckIsFileHashSecure(const PUNICODE_STRING filename) { ///////////////////////////////////////////// // 比较已经过滤的文件名 if(IsInBlackCache(filename) == true) return false; /////////////////////////////////////// HANDLE hFile; OBJECT_ATTRIBUTES oaFile; InitializeObjectAttributes(&oaFile, filename, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); // 读权限打开文件,如果失败则认为文件不安全,返回false。 IO_STATUS_BLOCK ioStatus; NTSTATUS status = ZwOpenFile(&hFile, GENERIC_READ, &oaFile, &ioStatus, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if(!NT_SUCCESS(status)) { KdPrint(("VerifyModule: ZwOpenFile: %ws %08x\n", filename->Buffer, status)); return false; } unsigned char* fileBuf = (unsigned char*)ExAllocatePoolWithTag(PagedPool, FILE_BUFFER_SIZE, 'knab'); if(fileBuf == NULL) { ZwClose(hFile); return false; } // 获取文件hash。 MD5_CTX md5; MD5Init(&md5); ULONG sizeAll=0; FILE_STANDARD_INFORMATION fsi; ZwQueryInformationFile(hFile,&ioStatus,&fsi,sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation); while(1) { NTSTATUS status = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, fileBuf, FILE_BUFFER_SIZE, NULL, NULL); if(!NT_SUCCESS(status)) break; if(ioStatus.Information == 0) break; sizeAll += ioStatus.Information; MD5Update(&md5, fileBuf, ioStatus.Information); } ExFreePoolWithTag(fileBuf, 'knab'); unsigned char final[16]; MD5Final(final, &md5); ZwClose(hFile); //黑白名单校验 bool bOK = IsHashBlack(final); if( bOK ) { if(!IsInBlackCache(filename)) { WriteSysLog(LOG_TYPE_DEBUG,L" Fileter Module :%s", filename->Buffer); AddBlackCache(filename); } return false; } else if( !IsHashSecure(final) )//传递到上层 { if( setData(filename->Buffer,filename->Length,final,16) ) setSigned(); } // return true; }
static VOID TestAllInformation(VOID) { NTSTATUS Status; UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntoskrnl.exe"); UNICODE_STRING Ntoskrnl = RTL_CONSTANT_STRING(L"ntoskrnl.exe"); OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandle; IO_STATUS_BLOCK IoStatus; PFILE_ALL_INFORMATION FileAllInfo; SIZE_T Length; ULONG NameLength; PWCHAR Name = NULL; UNICODE_STRING NamePart; InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&FileHandle, SYNCHRONIZE | FILE_READ_ATTRIBUTES, &ObjectAttributes, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE); if (Status == STATUS_PENDING) { Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); Status = IoStatus.Status; } ok_eq_hex(Status, STATUS_SUCCESS); if (skip(NT_SUCCESS(Status), "No file handle, %lx\n", Status)) return; /* NtQueryInformationFile doesn't do length checks for kernel callers in a free build */ if (KmtIsCheckedBuild) { /* Zero length */ Length = 0; Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_INFO_LENGTH_MISMATCH); ok_eq_size(Length, (ULONG_PTR)0x5555555555555555); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); /* One less than the minimum */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) - 1; Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_INFO_LENGTH_MISMATCH); ok_eq_size(Length, (ULONG_PTR)0x5555555555555555); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); } /* The minimum allowed */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName); Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName)); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); /* Plenty of space -- determine NameLength and copy the name */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + MAX_PATH * sizeof(WCHAR); Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status) && FileAllInfo != NULL, "No info\n")) { NameLength = FileAllInfo->NameInformation.FileNameLength; ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); Name = ExAllocatePoolWithTag(PagedPool, NameLength + sizeof(UNICODE_NULL), 'sFmK'); if (!skip(Name != NULL, "Could not allocate %lu bytes\n", NameLength + (ULONG)sizeof(UNICODE_NULL))) { RtlCopyMemory(Name, FileAllInfo->NameInformation.FileName, NameLength); Name[NameLength / sizeof(WCHAR)] = UNICODE_NULL; ok(Name[0] == L'\\', "Name is %ls, expected first char to be \\\n", Name); ok(NameLength >= Ntoskrnl.Length + sizeof(WCHAR), "NameLength %lu too short\n", NameLength); if (NameLength >= Ntoskrnl.Length) { NamePart.Buffer = Name + (NameLength - Ntoskrnl.Length) / sizeof(WCHAR); NamePart.Length = Ntoskrnl.Length; NamePart.MaximumLength = NamePart.Length; ok(RtlEqualUnicodeString(&NamePart, &Ntoskrnl, TRUE), "Name ends in '%wZ', expected %wZ\n", &NamePart, &Ntoskrnl); } } ok(FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)] == 0xdddd, "Char past FileName is %x\n", FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)]); } if (FileAllInfo) KmtFreeGuarded(FileAllInfo); /* One char less than needed */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR); Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR)); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); /* One byte less than needed */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1; Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW); ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); /* Exactly the required size */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength; Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); /* One byte more than needed */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + 1; Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); /* One char more than needed */ Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + sizeof(WCHAR); Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength); if (FileAllInfo) KmtFreeGuarded(FileAllInfo); ExFreePoolWithTag(Name, 'sFmK'); Status = ObCloseHandle(FileHandle, KernelMode); ok_eq_hex(Status, STATUS_SUCCESS); }
NTSTATUS AFSInitializeRedirector( IN AFSRedirectorInitInfo *RedirInitInfo) { NTSTATUS ntStatus = STATUS_SUCCESS; LARGE_INTEGER cacheSizeBytes; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSRDRDeviceObject->DeviceExtension; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; UNICODE_STRING uniServiceName; __Enter { // // First this is to load the library // RtlInitUnicodeString( &uniServiceName, AFS_REDIR_LIBRARY_SERVICE_ENTRY); ntStatus = AFSLoadLibrary( 0, &uniServiceName); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFSLoadLibrary failure %08lX\n", ntStatus)); try_return( ntStatus); } // // Save off the cache file information // pDevExt->Specific.RDR.CacheBlockSize = RedirInitInfo->CacheBlockSize; pDevExt->Specific.RDR.CacheBlockCount = RedirInitInfo->ExtentCount; pDevExt->Specific.RDR.MaximumRPCLength = RedirInitInfo->MaximumChunkLength; cacheSizeBytes = RedirInitInfo->ExtentCount; cacheSizeBytes.QuadPart *= RedirInitInfo->CacheBlockSize; AFSDumpFileLocation.Length = 0; AFSDumpFileLocation.MaximumLength = (USHORT)RedirInitInfo->DumpFileLocationLength + (4 * sizeof( WCHAR)); AFSDumpFileLocation.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, AFSDumpFileLocation.MaximumLength, AFS_GENERIC_MEMORY_23_TAG); if( AFSDumpFileLocation.Buffer == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFS_GENERIC_MEMORY_23_TAG allocation error\n")); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( AFSDumpFileLocation.Buffer, L"\\??\\", 4 * sizeof( WCHAR)); AFSDumpFileLocation.Length = 4 * sizeof( WCHAR); RtlCopyMemory( &AFSDumpFileLocation.Buffer[ AFSDumpFileLocation.Length/sizeof( WCHAR)], (void *)((char *)RedirInitInfo + RedirInitInfo->DumpFileLocationOffset), RedirInitInfo->DumpFileLocationLength); AFSDumpFileLocation.Length += (USHORT)RedirInitInfo->DumpFileLocationLength; // // Be sure the shutdown flag is not set // ClearFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_REDIRECTOR_SHUTDOWN); // // Set up the Throttles. // // Max IO is 10% of the cache, or the value in the registry, // with a minimum of 5Mb (and a maximum of 50% cache size) // if( AFSMaxDirectIo) { // // collect what the user // pDevExt->Specific.RDR.MaxIo.QuadPart = AFSMaxDirectIo; pDevExt->Specific.RDR.MaxIo.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } if (pDevExt->Specific.RDR.MaxIo.QuadPart < (5 * 1024 * 1204)) { pDevExt->Specific.RDR.MaxIo.QuadPart = 5 * 1024 * 1204; } // // For small cache configurations ... // if (pDevExt->Specific.RDR.MaxIo.QuadPart > cacheSizeBytes.QuadPart / 2) { pDevExt->Specific.RDR.MaxIo.QuadPart = cacheSizeBytes.QuadPart / 2; } // // Maximum Dirty is 50% of the cache, or the value in the // registry. No minimum, maximum of 90% of cache size. // if (AFSMaxDirtyFile) { pDevExt->Specific.RDR.MaxDirty.QuadPart = AFSMaxDirtyFile; pDevExt->Specific.RDR.MaxDirty.QuadPart *= (1024 * 1024); } else { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart/2; } cacheSizeBytes.QuadPart *= 9; cacheSizeBytes.QuadPart = cacheSizeBytes.QuadPart / 10; if (pDevExt->Specific.RDR.MaxDirty.QuadPart > cacheSizeBytes.QuadPart) { pDevExt->Specific.RDR.MaxDirty.QuadPart = cacheSizeBytes.QuadPart; } // // Store off any flags for the file system // if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES)) { // // Hide files which begin with . // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_HIDE_DOT_NAMES); } if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES)) { // // Hide files which begin with . // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DISABLE_SHORTNAMES); } // // Global Reparse Point Policy // pDevExt->Specific.RDR.ReparsePointPolicy = RedirInitInfo->GlobalReparsePointPolicy; // // Are we performing direct to service IO? // if( BooleanFlagOn( RedirInitInfo->Flags, AFS_REDIR_INIT_PERFORM_SERVICE_IO)) { // // Send IO requests directly to service // SetFlag( pDevExt->DeviceFlags, AFS_DEVICE_FLAG_DIRECT_SERVICE_IO); } else { if( RedirInitInfo->MemoryCacheOffset.QuadPart != 0 && RedirInitInfo->MemoryCacheLength.QuadPart != 0) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; #ifdef AMD64 pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.QuadPart, RedirInitInfo->MemoryCacheLength.QuadPart); #else pDevExt->Specific.RDR.CacheMdl = MmCreateMdl( NULL, (void *)RedirInitInfo->MemoryCacheOffset.LowPart, RedirInitInfo->MemoryCacheLength.LowPart); #endif if( pDevExt->Specific.RDR.CacheMdl != NULL) { __try { MmProbeAndLockPages( pDevExt->Specific.RDR.CacheMdl, KernelMode, IoModifyAccess); pDevExt->Specific.RDR.CacheBaseAddress = MmGetSystemAddressForMdlSafe( pDevExt->Specific.RDR.CacheMdl, NormalPagePriority); } __except( AFSExceptionFilter( __FUNCTION__, GetExceptionCode(), GetExceptionInformation()) ) { AFSDumpTraceFilesFnc(); IoFreeMdl( pDevExt->Specific.RDR.CacheMdl); pDevExt->Specific.RDR.CacheMdl = NULL; } if( pDevExt->Specific.RDR.CacheMdl != NULL) { pDevExt->Specific.RDR.CacheLength = RedirInitInfo->MemoryCacheLength; ntStatus = STATUS_SUCCESS; } } } if( !NT_SUCCESS( ntStatus) && RedirInitInfo->CacheFileNameLength == 0) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector Unable to initialize cache file %08lX\n", ntStatus)); try_return( ntStatus); } if( pDevExt->Specific.RDR.CacheMdl == NULL) { if( RedirInitInfo->CacheFileNameLength == 0) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector CacheMdl == NULL\n")); try_return( ntStatus = STATUS_INVALID_PARAMETER); } // // Go open the cache file // pDevExt->Specific.RDR.CacheFile.Length = 0; pDevExt->Specific.RDR.CacheFile.MaximumLength = (USHORT)RedirInitInfo->CacheFileNameLength + (4 * sizeof( WCHAR)); pDevExt->Specific.RDR.CacheFile.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, pDevExt->Specific.RDR.CacheFile.MaximumLength, AFS_GENERIC_MEMORY_24_TAG); if( pDevExt->Specific.RDR.CacheFile.Buffer == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector AFS_GENERIC_MEMORY_24_TAG allocation failure\n")); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlCopyMemory( pDevExt->Specific.RDR.CacheFile.Buffer, L"\\??\\", 4 * sizeof( WCHAR)); pDevExt->Specific.RDR.CacheFile.Length = 4 * sizeof( WCHAR); RtlCopyMemory( &pDevExt->Specific.RDR.CacheFile.Buffer[ pDevExt->Specific.RDR.CacheFile.Length/sizeof( WCHAR)], RedirInitInfo->CacheFileName, RedirInitInfo->CacheFileNameLength); pDevExt->Specific.RDR.CacheFile.Length += (USHORT)RedirInitInfo->CacheFileNameLength; InitializeObjectAttributes( &stObjectAttribs, &pDevExt->Specific.RDR.CacheFile, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwOpenFile( &pDevExt->Specific.RDR.CacheFileHandle, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_WRITE_THROUGH | FILE_RANDOM_ACCESS); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector ZwOpenFile failure %08lX\n", ntStatus)); try_return( ntStatus); } // // Map to the fileobject // ntStatus = ObReferenceObjectByHandle( pDevExt->Specific.RDR.CacheFileHandle, SYNCHRONIZE, NULL, KernelMode, (void **)&pDevExt->Specific.RDR.CacheFileObject, NULL); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSInitializeRedirector ObReferenceObjectByHandle failure %08lX\n", ntStatus)); try_return( ntStatus); } } }
NTSTATUS PsLocateSystemDll ( VOID ) /*++ Routine Description: This function locates the system dll and creates a section for the DLL and maps it into the system process. Arguments: None. Return Value: TRUE - Initialization was successful. FALSE - Initialization Failed. --*/ { HANDLE File; HANDLE Section; NTSTATUS st; UNICODE_STRING DllPathName; WCHAR PathBuffer[DOS_MAX_PATH_LENGTH]; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus; // // Initialize the system DLL // DllPathName.Length = 0; DllPathName.Buffer = PathBuffer; DllPathName.MaximumLength = 256; RtlInitUnicodeString(&DllPathName,L"\\SystemRoot\\System32\\ntdll.dll"); InitializeObjectAttributes( &ObjectAttributes, &DllPathName, OBJ_CASE_INSENSITIVE, NULL, NULL ); st = ZwOpenFile( &File, SYNCHRONIZE | FILE_EXECUTE, &ObjectAttributes, &IoStatus, FILE_SHARE_READ, 0 ); if (!NT_SUCCESS(st)) { #if DBG DbgPrint("PS: PsLocateSystemDll - NtOpenFile( NTDLL.DLL ) failed. Status == %lx\n", st ); #endif KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,2,0,0); return st; } st = MmCheckSystemImage(File); if ( st == STATUS_IMAGE_CHECKSUM_MISMATCH ) { ULONG ErrorParameters; ULONG ErrorResponse; // // Hard error time. A driver is corrupt. // ErrorParameters = (ULONG)&DllPathName; NtRaiseHardError( st, 1, 1, &ErrorParameters, OptionOk, &ErrorResponse ); return st; } PsNtDllPathName.MaximumLength = DllPathName.Length + sizeof( WCHAR ); PsNtDllPathName.Length = 0; PsNtDllPathName.Buffer = RtlAllocateStringRoutine( PsNtDllPathName.MaximumLength ); RtlCopyUnicodeString( &PsNtDllPathName, &DllPathName ); st = ZwCreateSection( &Section, SECTION_ALL_ACCESS, NULL, 0, PAGE_EXECUTE, SEC_IMAGE, File ); ZwClose( File ); if (!NT_SUCCESS(st)) { #if DBG DbgPrint("PS: PsLocateSystemDll: NtCreateSection Status == %lx\n",st); #endif KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,3,0,0); return st; } // // Now that we have the section, reference it, store its address in the // PspSystemDll and then close handle to the section. // st = ObReferenceObjectByHandle( Section, SECTION_ALL_ACCESS, MmSectionObjectType, KernelMode, &PspSystemDll.Section, NULL ); ZwClose(Section); if ( !NT_SUCCESS(st) ) { KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,4,0,0); return st; } // // Map the system dll into the user part of the address space // st = PspMapSystemDll(PsGetCurrentProcess(),&PspSystemDll.DllBase); PsSystemDllDllBase = PspSystemDll.DllBase; if ( !NT_SUCCESS(st) ) { KeBugCheckEx(PROCESS1_INITIALIZATION_FAILED,st,5,0,0); return st; } PsSystemDllBase = PspSystemDll.DllBase; return STATUS_SUCCESS; }
NTSTATUS ForceDelete( wchar_t *path ) { HANDLE fileHandle; NTSTATUS result; IO_STATUS_BLOCK ioBlock; DEVICE_OBJECT *device_object; void* object = NULL; OBJECT_ATTRIBUTES fileObject; wchar_t deviceName[14]; UNICODE_STRING uDeviceName; UNICODE_STRING uPath; EPROCESS *eproc = IoGetCurrentProcess(); //switch context to UserMode KeAttachProcess(eproc); //initialize file to delete variable g_fileToDelete = path; g_fileToDelete += 6; //take from \??\C:\example only \example //e.g "\??\C:\" memset(deviceName,0,sizeof(deviceName)); wcsncpy(deviceName,path,7); uDeviceName.Buffer = deviceName; uDeviceName.Length = 14; //file path to unicode string RtlInitUnicodeString(&uPath,path); InitializeObjectAttributes(&fileObject, &uDeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL); result = ZwOpenFile(&fileHandle, SYNCHRONIZE, &fileObject, &ioBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE); if(result != STATUS_SUCCESS) { DbgPrint("Some problems with open file ;["); goto _end; } if ( !ObReferenceObjectByHandle(fileHandle, 0, 0, 0, &object, 0) ) { device_object = IoGetBaseFileSystemDeviceObject(object); ObfDereferenceObject(object); } ZwClose(fileHandle); InitializeObjectAttributes(&fileObject, &uPath, OBJ_CASE_INSENSITIVE, NULL, NULL); result = IoCreateFileSpecifyDeviceObjectHint( &fileHandle, SYNCHRONIZE | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_READ_DATA, //0x100181 &fileObject, &ioBlock, 0, 0, FILE_SHARE_READ | FILE_SHARE_WRITE |FILE_SHARE_DELETE, //FILE_SHARE_VALID_FLAGS, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,//0x60, 0, 0, CreateFileTypeNone, 0, IO_IGNORE_SHARE_ACCESS_CHECK, device_object); if(result != STATUS_SUCCESS) { DbgPrint("error in IoCreateFileSpecifyDeviceObjectHint"); goto _end; } result = ObReferenceObjectByHandle(fileHandle, 0, 0, 0, &object, 0); if(result != STATUS_SUCCESS) { DbgPrint("error in ObReferenceObjectByHandle"); ZwClose(fileHandle); goto _end; } /* METHOD 1 */ ((FILE_OBJECT*)object)->SectionObjectPointer->ImageSectionObject = 0; ((FILE_OBJECT*)object)->DeleteAccess = 1; result = ZwDeleteFile(&fileObject); if(result != STATUS_SUCCESS) { DbgPrint("\n[+]error in ZwDeleteFile"); } ObDereferenceObject(object); ZwClose(fileHandle); result = ZwDeleteFile(&fileObject); if(result != STATUS_SUCCESS) { DbgPrint("\n[+]error in ZwDeleteFile"); /* METHOD 2 */ r0_fileToDelete(path); /* METHOD 3 If simple solutions did not help, try this one. */ hook_it(device_object) }
static _Check_return_ NTSTATUS LcOpenFile ( _In_ PUNICODE_STRING SourceFile, _In_ PUNICODE_STRING TargetFile, _Out_ PHANDLE Handle ) /*++ Summary: This function tries to open the 'FilePath' given. If open operation fails in the current context, it asks for the user-mode service to open that file. Arguments: SourceFile - Path to the file to open. TargetFile - Path to the file the content should be stored to. Handle - Receives handle to the opened file. Return Value: The return value is the status of the operation. --*/ { NTSTATUS status = STATUS_SUCCESS; IO_STATUS_BLOCK statusBlock = { 0 }; OBJECT_ATTRIBUTES objectAttributes = { 0 }; HANDLE fileHandle = NULL; PAGED_CODE(); FLT_ASSERT(SourceFile != NULL); FLT_ASSERT(TargetFile != NULL); FLT_ASSERT(Handle != NULL); EventWriteFile_Open_Start(NULL, SourceFile->Buffer); __try { // The current minifilter instance may not be attached to the target volume, // so the ZwOpenFile/ZwReadFile functions should be used here instead of the FltCreateFile/FltReadFile. InitializeObjectAttributes(&objectAttributes, SourceFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); // Open file for asynchronous reads. status = ZwOpenFile( &fileHandle, GENERIC_READ, &objectAttributes, &statusBlock, FILE_SHARE_READ, FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY); // Open operation may fail, if a remote file is opened by a system, which does not have access to the remote share. // If this happens, we want the user-mode client to open it for us. if (!NT_SUCCESS(status) && status == STATUS_ACCESS_DENIED) { NTSTATUS notificationStatus = STATUS_SUCCESS; LOG((DPFLTR_IHVDRIVER_ID, DPFLTR_WARNING_LEVEL, "[LazyCopy] '%wZ' cannot be accessed by the system, trying to use user-mode service instead.\n", FilePath)); notificationStatus = LcOpenFileInUserMode(SourceFile, TargetFile, &fileHandle); // Return original status, if error occurred while sending notification to the user-mode client. status = notificationStatus == STATUS_PORT_DISCONNECTED || notificationStatus == STATUS_TIMEOUT ? status : notificationStatus; } } __finally { if (NT_SUCCESS(status)) { *Handle = fileHandle; // Make sure it's not closed by the code below. fileHandle = NULL; } if (fileHandle != NULL) { ZwClose(fileHandle); } } EventWriteFile_Open_Stop(NULL); return status; }
// // Initializes the NRER subsystem by creating a file-backed section that is // pointed at the NRER user-mode DLL on disk. This section is used for // randomization purposes. // NTSTATUS InitializeNreSubsystem() { OBJECT_ATTRIBUTES Attributes; IO_STATUS_BLOCK IoStatus; UNICODE_STRING FilePath; NTSTATUS Status = STATUS_SUCCESS; HANDLE FileHandle; HANDLE SectionHandle; do { // // Get a file handle to the user-mode DLL // RtlInitUnicodeString( &FilePath, NRER_USER_MODE_DLL_PATH); InitializeObjectAttributes( &Attributes, &FilePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); if (!NT_SUCCESS(Status = ZwOpenFile( &FileHandle, GENERIC_READ | GENERIC_EXECUTE, &Attributes, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, 0))) { DebugPrint(("InitializeNreSubsystem(): ZwCreateFile(%wZ) failed, %.8x.", &FilePath, Status)); break; } // // Create an image file-backed section that is associated with the DLL // if (!NT_SUCCESS(Status = ZwCreateSection( &SectionHandle, SECTION_ALL_ACCESS, NULL, NULL, PAGE_EXECUTE_WRITECOPY, SEC_IMAGE, FileHandle))) { DebugPrint(("InitializeNreSubsystem(): ZwCreateSection() failed, %.8x.", Status)); break; } // // Get the section object that's associated with the section handle // if (!NT_SUCCESS(Status = ObReferenceObjectByHandle( SectionHandle, 0, NULL, KernelMode, (PVOID *)&NrerUserModeDllSectionObject, NULL))) { DebugPrint(("InitializeNreSubsystem(): ObReferenceObjectByHandle() failed, %.8x.", Status)); break; } DebugPrint(("InitializeNreSubsystem(): NRER user-mode DLL section at: %p.", NrerUserModeDllSectionObject)); NrerInitialized = TRUE; } while (0); // // Close the handles that were opened // if (FileHandle) ZwClose( FileHandle); if (SectionHandle) ZwClose( SectionHandle); return Status; }
//static VOID NTAPI UserModeTest(VOID) { NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE ParentHandle, SystemRootHandle; ok(ExGetPreviousMode() == UserMode, "KernelMode returned!\n"); /* Attempt direct target open */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRootRegedit, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_ACCESS_VIOLATION); ok_eq_hex(IoStatusBlock.Status, 0xFFFFFFFF); if (Status == STATUS_SUCCESS) { ObCloseHandle(ParentHandle, UserMode); } /* Attempt relative target open */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&SystemRootHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &Regedit, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, SystemRootHandle, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_ACCESS_VIOLATION); ok_eq_hex(IoStatusBlock.Status, 0xFFFFFFFF); if (Status == STATUS_SUCCESS) { ObCloseHandle(ParentHandle, KernelMode); } ObCloseHandle(SystemRootHandle, KernelMode); } }
static VOID NTAPI TestSymlinks(VOID) { HANDLE ReparseHandle; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; PREPARSE_DATA_BUFFER Reparse; FILE_DISPOSITION_INFORMATION ToDelete; PFILE_OBJECT FileObject; UNICODE_STRING SysDir, Foobar, Regedit; ULONG Size; /* Get Windows/ReactOS directory */ InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&ReparseHandle, FILE_READ_DATA, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_DIRECTORY_FILE); if (skip(NT_SUCCESS(Status), "Opening \\SystemRoot failed: %lx\n", Status)) { return; } Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); if (skip(NT_SUCCESS(Status), "Querying name failed: %lx\n", Status)) { ZwClose(ReparseHandle); return; } SysDir.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\??\\C:")); if (skip(SysDir.Buffer != NULL, "Allocating memory failed\n")) { ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } SysDir.Length = sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL); SysDir.MaximumLength = FileObject->FileName.Length + sizeof(L"\\??\\C:"); RtlCopyMemory(SysDir.Buffer, L"\\??\\C:", sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL)); RtlAppendUnicodeStringToString(&SysDir, &FileObject->FileName); Foobar.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\foobar.exe")); if (skip(Foobar.Buffer != NULL, "Allocating memory failed\n")) { ExFreePool(SysDir.Buffer); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } Foobar.Length = 0; Foobar.MaximumLength = FileObject->FileName.Length + sizeof(L"\\foobar.exe"); RtlCopyUnicodeString(&Foobar, &FileObject->FileName); RtlCopyMemory(&Foobar.Buffer[Foobar.Length / sizeof(WCHAR)], L"\\foobar.exe", sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL)); Foobar.Length += (sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL)); Regedit.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\regedit.exe")); if (skip(Regedit.Buffer != NULL, "Allocating memory failed\n")) { ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } Regedit.Length = 0; Regedit.MaximumLength = FileObject->FileName.Length + sizeof(L"\\regedit.exe"); RtlCopyUnicodeString(&Regedit, &FileObject->FileName); RtlCopyMemory(&Regedit.Buffer[Regedit.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); Regedit.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); ToDelete.DeleteFile = TRUE; Size = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL); InitializeObjectAttributes(&ObjectAttributes, &SystemRootFoobar, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwCreateFile(&ReparseHandle, GENERIC_READ | GENERIC_WRITE | DELETE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE, NULL, 0); ok_eq_hex(Status, STATUS_SUCCESS); if (skip(NT_SUCCESS(Status), "Creating file failed: %lx\n", Status)) { ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); return; } Reparse = ExAllocatePool(NonPagedPool, Size); RtlZeroMemory(Reparse, Size); Reparse->ReparseTag = IO_REPARSE_TAG_SYMLINK; Reparse->ReparseDataLength = 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL); Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL); Reparse->SymbolicLinkReparseBuffer.PrintNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(L"\\??\\"); Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset = Reparse->SymbolicLinkReparseBuffer.PrintNameLength; RtlCopyMemory(Reparse->SymbolicLinkReparseBuffer.PathBuffer, (WCHAR *)((ULONG_PTR)SysDir.Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL)), SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL)); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL)), L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset), SysDir.Buffer, SysDir.Length); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset + SysDir.Length), L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, Reparse, Size, NULL, 0); ok_eq_hex(Status, STATUS_SUCCESS); if (!NT_SUCCESS(Status)) { ZwClose(ReparseHandle); Status = ZwCreateFile(&ReparseHandle, FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0); if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status)) { Status = ZwOpenFile(&ReparseHandle, DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); ok_eq_hex(Status, STATUS_SUCCESS); ZwClose(ReparseHandle); ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, Reparse, Size, NULL, 0); } if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status)) { ZwSetInformationFile(ReparseHandle, &IoStatusBlock, &ToDelete, sizeof(ToDelete), FileDispositionInformation); ZwClose(ReparseHandle); ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } ZwClose(ReparseHandle); Status = ZwCreateFile(&ReparseHandle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); ok(Status == STATUS_SUCCESS || /* Windows Vista+ */ Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */ "ZwCreateFile returned unexpected status: %lx\n", Status); if (NT_SUCCESS(Status)) { Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (NT_SUCCESS(Status)) { ok(RtlCompareUnicodeString(&Regedit, &FileObject->FileName, TRUE) == 0, "Expected: %wZ. Opened: %wZ\n", &Regedit, &FileObject->FileName); ObDereferenceObject(FileObject); } ZwClose(ReparseHandle); } ExFreePool(Regedit.Buffer); Status = IoCreateFile(&ReparseHandle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING | IO_STOP_ON_SYMLINK); ok(Status == STATUS_STOPPED_ON_SYMLINK || /* Windows Vista+ */ Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */ "ZwCreateFile returned unexpected status: %lx\n", Status); if (NT_SUCCESS(Status)) { ZwClose(ReparseHandle); } Status = ZwCreateFile(&ReparseHandle, GENERIC_READ | GENERIC_WRITE | DELETE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0); if (skip(NT_SUCCESS(Status), "Creating opening reparse point: %lx\n", Status)) { Status = ZwOpenFile(&ReparseHandle, DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); ok_eq_hex(Status, STATUS_SUCCESS); ZwClose(ReparseHandle); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (NT_SUCCESS(Status)) { ok(RtlCompareUnicodeString(&Foobar, &FileObject->FileName, TRUE) == 0, "Expected: %wZ. Opened: %wZ\n", &Foobar, &FileObject->FileName); ObDereferenceObject(FileObject); } ExFreePool(Foobar.Buffer); RtlZeroMemory(Reparse, Size); Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_GET_REPARSE_POINT, NULL, 0, Reparse, Size); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Information, Size); if (NT_SUCCESS(Status)) { PWSTR Buffer; UNICODE_STRING ReparsePath, FullPath; ok_eq_hex(Reparse->ReparseTag, IO_REPARSE_TAG_SYMLINK); ok_eq_hex(Reparse->ReparseDataLength, 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); ok_eq_hex(Reparse->SymbolicLinkReparseBuffer.Flags, 0); FullPath.Length = 0; FullPath.MaximumLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL); Buffer = FullPath.Buffer = ExAllocatePool(NonPagedPool, FullPath.MaximumLength); if (!skip(Buffer != NULL, "Memory allocation failed!\n")) { RtlCopyUnicodeString(&FullPath, &SysDir); RtlCopyMemory(&FullPath.Buffer[FullPath.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); FullPath.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset); ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength; ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath); FullPath.Length -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); FullPath.MaximumLength -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); FullPath.Buffer = (PWSTR)((ULONG_PTR)Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.PrintNameOffset); ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.PrintNameLength; ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath); ExFreePool(Buffer); } } ExFreePool(SysDir.Buffer); ExFreePool(Reparse); ZwSetInformationFile(ReparseHandle, &IoStatusBlock, &ToDelete, sizeof(ToDelete), FileDispositionInformation); ZwClose(ReparseHandle); }
static VOID NTAPI KernelModeTest(IN PVOID Context) { NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE ParentHandle, SystemRootHandle, TargetHandle; PFILE_OBJECT ParentFileObject, TargetFileObject, SystemRootFileObject; UNREFERENCED_PARAMETER(Context); /* Kernelmode mandatory for IoCreateFile */ ok(ExGetPreviousMode() == KernelMode, "UserMode returned!\n"); /* First of all, open \\SystemRoot * We're interested in 3 pieces of information about it: * -> Its target (it's a symlink): \Windows or \ReactOS * -> Its associated File Object * -> Its associated FCB */ TargetFileObject = NULL; IoStatusBlock.Status = 0xFFFFFFFF; TargetHandle = INVALID_HANDLE_VALUE; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&TargetHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(TargetHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&TargetFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); } ok(TargetFileObject != NULL, "Not target to continue!\n"); if (TargetFileObject == NULL) { if (TargetHandle != INVALID_HANDLE_VALUE) { ObCloseHandle(TargetHandle, KernelMode); } return; } /* Open target directory of \SystemRoot\Regedit.exe * This must lead to \SystemRoot opening */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRootRegedit, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { /* At that point, file object must point to \SystemRoot * But must not be the same FO than target (diverted file object) * This means FCB & FileName are equal * But CCB & FO are different * CCB must be != NULL, otherwise it means open failed */ ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->RelatedFileObject, NULL); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); ObDereferenceObject(ParentFileObject); } /* Because target exists FSD must signal it */ ok_eq_long(IoStatusBlock.Information, FILE_EXISTS); ObCloseHandle(ParentHandle, KernelMode); } /* Do the same with relative open */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&SystemRootHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &Regedit, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, SystemRootHandle, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); Status = ObReferenceObjectByHandle(SystemRootHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&SystemRootFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok_eq_pointer(ParentFileObject->RelatedFileObject, SystemRootFileObject); ok(ParentFileObject->RelatedFileObject != TargetFileObject, "File objects must be different\n"); ok(SystemRootFileObject != TargetFileObject, "File objects must be different\n"); ObDereferenceObject(SystemRootFileObject); } ObDereferenceObject(ParentFileObject); } ok_eq_long(IoStatusBlock.Information, FILE_EXISTS); ObCloseHandle(ParentHandle, KernelMode); } ObCloseHandle(SystemRootHandle, KernelMode); } /* *** */ /* Now redo the same scheme, but using a target that doesn't exist * The difference will be in IoStatusBlock.Information, the FSD will * inform that the target doesn't exist. * Clear for rename :-) */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRootFoobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->RelatedFileObject, NULL); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); ObDereferenceObject(ParentFileObject); } ok_eq_long(IoStatusBlock.Information, FILE_DOES_NOT_EXIST); ObCloseHandle(ParentHandle, KernelMode); } IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&SystemRootHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &Foobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, SystemRootHandle, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { Status = ObReferenceObjectByHandle(ParentHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&ParentFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok(ParentFileObject != TargetFileObject, "Diverted file object must be different\n"); ok_eq_pointer(ParentFileObject->FsContext, TargetFileObject->FsContext); ok(ParentFileObject->FsContext2 != 0x0, "Parent must be open!\n"); ok(ParentFileObject->FsContext2 != TargetFileObject->FsContext2, "Parent open must have its own context!\n"); ok_eq_long(RtlCompareUnicodeString(&ParentFileObject->FileName, &TargetFileObject->FileName, FALSE), 0); Status = ObReferenceObjectByHandle(SystemRootHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, (PVOID *)&SystemRootFileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { ok_eq_pointer(ParentFileObject->RelatedFileObject, SystemRootFileObject); ok(ParentFileObject->RelatedFileObject != TargetFileObject, "File objects must be different\n"); ok(SystemRootFileObject != TargetFileObject, "File objects must be different\n"); ObDereferenceObject(SystemRootFileObject); } ObDereferenceObject(ParentFileObject); } ok_eq_long(IoStatusBlock.Information, FILE_DOES_NOT_EXIST); ObCloseHandle(ParentHandle, KernelMode); } ObCloseHandle(SystemRootHandle, KernelMode); } ObDereferenceObject(TargetFileObject); ObCloseHandle(TargetHandle, KernelMode); /* *** */ /* Direct target open of something that doesn't exist */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRootFoobarFoobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_OBJECT_PATH_NOT_FOUND); ok_eq_hex(IoStatusBlock.Status, 0xFFFFFFFF); if (Status == STATUS_SUCCESS) { ObCloseHandle(ParentHandle, KernelMode); } /* Relative target open of something that doesn't exist */ IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenFile(&SystemRootHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Status, STATUS_SUCCESS); if (Status == STATUS_SUCCESS) { IoStatusBlock.Status = 0xFFFFFFFF; IoStatusBlock.Information = 0xFFFFFFFF; InitializeObjectAttributes(&ObjectAttributes, &FoobarFoobar, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, SystemRootHandle, NULL); Status = IoCreateFile(&ParentHandle, GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0, CreateFileTypeNone, NULL, IO_OPEN_TARGET_DIRECTORY); ok_eq_hex(Status, STATUS_OBJECT_PATH_NOT_FOUND); ok_eq_hex(IoStatusBlock.Status, 0xFFFFFFFF); if (Status == STATUS_SUCCESS) { ObCloseHandle(ParentHandle, KernelMode); } ObCloseHandle(SystemRootHandle, KernelMode); } }
/** * 先检测黑名单,如果在黑名单内,直接拒,否则放行。 如果不在黑名单,则检查白名单,在白名单内,无操作。 如果不在白名单内,则将文件全路径及hash值传递到上层 * @param filename 文件全路径。 * return 如果文件安全则返回true,否则返回false。 */ bool CheckIsFileHashSecure(const PUNICODE_STRING filename) { /////////////////////////////////////////////比较已经过滤的文件名 if(IsInBlackCache(filename) == true) return false; if( MODULE_FILTERED == GetModuleFilter((ULONG)PsGetCurrentProcessId(),filename) ) return true; /////////////////////////////////////// HANDLE hFile; OBJECT_ATTRIBUTES oaFile; InitializeObjectAttributes(&oaFile, filename, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); // 读权限打开文件,如果失败则认为文件不安全,返回false。 IO_STATUS_BLOCK ioStatus; NTSTATUS status = ZwOpenFile(&hFile, GENERIC_READ, &oaFile, &ioStatus, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if(!NT_SUCCESS(status)) { KdPrint(("VerifyModule: ZwOpenFile: %ws %08x\n", filename->Buffer, status)); return false; } unsigned char* fileBuf = (unsigned char*)ExAllocatePoolWithTag(PagedPool, FILE_BUFFER_SIZE, 'knab'); if(fileBuf == NULL) { ZwClose(hFile); return false; } // 获取文件hash。 MD5_CTX md5; MD5Init(&md5); ULONG sizeAll=0; FILE_STANDARD_INFORMATION fsi; ZwQueryInformationFile(hFile,&ioStatus,&fsi,sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation); while(1) { NTSTATUS status = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, fileBuf, FILE_BUFFER_SIZE, NULL, NULL); if(!NT_SUCCESS(status)) break; if(ioStatus.Information == 0) break; sizeAll += ioStatus.Information; MD5Update(&md5, fileBuf, ioStatus.Information); } ExFreePoolWithTag(fileBuf, 'knab'); unsigned char final[16]; MD5Final(final, &md5); ZwClose(hFile); //黑白名单校验 // bool bOK = IsHashBlack(final); // // if( bOK ) // { // if(!IsInBlackCache(filename)) // { // WriteSysLog(LOG_TYPE_DEBUG,L" Fileter Module :%s", filename->Buffer); // AddBlackCache(filename); // } // return false; // } // else if( !IsHashSecure(final) )//传递到上层 // { // if( setData(filename->Buffer,filename->Length,final,16) ) // setSigned(); // } bool bOK = IsHashBlack(final); bool bReturn = true; if( bOK ) { if(!IsInBlackCache(filename)) { WriteSysLog(LOG_TYPE_INFO,L" Fileter Module :%s", filename->Buffer); AddBlackCache(filename); } bReturn = false; } else if( !IsHashSecure(final) )//传递到上层 { if( !IsInstall() ) { if( setData(filename->Buffer,filename->Length,final,16) ) setSigned(); LARGE_INTEGER lWaitTimeOuts; lWaitTimeOuts.QuadPart = -10 * 1000 * 1000; //DbgPrint("###kernel wait event!"); WriteSysLog(LOG_TYPE_INFO,L" kernel is waitint for event signal!"); if( STATUS_TIMEOUT == KeWaitForSingleObject(g_pEventFilterGo, Executive, KernelMode, FALSE, &lWaitTimeOuts) ) { IsInstall(true); if( GetPIDNumber() > 2) bReturn = false; else bReturn = true; } else bReturn = g_bPassFilter; //DbgPrint("###kernel continue: file path : %ws is %ws \n", filename->Buffer, bReturn? L"pass":L"noPass"); WriteSysLog(LOG_TYPE_INFO,L" kernel continue: file path : %ws is %ws", filename->Buffer, bReturn? L"pass":L"noPass"); if( bReturn ) if( MODULE_FILTERED != GetModuleFilter((ULONG)PsGetCurrentProcessId(),filename) && (GetPIDNumber() > 2) ) SetModuleFilter((ULONG)PsGetCurrentProcessId(), filename, true); } } // return bReturn; }
EXTERN_C NTSTATUS EnumDirectory( char *lpDirName ) { NTSTATUS status, fStatus; ULONG dwBytesReturned; OBJECT_ATTRIBUTES objectAttributes; PDEVICE_OBJECT lpDeviceObject; IO_STACK_LOCATION iost; PIO_STACK_LOCATION lpsp; IO_STATUS_BLOCK IoStatus; HANDLE hFile = NULL; PFILE_DIRECTORY_INFORMATION lpInformation; PDIRECTORY_INFO lpDirInfo = NULL, lpPreDirInfo = NULL; PFILE_OBJECT lpFileObject = NULL; UNICODE_STRING unFileName; ANSI_STRING anFileName; HANDLE eventHandle = NULL; CHAR buffer[1024]; PUCHAR lpNext; dwBytesReturned = 0; status = STATUS_UNSUCCESSFUL; RtlZeroMemory(buffer,1024); strcpy(buffer,"\\DosDevices\\"); strcat(buffer,lpDirName); RtlInitAnsiString(&anFileName,buffer); RtlAnsiStringToUnicodeString(&unFileName,&anFileName,TRUE); InitializeObjectAttributes(&objectAttributes,&unFileName,OBJ_CASE_INSENSITIVE + OBJ_KERNEL_HANDLE,NULL,NULL); __try { //打开文件 fStatus = ZwOpenFile(&hFile,\ FILE_LIST_DIRECTORY | SYNCHRONIZE | FILE_ANY_ACCESS,\ &objectAttributes,\ &IoStatus,\ FILE_SHARE_READ | FILE_SHARE_WRITE| FILE_SHARE_DELETE, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); ObReferenceObjectByHandle(hFile, FILE_LIST_DIRECTORY | SYNCHRONIZE, 0, KernelMode, (PVOID *)&lpFileObject, NULL); status = ZwCreateEvent(&eventHandle, GENERIC_ALL, 0, NotificationEvent, FALSE); lpInformation = (PFILE_DIRECTORY_INFORMATION)ExAllocatePool(PagedPool, 655350); status = ZwQueryDirectoryFile(hFile, eventHandle,0, 0, &IoStatus, lpInformation, 655350, FileDirectoryInformation, FALSE, NULL, FALSE ); if (!NT_SUCCESS(status) && status != STATUS_PENDING) { goto LeaveBefore; } if (status == STATUS_PENDING) { KeWaitForSingleObject(eventHandle, Executive, KernelMode, TRUE, 0); } FreePagedLookasideListForDirectory(); g_pPageListDirectory = (PPAGED_LOOKASIDE_LIST)ExAllocatePool(PagedPool, sizeof(PAGED_LOOKASIDE_LIST)); ExInitializePagedLookasideList(g_pPageListDirectory, NULL, NULL, 0, sizeof(DIRECTORY_INFO), NULL, 0); while(1) { lpDirInfo = (PDIRECTORY_INFO)ExAllocateFromPagedLookasideList(g_pPageListDirectory); RtlZeroMemory(lpDirInfo, sizeof(DIRECTORY_INFO)); RtlCopyMemory(lpDirInfo->FileName, lpInformation->FileName, lpInformation->FileNameLength); lpDirInfo->AllocationSize = lpInformation->AllocationSize; lpDirInfo->FileAttributes = lpInformation->FileAttributes; RtlTimeToTimeFields(&(lpInformation->CreationTime), &(lpDirInfo->CreationTime)); RtlTimeToTimeFields(&(lpInformation->LastAccessTime), &(lpDirInfo->LastAccessTime)); RtlTimeToTimeFields(&(lpInformation->LastWriteTime), &(lpDirInfo->LastWriteTime)); RtlTimeToTimeFields(&(lpInformation->ChangeTime), &(lpDirInfo->ChangeTime)); lpDirInfo->next = NULL; if (NULL == g_pDirectoryInfo) { g_pDirectoryInfo = lpDirInfo; lpPreDirInfo = lpDirInfo; } else { lpPreDirInfo->next = lpDirInfo; lpPreDirInfo = lpDirInfo; } if(!lpInformation->NextEntryOffset) { break; } lpInformation = (PFILE_DIRECTORY_INFORMATION)((PUCHAR)lpInformation + lpInformation->NextEntryOffset); } LeaveBefore: ; } __finally { if (NT_SUCCESS(fStatus)) { ZwClose(hFile); } if (NULL != lpFileObject) { ObDereferenceObject(lpFileObject); lpFileObject = NULL; } if (NULL != eventHandle) { ZwClose(eventHandle); eventHandle = NULL; } } return status; }