Parent Process id

Hi all,

I am writing minifilter driver, and intercept IRP_MJ_CREATE during this I want to get parent process id. Now, I am getting parent process id ( When any file is accessed from my application then I get parent process id of application) e.g : abc.doc file is accessed then I got parent process id of my application even in MSWord’s parent and all dll’s parent all belongs my application.

Problem is that when MSWord already is running then my application access abc.doc file in this case I don’t get parent process id of my application.

Please , let me know if anybody can help this.

Thanks

There is something slightly suspect about needing a process ID. Note that
there is no concept of “parent process” for most of Windows; you have to
create a process group, something which is so rarely done as to not matter
in practice. Since all drivers except the top level driver run in an
unknown process context, it is not clear what the value of this
information is. What problem are you trying to solve?

What you probably meant to ask was how to get the process ID of the
process that initiated the I/O operation, which would not be referred to
as a “parent process”. Nonetheless, you have probably fastened onto this
idea as the One True Solution to your unspecified problem. I see only two
outcomes: (a) this is some kind of p-baked “security” design (for p <
0.05) and can probably be easily defeated, and (b) this is some kind of
p-baked “security” design (for p < 0.01) which will interfere with all
kinds of legitimate uses of the file. Since we don’t know what you are
trying to accomplish, it is hard to reccomend a workable solution, but
when I see these kinds of questions, alarm bells start going off.
joe

Hi all,

I am writing minifilter driver, and intercept IRP_MJ_CREATE during this I
want to get parent process id. Now, I am getting parent process id ( When
any file is accessed from my application then I get parent process id of
application) e.g : abc.doc file is accessed then I got parent process id
of my application even in MSWord’s parent and all dll’s parent all belongs
my application.

Problem is that when MSWord already is running then my application access
abc.doc file in this case I don’t get parent process id of my application.

Please , let me know if anybody can help this.

Thanks


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Not sure what the OP means when they say “parent process ID”. I mean, there is a parent process concept for windows processes and there are documented ways in windows to build the tree of process IDs (where possible) but i’m not sure what one can do with them. Anyway, see the Process32First function (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684834(v=vs.85).aspx) returns a PROCESSENTRY32 structure (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx) that contains the th32ParentProcessID member.

Could you please show the code you use to get the parent process ID in your code ? Could you also please explain how do you plan do use this parent process ID?

Thanks,
Alex.

I am reasonably certain the OP meant “process which performed the I/O
operation”, because process trees, although a supported concept, are
sufficiently nonexistent in practice as to not be worth bothering about.

My major concern here is that a driver should not care about the process
ID, because the end result is very suspect, and the perceived need for
this will result in a solution which probably does not solve the intended
problem.

Process32First/Next apply only to application space, and could not be
called from a driver.

Another alarm bell goes off when someone sufficiently unfamiliar with
Windows uses the phrase “process tree” and then proposes writing a driver
that cares about process ID. There are probably several documented,
supported mechanisms that would solve the problem, if we only knew what it
is.

This question is not a discussion about how to make pigs fly; it is a
question of the form “How do I attach those things birds have to something
else.” We are far, far from discussing wings, pigs, and brands of
cyanoacrylate.
joe

Not sure what the OP means when they say “parent process ID”. I mean,
there is a parent process concept for windows processes and there are
documented ways in windows to build the tree of process IDs (where
possible) but i’m not sure what one can do with them. Anyway, see the
Process32First function
(http://msdn.microsoft.com/en-us/library/windows/desktop/ms684834(v=vs.85).aspx)
returns a PROCESSENTRY32 structure
(http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx)
that contains the th32ParentProcessID member.

Could you please show the code you use to get the parent process ID in
your code ? Could you also please explain how do you plan do use this
parent process ID?

Thanks,
Alex.


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

A slight typo in my response; I meant to write

Another alarm bell goes off when someone insufficienty familiar with
Windows uses the phrase “parent process”…

joe

I am reasonably certain the OP meant “process which performed the I/O
operation”, because process trees, although a supported concept, are
sufficiently nonexistent in practice as to not be worth bothering about.

My major concern here is that a driver should not care about the process
ID, because the end result is very suspect, and the perceived need for
this will result in a solution which probably does not solve the intended
problem.

Process32First/Next apply only to application space, and could not be
called from a driver.

Another alarm bell goes off when someone sufficiently unfamiliar with
Windows uses the phrase “process tree” and then proposes writing a driver
that cares about process ID. There are probably several documented,
supported mechanisms that would solve the problem, if we only knew what it
is.

This question is not a discussion about how to make pigs fly; it is a
question of the form “How do I attach those things birds have to something
else.” We are far, far from discussing wings, pigs, and brands of
cyanoacrylate.
joe

> Not sure what the OP means when they say “parent process ID”. I mean,
> there is a parent process concept for windows processes and there are
> documented ways in windows to build the tree of process IDs (where
> possible) but i’m not sure what one can do with them. Anyway, see the
> Process32First function
> (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684834(v=vs.85).aspx)
> returns a PROCESSENTRY32 structure
> (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839(v=vs.85).aspx)
> that contains the th32ParentProcessID member.
>
> Could you please show the code you use to get the parent process ID in
> your code ? Could you also please explain how do you plan do use this
> parent process ID?
>
> Thanks,
> Alex.
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


NTFSD is sponsored by OSR

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Hi Alex,

I am using following code :

if(gLock && Data->Iopb->MajorFunction == IRP_MJ_CREATE ) // Access Denied (Locking Case)
{
uStrParentPath.Length = 0 ;
uStrParentPath.MaximumLength = nameInfo->Name.Length + 520;
uStrParentPath.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool,nameInfo->Name.Length + 520,‘uPr3’);

if(uStrParentPath.Buffer != NULL)
{

RtlAppendUnicodeStringToString(&uStrParentPath,&uStrGuidName);
RtlAppendUnicodeStringToString(&uStrParentPath,&nameInfo->ParentDir);

// File Execution Scenario

bMatched = Traverseinto_Lock_List(uStrPath,uStrParentPath,bApp); // Search existing path in list

pRocess = IoThreadToProcess(Data->Thread); // Get Current Process that belongs to existing thread

if(pRocess != NULL && nameInfo->Extension.Length > 0 && gAppRunning)

{
hProcess = PsGetProcessId(pRocess);
szProcess = PsGetProcessImageFileName(pRocess);
if(szProcess != NULL)
{

RtlMultiByteToUnicodeSize( &exLen, szProcess, strlen(szProcess)-3);

exeName.Length = 0 ;
exeName.MaximumLength = 50;
exeName.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool,50,‘uPe1’);

uStr1.Length = 0 ;
uStr1.MaximumLength = 50;
uStr1.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool,50,‘uEt1’);

if(exeName.Buffer != NULL && uStr1.Buffer != NULL)
{

RtlMultiByteToUnicodeN(exeName.Buffer, exLen, &len, szProcess, strlen(szProcess)-3);

exeName.Length = (USHORT)len;

RtlUnicodeStringCbCatN(&uStr1,&exeName,22);

if( NT_SUCCESS(GetParentProcessId (hProcess, &hParent)) ) // Get handle of Parent Process
{
if(hParent != 0)
{
exePName.Length = 0 ;
exePName.MaximumLength = 50;
exePName.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool,50,‘uPe2’);

uStrP1.Length = 0 ;
uStrP1.MaximumLength = 50;
uStrP1.Buffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool,50,‘uEt2’);

if(exePName.Buffer != NULL && uStrP1.Buffer != NULL)
{
PsLookupProcessByProcessId(hParent, &pParentProcess);

pParentImageName= PsGetProcessImageFileName(pParentProcess);

if(pParentImageName != NULL)
{

if(NT_SUCCESS (RtlMultiByteToUnicodeSize( &exPLen, (PCHAR)pParentImageName, strlen((PCHAR)pParentImageName)-3)) )
{
RtlMultiByteToUnicodeN(exePName.Buffer, exPLen, &Plen, (PCHAR)pParentImageName, strlen((PCHAR)pParentImageName)-3);

exePName.Length = (USHORT)Plen;

RtlUnicodeStringCbCatN(&uStrP1,&exePName,22);

if(bMatched && (RtlCompareUnicodeString(&uStr1,&exeFolderLock,TRUE) == 0 || RtlCompareUnicodeString(&uStrP1,&exeFolderLock,TRUE) == 0))
{
bMatched = FALSE;
}

}
}

ExFreePoolWithTag(uStrP1.Buffer,‘uEt2’);
ExFreePoolWithTag(exePName.Buffer,‘uPe2’);
ObDereferenceObject((PVOID)pParentProcess);
}
}
}

#ifdef _RELEASE
DbgPrint(“File Accessed in Locking %ws”,uStrPath.Buffer);
#endif

ExFreePoolWithTag(uStr1.Buffer,‘uEt1’);
ExFreePoolWithTag(exeName.Buffer,‘uPe1’);
}
}
}
// File Execution Scenario
ExFreePoolWithTag(uStrParentPath.Buffer,‘uPr3’);
}
}

NTSTATUS GetParentProcessId ( __in HANDLE processId, __out PHANDLE parentProcessId )
{
NTSTATUS status;
PEPROCESS eProcess;
HANDLE hProcess;
PROCESS_BASIC_INFORMATION pbi;
PAGED_CODE();

if ( processId == (HANDLE) 4 )
{
*parentProcessId = 0;
return STATUS_SUCCESS;
}
status = PsLookupProcessByProcessId(processId, &eProcess);
if(NT_SUCCESS(status))
{
status = ObOpenObjectByPointer(eProcess,0, NULL, 0,0,KernelMode,&hProcess);
if( ! NT_SUCCESS(status))
{
// DbgPrint(“Error: ObOpenObjectByPointer Failed: %08x\n”, status);
}
ObDereferenceObject(eProcess);
}
else
{
//DbgPrint(“Error: 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”);
}
}
status = ZwQueryInformationProcess( hProcess, ProcessBasicInformation, &pbi, sizeof (PROCESS_BASIC_INFORMATION), NULL);
if (NT_SUCCESS(status))
{
*parentProcessId = (HANDLE) pbi.InheritedFromUniqueProcessId;
//DbgPrint(“Get Current Process…”);
}
return status;
}

Thanks

Judging by the use of the InheritedFromUniqueProcessId member of the PROCESS_BASIC_INFORMATION structure i’d say this code is indeed looking for the parent process of the process that issued the IO.

I’d suggest using FltGetRequestorProcess() to get the PEPROCESS (as opposed to IoThreadToProcess and friends). PsGetProcessImageFileName() is rather limited and a better technique is discussed in the article “What’s in a (Process) Name? Obtaining A Useful Name for the Executable Image in a Process” (http://www.osronline.com/article.cfm?article=472). You need to do this especially if you’re doing this for a security solution since if I remember correctly the name returned by PsGetProcessImageFileName() can be faked.

One other thing that I would do is to set the ZwQueryInformationProcess pointer using an interlocked operation.

Could you please explain what it is you’re trying to do here ? I’m still a bit confused about what the intent is…

Thanks,
Alex.


I must admit I find it frustrating to still find people years later using the undocumented (and VERY ill-advised) PsGetProcessImageFileName function rather than the technique I described in the cited article (for which I did quite a bit of groundwork to get permission from folks at Microsoft to agree to reveal some undocumented material.)

PsGetProcessImageFileName can not only be spoofed but doesn’t contain the path to the file. So if you see “word.exe” running, you can’t tell if it is “d:\My Malware\temp\winword.exe” or “c:\Program Files\Microsoft Office\Office14\winword.exe” (the path to my copy of Word, as I’m one of those crazies who runs the 64 bit version precisely BECAUSE 32 bit add-ins don’t work with it…")

Russinovich taught people this trick (including the “walk through the EPROCESS in the system process to find the name “SYSTEM” to determine the offset to this field” hack) and we’ve been suffering for it ever since then.

Don’t use it for anything other than a debugging aid.

Tony
OSR