forked from zodiacon/ObjectExplorer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathObjectHelpers.cpp
217 lines (208 loc) · 8.75 KB
/
ObjectHelpers.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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#include "pch.h"
#include "ObjectHelpers.h"
#include "GenericPage.h"
#include "ObjectPropertiesDlg.h"
#include "NtDll.h"
#include "ProcessHelper.h"
#include <atltime.h>
#include "StringHelper.h"
#include "HandlesPage.h"
#include "ObjectManager.h"
#include "StructurePage.h"
#include "SymbolManager.h"
#include "DriverHelper.h"
UINT ObjectHelpers::ShowObjectProperties(HANDLE hObject, PCWSTR typeName, PCWSTR name, PCWSTR target, DWORD handleCount) {
CString title = typeName;
if (name && name[0])
title += L" (" + CString(name) + L")";
CObjectPropertiesDlg dlg((PCWSTR)title, typeName);
CGenericPage page1(hObject, typeName, name, target);
page1.Create(::GetActiveWindow());
handleCount = page1.GetHandleCount();
dlg.AddPage(L"General", page1);
CHandlesPage page2(hObject, typeName, handleCount);
if (handleCount) {
CWaitCursor wait; // handle count may be large
page2.Create(::GetActiveWindow());
dlg.AddPage(L"Handles", page2);
}
CStructPage page3(hObject);
if(auto it = KernelTypes.find(typeName); it != KernelTypes.end()) {
auto sym = SymbolManager::Get().GetSymbol(it->second);
if (sym) {
page3.SetSymbol(std::move(sym), DriverHelper::GetObjectAddress(hObject));
page3.Create(::GetActiveWindow());
dlg.AddPage(L"Object", page3);
}
}
dlg.DoModal();
return 0;
}
std::vector<std::pair<CString, CString>> ObjectHelpers::GetSimpleProps(HANDLE hObject, PCWSTR type, PCWSTR name, PCWSTR target) {
std::vector<std::pair<CString, CString>> props;
props.reserve(4);
CString text;
if (::_wcsicmp(type, L"Mutant") == 0) {
NT::MUTANT_BASIC_INFORMATION info;
if (NT_SUCCESS(NT::NtQueryMutant(hObject, NT::MutantBasicInformation, &info, sizeof(info), nullptr))) {
props.push_back({ L"Held:", info.CurrentCount <= 0 ? L"Yes" : L"No" });
props.push_back({ L"Abandoned:", info.AbandonedState ? L"Yes" : L"No" });
}
NT::MUTANT_OWNER_INFORMATION owner;
if (NT_SUCCESS(NT::NtQueryMutant(hObject, NT::MutantOwnerInformation, &owner, sizeof(owner), nullptr))) {
if (owner.ClientId.UniqueThread) {
auto pid = HandleToUlong(owner.ClientId.UniqueProcess);
text.Format(L"%u (%s)", pid, (PCWSTR)ProcessHelper::GetProcessName(pid));
props.push_back({ L"Owner PID:", text });
props.push_back({ L"Owner TID:", std::to_wstring(HandleToUlong(owner.ClientId.UniqueThread)).c_str() });
}
}
}
else if (::_wcsicmp(type, L"Event") == 0) {
NT::EVENT_BASIC_INFORMATION info;
if (NT_SUCCESS(NT::NtQueryEvent(hObject, NT::EventBasicInformation, &info, sizeof(info), nullptr))) {
props.push_back({ L"Type:", info.EventType == NT::NotificationEvent ? L"Notification (Manual Reset)" : L"Synchronization (Auto Reset)" });
props.push_back({ L"Signaled:", info.EventState ? L"Yes" : L"No" });
}
}
else if (::_wcsicmp(type, L"Semaphore") == 0) {
NT::SEMAPHORE_BASIC_INFORMATION info;
if (NT_SUCCESS(NT::NtQuerySemaphore(hObject, NT::SemaphoreBasicInformation, &info, sizeof(info), nullptr))) {
text.Format(L"%u (0x%X)", info.CurrentCount, info.CurrentCount);
props.push_back({ L"Count:", text });
text.Format(L"%u (0x%X)", info.MaximumCount, info.MaximumCount);
props.push_back({ L"Maximum:", text });
}
}
else if (::_wcsicmp(type, L"SymbolicLink") == 0) {
NT::OBJECT_BASIC_INFORMATION info;
if (NT_SUCCESS(NT::NtQueryObject(hObject, NT::ObjectBasicInformation, &info, sizeof(info), nullptr))) {
CString starget(target);
if (starget.IsEmpty()) {
auto buffer = std::make_unique<BYTE[]>(1 << 12);
if (buffer) {
UNICODE_STRING result;
result.MaximumLength = 1 << 12;
result.Buffer = (PWSTR)buffer.get();
auto status = NT::NtQuerySymbolicLinkObject(hObject, &result, nullptr);
if (NT_SUCCESS(status))
starget.SetString(result.Buffer, result.Length / sizeof(WCHAR));
}
}
props.push_back({ L"Target:", starget });
props.push_back({ L"Creation Time:", CTime(*(FILETIME*)&info.CreationTime).Format(L"%c") });
}
}
else if (::_wcsicmp(type, L"Section") == 0) {
NT::SECTION_BASIC_INFORMATION info;
if (NT_SUCCESS(NT::NtQuerySection(hObject, NT::SectionBasicInformation, &info, sizeof(info), nullptr))) {
text.Format(L"0x%llX Bytes", info.MaximumSize.QuadPart);
props.push_back({ L"Size:", text });
text.Format(L"0x%08X (%s)", info.AllocationAttributes, (PCWSTR)StringHelper::SectionAttributesToString(info.AllocationAttributes));
props.push_back({ L"Attributes:", text });
}
}
else if (::_wcsicmp(type, L"Type") == 0) {
ObjectManager::EnumTypes();
auto info = ObjectManager::GetType(name);
ATLASSERT(info);
if (info) {
text.Format(L"%u", info->TotalNumberOfObjects);
props.push_back({ L"Objects: ", text });
text.Format(L"%u", info->TotalNumberOfHandles);
props.push_back({ L"Handles: ", text });
}
}
else if (::_wcsicmp(type, L"Process") == 0) {
auto pid = ::GetProcessId(hObject);
auto name = ProcessHelper::GetProcessName2(pid);
props.push_back({ L"Process ID: ", std::to_wstring(pid).c_str() });
if (!name.IsEmpty())
props.push_back({ L"Image Name: ", name });
FILETIME create, exit, kernel, user;
if (::GetProcessTimes(hObject, &create, &exit, &kernel, &user)) {
props.push_back({ L"Started: ", CTime(create).Format(L"%c") });
auto total = (*(ULONGLONG*)&kernel + *(ULONGLONG*)&user) / 10000; // msec
auto seconds = CTimeSpan(total / 1000).Format(L"%H:%M:%S");
props.push_back({ L"CPU Time: ", std::format(L"{}.{}", (PCWSTR)seconds, total % 1000).c_str() });
if (::WaitForSingleObject(hObject, 0) == WAIT_OBJECT_0) {
//
// process dead
//
props.push_back({ L"Exited: ", CTime(exit).Format(L"%c") });
}
}
}
else if (::_wcsicmp(type, L"Thread") == 0) {
auto name = ProcessHelper::GetProcessName2(::GetProcessIdOfThread(hObject));
if (!name.IsEmpty())
props.push_back({ L"Process Image Name: ", name });
FILETIME create, exit, kernel, user;
if (::GetThreadTimes(hObject, &create, &exit, &kernel, &user)) {
props.push_back({ L"Started: ", CTime(create).Format(L"%c") });
auto total = (*(ULONGLONG*)&kernel + *(ULONGLONG*)&user) / 10000; // msec
auto seconds = CTimeSpan(total / 1000).Format(L"%H:%M:%S");
props.push_back({ L"CPU Time: ", std::format(L"{}.{:03}", (PCWSTR)seconds, total % 1000).c_str() });
if (::WaitForSingleObject(hObject, 0) == WAIT_OBJECT_0) {
//
// thread dead
//
props.push_back({ L"Exited: ", CTime(exit).Format(L"%c") });
}
}
}
else if (::_wcsicmp(type, L"Job") == 0) {
JOBOBJECT_BASIC_ACCOUNTING_INFORMATION info;
if (::QueryInformationJobObject(hObject, JobObjectBasicAccountingInformation, &info, sizeof(info), nullptr)) {
props.push_back({ L"Active Processes: ", std::to_wstring(info.ActiveProcesses).c_str() });
props.push_back({ L"Total Processes: ", std::to_wstring(info.TotalProcesses).c_str() });
auto total = (info.TotalUserTime.QuadPart + info.TotalKernelTime.QuadPart) / 10000;
auto seconds = CTimeSpan(total / 1000).Format(L"%H:%M:%S");
props.push_back({ L"CPU Time: ", std::format(L"{}.{:03}", (PCWSTR)seconds, total % 1000).c_str() });
props.push_back({ L"Page Faults: ", std::to_wstring(info.TotalPageFaultCount).c_str() });
}
}
return props;
}
bool ObjectHelpers::IsNamedObjectType(USHORT index) {
auto type = ObjectManager::GetType(index)->TypeName;
static const CString nonNamed[] = {
L"Process", L"Thread", L"Token", L"EtwRegistration", L"IoCompletion",
L"WaitCompletionPacket", L"TpWorkerFactory",
};
return std::find(std::begin(nonNamed), std::end(nonNamed), type) == std::end(nonNamed);
}
HANDLE ObjectHelpers::OpenObject(PCWSTR name, PCWSTR typeName, DWORD access) {
HANDLE hObject = nullptr;
CString type(typeName);
OBJECT_ATTRIBUTES attr;
UNICODE_STRING uname;
RtlInitUnicodeString(&uname, name);
InitializeObjectAttributes(&attr, &uname, 0, nullptr, nullptr);
auto status = STATUS_UNSUCCESSFUL;
if (type == L"Event")
status = NT::NtOpenEvent(&hObject, access, &attr);
else if (type == L"Mutant")
status = NT::NtOpenMutant(&hObject, access, &attr);
else if (type == L"Section")
status = NT::NtOpenSection(&hObject, access, &attr);
else if (type == L"Session")
status = NT::NtOpenSession(&hObject, access, &attr);
else if (type == L"Semaphore")
status = NT::NtOpenSemaphore(&hObject, access, &attr);
else if (type == "EventPair")
status = NT::NtOpenEventPair(&hObject, access, &attr);
else if (type == L"IoCompletion")
status = NT::NtOpenIoCompletion(&hObject, access, &attr);
else if (type == L"SymbolicLink")
status = NT::NtOpenSymbolicLinkObject(&hObject, access, &attr);
else if (type == L"Key")
status = NT::NtOpenKey(&hObject, access, &attr);
else if (type == L"Job")
status = NT::NtOpenJobObject(&hObject, access, &attr);
else if (type == L"File" || type == L"Device") {
IO_STATUS_BLOCK ioStatus;
status = NT::NtOpenFile(&hObject, access, &attr, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0);
}
return hObject;
}