获取进程完整Handle列表失败求助:已提权仍未解决
无法获取进程完整Handle列表的问题排查与解决
问题描述
已以管理员身份运行程序,目标为获取普通进程的完整Handle列表,但与Process Hacker的结果对比存在明显缺失。已按建议添加SE_DEBUG_NAME权限,但问题仍未解决。
提供的代码
void SetPrivilege() { TOKEN_PRIVILEGES NewState; LUID luid; HANDLE hToken; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken); LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); NewState.PrivilegeCount = 1; NewState.Privileges[0].Luid = luid; NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, FALSE, &NewState, sizeof(NewState), NULL, NULL); CloseHandle(hToken); } int main(int argc, WCHAR* argv[]) { SetPrivilege(); _NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)GetLibraryProcAddress((PSTR)"ntdll.dll", (PSTR)"NtQuerySystemInformation"); _NtDuplicateObject NtDuplicateObject = (_NtDuplicateObject)GetLibraryProcAddress((PSTR)"ntdll.dll", (PSTR)"NtDuplicateObject"); _NtQueryObject NtQueryObject = (_NtQueryObject)GetLibraryProcAddress((PSTR)"ntdll.dll", (PSTR)"NtQueryObject"); NTSTATUS status; PSYSTEM_HANDLE_INFORMATION handleInfo; ULONG handleInfoSize = 0x10000; HANDLE processHandle; ULONG i; unsigned __int16 pid = 0; std::cin >> pid; if (!(processHandle = OpenProcess(PROCESS_DUP_HANDLE, 0, pid))) { printf("Could not open PID %d! (Don't try to open a system process.)\n", pid); return 1; } handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); while ((status = NtQuerySystemInformation( SystemHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); if (!NT_SUCCESS(status)) { printf("NtQuerySystemInformation failed!\n"); return 1; } for (i = 0; i < handleInfo->HandleCount; i++) { SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; POBJECT_TYPE_INFORMATION objectTypeInfo; PVOID objectNameInfo; UNICODE_STRING objectName; ULONG returnLength; if (handle.ProcessId != pid) continue; if (!NT_SUCCESS(NtDuplicateObject( processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0 ))) { printf("[%#x] Error!\n", handle.Handle); continue; } objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectTypeInformation, objectTypeInfo, 0x1000, NULL ))) { printf("[%#x] Error!\n", handle.Handle); CloseHandle(dupHandle); continue; } if (handle.GrantedAccess == 0x0012019f) { printf( "[%#x] %.*S: (did not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); free(objectTypeInfo); CloseHandle(dupHandle); continue; } objectNameInfo = malloc(0x1000); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, 0x1000, &returnLength ))) { objectNameInfo = realloc(objectNameInfo, returnLength); if (!NT_SUCCESS(NtQueryObject( dupHandle, ObjectNameInformation, objectNameInfo, returnLength, NULL ))) { printf( "[%#x] %.*S: (could not get name)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); continue; } } objectName = *(PUNICODE_STRING)objectNameInfo; if (objectName.Length) { printf( "[%#x] %.*S: %.*S\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer, objectName.Length / 2, objectName.Buffer ); } else { printf( "[%#x] %.*S: (unnamed)\n", handle.Handle, objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer ); } free(objectTypeInfo); free(objectNameInfo); CloseHandle(dupHandle); } free(handleInfo); CloseHandle(processHandle); system("pause"); return 0; }
排查与修复方案
1. 完善权限设置的错误检查
原SetPrivilege函数未检查任何API返回值,可能权限并未成功启用。修改后添加完整错误校验:
BOOL SetPrivilege() { TOKEN_PRIVILEGES NewState; LUID luid; HANDLE hToken = NULL; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { printf("OpenProcessToken failed: %lu\n", GetLastError()); return FALSE; } if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { printf("LookupPrivilegeValue failed: %lu\n", GetLastError()); CloseHandle(hToken); return FALSE; } NewState.PrivilegeCount = 1; NewState.Privileges[0].Luid = luid; NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, FALSE, &NewState, sizeof(NewState), NULL, NULL)) { printf("AdjustTokenPrivileges failed: %lu\n", GetLastError()); CloseHandle(hToken); return FALSE; } else if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) { printf("Privilege not assigned\n"); CloseHandle(hToken); return FALSE; } CloseHandle(hToken); return TRUE; }
2. 提升OpenProcess的权限
原调用仅传入PROCESS_DUP_HANDLE,部分对象复制需要更高权限,改为:
processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_DUP_HANDLE, FALSE, pid);
3. 使用扩展句柄信息接口
SystemHandleInformation在部分Windows版本返回信息不全,改用SystemExtendedHandleInformation获取完整数据:
while ((status = NtQuerySystemInformation( SystemExtendedHandleInformation, handleInfo, handleInfoSize, NULL )) == STATUS_INFO_LENGTH_MISMATCH) handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
需注意补充SYSTEM_HANDLE_INFORMATION_EX结构定义(参考Windows SDK文档)。
4. 优化句柄复制权限
调用NtDuplicateObject时传入DUPLICATE_SAME_ACCESS,确保复制的句柄拥有原句柄相同权限:
if (!NT_SUCCESS(NtDuplicateObject( processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, DUPLICATE_SAME_ACCESS )))
5. 取消不必要的句柄过滤
原代码跳过了GrantedAccess == 0x0012019f的句柄,导致遗漏,可注释该判断:
// if (handle.GrantedAccess == 0x0012019f) // { // printf("[%#x] %.*S: (did not get name)\n", // handle.Handle, // objectTypeInfo->Name.Length / 2, // objectTypeInfo->Name.Buffer); // free(objectTypeInfo); // CloseHandle(dupHandle); // continue; // }
内容的提问来源于stack exchange,提问作者IvanM1999
相关产品推荐
相关产品推荐

