Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Proper way to get the main thread ID in the non Ex process creation callback?

david_mk85david_mk85 Member Posts: 16
edited February 21 in NTDEV

Hello everyone

I want to get the thread ID inside my PCREATE_PROCESS_NOTIFY_ROUTINE callback, since unlike the EX version there is no PPS_CREATE_NOTIFY_INFO in the third argument, what is the proper way of doing this?

I don't want to parse EPROCESS structure of the corresponding PID since its undocumented, i want a stable way of getting the thread ID that works in all windows versions.
I thought of using PsGetCurrentThreadId, but does PsGetCurrentThreadId always return the thread ID of the created process?

Post edited by david_mk85 on

Comments

  • david_mk85david_mk85 Member Posts: 16

    I also tried to use ZwQuerySystemInformation to find the corresponding PID then find its TID that way, but it seems like when i use this inside the create process callback, the process is still not fully created and i cannot find the PID using ZwQuerySystemInformation.

  • ThatsBerkanThatsBerkan Member Posts: 44
    edited February 21

    You might want and try to use PsSetCreateThreadNotifyRoutine for this.

    Post edited by ThatsBerkan on
  • david_mk85david_mk85 Member Posts: 16

    @ThatsBerkan said:
    You might want and try to use PsSetCreateThreadNotifyRoutine for this.

    Thank you for the suggestion, but i want to use only the create process callback for efficiency, i want to block certain processes from getting created and using thread creation callback is not really good. there has to be a way that i can get the thread ID considering i already have the PID and the EPROCESS, but i don't want to use unstable methods to do so.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 399
    via Email
    The "older" callbacks would not let you prevent process creation, IIRC, so
    how does main thread help?
  • david_mk85david_mk85 Member Posts: 16
    edited February 22

    @Dejan_Maksimovic said:
    The "older" callbacks would not let you prevent process creation, IIRC, so
    how does main thread help?

    Yes you can, i have already implemented it using ZwTerminateProcess, but what is the most efficient and documented way of getting the thread ID?

    Also i did manage to get the thread ID using ZwQuerySystemInformation, turns out there was a bug in the structs that i defined. but the problem with using ZwQuerySystemInformation is that it needs undocumented structs, and i really want to step away from using undocumented structs as much as i can, my company really discourages us from using undocumented stuff, unless we have valid reasons that its the only way of doing it, so any help is appreciated.

  • anton_bassovanton_bassov Member MODERATED Posts: 5,223

    First of all, what is the "main thread" in this context??? Please note that the very concept of the "main thread" is a 100% Win32 thing, which is simply meaningless in the kernel, because the kernel does not make any distinction between the "main" thread and all other ones. As far as there is at least one thread in some state other than 'terminated' one, the process is considered alive and kicking by the kernel.....

    what is the most efficient and documented way of getting the thread ID?

    Well, you already got the answer to this question (i.e to use thread creation callbacks), but you claim that this approach is not good for you....

    Anton Bassov

  • Don_BurnDon_Burn Member - All Emails Posts: 1,725

    You cannot do this without the PsSetCreateThreadNotifyRoutine. In older versions of Windows (I never tried it beyond Win7) depending on the type of process create there is no thread at the time of the callback. Windows allows people to create a process in a number of ways (for example emulate a fork) each of these is different. I had clients who tried what you are proposing to do, only to find they were killing the process that was specified to be inherited from.

  • david_mk85david_mk85 Member Posts: 16

    @anton_bassov said:
    First of all, what is the "main thread" in this context??? Please note that the very concept of the "main thread" is a 100% Win32 thing, which is simply meaningless in the kernel, because the kernel does not make any distinction between the "main" thread and all other ones. As far as there is at least one thread in some state other than 'terminated' one, the process is considered alive and kicking by the kernel.....

    what is the most efficient and documented way of getting the thread ID?

    Well, you already got the answer to this question (i.e to use thread creation callbacks), but you claim that this approach is not good for you....

    Anton Bassov

    By main thread i mean the only thread that exists when the create process callback gets called.
    Trying to use thread callback just so i can get the main thread ID doesn't make any sense, i already have the process ID and its structure in the process creation callback.. and yes i tested it with 10-12 windows versions and all of them do have a thread ID when process callback gets called.

    And i already solved this problem using the undocumented way of using ZwQuerySystemInformation, but was wondering if theres any better way.
    I need the thread ID before killing the process for logging purposes, long story. (supervisor says log thread ID, i can't say no..)

  • david_mk85david_mk85 Member Posts: 16
    edited February 22

    @Don_Burn said:
    You cannot do this without the PsSetCreateThreadNotifyRoutine. In older versions of Windows (I never tried it beyond Win7) depending on the type of process create there is no thread at the time of the callback. Windows allows people to create a process in a number of ways (for example emulate a fork) each of these is different. I had clients who tried what you are proposing to do, only to find they were killing the process that was specified to be inherited from.

    But i already did!! I literally tested it with 10-12 windows versions. i got the thread ID using ZwQuerySystemInformation, but i was wondering if there's any documented and easier way of doing this, because right now i need to enumerate all the processes.. and yes there is a thread a the time of callback, you can easily check it yourself if you don't believe me.

  • Don_BurnDon_Burn Member - All Emails Posts: 1,725

    I no longer have access to the source, but at one time there were at least four major code paths through process create. Over the years I found that developers tested one of the paths, and the other three they just assumed that it was the same. It isn't the versions of Windows as much as the subtle variations in code paths for variations on the creation of a process.

  • anton_bassovanton_bassov Member MODERATED Posts: 5,223

    By main thread i mean the only thread that exists when the create process callback gets called.

    Again, you seem to be thinking in terms of Win32.....

    In actuality, process and thread creation are, from the kernel's perspective, two separate system calls. When a new process gets created it does not yet have any threads associated with it

    and yes i tested it with 10-12 windows versions and all of them do have a thread ID when process callback gets called.

    This is nothing more than just an observed behavior. Once your callback gets invoked in context of a system thread, you were, up to this point, just (un?)lucky enough to have had both syscalls executed by the time your callback got invoked. However, things are not guaranteed to work this way in 100% cases

    And i already solved this problem using the undocumented way of using ZwQuerySystemInformation

    This"solution" belongs to "works fine most of the time" class, i.e. is just a classical example of a "Heisenbug" that reveals itself once in a VERY while

    Anton Bassov

  • Don_BurnDon_Burn Member - All Emails Posts: 1,725

    It is possible to create a process in the kernel without any threads. I've done this to have a user space address space to manage memory. What is your approach going to do with a process like that?

  • anton_bassovanton_bassov Member MODERATED Posts: 5,223

    Don,

    It is possible to create a process in the kernel without any threads.I've done this to have a user space address space to manage memory.

    Could you please expand it a bit.

    IIRC, there is simply no way to create a process without a userland representation of any description. Although a newly-created process, indeed, does not have any threads in it, it still needs the address space, and, hence its image section. Depending on your objectives, it can be either the one of the process that you want to inherit the address space from, or the one of the target executable file, but it has to be mapped to its address space (along with ntdll.dll,of course - IIRC, there is simply no way to avoid this part).

    Anton Bassov

  • Don_BurnDon_Burn Member - All Emails Posts: 1,725

    Anton,

     Sorry if I wasn't clear.  This was done when NonPagedPool was limited and a client had a system that needed a lot of memory.  I created a process to have the address space.  Then I allocated memory in that address space with ZwAllocateVirtualMemory and mapped it to the kernel.  
    

    Don Burn

  • david_mk85david_mk85 Member Posts: 16
    edited February 22

    @anton_bassov said:

    By main thread i mean the only thread that exists when the create process callback gets called.

    Again, you seem to be thinking in terms of Win32.....

    In actuality, process and thread creation are, from the kernel's perspective, two separate system calls. When a new process gets created it does not yet have any threads associated with it

    That makes sense, thank you for the response.

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 399
    via Email
    Where???
  • MBond2MBond2 Member Posts: 277

    IIRC the reason that these callbacks were changed was because of horrible race conditions with doing exactly that. that was back in the server 2003 days i think though

  • brandon_85brandon_85 Member Posts: 1

    @anton_bassov said:
    In actuality, process and thread creation are, from the kernel's perspective, two separate system calls. When a new process gets created it does not yet have any threads associated with it
    This is nothing more than just an observed behavior. Once your callback gets invoked in context of a system thread, you were, up to this point, just (un?)lucky enough to have had both syscalls executed by the time your callback got invoked. However, things are not guaranteed to work this way in 100% cases

    Thank you for the answer, But how come the new create process callbacks (Ex and Ex2) do provide the creating thread ID in the PS_CREATE_NOTIFY_INFO struct? if thread ID being available is just the matter of luck, why would microsoft provide it in the PS_CREATE_NOTIFY_INFO structure?

  • anton_bassovanton_bassov Member MODERATED Posts: 5,223

    how come the new create process callbacks (Ex and Ex2) do provide the creating thread ID

    Well, simply because the creating thread is known to have been alive and kicking at the time it has called ZwCreateProcess(,) don't you think. Therefore, there is no particular problem with identifying it. However, the same thing cannot be said about the main thread of the newly-created process - it does not yet exist at the moment.....

    Anton Bassov

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Internals & Software Drivers 25 Jan 2021 LIVE ONLINE
Developing Minifilters 8 March 2021 LIVE ONLINE