none
Process Creation Notification RRS feed

  • Question

  • I will try to speed things up a bit by answering the mandatory challenges ahead of time, as they are all very standard challenges.

    Issue: I need to get notification of a new process being created - but there's a catch.  PsSetCreateProcessNotifyRoutineEx is working just fine but the notification comes in too early.  Nothing has loaded yet.  I need to get notification (and thereby control) after loading of all modules completes but before the entry point is called.  I have (or can get) a main thread handle for the process but if I suspend that handle, it either crashes or just keeps on going anyway.  Windows is Windows; nothing works as advertised. 

    On to the challenges:

    Challenge #1: "Why do you want to do this?"  Because I'm writing a download manager for browsers and even with an extension, add-on, plug-in, or whatever it's called, for Google Chrome, I cannot invoke my app to handle the download.  It is explicitly disallowed and I find this explicitly unacceptable.  Therefore I am doing it anyway.  I never liked Google.  Now I like them even less.  But it's reported that Chrome has 51% of the browser user base and therefore it must be supported.

    Challenge #2: "you have not posted any code!"  This is a question of process, not of implementation, and posting any code will not assist in answering the question.  It is all hand coded assembly language anyway - instead of a 650 gigabyte app that is all things to all platforms, dragging everybody down to the lowest common denominator, my approach is to actually do some work (what others call "a failure of reinventing the wheel") and target the zillion desktops in the world that are running Windows. 

    Challenge #3: "that way is really stupid, you can't do it that way."  I don't care.  My purpose is to provide product that works; that performs a job the end user needs performed.  I do not worship at the altar of red tape.  Rules are not obeyed just for the thrill of obeying the rules. 

    So, bearing in mind that my purpose here is to pose the question "how do I get notification that a new process has completed loading before the entry point is called," I am not here for a critique on the viability, level conformance, or political correctness of the work I'm doing.  I am doing it this way because this is the way I want to do it.  I require no further justification.  If the question cannot be answered, or if those who truly know what they're talking about tell me it cannot be done, I will do what I always do, and do it anyway.  Even if I have to hook NtCreateFile / NtReadFile, capture the image read off the disk and modify the entry point in memory, I will do that.  I am trying to find an easier way.  I realize there is "no way to do it" within the endless realm of politically correct red tape.  However politically correct red tape does not comprise any recognized bounds for me.  I have a job to do; I will get results.  Whatever it takes.

    If somebody has an answer instead of a critique, insult, slam, challenge, or other judgment, many thanks in advance.


    Those who can, do. Those who can't, teach.

    Tuesday, June 3, 2014 2:17 AM

Answers

  • There are very good reasons for the "rules", having to do with security and ensuring system integrity and they are not there just to extend the red tape. Violate them at your peril.

    I don't believe that there is a supported mechanism to get called in the creation of a process at the point which you desire, but you can get close. When you get called in your process creation callback routine, verify that this process is one that you care about, and then register for a thread creation callback routine using PsSetCreateThreadNotifyRoutine. When your thread creation callback routine is called, verify that the thread is a part of the process that you're interested in.

    P.S.  I do, and I teach

     -Brian


    Azius Developer Training www.azius.com Windows device driver, internals, security, & forensics training and consulting. Blog at www.azius.com/blog

    Tuesday, June 3, 2014 4:44 AM
    Moderator

All replies

  • There are very good reasons for the "rules", having to do with security and ensuring system integrity and they are not there just to extend the red tape. Violate them at your peril.

    I don't believe that there is a supported mechanism to get called in the creation of a process at the point which you desire, but you can get close. When you get called in your process creation callback routine, verify that this process is one that you care about, and then register for a thread creation callback routine using PsSetCreateThreadNotifyRoutine. When your thread creation callback routine is called, verify that the thread is a part of the process that you're interested in.

    P.S.  I do, and I teach

     -Brian


    Azius Developer Training www.azius.com Windows device driver, internals, security, & forensics training and consulting. Blog at www.azius.com/blog

    Tuesday, June 3, 2014 4:44 AM
    Moderator
  • Actually, beyond the thread notification that Brian mentions, if you use PsLoadImageNotify and check it against the process being created, things start running at the time of the first image load.  There will be a number of loads after that, but all of these can be dynamic potentially.


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Tuesday, June 3, 2014 10:31 AM
  • The docs say "For a new process, the CreateProcessNotifyEx routine is called after the initial thread is created, but before the thread begins running."  Which creates a very undefined state of affairs because the system sees the process as sort of existing but not really.  It's hard to tell what has actually been loaded as far as the executable image, and what has simply prepared to load via setting up various structures like the PEB, EProcess, etc.  The notification routine itself has the option of preventing process creation so it's going to be a blocking call and this is where it kicks down to user mode to do its dirty work.  From there, I can get the thread's handle for the new process but if I try to freeze it via SuspendThread - which should only increment the suspend counter and do nothing more - all user mode apps freeze solid.  All of them.  Which indicates the thread's suspend counter does not actually exist yet, and that suspend call is using some as-yet undefined page table entry that could very well (ultimately) be attached to some system process.  So much is so undefined on all this and I hate to rely on any kind of undocumented behavior since - especially with the jump to Windows 8 - Microsoft is getting more and more aggressive and sweeping about making more and more radical changes faster and faster.  To the point of highly unprofessional desperation.  So any solution I rely on could change in Win 8 or 9 or whatever.  Such is the peril Brian referenced.  For now, I need to know what I'm dealing with - what has loaded, what has not - before I do anything more.  I am leaning toward getting the main thread's context and reading its EIP field which, since the thread has not begun execution yet, should ultimately point to the process image's entry point, post-load in virtual memory.  And that is where I can insert a self-jump instruction to spin the thread until I can exit the entire notification chain of calls, let the system "return to normal," then have my userland app return, set its hooks, and remove the "spin" instruction.  Being an assembly language app, it is blindingly fast and the user will not discern any real delays with this approach - since, half the time, most browsers can't even keep up with the keyboard or mouse.  It took some real effort to create that situation even on the original 8086.

    Those who can, do. Those who can't, teach.

    Tuesday, June 3, 2014 2:52 PM
  • Moderation in all things.  Nobody wants an OS that is pure anarchy, but at the same time, things with Windows have become much like airport security, where only those not requiring that security are absolutely smothered by it.  Those most likely to do damage are sent right on through.  And it just keeps increasing.  Very accurately, 98% of what I try to do under Windows simply does not work and there is never any explanation for it.  I read documentation fervently.  I have to.  I read blogs and articles and I test until I'm blue in the face.  I push, and I push very hard, so I of all people know the dismal truth of the matter: around Win 2k, "security" started becoming far more of a hindrance than an asset, and by now it is only 14 years farther down that road.  Most of what I achieve in a week should be doable in 5 minutes.  The red tape has gone so far off the deep end as to be ridiculous.  Check out http://www.formation-research.com/testing.htm.  It'll give you a good idea where we stand today - and this is on DirectX, an area where performance is supposedly everything.

    Those who can, do. Those who can't, teach.

    Tuesday, June 3, 2014 2:58 PM
  • I haven't looked at the process creation code since Windows 7, but the reason things are locking at least for the older systems is that when you suspend the thread it running process creation code and holding some locks.

    Unfortunately, what you are trying to do is something that can be quite challenging.  A less than perfect solution, is have a filter that monitors opening files, creating new threads, accessing the registry, and the opening of threads and processes, and suspend things at that point.  This is an approach that has been used by firms, because it means that for the most part the process cannot do anything damaging before it attempts one of these operations.  It is a pain, but it does work.

     


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Tuesday, June 3, 2014 3:05 PM
  • I will march down this path.  Thank you.  If I can stay within documented parameters, that's what I need to do - although anymore that doesn't seem to afford very much protection over just winging it with undocumented stuff.  Now you can't even get the OS version without using a "helper API."  I thought that was hilarious - an entire API to return 2 bytes of data.  It has gotten that bad - but the point is, without warning, GetVersionEx was simply deprecated just like that and it should have been a safe call to rely on forever into the future.  So that's the minefield we're all playing in these days.  The app I'm creating has the added functionality of capturing all browser throughput - images, videos, etc.  The problem necessitating all this is that with a process polling system, by the time I get the socket hooks in, the home page has already finished loading.  I have to nail that home page before it loads, otherwise I have a product that "sort of works."  The code I'm injecting uses on-the-fly "manual" fixups so I don't have to mess with loading any actual DLL's; I can simply copy functions directly out of my own app, apply the fixups, and put the end product right into the virtual block.  The point being, there are no LoadLibrary calls going on to further complicate matters.  I am having absolutely no problems with the hooks or their removal.  They are working perfectly.  It's that home page access on browser load that keeps slipping through my fingers.  May the Force be with me because the Farce is forever on my back.  A "get version helper API."  I'm just imagining a group of people sitting around a conference table in building 110 trying to make this official without falling out of their chairs laughing.

    Those who can, do. Those who can't, teach.

    Tuesday, June 3, 2014 3:17 PM
  • The only other suggestion is to look if the Windows Filtering Platform (WFP) will get you the hook you need early enough.  I've never used WFP (mainly a storage guy), but it may help.


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Tuesday, June 3, 2014 3:27 PM
  • Don is correct, a WFP filter is probably more appropriate for what you are trying to do.

     -Brian


    Azius Developer Training www.azius.com Windows device driver, internals, security, & forensics training and consulting. Blog at www.azius.com/blog

    Tuesday, June 3, 2014 5:09 PM
    Moderator
  • Hi,

    I am not an expert in Windows Development, but from what i know , each process loads first ntdll and kernel32,

    I suggest catch the the process creation with PsSetCreateThreadNotifyRoutineregister the process id in some global variable, 

    when the ntdll or/and kernel32 are loaded for the process ( compare the ids ) - can be identified by PsSetLoadImageNotifyRoutine, this means that the process have been mapped to memory but the modules are mapped only partially, modify the list of modules dependency in the mapped PE -> add your own dll at the end (inject).

    when dllmain of your module will be called you know that everything is mapped but the process is still not running.

    Please  forgive my ignorance if i am missing something.

    Michael

    Tuesday, August 12, 2014 4:18 PM