2010-09-14 48 views
8

J'écris d'un simple pilote du noyau pour mon application (pensez à une application anti-malware très simple.)Comment utiliser ZwQueryInformationProcess pour obtenir ProcessImageFileName dans un pilote de noyau?

J'ai accroché ZwOpenFile() et utilisé PsGetCurrentProcess() pour obtenir une poignée au processus de l'appelant.

Il renvoie une structure PEPROCESS:

PEPROCESS proc = PsGetCurrentProcess(); 

J'utilise ZwQueryInformationProcess() pour obtenir le PID et ImageFileName:

DbgPrint("ZwOpenFile Called...\n"); 
DbgPrint("PID: %d\n", PsGetProcessId(proc)); 
DbgPrint("ImageFileName: %.16s\n", PsGetProcessImageFileName(proc)); 

et essayer d'obtenir le processus FullPath cette façon (mais je reçois BSOD):

WCHAR strBuffer[260]; 
UNICODE_STRING str; 

//initialize 
str.Buffer = strBuffer; 
str.Length = 0x0; 
str.MaximumLength = sizeof(strBuffer); 

//note that the seconds arg (27) is ProcessImageFileName 
ZwQueryInformationProcess(proc, 27, &str, sizeof(str), NULL); 

DbgPrint("FullPath: %wZ\n", str.Buffer); 

012 Comme vous le voyez, le str.Buffer est vide ou rempli d'ordures. Peut-être un débordement de tampon lors du remplissage du str via ZwQueryInformationProcess() déclenche le BSOD.

alt text

Toute aide serait appréciée.

Répondre

6

Les docs MSDN pour cette API indiquent que

Lorsque le paramètre ProcessInformationClass est ProcessImageFileName, le tampon pointé par le paramètre de ProcessInformation devrait être assez grand pour contenir une structure UNICODE_STRING ainsi que la chaîne elle-même. La chaîne stockée dans le membre Buffer est le nom de l'image file.file.

Dans cet esprit, je vous suggère d'essayer de modifier la structure de votre tampon comme celui-ci:

WCHAR strBuffer[(sizeof(UNICODE_STRING)/sizeof(WCHAR)) + 260]; 
UNICODE_STRING str; 
str = (UNICODE_STRING*)&strBuffer; 

//initialize 
str.Buffer = &strBuffer[sizeof(UNICODE_STRING)/sizeof(WCHAR)]; 
str.Length = 0x0; 
str.MaximumLength = 260 * sizeof(WCHAR); 

//note that the seconds arg (27) is ProcessImageFileName 
ZwQueryInformationProcess(proc, 27, &strBuffer, sizeof(strBuffer), NULL); 

De plus, votre code doit vérifier et traiter le cas d'erreur décrite dans la documentation ici. C'est peut-être pourquoi vous avez manqué le cas de déclenchement BSOD.

Si le tampon est trop petite, la fonction échoue avec le code d'erreur de STATUS_INFO_LENGTH_MISMATCH et le paramètre est réglé ReturnLength à la taille du tampon nécessaire.

0

ZwQueryInformationProcess a besoin d'un HANDLE, pas PROCESS! Vous devez utiliser ObOpenObjectByPointer pour obtenir la poignée en premier.

1

// Déclare cette partie de code dans le fichier d'en-tête si disponible avant la définition de la fonction.

typedef NTSTATUS (*QUERY_INFO_PROCESS) (
__in HANDLE ProcessHandle, 
__in PROCESSINFOCLASS ProcessInformationClass, 
__out_bcount(ProcessInformationLength) PVOID ProcessInformation, 
__in ULONG ProcessInformationLength, 
__out_opt PULONG ReturnLength 
); 

QUERY_INFO_PROCESS ZwQueryInformationProcess; 

// Fonction Définition

NTSTATUS GetProcessImageName(HANDLE processId, PUNICODE_STRING ProcessImageName) 
{ 
NTSTATUS status; 
ULONG returnedLength; 
ULONG bufferLength; 
HANDLE hProcess; 
PVOID buffer; 
PEPROCESS eProcess; 
PUNICODE_STRING imageName; 

PAGED_CODE(); // this eliminates the possibility of the IDLE Thread/Process 

status = PsLookupProcessByProcessId(processId, &eProcess); 

if(NT_SUCCESS(status)) 
{ 
    status = ObOpenObjectByPointer(eProcess,0, NULL, 0,0,KernelMode,&hProcess); 
    if(NT_SUCCESS(status)) 
    { 
    } else { 
     DbgPrint("ObOpenObjectByPointer Failed: %08x\n", status); 
    } 
    ObDereferenceObject(eProcess); 
} else { 
    DbgPrint("PsLookupProcessByProcessId Failed: %08x\n", status); 
} 


if (NULL == ZwQueryInformationProcess) { 

    UNICODE_STRING routineName; 

    RtlInitUnicodeString(&routineName, L"ZwQueryInformationProcess"); 

    ZwQueryInformationProcess = 
      (QUERY_INFO_PROCESS) MmGetSystemRoutineAddress(&routineName); 

    if (NULL == ZwQueryInformationProcess) { 
     DbgPrint("Cannot resolve ZwQueryInformationProcess\n"); 
    } 
} 

/* Query the actual size of the process path */ 
status = ZwQueryInformationProcess(hProcess, 
            ProcessImageFileName, 
            NULL, // buffer 
            0, // buffer size 
            &returnedLength); 

if (STATUS_INFO_LENGTH_MISMATCH != status) { 
    return status; 
} 

/* Check there is enough space to store the actual process 
    path when it is found. If not return an error with the 
    required size */ 
bufferLength = returnedLength - sizeof(UNICODE_STRING); 
if (ProcessImageName->MaximumLength < bufferLength) 
{ 
    ProcessImageName->MaximumLength = (USHORT) bufferLength; 
    return STATUS_BUFFER_OVERFLOW; 
} 

/* Allocate a temporary buffer to store the path name */ 
buffer = ExAllocatePoolWithTag(NonPagedPool, returnedLength, 'uLT1'); 

if (NULL == buffer) 
{ 
    return STATUS_INSUFFICIENT_RESOURCES; 
} 

/* Retrieve the process path from the handle to the process */ 
status = ZwQueryInformationProcess(hProcess, 
            ProcessImageFileName, 
            buffer, 
            returnedLength, 
            &returnedLength); 

if (NT_SUCCESS(status)) 
{ 
    /* Copy the path name */ 
    imageName = (PUNICODE_STRING) buffer; 
    RtlCopyUnicodeString(ProcessImageName, imageName); 
} 

/* Free the temp buffer which stored the path */ 
ExFreePoolWithTag(buffer, 'uLT1'); 

return status; 
} 

// Appel de fonction .. Écrivez ce morceau de code dans préopératoires Rappel et IRQ doit être PASSIVE_LEVEL

PEPROCESS objCurProcess=NULL; 
HANDLE hProcess; 
UNICODE_STRING fullPath; 

objCurProcess=IoThreadToProcess(Data->Thread);//Note: Date is type of FLT_CALLBACK_DATA which is in PreOperation Callback as argument 

hProcess=PsGetProcessID(objCurProcess); 

fullPath.Length=0; 
fullPath.MaximumLength=520; 
fullPath.Buffer=(PWSTR)ExAllocatePoolWithTag(NonPagedPool,520,'uUT1'); 

GetProcessImageName(hProcess,&fullPath); 

dans la variable fullPath il y a Chemin complet du processus .. Comme si le processus est explorer.exe, le chemin ressemblera à ceci: -

\Device\HarddiskVolume3\Windows\explorer.exe 

Remarque: - \ Device \ HarddiskVolume3 Path peut être modifié en raison de la machine et du volume différent sur le disque dur. Ceci est un exemple dans mon cas.