Skip to content

Instantly share code, notes, and snippets.

@ohaval
Last active October 1, 2021 07:48
Show Gist options
  • Save ohaval/a922fc07f4585b81c119614e852d9dbd to your computer and use it in GitHub Desktop.
Save ohaval/a922fc07f4585b81c119614e852d9dbd to your computer and use it in GitHub Desktop.
/*
This program receives the accurate string of the username (as written by `net user`)
and log offs the session associated with that user, if any is active.
In order to log off another users on the system, Administrator permissions
are required. Thus, the program should be run as an Administrator.
Flow of the code is:
1) Enumerate active sessions
2) For each session, enumerate the username string associated with the session
3) Logoff the session which it's username matches the requested username to log off
Compile with Visual Studio 2019, make sure to add 'Wtsapi32.lib' to the Linker input.
*/
#include <iostream>
#include <Windows.h>
#include <wtsapi32.h>
LPWSTR GetUsernameFromSessionId(DWORD dwSessionId) {
DWORD rv = NULL;
LPWSTR pBuffer;
DWORD dwBytesReturend;
rv = WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
dwSessionId,
WTSUserName,
&pBuffer,
&dwBytesReturend
);
if (!rv) {
printf("[!] WTSQuerySessionInformation failed (GetLastError: %d)\n", GetLastError());
return NULL;
}
return pBuffer;
}
DWORD LogoffSessionById(DWORD dwSessionId) {
DWORD rv = NULL;
rv = WTSLogoffSession(
WTS_CURRENT_SERVER_HANDLE,
dwSessionId,
TRUE // Indicates whether the operation is synchronous
);
if (!rv) {
printf("[!] WTSLogoffSession failed (GetLastError: %d)\n", GetLastError());
}
return rv;
}
int main() {
int argc;
LPWSTR* pArgvW = CommandLineToArgvW(GetCommandLineW(), &argc);
if (argc != 2) {
printf("Usage: LogoffUser.exe USERNAME (USERNAME is case sensitive)\n");
exit(1);
}
DWORD rv = NULL;
WTS_SESSION_INFO* pWTSSessionInfo = NULL;
DWORD dwCount = NULL;
rv = WTSEnumerateSessionsW(
WTS_CURRENT_SERVER_HANDLE,
0, // Must be 0 as documented in docs.microsoft.com
1, // Must be 1 as documented in docs.microsoft.com
&pWTSSessionInfo,
&dwCount
);
if (!rv) {
printf("[!] WTSEnumerateSessionsW failed (GetLastError: %d)\n", GetLastError());
exit(1);
}
LPWSTR pUsername;
BOOL bFound = FALSE;
for (int i = 0; i < dwCount; i++) {
pUsername = GetUsernameFromSessionId(pWTSSessionInfo[i].SessionId);
if (pUsername == NULL) {
continue;
}
if (wcscmp(pUsername, pArgvW[1]) == 0) {
bFound = TRUE;
printf("[*] Found a session associated with '%ws'\n", pArgvW[1]);
rv = LogoffSessionById(pWTSSessionInfo[i].SessionId);
if (!rv) {
exit(1);
}
printf("[*] Successfully logged off '%ws'\n", pArgvW[1]);
break;
}
}
if (!bFound) {
printf("[!] Couldn't find any session associated with the username '%ws'\n", pArgvW[1]);
exit(1);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment