1

I'm working on an application that runs with SYSTEM level privileges and is created by the SYSTEM user. I need to track foreground activities for the currently logged-in user. I'm using SetWinEventHook for the same. It works fine when I run the application from my current user. But if I started the application with the SYSTEM user, it was unable to receive events. Is there any workaround to trigger this with user context?

Edit: g_hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, focusChangeCallbackHandle, 0, 0, WINEVENT_OUTOFCONTEXT); focusChangeCallbackHandle is a in same namespace as the caller function

Edit 2:

Adding my boilerplate code here: I'm using pstools to run the binary with the SYSTEM user. Also not sure why but after running any of the getter/setters of ThreadDesktop and WindowStation my application stop printing on the console.

    void ForegroundCheck() {
        printf("In thread \n");
        HWINSTA orgWS = GetProcessWindowStation();
        printf("Done GetProcessWindowStation \n");
        if (orgWS) {
            printf("In GetProcessWindowStation \n");
            HWINSTA itrWS = OpenWindowStation(TEXT("WinSta0"), true, GENERIC_ALL);
            if (itrWS) {
                printf("In OpenWindowStation \n");
                if (SetProcessWindowStation(itrWS)) {
                    printf("In SetProcessWindowStation \n");
                    HDESK iD = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, true, GENERIC_ALL);
                    if (iD) {
                        if (!SetThreadDesktop(iD)) {
                            printf("SetThreadDesktop failed: %lu \n", GetLastError());
                        } else {
                            printf("setting hoook");
                            // SetWinEventHook sets the hook for the mentioned event. 
    // In current case EVENT_SYSTEM_FOREGROUND. When ever EVENT_SYSTEM_FOREGROUND is triggerd HandleWinEvent will be called
                            g_hook = SetWinEventHook(
                                EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND,  // Range of events (4 to 5).
                                NULL,                                          // Handle to DLL.
                                HandleWinEvent,                                // The callback.
                                0, 0,              // Process and thread IDs of interest (0 = all)
                                WINEVENT_OUTOFCONTEXT);
                            MSG msg;
                            //GetMessage(&msg, NULL, 0, 0);
                            while (WaitMessage() && set) {
                                PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
                            }
                        }
                    } else {
                        printf("OpenInputDesktop failed: %lu \n", GetLastError());
                    }
                    SetProcessWindowStation(orgWS);
                } else {
                    printf("SetProcessWindowStation failed: %lu \n", GetLastError());
                }
                CloseWindowStation(itrWS);
            } else {
                printf("OpenWindowStation failed: %lu \n", GetLastError());
            }
        } else {
            printf("GetProcessWindowStation failed: %lu \n", GetLastError());
        }
    
    
    }
    
    int main() {
        bool retVal = false;
    
        printf("In Main \n");
    
        CoInitialize(NULL);
    
        std::thread t(ForegroundCheck);
        printf("In thread started \n");
        std::cin.get();
        // Deinit
        UnhookWinEvent(g_hook);
        set = false;
        t.join();
        CoUninitialize();
        return 0;
    }

Thanks

aker99
  • 11
  • 4

1 Answers1

0

Each logged on user has separate desktop. So if you want to track foreground activities, your process need to run as Users group. You can create another process as user with CreateProcessAsUser.

Zeltrax
  • 310
  • 2
  • 10
  • Hi, with my current product design, it would be difficult to add a separate process for this use case. Is there any way to create a thread as a different user? – aker99 Jan 25 '22 at 15:46
  • @aker99: You can join a different desktop on a per-thread basis, but the window station is shared process-wide. And you can't do either unless running in a session associated with the window station. See [`SetProcessWindowStation`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocesswindowstation) and [`SetThreadDesktop`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setprocesswindowstation) – Ben Voigt Jan 25 '22 at 16:01
  • @Zeltrax: The Window Station is just as important here as the desktop. And the Users group has nothing to do with it. – Ben Voigt Jan 25 '22 at 16:02
  • Thanks, @BenVoigt for sharing those. But still, nothing helped. Add my POC code. Let me know if you find any mistakes. – aker99 Jan 28 '22 at 14:34