Beispiel #1
1
EXTERN_C static NTSTATUS ScvnpWriteFile(_In_ PCFLT_RELATED_OBJECTS FltObjects,
                                        _In_ const wchar_t *OutPathW,
                                        _In_ void *Buffer,
                                        _In_ ULONG BufferSize,
                                        _In_ ULONG CreateDisposition) {
  PAGED_CODE();

  UNICODE_STRING outPath = {};
  RtlInitUnicodeString(&outPath, OutPathW);
  OBJECT_ATTRIBUTES objAttr = RTL_INIT_OBJECT_ATTRIBUTES(
      &outPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE);

  HANDLE fileHandle = nullptr;
  IO_STATUS_BLOCK ioStatus = {};
  auto status = FltCreateFile(
      FltObjects->Filter, FltObjects->Instance, &fileHandle, GENERIC_WRITE,
      &objAttr, &ioStatus, nullptr, FILE_ATTRIBUTE_NORMAL, 0, CreateDisposition,
      FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT |
          FILE_NON_DIRECTORY_FILE,
      nullptr, 0, 0);
  if (status == STATUS_OBJECT_NAME_COLLISION ||
      status == STATUS_DELETE_PENDING) {
    return status;
  }
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltCreateFile failed (%08x) for %S", status, OutPathW);
    return status;
  }

  PFILE_OBJECT fileObject = nullptr;
  status = ObReferenceObjectByHandle(fileHandle, 0, nullptr, KernelMode,
                                     reinterpret_cast<void **>(&fileObject),
                                     nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("ObReferenceObjectByHandle failed (%08x) for %S", status,
                   OutPathW);
    goto End;
  }

  status = FltWriteFile(FltObjects->Instance, fileObject, nullptr, BufferSize,
                        Buffer, 0, nullptr, nullptr, nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltWriteFile failed (%08x) for %S", status, OutPathW);
    goto End;
  }

End:
  if (fileObject) {
    ObDereferenceObject(fileObject);
  }
  if (fileHandle) {
    FltClose(fileHandle);
  }
  return status;
}
Beispiel #2
0
EXTERN_C static NTSTATUS ScvnpCreateDirectory(_In_ const wchar_t *PathW) {
  PAGED_CODE();

  UNICODE_STRING path = {};
  RtlInitUnicodeString(&path, PathW);
  OBJECT_ATTRIBUTES objAttr = RTL_INIT_OBJECT_ATTRIBUTES(
      &path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE);

  IO_STATUS_BLOCK ioStatus = {};
  HANDLE directory = nullptr;
  NTSTATUS status = ZwCreateFile(
      &directory, GENERIC_WRITE, &objAttr, &ioStatus, nullptr,
      FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF,
      FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE, nullptr, 0);
  if (NT_SUCCESS(status)) {
    ZwClose(directory);
  }

  return status;
}
Beispiel #3
0
_Use_decl_annotations_ EXTERN_C NTSTATUS
UtilLoadPointerVaule(const wchar_t *Key, const wchar_t *Value, void **Data) {
  PAGED_CODE();

  UNICODE_STRING path = {};
  RtlInitUnicodeString(&path, Key);
  OBJECT_ATTRIBUTES oa = RTL_INIT_OBJECT_ATTRIBUTES(
      &path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE);

  // Open the registry
  HANDLE keyNaked = nullptr;
  auto status = ZwOpenKey(&keyNaked, KEY_READ, &oa);
  if (!NT_SUCCESS(status)) {
    return status;
  }
  auto key =
      std::experimental::make_unique_resource(std::move(keyNaked), &::ZwClose);

  UNICODE_STRING valueName = {};
  RtlInitUnicodeString(&valueName, Value);

  // Read value
  ULONG resultLength = 0;
  UCHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(void *)] = {};
  status = ZwQueryValueKey(key.get(), &valueName, KeyValuePartialInformation,
                           buffer, sizeof(buffer), &resultLength);
  if (!NT_SUCCESS(status)) {
    return status;
  }

  // Error if it is not an expected type or not a pointer size.
  ULONG expectedRegType = (IsX64()) ? REG_QWORD : REG_DWORD;
  auto data = reinterpret_cast<KEY_VALUE_PARTIAL_INFORMATION *>(buffer);
  if (data->Type != expectedRegType || data->DataLength != sizeof(void *)) {
    return STATUS_DATA_NOT_ACCEPTED;
  }

  *Data = *reinterpret_cast<void **>(data->Data);
  return status;
}
Beispiel #4
0
EXTERN_C static NTSTATUS ScvnpReadFile(_In_ PFLT_CALLBACK_DATA Data,
                                       _In_ PCFLT_RELATED_OBJECTS FltObjects,
                                       _Out_ void *Buffer,
                                       _In_ ULONG BufferSize) {
  PAGED_CODE();

  // Use an existing file object when it is NOT IRP_MJ_CLEANUP.
  if (Data->Iopb->MajorFunction != IRP_MJ_CLEANUP) {
    LARGE_INTEGER byteOffset = {};
    auto status = FltReadFile(FltObjects->Instance, FltObjects->FileObject,
                              &byteOffset, BufferSize, Buffer,
                              FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
                              nullptr, nullptr, nullptr);
    if (!NT_SUCCESS(status)) {
      LOG_ERROR_SAFE("FltReadFile failed (%08x)", status);
      return status;
    }
    return status;
  }

  PFILE_OBJECT fileObject = nullptr;

  // Make a new file object since the file is already out of the current IO
  // path.
  PFLT_FILE_NAME_INFORMATION fileNameInformation = nullptr;
  auto status = FltGetFileNameInformationUnsafe(
      FltObjects->FileObject, FltObjects->Instance, FLT_FILE_NAME_NORMALIZED,
      &fileNameInformation);
  if (!NT_SUCCESS(status)) {
    return status;
  }

  OBJECT_ATTRIBUTES objAttr = RTL_INIT_OBJECT_ATTRIBUTES(
      &fileNameInformation->Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE);

  HANDLE fileHandle = nullptr;
  IO_STATUS_BLOCK ioStatus = {};
  status = FltCreateFile(
      FltObjects->Filter, FltObjects->Instance, &fileHandle, GENERIC_READ,
      &objAttr, &ioStatus, nullptr, FILE_ATTRIBUTE_NORMAL,
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF,
      FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT |
          FILE_NON_DIRECTORY_FILE,
      nullptr, 0, 0);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltCreateFile failed (%08x) for %wZ", status,
                   &fileNameInformation->Name);
    goto End;
  }

  status = ObReferenceObjectByHandle(fileHandle, 0, nullptr, KernelMode,
                                     reinterpret_cast<void **>(&fileObject),
                                     nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("ObReferenceObjectByHandle failed (%08x) for %wZ", status,
                   &fileNameInformation->Name);
    goto End;
  }

  status = FltReadFile(FltObjects->Instance, fileObject, nullptr, BufferSize,
                       Buffer, 0, nullptr, nullptr, nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltReadFile failed (%08x) for %wZ", status,
                   &fileNameInformation->Name);
    goto End;
  }

End:
  if (fileObject) {
    ObDereferenceObject(fileObject);
  }
  if (fileHandle) {
    FltClose(fileHandle);
  }
  if (fileNameInformation) {
    FltReleaseFileNameInformation(fileNameInformation);
  }
  return status;
}
Beispiel #5
0
HANDLE
SymlinkCreateTests(OUT PHANDLE OddLink)
{
    NTSTATUS Status;
    HANDLE LinkHandle;
    UNICODE_STRING TargetName = RTL_CONSTANT_STRING(L"\\");
    UNICODE_STRING TargetName2 = RTL_CONSTANT_STRING(L"\\");
    UNICODE_STRING TargetName3 = RTL_CONSTANT_STRING(L"\\");
    UNICODE_STRING TargetName4 = RTL_CONSTANT_STRING(L"\\");
    UNICODE_STRING TargetName5 = RTL_CONSTANT_STRING(L"\\");
    UNICODE_STRING OkName = RTL_CONSTANT_STRING(L"\\OddLink");
    UNICODE_STRING OkName2 = RTL_CONSTANT_STRING(L"\\TestLink");

    //
    // Test1: Empty Attributes
    //
    {
    OBJECT_ATTRIBUTES Test1 = RTL_INIT_OBJECT_ATTRIBUTES(NULL, 0);
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test1,
                                        &TargetName);
    TEST_ASSERT(NT_SUCCESS(Status));
    }

    //
    // Test2: No Attributes
    //
    {
    POBJECT_ATTRIBUTES Test2 = NULL;
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        Test2,
                                        &TargetName);
    TEST_ASSERT(NT_SUCCESS(Status));
    }

    //
    // Test3: Attributes with an empty name
    //
    {
    UNICODE_STRING TestName1 = {0, 0, NULL};
    OBJECT_ATTRIBUTES Test3 = RTL_INIT_OBJECT_ATTRIBUTES(&TestName1, 0);
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test3,
                                        &TargetName);
    TEST_ASSERT(NT_SUCCESS(Status));
    }

    //
    // Test4: Attributes with an invalid name
    //
    {
    UNICODE_STRING TestName2 = {10, 12, UlongToPtr(0x81000000)};
    OBJECT_ATTRIBUTES Test4 = RTL_INIT_OBJECT_ATTRIBUTES(&TestName2, 0);
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test4,
                                        &TargetName);
    TEST_ASSERT(Status == STATUS_ACCESS_VIOLATION);
    }

    //
    // Test5: Target with an odd name len
    //
    {
    UNICODE_STRING OddName = RTL_CONSTANT_STRING(L"\\TestLink");
    OBJECT_ATTRIBUTES Test5 = RTL_INIT_OBJECT_ATTRIBUTES(&OkName, 0);
    TargetName3.Length--;
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test5,
                                        &TargetName3);
    TEST_ASSERT(Status == STATUS_INVALID_PARAMETER);
    }

    //
    // Test6: Target with an emtpy name len
    //
    {
    OBJECT_ATTRIBUTES Test5 = RTL_INIT_OBJECT_ATTRIBUTES(&OkName, 0);
    TargetName4.MaximumLength = 0;
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test5,
                                        &TargetName4);
    TEST_ASSERT(Status == STATUS_INVALID_PARAMETER);
    }

    //
    // Test7: Target with an name len larger then maxlen
    //
    {
    OBJECT_ATTRIBUTES Test6 = RTL_INIT_OBJECT_ATTRIBUTES(&OkName, 0);
    TargetName5.Length = TargetName5.MaximumLength + 2;
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test6,
                                        &TargetName5);
    TEST_ASSERT(Status == STATUS_INVALID_PARAMETER);
    }

    //
    // Test5: Target with an odd name maxlen
    //
    {
    OBJECT_ATTRIBUTES Test5 = RTL_INIT_OBJECT_ATTRIBUTES(&OkName, 0);
    TargetName2.MaximumLength--;
    TEST_ASSERT(TargetName2.MaximumLength % sizeof(WCHAR));
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test5,
                                        &TargetName2);
    *OddLink = LinkHandle;
    TEST_ASSERT(NT_SUCCESS(Status));
    TEST_ASSERT(TargetName2.MaximumLength % sizeof(WCHAR));
    }

    //
    // Test6: collission
    //
    {
    OBJECT_ATTRIBUTES Test6 = RTL_INIT_OBJECT_ATTRIBUTES(&OkName, 0);
    TargetName2.MaximumLength++;
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test6,
                                        &TargetName2);
    TEST_ASSERT(Status == STATUS_OBJECT_NAME_COLLISION);
    }

    //
    // Test7: OK!
    //
    {
    OBJECT_ATTRIBUTES Test7 = RTL_INIT_OBJECT_ATTRIBUTES(&OkName2, 0);
    Status = NtCreateSymbolicLinkObject(&LinkHandle,
                                        SYMBOLIC_LINK_ALL_ACCESS,
                                        &Test7,
                                        &TargetName2);
    TEST_ASSERT(NT_SUCCESS(Status));
    }

    //
    // Return the last valid handle
    //
    return LinkHandle;
};