Closed pseymour closed 2 years ago
I just wanted to make sure you are aware of the limitations of logging processes with WMI. You defined the WMI query as:
"SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'";
Even though this seems like you get an event-based stream of all process changes, what is actually happening under the covers is that WMI is enumerating all processes every 1 second (that's the WITHIN 1) comparing them to the previous list and sending you off modification events based on that.
This means that a process that is created and destroyed within that one second interval will be missed and you'll never get an event for it. It is also possible that it exits after WMI provides the event, but before your code has a chance to check the process information and log it.
It also uses more CPU than you'd expect to do this if you have a lot of processes running - not enough to hugely affect the system, but more CPU than you'd like. If you want basic logging while MakeMeAdmin has added a user as an admin then it is probably a reasonable tradeoff to do it this way.
But, if you want constant monitoring then i'd recommend using sysmon instead. This does the logging by having a kernel driver that can do true event-based process monitoring without the possibility of missing processes and without the overhead of WMI. It should be fairly easy to create a sysmon configuration filter that will log all elevated user processes based on integrity level=high and perhaps with a user exclusion as well. I'll probably try that out later and post a suitable config. Perhaps MakeMeAdmin could offer to set up sysmon with this basic configuration as part of its install process, but people could also modify it to record far more detail if they want to.
The other thing I'm doing is adding a UI so that you can right-click on a file and choose "Run as Administrator with MakeMeAdmin". This can then log the process that gets elevated (but not sub-processes) which may be enough logging for some use cases.
Yep, I am aware of the drawbacks of using WMI, but thank you for making sure. The sysmon idea is interesting and something I had not thought of. I need to do more than logging though. There is also a feature in the queue to kill processes if they are running elevated (browsers, email clients, etc.). So we'd have to find some way to handle that. Not a big problem, but something that needs to be handled if we switch to sysmon.
I do especially like the RunAs idea. It's been on my personal wish list for a while. I should probably post all of those items on here, so they're stored with the feature requests that others have made.
We used it for a while in another context before realizing how it actually worked which is why I mentioned it. We backed off form using a 1-second polling interval specifically because of the performance overhead.
Fortunately terminating elevated processes doesn't have the same timing issues. And there is another potential way of stopping them - if you change the ACL on the executables that you don't want to run elevated to deny execute for the Administrators then they can't run elevated, but they can still be inspected and changed by elevated processes and run by users. i.e. you add advanced permissions and Deny Traverse folder/execute file to .\Administrators. I guess the appropriate approach my depend on lots of factors, but that is at least a nice simple and very low-overhead way of doing it (and an access denied error is probably nicer than it being killed after a second). In some cases you may event want to both and change the ACL and still keep monitoring the processes as well as a backup.
I'll post the code for the UI up here soon, but it isn't quite ready for that yet. The UI is rewritten in WPF and uses async. It also includes a right-click option which does a VT lookup, checks the signature and checks the download URL for the file (if it came from Chrome, FireFox or Edge) and both shows that to the user and logs it for later reference before adding the user to the Adminsitrators group, invoking a RunAs for the command so that the user can put in their creds and then immediately removing them back out of the administrators group.
Here's the sysmon config I came up with. This config will log processes created with a High integrity level (so system processes and normal user processes are both excluded). It excludes conhost.exe as these are so common and uninteresting and also includes the MakeMeAdmin UI. Including the UI in the log might not be much use now, but with the right-click option it will be useful to log that.
<Sysmon schemaversion="4.22">
<!--SYSMON META CONFIG-->
<HashAlgorithms>sha256</HashAlgorithms>
<EventFiltering>
<!-- Log high integrity process creation -->
<RuleGroup name="MakeMeAdmin_ProcessInclude" groupRelation="or">
<ProcessCreate onmatch="include">
<IntegrityLevel condition="is">High</IntegrityLevel>
<Image condition="is">C:\Program Files\Make Me Admin\MakeMeAdminUI.exe</Image>
</ProcessCreate>
</RuleGroup>
<RuleGroup name="MakeMeAdmin_ProcessExclude" groupRelation="or">
<ProcessCreate onmatch="exclude">
<Image condition="is">C:\Windows\System32\conhost.exe</Image>
</ProcessCreate>
</RuleGroup>
<!-- Exclude all other events that are included by default by Sysmon -->
<FileCreateTime onmatch="include"/>
<ProcessTerminate onmatch="include"/>
<DriverLoad onmatch="include"/>
<FileCreate onmatch="include"/>
<RegistryEvent onmatch="include"/>
<FileCreateStreamHash onmatch="include"/>
</EventFiltering>
</Sysmon>
Unfortunately, as far as I know it isn't possible to log actions associated with elevated processes (e.g. termination, file modification and registry modification) with sysmon without logging everything because the IntegirtyLevel property that we need to filter on is only on the Process Creation events and not the others, but just the process creation events make a pretty good log in this case.
I just ran across something that might be better than the WMI method you currently have without requiring sysmon - https://docs.microsoft.com/en-au/previous-versions/windows/desktop/krnlprov/win32-processtrace looks like it hooks into process creation tracing rather than enumerating all processes and looking for changes. I found this in used by another product and documented here: https://www.velocidex.com/docs/artifacts/events/.
I've been having pretty good luck with Event Tracing for Windows (ETW). It doesn't gobble up RAM or CPU. I've ditched all of the WMI code in my local repo, along with the P/Invoke stuff to look up tokens.
@martshep Can you play with the code that I just checked in? I'm pretty happy with the performance gains from using ETW rather than WMI. I'm not set on what is getting logged at the moment (e.g., we should probably log the SID of the user that started the process, not just the session number), but I think it's at the point where someone else can critique it. :)
Add an option to log information about elevated processes. Logging should be available either while a user is administrator, or always.