Jump to content
Tuts 4 You

How many PID ( Process Identifier ) for each process?


Amer

Recommended Posts

Most of us know there is one ID for each process, actually no, there is more than one.

Very Simple and new for some users:

1- How many PID ( Process Identifier ) for each process?

2- Why windows task listing methods or enumerating methods deal with one PID (the first one of them) ?

Regards

Amer

Edited by Amer
Link to comment

it doesnt depend..

EACH process has its own processid, given to it by the system at the time of launch, the pid of each process is UNIQUE - look at task manager, it lists all the processes, and their id's if you look closely enough..

each processid typically goes up by 4, so process 0 = system idle process, 4 = the next one and so on...

sometimes the system will recycle unused id's from processes that previously exited.. but in a nutshell 1 process, 1 pid

  • Like 1
Link to comment
12 hours ago, kuqadk3 said:

It's depend

Not Clear

6 hours ago, evlncrn8 said:

it doesnt depend..

EACH process has its own processid, given to it by the system at the time of launch, the pid of each process is UNIQUE - look at task manager, it lists all the processes, and their id's if you look closely enough..

each processid typically goes up by 4, so process 0 = system idle process, 4 = the next one and so on...

sometimes the system will recycle unused id's from processes that previously exited.. but in a nutshell 1 process, 1 pid

No evlncrn8, it is more than one PID for each process and windows use the first (Smallest) one from the sequence.

 

 

 

Link to comment

no they dont, process id is unique, check in task manager..the ones recorded in the system modules info is the parent process id

edit : kao got there before me

Edited by evlncrn8
Link to comment

Output of tasklist command:

C:\Users\DBNull>tasklist

Nom de l’image                 PID Nom de la sessio Numéro de s Utilisation
========================= ======== ================ =========== ============
System Idle Process              0 Services                   0        24 Ko
System                           4 Services                   0       676 Ko
smss.exe                       340 Services                   0        68 Ko
csrss.exe                      448 Services                   0       816 Ko
wininit.exe                    508 Services                   0       172 Ko
...

but an application can be started many times, and different processes will be created and assigned different and UNIQUE PID for each instance even if it is the same application.

Link to comment

I think he may be referring to threads. @Amer, Microsofts own documentation on their MSDN website is very useful and a good read, it nicely explains process identifiers and thread identifiers...
 

Quote

Each process provides the resources needed to execute a program. A process has a virtual address space, executable code, open handles to system objects, a security context, a unique process identifier, environment variables, a priority class, minimum and maximum working set sizes, and at least one thread of execution. Each process is started with a single thread, often called the primary thread, but can create additional threads from any of its threads.

A thread is the entity within a process that can be scheduled for execution. All threads of a process share its virtual address space and system resources. In addition, each thread maintains exception handlers, a scheduling priority, thread local storage, a unique thread identifier, and a set of structures the system will use to save the thread context until it is scheduled. The thread context includes the thread's set of machine registers, the kernel stack, a thread environment block, and a user stack in the address space of the thread's process. Threads can also have their own security context, which can be used for impersonating clients.

https://msdn.microsoft.com/en-us/library/windows/desktop/ms681917(v=vs.85).aspx

Ted.

  • Like 1
Link to comment
3 hours ago, kao said:

:kick: 

Process ID is unique, each process has one and only one. http://materias.fi.uba.ar/7508/WI6/Windows Internals Part 1 (6th Edition).pdf - chapter 5.

 

Kao and Etor Madiv, no there is more than one ID for every process running in windows and every PID can be used as unique PID.

task manager shows only one of them.

@Teddy Rogers No ted i don't  referring to threads I'm talking about Main Process it self for example Notepad.exe or explorer.exe.

believe me no search engine will find the correct answer and Microsoft did not mentioned about it before , you have to do a little research by coding to find it.

Thank You Every One For Sharing.

 Regards

Link to comment

PID - UNIQUE - one per process

TID - THREAD - also unique

One PID can have multiple TID'S

the 'only one' of them is - are you referring to the tebptr->RealClientId.UniqueProcess entry in the peb perhaps ?

or tebptr->RealClientId.UniqueThread  ?

if so.. not undocumented - you just didnt know where to look

 

Link to comment
26 minutes ago, Amer said:

you have to do a little research by coding to find it.

I'm happy to view some code to have a better understanding of what you are explaining...

Ted.

Link to comment

 

14 minutes ago, Teddy Rogers said:

I'm happy to view some code to have a better understanding of what you are explaining...

Ted.

@Teddy Rogers @evlncrn8

OK, launch notepad.exe launch task manager.
for example (notepad.exe PID = 3692) you can use OpenProcess var,var,dwProcId = 3693 or 3694 or 3695 then EnumProcessModules.


and tell me what you think
Regards

Edited by Amer
Link to comment
4 minutes ago, evlncrn8 said:

you're checking the return values from OpenProcess etc in your code ?

no I'm using it as real result and it is work of course with no doubt.

 

Link to comment

what happens if you're doing process id - 1 (as opposed to the +1, +2 , in your example, is it right then ?

i suspect the enumeration you're using for the process id's is doing a range check on a value, and if its within it'll return success.. as opposed to an ==

and check the return value of openprocess..you might just be getting lucky

Edited by evlncrn8
Link to comment

@evlncrn8 no luck here it is real result every time you can try it with any different process.

now you can think about the part tow of the puzzle:

2- Why windows task listing methods or enumerating methods deal with one PID (the first one of them) ?

Link to comment

Here is a proof of concept to show that -/+ process ids from the real one are useless for purpose:

(This will get the notepad.exe process id then loop -5/+5 pids around it trying to write to its window.)


/**
 * Process Id Example
 * (c) 2016 atom0s [atom0s@live.com]
 */

#include <Windows.h>
#include <string>
#include <TlHelp32.h>

/**
 * Obtains the process id of notepad.exe.
 *
 * @returns {uint32_t} The process id if successful, 0 otherwise.
 */
uint32_t getNotepadProcessId(void)
{
    PROCESSENTRY32 pe32 = { sizeof(PROCESSENTRY32) };

    // Obtain a snapshot of the current process list..
    auto snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot == INVALID_HANDLE_VALUE)
        return 0;

    // Ensure we can obtain the first process..
    if (!::Process32First(snapshot, &pe32))
    {
        ::CloseHandle(snapshot);
        return 0;
    }

    do
    {
        // Locate notepad.exe running..
        if (_stricmp(pe32.szExeFile, "notepad.exe") == 0)
        {
            ::CloseHandle(snapshot);
            return pe32.th32ProcessID;
        }
    } while (::Process32Next(snapshot, &pe32));

    ::CloseHandle(snapshot);
    return 0;
}

/**
 * Obtains a processes main thread id.
 *
 * @param {uint32_t} processId - The process id to obtain the thread id of.
 * @returns {uint32_t} The thread id if successful, 0 otherwise.
 */
uint32_t getProcessThreadId(uint32_t processId)
{
    THREADENTRY32 te32 = { sizeof(THREADENTRY32) };

    // Obtain a snapshot of the target processes threads..
    auto snapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, processId);
    if (snapshot == INVALID_HANDLE_VALUE)
        return 0;

    // Ensure we can obtain the first thread..
    if (!::Thread32First(snapshot, &te32))
    {
        ::CloseHandle(snapshot);
        return 0;
    }

    do
    {
        // Locate the first thread to match our process id as the parent..
        if (te32.th32OwnerProcessID == processId)
        {
            ::CloseHandle(snapshot);
            return te32.th32ThreadID;
        }
    } while (::Thread32Next(snapshot, &te32));

    ::CloseHandle(snapshot);
    return 0;
}

/**
 * Enumerates a threads windows.
 *
 * @param {HWND} hWnd - The current window handle.
 * @param {LPARAM} lParam - Custom parameter data passed from the EnumThreadWindows call.
 * @returns {BOOL} TRUE if continue enumeration, FALSE otherwise.
 */
BOOL CALLBACK EnumThreadWindowsCallback(HWND hWnd, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);

    // Obtain the window class..
    char className[2048] = { 0 };
    ::GetClassName(hWnd, className, 2048);

    // Locate the notepad window class..
    if (_stricmp(className, "Notepad") == 0)
    {
        printf_s("[!] Found a notepad window! - Handle: %08X\r\n", hWnd);

        // Locate the editor control..
        auto hWndEdit = ::FindWindowEx(hWnd, nullptr, "Edit", nullptr);
        if (hWndEdit != nullptr)
        {
            // Obtain the current text..
            char buffer[4096] = { 0 };
            ::SendMessage(hWndEdit, WM_GETTEXT, (WPARAM)4096, (LPARAM)&buffer);

            // Append a message from the current process id..
            strcat_s(buffer, 4096, "Hello world from process id: ");
            strcat_s(buffer, 4096, std::to_string((uint32_t)lParam).c_str());
            strcat_s(buffer, 4096, "\r\n");
            ::SendMessage(hWndEdit, WM_SETTEXT, NULL, (LPARAM)buffer);
        }
    }

    return TRUE;
}

/**
 * Application entry point.
 *
 * @param {int} argc - The number of arguments passed to this application.
 * @param {char*[]} argv - The arguments passed to this application.
 * @returns {int} 0 on success, -1 otherwise.
 */
int __cdecl main(int argc, char* argv[])
{
    printf_s("[!] Process Id Accessibility Proof-of-Concept - by atom0s\r\n\r\n");

    // Obtain the notepad.exe process id..
    auto pid = getNotepadProcessId();
    if (pid == 0)
    {
        printf_s("[!] Failed to locate notepad.exe, cannot continue.\r\n");
        return -1;
    }

    // Loop -/+ 5 pids from the found one for testing..
    auto minPid = pid - 5;
    auto maxPid = pid + 5;

    for (auto x = minPid; x <= maxPid; x++)
    {
        // Obtain the notepad.exe thread id..
        auto tid = getProcessThreadId(x);
        if (tid == 0)
            printf_s("[!] Failed to obtain notepad.exe thread id for pid: %08X\r\n", x);
        else
        {
            // Enumerate the threads windows to find the main notepad window..
            ::EnumThreadWindows(tid, EnumThreadWindowsCallback, (LPARAM)x);
        }
    }

    return 0;
}

 

  • Like 1
Link to comment

Second time I have to do:kick:.

The fact that some Windows APIs accept not only actual ProcessID (which is always divisible by 4), but also values +1, +2, +3 and return information about the same process - it's a bug-feature in specific APIs. It doesn't mean that process has several ProcessIDs. Further reference:

https://blogs.msdn.microsoft.com/oldnewthing/20080228-00/?p=23283

https://blogs.msdn.microsoft.com/oldnewthing/20050121-00/?p=36633

  • Like 2
Link to comment
Extreme Coders

I did some digging about this, and the reason for this seems to come from the function ExpLookupHandleTableEntry.
Internally, PsLookupProcessByProcessId calls upon ExMapHandleToPointer -> ExpLookupHandleTableEntry to search for the process.

Within ExpLookupHandleTableEntry a mask of ~3 (0xFFFFFFFC) is applied before searching in the handle table.
This in binary turns to 1111 1111 1111 1111 1111 1111 1111 1100. The last two bits are zero. Hence there are 4 possible values.

There is also a tweet on this: 

 

Edited by Extreme Coders
EDIT: Added tweet
  • Like 3
Link to comment
4 hours ago, kao said:

Second time I have to do:kick:.

The fact that some Windows APIs accept not only actual ProcessID (which is always divisible by 4), but also values +1, +2, +3 and return information about the same process - it's a bug-feature in specific APIs. It doesn't mean that process has several ProcessIDs. Further reference:

https://blogs.msdn.microsoft.com/oldnewthing/20080228-00/?p=23283

https://blogs.msdn.microsoft.com/oldnewthing/20050121-00/?p=36633

@kaoNo it is not a bug in API it is a bug in windows OS.

Every Process has at list 4 IDs depends on how created and who created it.

I'll post full info about it as soon as possible.

Regards

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...