Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fetching parent process Id from child process

I create a child process using CreateProcess API. From the child process I need to fetch the parent's process id.

If my process tree have a child and a grand child. I need to fetch the top most parent's process id from the grand child as well.

like image 229
Muthukumar Palaniappan Avatar asked Feb 25 '23 19:02

Muthukumar Palaniappan


2 Answers

You should use the Native API and GetProcAddress to find the address of NtQueryInformationProcess.

typedef struct _PROCESS_BASIC_INFORMATION
{
    NTSTATUS ExitStatus;
    PPEB PebBaseAddress;
    ULONG_PTR AffinityMask;
    KPRIORITY BasePriority;
    HANDLE UniqueProcessId;
    HANDLE InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;

NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
    __in HANDLE ProcessHandle,
    __in PROCESS_INFORMATION_CLASS ProcessInformationClass,
    __out_bcount(ProcessInformationLength) PVOID ProcessInformation,
    __in ULONG ProcessInformationLength,
    __out_opt PULONG ReturnLength
    );

PROCESS_BASIC_INFORMATION basicInfo;

NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &basicInfo, sizeof(basicInfo), NULL);
// My parent PID (*) is in basicInfo.InheritedFromUniqueProcessId

To get the grandparent PID, open the parent process using the parent PID and call NtQueryInformationProcess again on the parent process.

Note * - Strictly speaking, the parent process (the process which created the child process) is not actually recorded. InheritedFromUniqueProcessId just gives you the process from which attributes were inherited. But this is very rarely a problem.

Alternatively, if you don't like the Native API, use CreateToolhelp32Snapshot with TH32CS_SNAPPROCESS, which gives you the required information, except that you'll have to search through the list.

like image 156
wj32 Avatar answered Mar 08 '23 16:03

wj32


wj32's answer should do what you need, but I figured I'd mention another way in case anyone else needs a ancestor at a different level. You can also take a snapshot enumerate the process tree and navigate the ancestors until you reach whatever level you're looking to reach as explained here.

The following example gets the process ID of the parent process (the process started the current one):

// Speed up build process with minimal headers.
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

#include <tchar.h>
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

/* Macros for prettier code. */
#ifndef MAX_PATH
#   define MAX_PATH _MAX_PATH
#endif

// Search each process in the snapshot for id.
BOOL FindProcessID(HANDLE snap, DWORD id, LPPROCESSENTRY32 ppe)
{
    BOOL fOk;
    ppe->dwSize = sizeof(PROCESSENTRY32);
    for (fOk = Process32First( snap, ppe ); fOk; fOk = Process32Next( snap, ppe ))
        if (ppe->th32ProcessID == id)
            break;
    return fOk;
}

// Obtain the process and thread identifiers of the parent process.
BOOL ParentProcess(LPPROCESS_INFORMATION ppi)
{
    HANDLE hSnap;
    PROCESSENTRY32 pe;
    THREADENTRY32   te;
    DWORD id = GetCurrentProcessId();
    BOOL fOk;

    hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS|TH32CS_SNAPTHREAD, id );

    if (hSnap == INVALID_HANDLE_VALUE)
        return FALSE;

    FindProcessID( hSnap, id, &pe );
    if (!FindProcessID( hSnap, pe.th32ParentProcessID, &pe ))
    {
        CloseHandle( hSnap );
        return FALSE;
    }

    te.dwSize = sizeof(te);
    for (fOk = Thread32First( hSnap, &te ); fOk; fOk = Thread32Next( hSnap, &te ))
        if (te.th32OwnerProcessID == pe.th32ProcessID)
            break;

    CloseHandle( hSnap );

    ppi->dwProcessId = pe.th32ProcessID;
    ppi->dwThreadId = te.th32ThreadID;

    return fOk;
}

int _tmain(int argc, _TCHAR* argv[])
{
    PROCESS_INFORMATION parentInformation;
    if(!ParentProcess(&parentInformation)) {
        _tprintf(TEXT("Fatal: Could not get parent information.\n"));
        return 1;
    }
    _tprintf(TEXT("Parent Process ID: %ul\n"), parentInformation.dwProcessId);
    return 0;
}
like image 34
Charles Grunwald Avatar answered Mar 08 '23 16:03

Charles Grunwald