c - Hvordan interface med NT mount manager til at tildele en driveletter?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at erstatte nogle ældre DefineDosDevice userspace-kode (som ikke virker på Vista med administratorbrugere på grund af at den forhøjede og normale session er repræsenteret af forskellige DosDevice-butikker og derfor skaber det temmelig mærkelige scenario, drevet er synligt, hvis det er oprettet fra uoprettede processer, men usynlig, hvis den er oprettet fra en forhøjet proces).


Udskiftningen af ​​dette, som jeg har fundet ud af ved at undersøge Truecrypt-kilden og denne WDM-prøve, er at udstede IOCTL\_MOUNTMGR\_VOLUME\_ARRIVAL\_NOTIFICATION meddelelser til mountmgr.sys og derefter IOCTL\_MOUNTMGR\_CREATE\_POINT/IOCTL\_MOUNTMGR\_DELETE\_POINT. [18] [19]


Så det er det jeg gør - min kode ser sådan ud:


For det første forskellige lokale:


NTSTATUS ntStatus;
PDEVICE\_EXTENSION device\_extension;
UNICODE\_STRING uVolumeName;

ULONG mntNameLen = 0;
ULONG mntPointLen = 0;
PMOUNTMGR\_TARGET\_NAME mntName = NULL;
PMOUNTMGR\_CREATE\_POINT\_INPUT mntPoint =  NULL;


Så konstruerer jeg og foretager mine to anmodninger. Den første mislykkes med ovennævnte statuskode. Den anden fejler med en anden statuskode (men forventes ikke at fungere, hvis den første mislykkes).


mntNameLen = sizeof(MOUNTMGR\_TARGET\_NAME) + device\_extension->sDevName.Length;
mntName = ExAllocatePool(PagedPool, mntNameLen);

mntName->DeviceNameLength = device\_extension->sDevName.Length;
RtlCopyMemory(mntName->DeviceName, device\_extension->sDevName.Buffer, 
              mntName->DeviceNameLength);

ntStatus = MakeDeviceIoRequest (MOUNTMGR\_DEVICE\_NAME, 
    IOCTL\_MOUNTMGR\_VOLUME\_ARRIVAL\_NOTIFICATION,
    mntName, mntNameLen, 0, 0);

mntPointLen = sizeof(PMOUNTMGR\_CREATE\_POINT\_INPUT) + 
    device\_extension->sDevName.Length + uVolumeName.Length;
mntPoint = ExAllocatePool(PagedPool, mntPointLen);

mntPoint->SymbolicLinkNameOffset = sizeof (MOUNTMGR\_CREATE\_POINT\_INPUT);
RtlCopyMemory(&mntPoint+mntPoint->SymbolicLinkNameOffset, 
    uVolumeName.Buffer, uVolumeName.Length * sizeof(WCHAR));
mntPoint->SymbolicLinkNameLength = uVolumeName.Length;

mntPoint->DeviceNameOffset = mntPoint->SymbolicLinkNameOffset + 
    mntPoint->SymbolicLinkNameLength;
RtlCopyMemory(&mntPoint+mntPoint->DeviceNameOffset, 
    device\_extension->sDevName.Buffer, device\_extension->sDevName.Length);
mntPoint->DeviceNameLength = device\_extension->sDevName.Length;

ntStatus = MakeDeviceIoRequest(MOUNTMGR\_DEVICE\_NAME, 
    IOCTL\_MOUNTMGR\_CREATE\_POINT, mntPoint,
mntPointLen, 0, 0);


Derefter opretter jeg den symbolske link \ GLOBAL ?? \ L: -> \ Device \ DeviceName


ntStatus = IoCreateSymbolicLink(&uVolumeName, &(device\_extension->sDevName));
DbgPrint("Mapped \%wZ -> \%wZ
", &uVolumeName, &(device\_extension->sDevName));
RtlFreeUnicodeString(&uVolumeName);
if ( mntName != NULL )
{
    ExFreePool(mntName);
}
if ( mntPoint != NULL)
{
    ExFreePool(mntPoint);
}


Men ntStatus svaret fra mount manager er 0xC0000010 STATUS\_INVALID\_DEVICE\_REQUEST; min enhedsstreng er af formen DeviceDevName og svarer til hver af:



  • IOCTL\_VOLUME\_ONLINE

  • IOCTL\_MOUNTDEV\_QUERY\_SUGGESTED\_LINK\_NAME

  • IOCTL\_MOUNTDEV\_QUERY\_UNIQUE\_ID

  • IOCTL\_MOUNTDEV\_QUERY\_DEVICE\_NAME



og en liste over andre IOCTL'er, der forventes for en lagerenhed. Men jeg har breakpoints indstillet på alle disse rutiner, og ingen af ​​dem er nået.


Min enhed oprettes via denne lille uddrag:


// Security descriptor
RtlInitUnicodeString(&sddl,
     \_T("D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;BU)(A;;GA;;;WD)"));

// named device
status = IoCreateDeviceSecure(
    DriverObject, 
    sizeof(DEVICE\_EXTENSION),
    &device\_name,     // DeviceDeviceName
    DeviceType,       // valid devicetype.
    0,
    FALSE,
    &sddl,            // security descriptor
    NULL,             // no idea what this does.
    &device\_object    // output device object.
);


Så så ned til nogle spørgsmål:



  1. Opretter jeg meddelelserne til mount manager korrekt? Opkaldet MakeDeviceIoRequest baserer sig grundlæggende IoCallDriver, og jeg er rimelig sikker på, at det ikke er problemet.

  2. Er noget jeg gør med CreateDevice et problem? Jeg spørger, fordi jeg læser dette blogindlæg, som indebærer noget om enhedsnavne, FDO'er og BOB'er, som jeg ærligt ikke forstår.

  3. Hvis jeg synes at være i dybden for dyb, er der nogen chance for en præcisering af min forståelse for, hvordan det hele virker?



Noter : Jeg har nogle begrænsninger. Koden, jeg bygger oven på, er ret arv, så jeg inkluderer ntddk.h and wdmsec.h; jeg kan ikke ændre disse til wdm.h eller ntifs.h på dette tidspunkt. [20]

Bedste reference


Før du dyker ind i dette yderligere, er der nogen chance for at du kan flytte dine opkald til DefineDosDevice til en tjeneste? Kald det fra en tjeneste sætter linket i den globale mappe, som helt vil slippe af med det aliasingproblem, du har.


Hvis du ikke kan gøre det, er mit første gæt det, at du ikke håndterer andre nødvendige mount manager IOCTL. Jeg ved, at du har breakpoints på alle de specifikke IOCTL'er, men har du et breakpoint i din standardhandler? Normalt er det her STATUS\_INVALID\_DEVICE\_REQUEST kommer fra.