Is there a way to check which process is recieving User input? - c++

Is there a way to check which process is receiving user input from a complete list of all running processes? For example:
PROCESSENTRY32 procentry;
HANDLE hproc;
BOOL retval, ProcFound = false;
hproc = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //GetsSnapshotOfAllProcesses
if(hproc == INVALID_HANDLE_VALUE)
{ // If Couldnt get snapshot
MessageBox(NULL, "Unable To Get Snapshot", "LoaderError", MB_OK);
return false;
}
procentry.dwSize = sizeof(PROCESSENTRY32); // Initialize
retval = Process32First(hproc, &procentry); //Copies Snapshot procentry
while(retval)
{
**if(UserInput == TRUE))**
{
return procentry.th32ProcessID; //
}
retval = Process32Next(hproc, &procentry); //
}
return 0;
}
Is there a function that will let me check which process is receiving user input?
if(UserInput == TRUE))
Also, is there a way to translate the processes to a string?

GetForegroundWindow() and GetWindowThreadProcessId() is the way to go:
DWORD dwProcessID = 0;
HWND hFGWnd = GetForegroundWindow();
if (hFGWnd != NULL)
GetWindowThreadProcessId(hFGWnd, &dwProcessID);
return dwProcessID;

Related

How to run functions from a service in current logged in users context using C++?

currently I have 1 main function which calls 3-4 utility functions that collectively block other browsers using Windows Registry and implements a firefox policy using mkdir + copy, currently, these functions aren't running under users context and are running under the system, My codebase has the function to run a cmd command under user's context but not other functions, below I have mentioned it. I am guessing running the main function under other user's contexts will automatically run the utility functions also under the user's context, since the main function calls the utility functions but I am not sure, anybody knows how to do this, the function basically first creates a directory and copy a file to it in Program Files folder and then get paths of browsers and create & set Registry keys and data-values for that user, but currently due to running from service it runs under SYSTEM.
BOOLEAN
CreateProcessInActiveSession(
const std::wstring wstrCmd
)
{
DWORD dwSId = 0xFFFFFFFF;
dwSId = WTSGetActiveConsoleSessionId();// LZGetActiveSessionId();
if (0xFFFFFFFF == dwSId)
{
return FALSE;
}
BOOL bRet;
HANDLE hTok = NULL;
bRet = WTSQueryUserToken(dwSId, &hTok);
if (FALSE == bRet)
{
return FALSE;
}
DWORD dwLinkedTokSz;
TOKEN_LINKED_TOKEN ElvTok;
bRet = GetTokenInformation(hTok, TokenLinkedToken, &ElvTok, sizeof(ElvTok), &dwLinkedTokSz);
if (TRUE == bRet)
{
CloseHandle(hTok);
hTok = ElvTok.LinkedToken;
}
HANDLE hTokDup = NULL;
bRet = DuplicateTokenEx(hTok, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokDup);
if (FALSE == bRet)
{
CloseHandle(hTok);
return FALSE;
}
CloseHandle(hTok);
DWORD dwCreationFlag;
dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
PVOID pEnv = NULL;
bRet = CreateEnvironmentBlock(&pEnv, hTokDup, FALSE);
if (FALSE == bRet)
{
pEnv = NULL;
}
else
{
dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;
}
STARTUPINFO stInfo;
memset(&stInfo, 0, sizeof(stInfo));
PROCESS_INFORMATION procInfo;
memset(&procInfo, 0, sizeof(procInfo));
stInfo.cb = sizeof(stInfo);
WCHAR szDesktop[] = L"winsta0\\default";
stInfo.lpDesktop = szDesktop;
WCHAR wszCmd[MAX_PATH];
wcscpy_s(wszCmd, ARRAY_SIZE(wszCmd), wstrCmd.c_str());
bRet = CreateProcessAsUserW(
hTokDup,
NULL,
wszCmd,
NULL,
NULL,
FALSE,
dwCreationFlag,
pEnv,
NULL,
&stInfo,
&procInfo
);
if (FALSE == bRet)
{
if (NULL != pEnv)
{
DestroyEnvironmentBlock(pEnv);
}
CloseHandle(hTokDup);
return FALSE;
}
CloseHandle(procInfo.hProcess);
CloseHandle(procInfo.hThread);
if (NULL != pEnv)
{
DestroyEnvironmentBlock(pEnv);
}
CloseHandle(hTokDup);
return TRUE;
}

C++ get windows title using process name

edit: how can i get windows title using processname? for example get current title of chrome.exe
You can get title of specific windows using it's process ID.
If you know the name of executed file(ex: Chrome.exe), you can get Handle with FindWindowEX() or get PID "Chrome.exe" with CreateToolHelp32Snapshot.
Then use EnumWindows to get HWND using HANDLE.
struct param_enum
{
unsigned long ulPID;
HWND hWnd_out;
};
HWND find_specific_window(unsigned long process_id)
{
param_enum param_data;
param_data.ulPID = process_id;
param_data.hWnd_out = 0;
EnumWindows(enum_windows_callback, (LPARAM)&param_data);
get_window_title(process_id, param_data.hWnd_out);
return param_data.hWnd_out;
}
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
param_enum& param_data = *(param_enum*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (param_data.ulPID != process_id)
{
return TRUE;
}
param_data.hWnd_out = handle;
return FALSE;
}
---------------------------Get Handle---------------------------
HANDLE GetHandleFromProcessPath(TCHAR* szExeName, DWORD& dwPID)
{
HANDLE hExeName = INVALID_HANDLE_VALUE;
HANDLE hSnap = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE != hSnap)
{
if (Process32First(hSnap, &pe32))
{
do
{
//!!! Attention pe32.szExeFile always return exe file name. not window title.
if (NULL != _tcsstr(pe32.szExeFile, szExeName))
{
hExeName = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pe32.th32ProcessID);
dwPID = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &pe32));
}
}
return hExeName;
}
Completing the answer of "G.Alexander" and and the comment of Skewjo
the get_window_title code is incomplete. So, worked for me, by removing it and calling find_specific_window like below:
wchar_t* caption = new wchar_t[MAX_PATH*2];
HWND h = find_specific_window(processID);
GetWindowTextW(h, caption, MAX_PATH*2);

Thread32First returning bogus thread id

Thread32First returns true so I know the function isn't failing. However, it keeps returning the same value for the th32ThreadID data member of THREADENTRY32, 0. Doesn't matter what process I try it on, it continues to be the same thread id: 0.
Here's my code:
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
BOOL EnableDebugPriv(HANDLE proc);
int main()
{
HANDLE hSnapshot;
HANDLE hThread;
THREADENTRY32 thread32;
DWORD dwPid = 15404;
EnableDebugPriv(OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid));
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPid);
if(hSnapshot == INVALID_HANDLE_VALUE)
{
printf("Error getting snapshot: %lu\n", GetLastError());
return 1;
}
thread32.dwSize = sizeof(THREADENTRY32);
if(!Thread32First(hSnapshot, &thread32))
{
printf("Error thread32first\n");
return 1;
}
printf("Thread Id: %lu\n", thread32.th32ThreadID);
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, thread32.th32ThreadID);
if(hThread == NULL)
{
printf("Error getting handle: %lu\n", GetLastError());
return 1;
}
return 0;
}
BOOL EnableDebugPriv(HANDLE proc)
{
HANDLE hToken;
LUID sedebugnameValue;
TOKEN_PRIVILEGES tkp;
// pass our opened process handle
OpenProcessToken(proc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
{
CloseHandle(hToken);
return TRUE;
}
else
{
MessageBox(NULL,"Bro, you gotta be an admin to set privs like this", "Shit", MB_OK);
CloseHandle(hToken);
return FALSE;
}
}
Note: I am aware that using a static process ID like I am could cause problems. However, I make sure the process is still running with the same process ID. That's not the problem.

How to tell if Windows partition is active by a path on it?

My goal is to know if Windows is installed on an active disk partition. I can obtain the path for Windows:
C:\WINDOWS
and then it's partition:
\Device\Harddisk4\Partition4
But the question is how to know if this partition is active?
Check this Link (http://msdn.microsoft.com/en-us/library/windows/desktop/aa365451(v=vs.85).aspx)
PARTITION_INFORMATION has BootIndicator. but it is not guarantee about the running windows was booted by that partition.
Edited It is a example function tested on Windows7. I think 'activate' partition is not your goal. The 'activate' has meaning such as bootable USB device. I don't like WMI but it could be help your goal (http://msdn.microsoft.com/en-us/library/windows/desktop/bb986746(v=vs.85).aspx)
BOOL
__stdcall
TP_IsPartitionActivated(
__in LPCWSTR pPartition,
__out PBOOL pbIsActivated
)
{
HANDLE hDevice = INVALID_HANDLE_VALUE;
PARTITION_INFORMATION_EX szPartitionInformation;
DWORD cbReturned = 0x00;
if (pPartition == NULL || pbIsActivated == NULL) { return FALSE; }
__try
{
hDevice = CreateFileW(pPartition, 0x00, 0x00, NULL, OPEN_EXISTING, 0x00, NULL);
if (hDevice == INVALID_HANDLE_VALUE) { return FALSE; }
RtlZeroMemory(&szPartitionInformation, sizeof(szPartitionInformation));
if (FALSE != DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0x00, (LPVOID)&szPartitionInformation, sizeof(PARTITION_INFORMATION_EX), &cbReturned, NULL))
{
if (PARTITION_STYLE_MBR == szPartitionInformation.PartitionStyle)
{
*pbIsActivated = szPartitionInformation.Mbr.BootIndicator;
}
else
{
}
return TRUE;
}
else
{
cbReturned = GetLastError();
wprintf(L"%08X(%d)\n", cbReturned, cbReturned);
}
}
__finally
{
if (hDevice != INVALID_HANDLE_VALUE) { CloseHandle(hDevice); }
}
return FALSE;
}
Call like
WCHAR szPartition[] = L"\\\\.\\C:";
BOOL bIsActivated = FALSE;
if (FALSE != TP_IsPartitionActivated(szPartition, &bIsActivated))
{
wprintf(L"%s \n", bIsActivated == FALSE ? L"not activated" : L"activated");
}
else
{
wprintf(L"function fail\n");
}

EnumDesktopWindows Error: (183) Cannot create a file when that file already exists

Anyone know why returns 183 in call EnumDesktopWindows
This process is an service running in System LocalService
I'm trying to put the window in the top, because the process starts minimized.
Thank for Help
My Code:
BOOL CALLBACK EnumWindowsProc( HWND hwnd, LPARAM lParam )
{
DWORD dwPID;
GetWindowThreadProcessId( hwnd, &dwPID );
if( dwPID == lParam ) {
SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE );
SwitchToThisWindow(hwnd, true);
SetFocus( hwnd );
return FALSE;
}
return TRUE;
}
BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam) {
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);
if(hDesk != NULL) {
if(!EnumDesktopWindows(hDesk,&EnumWindowsProc, lParam)) {
//This call returns (183) Cannot create a file when that file already exists
}
CloseDesktop(hDesk);
}
return TRUE;
}
BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{
HWINSTA hWinStat = OpenWindowStation(lpszWindowStation,FALSE,WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);
if(hWinStat) {
SetProcessWindowStation(hWinStat);
EnumDesktops(hWinStat,&EnumDesktopProc,lParam);
CloseWindowStation(hWinStat);
}
return TRUE;
}
bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL bResult = FALSE;
DWORD dwSessionId,winlogonPid;
HANDLE hUserToken,hUserTokenDup,hPToken,hProcess;
DWORD dwCreationFlags;
// Log the client on to the local computer.
dwSessionId = WTSGetActiveConsoleSessionId();
//////////////////////////////////////////
// Find the winlogon process
////////////////////////////////////////
PROCESSENTRY32 procEntry;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap == INVALID_HANDLE_VALUE)
return false;
procEntry.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hSnap, &procEntry))
return false;
do {
if (_wcsicmp(procEntry.szExeFile, L"winlogon.exe") == 0) {
// We found a winlogon process...make sure it's running in the console session
DWORD winlogonSessId = 0;
if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId) {
winlogonPid = procEntry.th32ProcessID;
break;
}
}
} while (Process32Next(hSnap, &procEntry));
WTSQueryUserToken(dwSessionId,&hUserToken);
dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = L"winsta0\\default";
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL|SW_RESTORE;
ZeroMemory(&pi, sizeof(pi));
TOKEN_PRIVILEGES tp;
LUID luid;
hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);
if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
|TOKEN_READ|TOKEN_WRITE,&hPToken))
{
return false;
}
if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
return false;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup);
//Adjust Token privilege
SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)dwSessionId,sizeof(DWORD));
if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,NULL))
return false;
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
return false;
LPVOID pEnv = NULL;
if(CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
else
pEnv = NULL;
// Launch the process in the client's logon session.
std::wstring params = aParams;
std::wstring path = aPath;
if(aMode == L"select") {
TCHAR infoBuffer[MAX_PATH];
GetSystemWindowsDirectory(infoBuffer, MAX_PATH);
std::wstring windowsDir(infoBuffer);
path = windowsDir+L"\\explorer.exe";
params = L" /n, /select,"+replaceString(aPath, L"\\\\", L"\\");
}
bResult = CreateProcessAsUser(
hUserTokenDup, // client's access token
path.c_str(), // file to execute
params.length() > 0 ? stringToLPWSTR(wideToUtf8(params)) : NULL, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
dwCreationFlags, // creation flags
pEnv, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
EnumWindowStations(&EnumWindowStationProc, (LPARAM)(pi.dwProcessId));
// End impersonation of client.
//GetLastError Shud be 0
int rv = GetLastError();
//Perform All the Close Handles task
CloseHandle(hProcess);
CloseHandle(hUserToken);
CloseHandle(hUserTokenDup);
CloseHandle(hPToken);
return !rv;
}
Error 183 is ERROR_ALREADY_EXISTS. EnumDesktopWindows() does not set that error, so it must be a carry-over from an earlier API call. If you read the documentation says this:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682615.aspx
You must ensure that the callback function sets SetLastError if it fails.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682614.aspx
If the callback function fails, the return value is zero. The callback function can call SetLastError to set an error code for the caller to retrieve by calling GetLastError.
So try something more like this:
struct WndInfo
{
DWORD dwProcessID;
HWND hWnd;
};
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
WndInfo *pInfo = (WndInfo*) lParam;
DWORD dwPID;
GetWindowThreadProcessId(hwnd, &dwPID);
if (dwPID == pInfo->dwProcessID)
{
pInfo->hWnd = hwnd;
SetLastError(0);
return FALSE;
}
return TRUE;
}
BOOL CALLBACK EnumDesktopProc(LPTSTR lpszDesktop, LPARAM lParam)
{
HDESK hDesk = OpenDesktop(lpszDesktop, NULL, FALSE, GENERIC_ALL);
if (hDesk != NULL)
{
if (!EnumDesktopWindows(hDesk, &EnumWindowsProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
CloseDesktop(hDesk);
WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}
return TRUE;
}
BOOL CALLBACK EnumWindowStationProc(LPTSTR lpszWindowStation, LPARAM lParam)
{
HWINSTA hWinStat = OpenWindowStation(lpszWindowStation, FALSE, WINSTA_ENUMDESKTOPS|WINSTA_ENUMERATE);
if (hWinStat != NULL)
{
SetProcessWindowStation(hWinStat);
if (!EnumDesktops(hWinStat, &EnumDesktopProc, lParam))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
CloseWindowStation(hWinStat);
WndInfo *pInfo = (WndInfo*) lParam;
if (pInfo->hWnd != NULL)
{
SetLastError(0);
return FALSE;
}
}
return TRUE;
}
HWND findWindowForProcess(DWORD PID)
{
WndInfo info;
info.dwProcessID = PID;
info.hWnd = NULL;
if (!EnumWindowStations(&EnumWindowStationProc, (LPARAM)&info))
{
if (GetLastError() != 0)
{
// handle error as needed...
}
}
return info.hWnd;
}
bool Utils::execIntoDifferentSession(const std::wstring &aPath, const std::wstring &aParams, const std::wstring &aMode)
{
...
bResult = CreateProcessAsUser(...);
if (bResult)
{
HWND hWnd = findWindowForProcess(pi.dwProcessId);
if (hWnd != NULL)
{
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
SwitchToThisWindow(hWnd, TRUE);
SetFocus(hWnd);
}
}
...
}
With that said, since all you are really trying to do is execute a new process in a specific user session, you don't need to bother with all that enumeration logic. You don't need to find the WinLogon process at all, you already have the user's token from WTSQueryUserToken() so just duplicate+adjust that token as needed. And you are not doing anything useful in your window enumeration that the new process would not already do by default when it is started, so just get rid of that logic, too.
And then finally fix your error handling (or lack of) so you can close any handles that are open and not leak them.