Skip to content

Commit 162fafc

Browse files
Merge 0e22033 into 645ee73
2 parents 645ee73 + 0e22033 commit 162fafc

1 file changed

Lines changed: 319 additions & 1 deletion

File tree

main.cpp

Lines changed: 319 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,104 @@ typedef NTSTATUS (NTAPI *pNtQueryInformationProcess)(HANDLE, UINT, PVOID, ULONG,
7272
typedef NTSTATUS (NTAPI *pNtWow64ReadVirtualMemory64)(HANDLE, ULONG64, PVOID, ULONG64, PULONG64);
7373
typedef NTSTATUS (NTAPI *pNtWow64QueryInformationProcess64)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
7474

75+
#ifndef NT_SUCCESS
76+
#define NT_SUCCESS(x) ((x) >= 0)
77+
#endif
78+
79+
#ifndef STATUS_INFO_LENGTH_MISMATCH
80+
#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
81+
#endif
82+
83+
#ifndef SystemHandleInformation
84+
#define SystemHandleInformation 16
85+
#endif
86+
87+
#ifndef ObjectBasicInformation
88+
#define ObjectBasicInformation 0
89+
#endif
90+
91+
#ifndef ObjectNameInformation
92+
#define ObjectNameInformation 1
93+
#endif
94+
95+
#ifndef ObjectTypeInformation
96+
#define ObjectTypeInformation 2
97+
#endif
98+
99+
typedef struct _SYSTEM_HANDLE {
100+
ULONG ProcessId;
101+
BYTE ObjectTypeNumber;
102+
BYTE Flags;
103+
USHORT Handle;
104+
PVOID Object;
105+
ACCESS_MASK GrantedAccess;
106+
} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
107+
108+
typedef struct _SYSTEM_HANDLE_INFORMATION {
109+
ULONG HandleCount;
110+
SYSTEM_HANDLE Handles[1];
111+
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
112+
113+
typedef enum _POOL_TYPE {
114+
NonPagedPool,
115+
PagedPool,
116+
NonPagedPoolMustSucceed,
117+
DontUseThisType,
118+
NonPagedPoolCacheAligned,
119+
PagedPoolCacheAligned,
120+
NonPagedPoolCacheAlignedMustS
121+
} POOL_TYPE, *PPOOL_TYPE;
122+
123+
typedef struct _OBJECT_TYPE_INFORMATION {
124+
UNICODE_STRING Name;
125+
ULONG TotalNumberOfObjects;
126+
ULONG TotalNumberOfHandles;
127+
ULONG TotalPagedPoolUsage;
128+
ULONG TotalNonPagedPoolUsage;
129+
ULONG TotalNamePoolUsage;
130+
ULONG TotalHandleTableUsage;
131+
ULONG HighWaterNumberOfObjects;
132+
ULONG HighWaterNumberOfHandles;
133+
ULONG HighWaterPagedPoolUsage;
134+
ULONG HighWaterNonPagedPoolUsage;
135+
ULONG HighWaterNamePoolUsage;
136+
ULONG HighWaterHandleTableUsage;
137+
ULONG InvalidAttributes;
138+
GENERIC_MAPPING GenericMapping;
139+
ULONG ValidAccess;
140+
BOOLEAN SecurityRequired;
141+
BOOLEAN MaintainHandleCount;
142+
USHORT MaintainTypeList;
143+
POOL_TYPE PoolType;
144+
ULONG PagedPoolUsage;
145+
ULONG NonPagedPoolUsage;
146+
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
147+
148+
typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
149+
SYSTEM_INFORMATION_CLASS SystemInformationClass,
150+
PVOID SystemInformation,
151+
ULONG SystemInformationLength,
152+
PULONG ReturnLength
153+
);
154+
155+
typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
156+
HANDLE SourceProcessHandle,
157+
HANDLE SourceHandle,
158+
HANDLE TargetProcessHandle,
159+
PHANDLE TargetHandle,
160+
ACCESS_MASK DesiredAccess,
161+
ULONG Attributes,
162+
ULONG Options
163+
);
164+
165+
typedef NTSTATUS (NTAPI *_NtQueryObject)(
166+
HANDLE ObjectHandle,
167+
OBJECT_INFORMATION_CLASS ObjectInformationClass,
168+
PVOID ObjectInformation,
169+
ULONG ObjectInformationLength,
170+
PULONG ReturnLength
171+
);
172+
75173
/*
76174
77175
This is a Windows version of the tool witr, which is a utility for finding details about specific processes.
@@ -1489,6 +1587,225 @@ return WideToString(stringBuffer);
14891587
}
14901588
#endif
14911589
}
1590+
PVOID GetLibraryProcAddress(const char* LibraryName, const char* ProcName) {
1591+
HMODULE hMod = GetModuleHandleA(LibraryName);
1592+
if (!hMod) {
1593+
hMod = LoadLibraryA(LibraryName);
1594+
if (!hMod) return nullptr;
1595+
}
1596+
return (PVOID)GetProcAddress(hMod, ProcName);
1597+
}
1598+
1599+
_NtQuerySystemInformation pfnNtQuerySystemInformation =
1600+
(_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
1601+
_NtDuplicateObject pfnNtDuplicateObject =
1602+
(_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
1603+
_NtQueryObject pfnNtQueryObject =
1604+
(_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
1605+
1606+
1607+
1608+
void ListProcHandles(HANDLE hproc, DWORD pid) {
1609+
// this is so that we can get the handles of a process
1610+
// the cool thing is, that the original witr doesn't actually display
1611+
// handles because either the AI that vibe coded didn't know how to get
1612+
// or perhaps it just isn't even possible using Go
1613+
// so C++ for the win
1614+
// for the win-DOWS!! Haha get it
1615+
1616+
// if you're wondering why this code looks like C... that's because...
1617+
// because it is. i just stole it from this random old obscure forum by a guy
1618+
// who did the same thing i needed in 2013
1619+
1620+
// https://cplusplus.com/forum/windows/95774/
1621+
// one thing i've learned while coding this is that when you want to do
1622+
// some weird obscure thing that you're sure nobody has done before, the most likely thing
1623+
// is that the same weird obscure thing has been done before, but it's just really obscure
1624+
1625+
_NtQuerySystemInformation pfnNtQuerySystemInformation =
1626+
(_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
1627+
_NtDuplicateObject pfnNtDuplicateObject =
1628+
(_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
1629+
_NtQueryObject pfnNtQueryObject =
1630+
(_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
1631+
NTSTATUS status;
1632+
PSYSTEM_HANDLE_INFORMATION handleInfo;
1633+
ULONG handleInfoSize = 0x10000;
1634+
ULONG i;
1635+
1636+
1637+
1638+
1639+
1640+
1641+
1642+
handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
1643+
1644+
/* NtQuerySystemInformation won't give us the correct buffer size,
1645+
so we guess by doubling the buffer size. */
1646+
while ((status = pfnNtQuerySystemInformation(
1647+
(SYSTEM_INFORMATION_CLASS)SystemHandleInformation,
1648+
handleInfo,
1649+
handleInfoSize,
1650+
NULL
1651+
)) == STATUS_INFO_LENGTH_MISMATCH)
1652+
handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
1653+
1654+
/* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
1655+
if (!NT_SUCCESS(status))
1656+
{
1657+
printf("NtQuerySystemInformation failed!\n");
1658+
return;
1659+
}
1660+
1661+
for (i = 0; i < handleInfo->HandleCount; i++)
1662+
{
1663+
SYSTEM_HANDLE handle = handleInfo->Handles[i];
1664+
HANDLE dupHandle = NULL;
1665+
POBJECT_TYPE_INFORMATION objectTypeInfo;
1666+
PVOID objectNameInfo;
1667+
UNICODE_STRING objectName;
1668+
ULONG returnLength;
1669+
1670+
/* Check if this handle belongs to the PID the user specified. */
1671+
if (handle.ProcessId != pid)
1672+
continue;
1673+
1674+
/* Duplicate the handle so we can query it. */
1675+
if (!NT_SUCCESS(pfnNtDuplicateObject(
1676+
hproc,
1677+
(HANDLE)(ULONG_PTR)handle.Handle,
1678+
GetCurrentProcess(),
1679+
&dupHandle,
1680+
0,
1681+
0,
1682+
DUPLICATE_SAME_ACCESS
1683+
)))
1684+
{
1685+
printf("[%#x] Error!\n", handle.Handle);
1686+
continue;
1687+
}
1688+
1689+
/* Query the object type. */
1690+
objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
1691+
if (!NT_SUCCESS(pfnNtQueryObject(
1692+
dupHandle,
1693+
(OBJECT_INFORMATION_CLASS)ObjectTypeInformation,
1694+
objectTypeInfo,
1695+
0x1000,
1696+
NULL
1697+
)))
1698+
{
1699+
printf("[%#x] Error!\n", handle.Handle);
1700+
CloseHandle(dupHandle);
1701+
continue;
1702+
}
1703+
/* Query the object type first */
1704+
objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
1705+
if (!NT_SUCCESS(pfnNtQueryObject(dupHandle, (OBJECT_INFORMATION_CLASS)ObjectTypeInformation, objectTypeInfo, 0x1000, NULL))) {
1706+
printf("[%#x] Error!\n", handle.Handle);
1707+
CloseHandle(dupHandle);
1708+
continue;
1709+
}
1710+
1711+
/* Check if this type is known to hang on name queries */
1712+
WCHAR typeName[64];
1713+
wcsncpy_s(typeName, 64, objectTypeInfo->Name.Buffer, objectTypeInfo->Name.Length / 2);
1714+
typeName[objectTypeInfo->Name.Length / 2] = L'\0';
1715+
1716+
if (wcscmp(typeName, L"File") == 0 || wcscmp(typeName, L"ALPC Port") == 0) {
1717+
printf("[%#x] %.*S: (name query skipped)\n", handle.Handle,
1718+
objectTypeInfo->Name.Length / 2, objectTypeInfo->Name.Buffer);
1719+
free(objectTypeInfo);
1720+
CloseHandle(dupHandle);
1721+
continue;
1722+
}
1723+
/* Query the object name (unless it has an access of
1724+
0x0012019f, on which NtQueryObject could hang. */
1725+
if (handle.GrantedAccess == 0x0012019f)
1726+
{
1727+
/* We have the type, so display that. */
1728+
printf(
1729+
"[%#x] %.*S: (did not get name)\n",
1730+
handle.Handle,
1731+
objectTypeInfo->Name.Length / 2,
1732+
objectTypeInfo->Name.Buffer
1733+
);
1734+
free(objectTypeInfo);
1735+
CloseHandle(dupHandle);
1736+
continue;
1737+
}
1738+
1739+
1740+
objectNameInfo = malloc(0x1000);
1741+
if (!NT_SUCCESS(pfnNtQueryObject(
1742+
dupHandle,
1743+
(OBJECT_INFORMATION_CLASS)ObjectNameInformation,
1744+
objectNameInfo,
1745+
0x1000,
1746+
&returnLength
1747+
)))
1748+
{
1749+
/* Reallocate the buffer and try again. */
1750+
objectNameInfo = realloc(objectNameInfo, returnLength);
1751+
if (!NT_SUCCESS(pfnNtQueryObject(
1752+
dupHandle,
1753+
(OBJECT_INFORMATION_CLASS)ObjectNameInformation,
1754+
objectNameInfo,
1755+
returnLength,
1756+
NULL
1757+
)))
1758+
{
1759+
/* We have the type name, so just display that. */
1760+
printf(
1761+
"[%#x] %.*S: (could not get name)\n",
1762+
handle.Handle,
1763+
objectTypeInfo->Name.Length / 2,
1764+
objectTypeInfo->Name.Buffer
1765+
);
1766+
free(objectTypeInfo);
1767+
free(objectNameInfo);
1768+
CloseHandle(dupHandle);
1769+
continue;
1770+
}
1771+
}
1772+
1773+
/* Cast our buffer into an UNICODE_STRING. */
1774+
objectName = *(PUNICODE_STRING)objectNameInfo;
1775+
1776+
/* Print the information! */
1777+
if (objectName.Length)
1778+
{
1779+
/* The object has a name. */
1780+
printf(
1781+
"[%#x] %.*S: %.*S\n",
1782+
handle.Handle,
1783+
objectTypeInfo->Name.Length / 2,
1784+
objectTypeInfo->Name.Buffer,
1785+
objectName.Length / 2,
1786+
objectName.Buffer
1787+
);
1788+
}
1789+
else
1790+
{
1791+
/* Print something else. */
1792+
printf(
1793+
"[%#x] %.*S: (unnamed)\n",
1794+
handle.Handle,
1795+
objectTypeInfo->Name.Length / 2,
1796+
objectTypeInfo->Name.Buffer
1797+
);
1798+
}
1799+
1800+
free(objectTypeInfo);
1801+
free(objectNameInfo);
1802+
CloseHandle(dupHandle);
1803+
}
1804+
1805+
free(handleInfo);
1806+
1807+
}
1808+
14921809

14931810
void PrintAncestry(DWORD pid) {
14941811
// now we're geting the name
@@ -1747,7 +2064,7 @@ void PIDinspect(DWORD pid) { // ooh guys look i'm in the void
17472064

17482065

17492066

1750-
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
2067+
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_DUP_HANDLE, FALSE, pid);
17512068
// The above little handle opener is currently a somwehat "agressive" flag, since it
17522069
// Requests read access directly to the process' actual memory. This can get us rejected if called
17532070
// on a very high privilege process, such as lsass.exe This means that we can't read the memory
@@ -1927,6 +2244,7 @@ std::string FRAM = ""; // fram means formatted ram, i'm so creative at var namin
19272244
PrintAncestry(pid);
19282245

19292246
FindProcessPorts(pid);
2247+
ListProcHandles(hProcess, pid);
19302248

19312249

19322250

0 commit comments

Comments
 (0)