-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathmain.cpp
158 lines (144 loc) · 5.79 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include <Windows.h>
#include <iostream>
#include <winternl.h>
#include <vector>
#include <string>
#include <codecvt>
// i ripped these structs from https://processhacker.sourceforge.io/doc/winsta_8h_source.html
typedef WCHAR WINSTATIONNAME[32 + 1];
typedef enum _WINSTATIONSTATECLASS {
State_Active = 0,
State_Connected,
State_ConnectQuery,
State_Shadow,
State_Disconnected,
State_Idle,
State_Listen,
State_Reset,
State_Down,
State_Init
} WINSTATIONSTATECLASS;
typedef struct _SESSIONIDW {
union {
ULONG SessionId;
ULONG LogonId;
};
WINSTATIONNAME WinStationName;
WINSTATIONSTATECLASS State;
} SESSIONIDW, * PSESSIONIDW;
typedef HANDLE(WINAPI* LPFN_WinStationOpenServerW)(PWSTR);
typedef BOOLEAN(WINAPI* LPFN_WinStationCloseServer)(HANDLE);
typedef BOOLEAN(WINAPI* LPFN_WinStationEnumerateW)(HANDLE, PSESSIONIDW*, PULONG);
typedef BOOLEAN(WINAPI* LPFN_WinStationQueryInformationW)(HANDLE, ULONG, WINSTATIONINFOCLASS, PVOID, ULONG, PULONG);
std::vector<std::wstring> extractWideStrings(const BYTE* byteArray, size_t size) {
std::vector<std::wstring> strings;
std::wstring currentString;
for (size_t i = 0; i < size / sizeof(WCHAR); ++i) {
if (byteArray[i * sizeof(WCHAR)] == 0 && currentString.empty()) {
continue; // Skip null characters at the beginning
}
currentString += static_cast<WCHAR>(byteArray[i * sizeof(WCHAR)]);
if (byteArray[i * sizeof(WCHAR)] == 0) {
strings.push_back(currentString);
currentString.clear();
}
}
return strings;
}
template <typename FuncPtr>
FuncPtr LoadFunctionFromDLL(HINSTANCE hDLL, const char* functionName) {
FuncPtr functionPtr = reinterpret_cast<FuncPtr>(GetProcAddress(hDLL, functionName));
if (functionPtr == nullptr) {
std::cerr << "Failed to find function: " << functionName << std::endl;
FreeLibrary(hDLL);
exit(1);
}
return functionPtr;
}
int main(int argc, char* argv[]) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <serverName>\n";
return 1;
}
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::wstring serverNameW = converter.from_bytes(argv[1]);
if (serverNameW.length() > 20) {
std::cerr << "Server name exceeds maximum length.\n";
return 1;
}
wchar_t* serverName = const_cast<wchar_t*>(serverNameW.c_str());
HINSTANCE hDLL = LoadLibrary(TEXT("winsta.dll"));
if (hDLL == NULL) {
std::cerr << "Failed to load winsta.dll\n";
return 1;
}
auto pfnWinStationOpenServerW = LoadFunctionFromDLL<LPFN_WinStationOpenServerW>(hDLL, "WinStationOpenServerW");
auto pfnWinStationCloseServer = LoadFunctionFromDLL<LPFN_WinStationCloseServer>(hDLL, "WinStationCloseServer");
auto pfnWinStationEnumerateW = LoadFunctionFromDLL<LPFN_WinStationEnumerateW>(hDLL, "WinStationEnumerateW");
auto pfnWinStationQueryInformationW = LoadFunctionFromDLL<LPFN_WinStationQueryInformationW>(hDLL, "WinStationQueryInformationW");
// Opens Server Handle - if invalid host provided, will hang (TODO: Fix that lol)
HANDLE hServer = pfnWinStationOpenServerW(serverName);
if (hServer == NULL) {
std::cerr << "Failed to open server\n";
FreeLibrary(hDLL);
return 1;
}
else {
std::wcout << L"Server Handle: " << hServer << std::endl;
}
// Enumerate Server for Active Sessions, store IDs in PSESSIONIDW struct
PSESSIONIDW pSessionIds = NULL;
ULONG count = 0;
BOOLEAN enumResult = pfnWinStationEnumerateW(hServer, &pSessionIds, &count);
if (enumResult) {
printf("Number of sessions: %lu\n", count);
for (ULONG i = 0; i < count; i++) {
std::wstring wsName(pSessionIds[i].WinStationName);
std::string sessionName(wsName.begin(), wsName.end());
WINSTATIONINFORMATIONW wsInfo{};
ULONG ReturnLen;
std::cout << "SessionID: " << pSessionIds[i].SessionId << std::endl;
std::cout << "State: " << pSessionIds[i].State << std::endl;
std::cout << "SessionName: " << sessionName << std::endl;
if (pfnWinStationQueryInformationW &&
pfnWinStationQueryInformationW(hServer,
pSessionIds[i].SessionId,
WinStationInformation,
&wsInfo,
sizeof(wsInfo),
&ReturnLen) &&
(wsInfo.LogonId != 0))
{
std::vector<std::wstring> reserved2Strings = extractWideStrings(wsInfo.Reserved2, sizeof(wsInfo.Reserved2));
std::vector<std::wstring> reserved3Strings = extractWideStrings(wsInfo.Reserved3, sizeof(wsInfo.Reserved3));
std::wstring userName;
if (!reserved3Strings.empty()) {
userName = reserved3Strings.back(); // Assuming last string in Reserved3 is username
}
std::string userNameStr(userName.begin(), userName.end());
std::cout << "UserName: " << userNameStr << std::endl;
}
else {
wprintf(L"Failed to query session info for SessionName: %s\n", pSessionIds[i].WinStationName);
}
}
LocalFree(pSessionIds);
//printf("Free'd Session IDs from memory.\n");
}
else {
printf("Failed to enumerate sessions.\n");
}
BOOLEAN hServerClosed = pfnWinStationCloseServer(hServer);
if (!hServerClosed) {
//printf("Failed to close server handle.\n");
return 1;
}
//printf("Gracefully closed server handle.\n");
BOOLEAN hDLLClosed = FreeLibrary(hDLL);
if (!hDLLClosed) {
//printf("Failed to close DLL handle.\n");
return 1;
}
//printf("Gracefully closed DLL handle.\n");
return 0;
}