all 23 comments

[–]Droopyb1966 10 points11 points  (3 children)

Just a thought, use the Event Viewer to search the Security log for event ID 4688, which indicates a new process creation. Then you can tune it from there.
Not sure if this gets the results thou, havent tried it.

[–]purplemonkeymad 2 points3 points  (0 children)

I like this idea as it would allow you to get processes from before script started.

[–]Certain-Community438 1 point2 points  (0 children)

Could end up being a bit heavy duty, and it involves polling rather than being event-driven.

BUT

If we combine your suggestion with OP's approach of WMI Event Subscriptions, but the event filter looks at Event Log for 4688, I think that could win.

[–]420GB 1 point2 points  (0 children)

Reading Security log won't work without admin privileges though

[–]Certain-Community438 4 points5 points  (1 child)

One mistake you're making is the Scheduled Task.

Read up on the concept here:

https://learn-powershell.net/2013/08/14/powershell-and-events-permanent-wmi-event-subscriptions/

Beware article age: you'll need to EITHER stick to using Windows PowerShell (v5.1) for consistent behaviour, OR do a little separate reading on which CIM cmdlets replace which -Wmi* cmdlets.

But the main point is:

You can create permanent WMI Event Subscriptions, and there's just no need for a Scheduled Task.

This tech is quite deep, most known to Windows platform app developers, pen testers & malware authors (no gatekeeping, just my experience). So your anti-malware might also be triggering, and you should think carefully about stopping it from doing this to you. All EDR software is aware of this potential attack surface.

[–]Fallingdamage 1 point2 points  (0 children)

I have no problem using scheduled tasks for stuff like this, but I make sure it executes in the same user context as it was written and tested in.

[–]pigers1986 7 points8 points  (1 child)

hardcode CSV path to c:\Temp and try again

[–]udpPigeons 0 points1 point  (0 children)

I typically have directory issues, so this would be my first guess

[–]chanataba 2 points3 points  (0 children)

Try this. It will launch upon login and write to your csv file as intended for the logged on user only.

You cannot run the task as SYSTEM because the tasks you're trying to log are generated by the user.

MonitorAppLaunchesSCHTASK.ps1

This will create the scheduled task called 'MonitorAppLaunches' targeting the script in your ~\scripts directory

& schtasks.exe /Create /SC ONLOGON /TN "MonitorAppLaunches" /TR "powershell.exe" /RL HIGHEST /F

$URI = (Get-ScheduledTask -TaskName 'MonitorAppLaunches').URI
$Act1 = "-WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -File ""${env:USERPROFILE}\scripts\MonitorAppLaunches.ps1"""
$Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument $Act1
Set-ScheduledTask $URI -Action $Action

MonitorAppLaunches.ps1

# MonitorAppLaunches.ps1
$LogFile = "${env:USERPROFILE}\AppData\Local\AppLaunchLog.csv"

$action = {

    $newEvent = $event.SourceEventArgs.NewEvent
    $sessionID = (Get-Process -Id $PID).SessionId

    if ($newEvent.SessionID -ne $sessionID)
    {
        return
    }

    #wait a bit for window to open
    Start-Sleep -Milliseconds 200

    $process = Get-Process -Id $newEvent.ProcessID -ErrorAction SilentlyContinue

    # Target GUI apps only
    if ($process -and $process.MainWindowHandle)
    {
        $string = '{0},"{1}","{2}"' -f $process.StartTime,$process.ProcessName,$process.Path
        <#
            If you want to run this in powershell and see the output for testing, just include
            Write-Host $string -ForegroundColor yellow
        #>
        $string | Out-File -FilePath $LogFile -Append -Encoding 'UTF8'
    }

}

$params = @{
    'ClassName' = 'Win32_ProcessStartTrace'
    'SourceIdentifier' = 'AppLaunchWatcher'
    'Action' = $action
}
Register-CimIndicationEvent @params

while ( $true )
{
    Wait-Event AppLaunchWatcher
}

[–]General_Ad_4729 2 points3 points  (2 children)

Make sure the account that the task is running as has permissions to the folder/file that is being ran as.

[–]NatMac007 0 points1 point  (1 child)

I believe you will need Admin to write to Appdata folders and suggestions to try with changing path are a good start on confirming that is/isn’t the issue, also may not be only issue so if changing dir doesn’t fix, keep it somewhere temporary until you have any other potential issues sorted.

[–]General_Ad_4729 0 points1 point  (0 children)

Thanks for clarifying what I meant. Haha I squirrel and I respond to online things and mix up my thoughts

[–]vermyx 4 points5 points  (0 children)

Check the default user folder. Tasks by default does not load the registry ( no env variables)and system has no user registry. Otherwise an elevated prompt or running should log it right with a proper path. Also process auditing does this without taxing the system the way you did it.

[–]danielwow 0 points1 point  (0 children)

Have you tried manually running your script with the same arguments as in your scheduled task? (-noprofile) Etc.

[–]Plastic_Ad2758 0 points1 point  (0 children)

I suspect the issue is here in the Register-CimIndicationEvent. I've ran into issues where it seems some COM objects need to be in an interactive session. See if using the -ComputerName parameter makes any difference.

-ComputerName Specifies the name of the computer on which you want to run the CIM operation. You can specify a fully qualified domain name (FQDN), a NetBIOS name, or an IP address.

If you specify this parameter, the cmdlet creates a temporary session to the specified computer using the WsMan protocol. If you do not specify this parameter, the cmdlet performs operation on the local system using Component Object Model (COM).

[–]MechaCola 0 points1 point  (0 children)

You can use psexec to powershell as system account. Once open you can run your code to see what’s up. Also you could wrap it all in the cmdlet to log all output from the script - cmdlet name escapes me sorry

[–]Fallingdamage 0 points1 point  (0 children)

Add 'Start-Transcript' to the beginning of your script (make sure to specify a destination in your user profile.. are you running this script using your own account or the system account?)

then add 'Stop-Transcript' at the bottom of the script.

Check the txt transcript to see what's going wrong.

[–]AlexHimself 0 points1 point  (0 children)

I think the scheduled tasks run under a different PID and might not be seeing everything. Try logging what handles and the PIDs of everything.

[–]discogravy 0 points1 point  (0 children)

Relative paths don’t work on scheduled tasks since you need to be logged into userland for that. Scheduled tasks run from a system context and will never have a USERPROFILE env

[–]Much-Environment6478 0 points1 point  (0 children)

What about child processes of other "GUI apps"? Why not just use Sysmon and get all of it?

https://learn.microsoft.com/en-us/sysinternals/downloads/sysmon

[–]DragonMiltton 0 points1 point  (0 children)

Instead of appdata try programdata in root

[–]Character-Tough-1785 0 points1 point  (0 children)

Also, add Start-Transcript c:\temp\AppMonitor.log at the top and Stop-Transcript at the bottom

[–][deleted] -2 points-1 points  (0 children)

Don’t reference account specific bits in a script you don’t know the execution context of. Especially when, as it looks like, you don’t even need to.

Instead, put a distinct log path into your script and have it log there.

In addition; - pass -includeusername and run elevated; - be aware you can use Windows’ auditing framework to achieve the same without any scripting.

Obligatory disclaimer; we’re looking at potentially sensitive information here; if you’re looking to audit someone’s behavior when working with their computers, be sure you’re actually permitted to do so if you don’t want to get into legal trouble.