Skip to content

Commit

Permalink
Improve PhUiCloseHandles for protected handles
Browse files Browse the repository at this point in the history
  • Loading branch information
DartVanya committed Nov 18, 2024
1 parent 5c82999 commit a8177bc
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 57 deletions.
30 changes: 25 additions & 5 deletions SystemInformer/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -5855,6 +5855,7 @@ BOOLEAN PhUiFreeMemory(
static BOOLEAN PhpShowErrorHandle(
_In_ HWND WindowHandle,
_In_ PCWSTR Verb,
_In_ PCWSTR Verb2,
_In_ PPH_HANDLE_ITEM Handle,
_In_ NTSTATUS Status,
_In_opt_ ULONG Win32Result
Expand All @@ -5869,10 +5870,11 @@ static BOOLEAN PhpShowErrorHandle(
return PhShowContinueStatus(
WindowHandle,
PhaFormatString(
L"Unable to %s handle \"%s\" (%s)",
L"Unable to %s handle \"%s\" (%s)%s",
Verb,
Handle->BestObjectName->Buffer,
value
value,
Verb2
)->Buffer,
Status,
Win32Result
Expand All @@ -5883,9 +5885,10 @@ static BOOLEAN PhpShowErrorHandle(
return PhShowContinueStatus(
WindowHandle,
PhaFormatString(
L"Unable to %s handle %s",
L"Unable to %s handle %s%s",
Verb,
value
value,
Verb2
)->Buffer,
Status,
Win32Result
Expand Down Expand Up @@ -5998,12 +6001,29 @@ BOOLEAN PhUiCloseHandles(
if (!PhpShowErrorHandle(
WindowHandle,
L"close",
NULL,
Handles[i],
status,
0
))
break;
}
// If handle is protected from closing NtDuplicateObject doesn't close handle but returns STATUS_SUCCESS.
// Show error to notify user that "Protected" attribute should be removed first (Dart Vanya)
else if (Handles[i]->Attributes & OBJ_PROTECT_CLOSE)
{
success = FALSE;

if (!PhpShowErrorHandle(
WindowHandle,
L"close",
L".\nRemove \"Protected\" attribute from menu and try again.",
Handles[i],
STATUS_HANDLE_NOT_CLOSABLE,
0
))
break;
}
}

NtClose(processHandle);
Expand Down Expand Up @@ -6060,7 +6080,7 @@ BOOLEAN PhUiSetAttributesHandle(

if (!NT_SUCCESS(status))
{
PhpShowErrorHandle(WindowHandle, L"set attributes of", Handle, status, 0);
PhpShowErrorHandle(WindowHandle, L"set attributes of", NULL, Handle, status, 0);
return FALSE;
}

Expand Down
5 changes: 4 additions & 1 deletion SystemInformer/findobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -1527,7 +1527,10 @@ INT_PTR CALLBACK PhpFindObjectsDlgProc(
DUPLICATE_CLOSE_SOURCE
)))
{
PhpRemoveHandleObjectNode(context, handleObjectNodes[i]);
if (handleObjectNodes[i]->HandleInfo.HandleAttributes & OBJ_PROTECT_CLOSE)
status = STATUS_HANDLE_NOT_CLOSABLE;
else
PhpRemoveHandleObjectNode(context, handleObjectNodes[i]);
}

NtClose(processHandle);
Expand Down
4 changes: 2 additions & 2 deletions SystemInformer/memsrcht.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ INT_PTR CALLBACK PhpMemoryStringsMinimumLengthDlgProc(

if (!minimumLength || minimumLength > MAXULONG32)
{
PhShowError(hwndDlg, L"%s", L"Invalid minimum length");
PhShowError2(hwndDlg, L"Invalid minimum length.", L"%s", L"");
break;
}

Expand Down Expand Up @@ -1542,7 +1542,7 @@ BOOLEAN PhpShowMemoryStringTreeDialog(

if (!NT_SUCCESS(PhCreateThread2(PhpShowMemoryStringDialogThreadStart, context)))
{
PhShowError(ParentWindowHandle, L"%s", L"Unable to create the window.");
PhShowError2(ParentWindowHandle, L"Unable to create the window.", L"%s", L"");
PhDereferenceObject(context->ProcessItem);
NtClose(context->ProcessHandle);
PhFree(context);
Expand Down
128 changes: 79 additions & 49 deletions plugins/ExtendedTools/objprp.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ typedef struct _COMMON_PAGE_CONTEXT
HANDLE ProcessId;
HWND WindowHandle;
HWND ListViewHandle;

// Handles tab
ULONG TotalHandlesCount;
ULONG OwnHandlesCount;
} COMMON_PAGE_CONTEXT, *PCOMMON_PAGE_CONTEXT;

typedef struct _ET_HANDLE_ENTRY
Expand Down Expand Up @@ -252,6 +256,22 @@ typedef enum _ET_OBJECT_POOLTYPE {
} ET_OBJECT_POOLTYPE;

#define OBJECT_CHILD_HANDLEPROP_WINDOW 1
#define OBJECT_CORRECT_HANDLES_COUNT(real_count, name) ((ULONG)(real_count) - EtpObjectManagerGetOwnHandlesCount(name))

ULONG EtpObjectManagerGetOwnHandlesCount(
_In_ PPH_STRING ObjectName
)
{
ULONG own_count = 0;
PPH_KEY_VALUE_PAIR entry;
ULONG i = 0;

while (PhEnumHashtable(EtObjectManagerPropWindows, &entry, &i))
if (PhEqualString(ObjectName, ((PPH_HANDLE_ITEM)entry->Value)->ObjectName, TRUE))
own_count++;

return own_count;
}

VOID EtHandlePropertiesWindowInitialized(
_In_ PVOID Parameter
Expand Down Expand Up @@ -283,15 +303,7 @@ VOID EtHandlePropertiesWindowInitialized(
PPH_STRING count = PH_AUTO(PhGetListViewItemText(context->ListViewHandle, PH_PLUGIN_HANDLE_GENERAL_INDEX_HANDLES, 1));

if (!PhIsNullOrEmptyString(count) && PhStringToUInt64(&count->sr, 0, &real_count) && real_count > 0) {
ULONG own_count = 0;
PPH_KEY_VALUE_PAIR entry;
ULONG i = 0;

while (PhEnumHashtable(EtObjectManagerPropWindows, &entry, &i))
if (PhEqualString(context->HandleItem->ObjectName, ((PPH_HANDLE_ITEM)entry->Value)->ObjectName, TRUE))
own_count++;

PhPrintUInt32(string, (ULONG)real_count - own_count);
PhPrintUInt32(string, OBJECT_CORRECT_HANDLES_COUNT(real_count, context->HandleItem->ObjectName));
PhSetListViewSubItem(context->ListViewHandle, PH_PLUGIN_HANDLE_GENERAL_INDEX_HANDLES, 1, string);
}

Expand Down Expand Up @@ -1066,7 +1078,7 @@ static NTSTATUS NTAPI EtpSearchHandleFunction(
return STATUS_SUCCESS;
}

INT EtpEnumObjectHandles(
VOID EtpEnumObjectHandles(
_In_ PCOMMON_PAGE_CONTEXT Context
)
{
Expand All @@ -1076,7 +1088,6 @@ INT EtpEnumObjectHandles(
COLORREF colorProtected = PhGetIntegerSetting(L"ColorProtectedHandles");
COLORREF colorProtectedInherit = PhGetIntegerSetting(L"ColorPartiallySuspended");

INT ownHandlesIndex = 0;
PSYSTEM_HANDLE_INFORMATION_EX handles;
ULONG_PTR i;
ULONG searchTypeIndex;
Expand Down Expand Up @@ -1215,9 +1226,9 @@ INT EtpEnumObjectHandles(

if (handleInfo->Object == Context->HandleItem->Object || objectNameMatched)
{
PhAcquireQueuedLockExclusive(&searchResultsLock);
if (useWorkQueue) PhAcquireQueuedLockExclusive(&searchResultsLock);
PhAddItemList(searchResults, handleInfo);
PhReleaseQueuedLockExclusive(&searchResultsLock);
if (useWorkQueue) PhReleaseQueuedLockExclusive(&searchResultsLock);
}
}
}
Expand All @@ -1233,6 +1244,7 @@ INT EtpEnumObjectHandles(

PhDereferenceObject(processHandleHashtable);

ULONG ownHandlesIndex = 0;
INT lvItemIndex;
WCHAR value[PH_INT64_STR_LEN_1];
PHANDLE_ENTRY entry;
Expand Down Expand Up @@ -1316,9 +1328,10 @@ INT EtpEnumObjectHandles(

PhDereferenceObject(searchResults);
PhFree(handles);
}

return ownHandlesIndex;
Context->TotalHandlesCount = ListView_GetItemCount(Context->ListViewHandle);
Context->OwnHandlesCount = ownHandlesIndex;
}
}

VOID EtUpdateHandleItem(
Expand Down Expand Up @@ -1367,40 +1380,60 @@ VOID EtpCloseObjectHandles(
_In_ ULONG NumberOfItems
)
{
HANDLE oldHandle;
NTSTATUS status;
ULONG64 count;
WCHAR string[PH_INT64_STR_LEN_1];
HWND generalPageList;
HANDLE processHandle = NtCurrentProcess();
BOOLEAN ownHandle;

for (ULONG i = 0; i < NumberOfItems; i++)
{
if (PhUiCloseHandles(Context->WindowHandle, ListviewItems[i]->ProcessId, &ListviewItems[i]->HandleItem, 1, TRUE))
{
if ((status = EtDuplicateHandleFromProcessEx(
&oldHandle,
0,
ListviewItems[i]->ProcessId,
ListviewItems[i]->HandleItem->Handle)) == STATUS_INVALID_HANDLE)
{
PhStringToUInt64(&PhaGetDlgItemText(Context->WindowHandle, IDC_OBJ_HANDLESTOTAL)->sr, 0, &count);
PhPrintUInt32(string, (ULONG)count - 1);
PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESTOTAL, string);
PhStringToUInt64(&PhaGetDlgItemText(Context->WindowHandle, ListviewItems[i]->OwnHandle ? IDC_OBJ_HANDLESBYOBJECT : IDC_OBJ_HANDLESBYNAME)->sr, 0, &count);
PhPrintUInt32(string, (ULONG)count - 1);
PhSetDialogItemText(Context->WindowHandle, ListviewItems[i]->OwnHandle ? IDC_OBJ_HANDLESBYOBJECT : IDC_OBJ_HANDLESBYNAME, string);

PhRemoveListViewItem(Context->ListViewHandle, PhFindListViewItemByParam(Context->ListViewHandle, INT_ERROR, ListviewItems[i]));
PhClearReference(&ListviewItems[i]->HandleItem);
PhFree(ListviewItems[i]);
}
else if (NT_SUCCESS(status))
{
NtClose(oldHandle);
}
ownHandle = !!ListviewItems[i]->OwnHandle;
PhRemoveListViewItem(Context->ListViewHandle, PhFindListViewItemByParam(Context->ListViewHandle, INT_ERROR, ListviewItems[i]));
PhClearReference(&ListviewItems[i]->HandleItem);
PhFree(ListviewItems[i]);

PhPrintUInt32(string, --Context->TotalHandlesCount);
PhSetDialogItemText(Context->WindowHandle, IDC_OBJ_HANDLESTOTAL, string);

Context->OwnHandlesCount -= ownHandle;
PhPrintUInt32(string, ownHandle ? Context->OwnHandlesCount : Context->TotalHandlesCount - Context->OwnHandlesCount);
PhSetDialogItemText(Context->WindowHandle, ownHandle ? IDC_OBJ_HANDLESBYOBJECT : IDC_OBJ_HANDLESBYNAME, string);
}
else
}

// Update General page references and handles count
if (generalPageList = FindWindowEx(PropSheet_IndexToHwnd(GetParent(Context->WindowHandle), 0), NULL, WC_LISTVIEW, NULL)) // HACK
{
if (Context->ProcessId == NtCurrentProcessId() ||
NT_SUCCESS(PhOpenProcess(
&processHandle,
(KsiLevel() >= KphLevelMed ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_DUP_HANDLE),
Context->ProcessId
)))
{
break;
OBJECT_BASIC_INFORMATION basicInfo;

if (NT_SUCCESS(PhGetHandleInformation(
processHandle,
Context->HandleItem->Handle,
Context->HandleItem->TypeIndex,
&basicInfo,
NULL,
NULL,
NULL
)))
{
PhPrintUInt32(string, basicInfo.PointerCount);
PhSetListViewSubItem(generalPageList, PH_PLUGIN_HANDLE_GENERAL_INDEX_REFERENCES, 1, string);

PhPrintUInt32(string, OBJECT_CORRECT_HANDLES_COUNT(basicInfo.HandleCount, Context->HandleItem->ObjectName));
PhSetListViewSubItem(generalPageList, PH_PLUGIN_HANDLE_GENERAL_INDEX_HANDLES, 1, string);
}

if (processHandle != NtCurrentProcess())
NtClose(processHandle);
}
}
}
Expand Down Expand Up @@ -1476,8 +1509,6 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc(
{
case WM_INITDIALOG:
{
INT ownHandlesCount;
INT totalHandlesCount;
WCHAR string[PH_INT64_STR_LEN_1];

context->WindowHandle = hwndDlg;
Expand All @@ -1500,24 +1531,23 @@ INT_PTR CALLBACK EtpObjHandlesPageDlgProc(

PhSetCursor(PhLoadCursor(NULL, IDC_WAIT));

ownHandlesCount = EtpEnumObjectHandles(context);
totalHandlesCount = ListView_GetItemCount(context->ListViewHandle);
EtpEnumObjectHandles(context);

PhSetCursor(PhLoadCursor(NULL, IDC_ARROW));

PhInitializeWindowTheme(hwndDlg, PhIsThemeSupportEnabled());

ExtendedListView_SetRedraw(context->ListViewHandle, TRUE);

PhPrintUInt32(string, totalHandlesCount);
PhPrintUInt32(string, context->TotalHandlesCount);
PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJ_HANDLESTOTAL), string);
PhPrintUInt32(string, ownHandlesCount);
PhPrintUInt32(string, context->OwnHandlesCount);
PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJ_HANDLESBYOBJECT), string);
PhPrintUInt32(string, totalHandlesCount - ownHandlesCount);
PhPrintUInt32(string, context->TotalHandlesCount - context->OwnHandlesCount);
PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJ_HANDLESBYNAME), string);

if (PhEqualString2(context->HandleItem->TypeName, L"Type", TRUE))
PhSetWindowText(GetDlgItem(hwndDlg, IDC_OBJ_HANDLESBYNAME_L), L"By type:");
PhSetDialogItemText(hwndDlg, IDC_OBJ_HANDLESBYNAME_L, L"By type:");
}
break;
case WM_SIZE:
Expand Down

0 comments on commit a8177bc

Please sign in to comment.