I'm developing a C++ windows application to monitor logon and logoff session activities in real-time.
It should have the followings:
Account Name
User
Account Domain
Logon ID
Audit success/failure
Logged on Time/Date
Session time period
It should alert if failure logon attempts or unusual activities occur.
I want to know how to read event logs (say for example only the critical level events in security event logs) using C++.
I can get these information from windows event viewer. Is there any good way to do this in C++ using windows native APIs.
Thanks in advance.
If your application is already a service that you probalby have service control handler already. If you make it register for and handle SERVICE_CONTROL_SESSIONCHANGE that could be your fist step.
Then WTSQuerySessionInformation will give you most of the information you need.
Re audit, you might want ot post a separate question (or maybe google?) on how to read event log.
Related
I need to write a C++ application that should read firewall status of Windows, and then need to keep an eye continuously if admin/someuser
changes the firewall status (lets say when my program was started firewall was disabled and after sometime Admin enabled it).
To implement this, I have created a thread that periodically(10 seconds) poll the code that checks Windows firewall status, but this doesn't look an efficient solution to me as continuous polling is required.
Is there a way to get event automatically in my program if firewall status changes (for example, FindFirstChangeNotification, using this I can get notification if any change in directory)? This will avoid continuous polling and will make program more efficient I think.
Any help is appreciated.
I know there is Windows ETW which anti-viruses use and which has all the info you need. It is a big system log where you subscribe to log/event providers. Pretty much everything that happens in system gets reported there via event which you can listen/wait for. I don't know the links to more useful pages with a list of loggers connected to ETW so here is the more general page: https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-. You need to find out how to use C++ ETW API and the name/ID of the firewall events provider with a list of event types, then using API subscribe to this provider and setup a callback for when an event that interests you (here change of firewall status) occurs and that is it.
Is is usually possible to check if a desktop is locked by using the SHQueryUserNotificationState API, but when running as LocalSystem, the state is not correctly detected.
Is anyone aware of any workarounds or alternative APIs that could be used to detect if the device is locked?
SHQueryUserNotificationState() queries the state of the desktop session of the calling user. But multiple users can be logged in at a time. So you will have to query the specific user session you are interested in.
You can use WTEnumerateSessions() to see which user sessions are running, and then use WTSQuerySessionInformation(WTSSessionInfoEx) to query the desired user session for its WTSINFOEX_LEVEL1 session info, which has a SessionFlags member that will be set to WTS_SESSIONSTATE_LOCK if the session is locked.
Alternatively, you can have your app track session locks/unlocks in real-time by listening for WM_WTSSESSION_CHANGE messages from WTSRegisterSessionNotification(). Or, you can write a separate background service that listens for SERVICE_CONTROL_SESSIONCHANGE notifications and then notifies your main app as needed via an IPC mechanism of you choosing.
I'm developing a custom credential provider and need to know at runtime if the scenario is a login or an unlock of the session. For this, I check the CREDENTIAL_PROVIDER_USAGE_SCENARIO returned by the SetUsageScenario of the ICredentialProvider interface.
On Windows 10, independently if I'm at login or when the session is locked, I always get CPUS_LOGON as usage scenario, while on previous version of Windows, CPUS_UNLOCK_WORKSTATION was returned when the session was locked and CPUS_LOGON at the login.
So it seems that changes appeared since Windows 10 that are not reported on MSDN.
Is there any other way to detect if the usage scenario is a session locked?
I am currently investigating the same issue and may have a work around until Microsoft can update the documentation.
Although I still receive a CPUS_LOGON, we are still inside the same session as the locked user. By using the function WTSQuerySessionInformationW, you can verify that there is currently a user logged in to the current session. From there, you can proceed as if you were in a CPUS_UNLOCK_WORKSTATION usage scenario.
UPDATE (1/18/2016): It seems Microsoft has finally updated their documentation on this issue. See the excerpt below from the CREDENTIAL_PROVIDER_USAGE_SCENARIO documentation:
Starting in Windows 10, the CPUS_LOGON and CPUS_UNLOCK_WORKSTATION
user scenarios have been combined. This enables the system to support
multiple users logging into a machine without creating and switching
sessions unnecessarily. Any user on the machine can log into it once
it has been locked without needing to back out of a current session
and create a new one. Because of this, CPUS_LOGON can be used both for
logging onto a system or when a workstation is unlocked. However,
CPUS_LOGON cannot be used in all cases. Because of policy restrictions
imposed by various systems, sometimes it is necessary for the user
scenario to be CPUS_UNLOCK_WORKSTATION. Your credential provider
should be robust enough to create the appropriate credential structure
based on the scenario given to it. Windows will request the
appropriate user scenario based on the situation. Some of the factors
that impact whether or not a CPUS_UNLOCK_WORKSTATION scenario must be
used include the following. Note that this is just a subset of
possibilities.
The operating system of the device.
Whether this is a console or remote session.
Group policies such as hiding entry points for fast user switching, or interactive logon that does not display the user's last name.
Credential providers that need to enumerate the
currently user logged into the system as the default tile can keep
track of the current user or leverage APIs such as
WTSQuerySessionInformation to obtain that information
If you turn fast user switching off, you will get the CPUS_UNLOCK_WORKSTATION messages upon locking. Otherwise you will only receive CPUS_LOGON. If you manually lock the PC using the windows API call from code to lock with fast user switching turned on, it will lock sending CPUS_UNLOCK_WORKSTATION and then immediately log off sending CPUS_LOGON.I Hope this helps, i don't have the reputation score to post an answer of my own so i edited this comment.
You might try SENS (System Event Notification Service). This is a Microsoft provided notification service.
https://msdn.microsoft.com/en-us/library/windows/desktop/cc185680(v=vs.85).aspx
It has different events for logon/logoff and screen lock/unlock notifications. It uses a COM+ interface. I am not familiar with the requirements of credential providers so I don't know if the service will run within the context you require or if the timing of the event arrival will meet your needs but it is something you might investigate.
Of all the answers, Justin's one is the more informative one, but nobody provides a workaround to properly restore the Windows7 behavior. Scott's answer mentions turning off Fast User Switching, but that turns off a feature that is available in Windows7, making it not a proper workaround. After carefully reading all the information available and several attempts, I found the following policies that allows only the previous logged user to unlock the machine, hence forcing the LogonUI framework to issue CPUS_UNLOCK_WORKSTATION scenario, but still allowing fast user switch:
Windows Registry Editor Version 5.00
; Computer Configuration -> Windows Settings -> Security Settings ->
; Local Policies -> Security Options "Interactive logon: Do not display last user name"
; Set to "Enabled": asks to unlock the machine only to currently logged user
; https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/interactive-logon-do-not-display-last-user-name
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
"dontdisplaylastusername"=dword:00000001
; Computer Configuration -> Administrative Templates -> Windows Components ->
; Windows Logon Options -> "Sign-in last interactive user automatically after a system-initiated restart"
; Set to "Enabled": Prevents last signed user to log in and lock automatically
; after a restart
; https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/winlogon-automatic-restart-sign-on--arso-
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
"DisableAutomaticRestartSignOn"=dword:00000001
; Similar in bevahior to "dontdisplaylastusername" but also disables Fast User
; Switching, which was available in Windows7
; https://learn.microsoft.com/en-us/windows/client-management/mdm/policy-csp-windowslogon#windowslogon-hidefastuserswitching
;[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
;"HideFastUserSwitching"=dword:00000001
I was wondering, what is the best way to do the following using C++/WinAPIs on a Windows system?
I have a local service application along with running client applications (that run on each logged on user session account.) The service application needs to notify all client applications to perform a one time operation (say, read data from registry and process it.) How do you implement this mechanism of notifying all client apps of a one-time event?
Service could send a broadcast windows message for which all client apps would listen. Of course, client apps need to have a message loop. Have you looked at SendNotifyMessage function?
You could use an event with a particular name that all the apps agree on. Then reset it after a period of time.
I have a service which constantly checks some application and assures that it wasn't closed. If this app closed - service launches it again.
The problem starts when user decides to log off the session. During logoff all applications are closing including the mine one. But the service is still running and constantly trying to start it again.
The questions is how to notify the service that user is going to log off and the application doesn't need to be restarted anymore? I've tried to make it using SERVICE_CONTROL_SESSIONCHANGE notification. But in accordance to MSDN they come to services when all apps already closed and logging off procedure completed. It is too late for me. Is there any way to programmatically find out that current session is in process of logging off?
My service launched under LocalSystem account.
Thanks.
p.s. I don't have the access to application source code. The goal need to be achieved without modifying it.
Have your service run two applications: the one it is a watchdog for, and a second one which you implement yourself. This second one can then respond to the log-off event by sending a message to the service (a la David Heffernan's answer), and the service will then know not to restart the watched job.
Open a communication channel between your app and your service and arrange for the app to tell the service that it is closing because of a logoff event.
You may not have access to the source code of the executable, but that doesn't mean that you can't affect the process. For instance, you could inject a DLL. Using SetWindowsHookEx, you'd catch the WM_ENDSESSION sent to the apps main window.
Why don't you create your service under the user that is running the App and tell it to startup automatic? In this case you should get the SERVICE_CONTROL_SHUTDOWN message when your user is logging off since the service would also be terminated.