[NTOSKRNL] Add a first implementation of !handle command in KDBG

It allows dumping all the handles (filtered by PID/Process)
and it displays basic information about file and key handles
This commit is contained in:
Pierre Schweitzer 2019-02-09 13:45:19 +01:00
parent 5bfe6a5376
commit 2991f6e76e
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
2 changed files with 229 additions and 0 deletions

View file

@ -1282,3 +1282,230 @@ ExEnumHandleTable(IN PHANDLE_TABLE HandleTable,
KeLeaveCriticalRegion();
return Result;
}
#if DBG && defined(KDBG)
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[])
{
USHORT i;
char *endptr;
HANDLE ProcessId;
EXHANDLE ExHandle;
PLIST_ENTRY Entry;
PEPROCESS Process;
WCHAR KeyPath[MAX_PATH];
PFILE_OBJECT FileObject;
PHANDLE_TABLE HandleTable;
POBJECT_HEADER ObjectHeader;
PHANDLE_TABLE_ENTRY TableEntry;
ULONG NeededLength, NameLength;
PCM_KEY_CONTROL_BLOCK Kcb, CurrentKcb;
POBJECT_HEADER_NAME_INFO ObjectNameInfo;
if (Argc > 1)
{
/* Get EPROCESS address or PID */
i = 0;
while (Argv[1][i])
{
if (!isdigit(Argv[1][i]))
{
i = 0;
break;
}
}
if (i == 0)
{
if (!KdbpGetHexNumber(Argv[1], (PVOID)&Process))
{
KdbpPrint("Invalid parameter: %s\n", Argv[1]);
return TRUE;
}
/* In the end, we always want a PID */
ProcessId = PsGetProcessId(Process);
}
else
{
ProcessId = (HANDLE)strtoul(Argv[1], &endptr, 10);
if (*endptr != '\0')
{
KdbpPrint("Invalid parameter: %s\n", Argv[1]);
return TRUE;
}
}
}
else
{
ProcessId = PsGetCurrentProcessId();
}
for (Entry = HandleTableListHead.Flink;
Entry != &HandleTableListHead;
Entry = Entry->Flink)
{
/* Only return matching PID
* 0 matches everything
*/
HandleTable = CONTAINING_RECORD(Entry, HANDLE_TABLE, HandleTableList);
if (ProcessId != 0 && HandleTable->UniqueProcessId != ProcessId)
{
continue;
}
KdbpPrint("\n");
KdbpPrint("Handle table at %p with %d entries in use\n", HandleTable, HandleTable->HandleCount);
ExHandle.Value = 0;
while ((TableEntry = ExpLookupHandleTableEntry(HandleTable, ExHandle)))
{
if ((TableEntry->Object) &&
(TableEntry->NextFreeTableEntry != -2))
{
ObjectHeader = ObpGetHandleObject(TableEntry);
KdbpPrint("%p: Object: %p GrantedAccess: %x Entry: %p\n", ExHandle.Value, &ObjectHeader->Body, TableEntry->GrantedAccess, TableEntry);
KdbpPrint("Object: %p Type: (%x) ", &ObjectHeader->Body, ObjectHeader->Type);
if (ObjectHeader->Type == IoFileObjectType)
{
KdbpPrint("File");
}
else if (ObjectHeader->Type == ExEventObjectType)
{
KdbpPrint("Event");
}
else if (ObjectHeader->Type == ExEventPairObjectType)
{
KdbpPrint("EventPair");
}
else if (ObjectHeader->Type == ExMutantObjectType)
{
KdbpPrint("Mutant");
}
else if (ObjectHeader->Type == ExSemaphoreObjectType)
{
KdbpPrint("Semaphore");
}
else if (ObjectHeader->Type == ExTimerType)
{
KdbpPrint("Timer");
}
else if (ObjectHeader->Type == ExWindowStationObjectType)
{
KdbpPrint("WindowStation");
}
else if (ObjectHeader->Type == ExDesktopObjectType)
{
KdbpPrint("Desktop");
}
else if (ObjectHeader->Type == ObpDirectoryObjectType)
{
KdbpPrint("Directory");
}
else if (ObjectHeader->Type == CmpKeyObjectType)
{
KdbpPrint("Key");
}
else if (ObjectHeader->Type == MmSectionObjectType)
{
KdbpPrint("Section");
}
else if (ObjectHeader->Type == PsThreadType)
{
KdbpPrint("Thread");
}
else if (ObjectHeader->Type == LpcPortObjectType)
{
KdbpPrint("ALPC Port");
}
KdbpPrint("\n");
KdbpPrint("\tObjectHeader: %p\n", ObjectHeader);
KdbpPrint("\t\tHandleCount: %u PointerCount: %u\n", ObjectHeader->HandleCount, ObjectHeader->PointerCount);
/* Specific objects debug prints */
/* For file, display path */
if (ObjectHeader->Type == IoFileObjectType)
{
FileObject = (PFILE_OBJECT)&ObjectHeader->Body;
KdbpPrint("\t\t\tName: %wZ\n", &FileObject->FileName);
}
/* For directory, and win32k objects, display object name */
else if (ObjectHeader->Type == ObpDirectoryObjectType ||
ObjectHeader->Type == ExWindowStationObjectType ||
ObjectHeader->Type == ExDesktopObjectType)
{
ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
if (ObjectNameInfo != NULL && ObjectNameInfo->Name.Buffer != NULL)
{
KdbpPrint("\t\t\tName: %wZ\n", &ObjectNameInfo->Name);
}
}
/* For registry keys, display full path */
else if (ObjectHeader->Type == CmpKeyObjectType)
{
Kcb = ((PCM_KEY_BODY)&ObjectHeader->Body)->KeyControlBlock;
if (!Kcb->Delete)
{
CurrentKcb = Kcb;
/* See: CmpQueryNameInformation() */
while (CurrentKcb != NULL)
{
if (CurrentKcb->NameBlock->Compressed)
NeededLength += CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
else
NeededLength += CurrentKcb->NameBlock->NameLength;
NeededLength += sizeof(OBJ_NAME_PATH_SEPARATOR);
CurrentKcb = CurrentKcb->ParentKcb;
}
if (NeededLength < MAX_PATH * sizeof(WCHAR))
{
CurrentKcb = Kcb;
while (CurrentKcb != NULL)
{
if (CurrentKcb->NameBlock->Compressed)
{
NameLength = CmpCompressedNameSize(CurrentKcb->NameBlock->Name, CurrentKcb->NameBlock->NameLength);
CmpCopyCompressedName(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
NameLength,
CurrentKcb->NameBlock->Name,
CurrentKcb->NameBlock->NameLength);
}
else
{
NameLength = CurrentKcb->NameBlock->NameLength;
RtlCopyMemory(&KeyPath[(NeededLength - NameLength)/sizeof(WCHAR)],
CurrentKcb->NameBlock->Name,
NameLength);
}
NeededLength -= NameLength;
NeededLength -= sizeof(OBJ_NAME_PATH_SEPARATOR);
KeyPath[NeededLength/sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
CurrentKcb = CurrentKcb->ParentKcb;
}
}
KdbpPrint("\t\t\tName: %S\n", KeyPath);
}
}
}
ExHandle.Value += INDEX_TO_HANDLE_VALUE(1);
}
}
return TRUE;
}
#endif

View file

@ -97,6 +97,7 @@ BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]);
#ifdef __ROS_DWARF__
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
@ -194,6 +195,7 @@ static const struct
{ "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
{ "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
{ "!irpfind", "!irpfind [Pool [startaddress [criteria data]]]", "Lists IRPs potentially matching criteria", ExpKdbgExtIrpFind },
{ "!handle", "!handle [Handle]", "Displays info about handles", ExpKdbgExtHandle },
};
/* FUNCTIONS *****************************************************************/