Могу предложить два способа.
1)Можно так сделать.
Сначала скачать с сайта книгу "Windows NT/2000 Native API" и использовать ее как справочник.
Потом при помощи ф-ции ZwQuerySystemInformation получить SystemHandleInformation, далее пройтись по всем полученным handle отобразить их в свой процесс и исследовать(не забывай их закрывать, а то таблица описателей разрастется, а также заблокируеш на время работы своего процесса возможность уничтожения объектов). Вот пример получения информации об открытых описателях для конкретного процесса, переделать его для получения инфы обо всех процессах не проблема(надо вместо проверки равенства pid открывать процесс с этим pid). Вот код из книги
#include "ntdll.h"
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
if (argc == 1) return 0;
ULONG pid = strtoul(argv[1], 0, 0);
EnablePrivilege(SE_DEBUG_NAME);
HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
ULONG n = 0x1000;
PULONG p = new ULONG[n];
while (NT::ZwQuerySystemInformation(NT::SystemHandleInformation,
p, n * sizeof *p, 0)
== STATUS_INFO_LENGTH_MISMATCH)
delete [] p, p = new ULONG[n *= 2];
NT::PSYSTEM_HANDLE_INFORMATION h = NT::PSYSTEM_HANDLE_INFORMATION(p + 1);
for (ULONG i = 0; i < *p; i++) {
if (h[i].ProcessId == pid) {
HANDLE hObject;
if (NT::ZwDuplicateObject(hProcess, HANDLE(h[i].Handle),
NtCurrentProcess(), &hObject,
0, 0, DUPLICATE_SAME_ATTRIBUTES)
!= STATUS_SUCCESS)
continue;
NT::OBJECT_BASIC_INFORMATION obi;
NT::ZwQueryObject(hObject, NT::ObjectBasicInformation,
&obi, sizeof obi, &n);
printf("%p %04hx %6lx %2x %3lx %3ld %4ld ",
h[i].Object, h[i].Handle, h[i].GrantedAccess,
int(h[i].Flags), obi.Attributes,
obi.HandleCount - 1, obi.PointerCount - 2);
n = obi.TypeInformationLength + 2;
NT::POBJECT_TYPE_INFORMATION oti
= NT::POBJECT_TYPE_INFORMATION(new CHAR[n]);
NT::ZwQueryObject(hObject, NT::ObjectTypeInformation,
oti, n, &n);
printf("%-14.*ws ", oti[0].Name.Length / 2, oti[0].Name.Buffer);
n = obi.NameInformationLength == 0
? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength;
NT::POBJECT_NAME_INFORMATION oni
= NT::POBJECT_NAME_INFORMATION(new CHAR[n]);
NTSTATUS rv = NT::ZwQueryObject(hObject,
NT::ObjectNameInformation,
oni, n, &n);
if (NT_SUCCESS(rv))
printf("%.*ws", oni[0].Name.Length / 2, oni[0].Name.Buffer);
printf("\n");
CloseHandle(hObject);
}
}
delete [] p;
CloseHandle(hProcess);
return 0;
}
Заметь- тебе нужна привилегия отладки.
Привожу код с сайта проекта HE4(
http://he4dev.e1.bmstu.ru). Там получают список процессов, но сначала получают привилегию отладки(код для получения списка процессов оставлю, может пригодится). Код для ф-ции NtGetProcessList смотри на сайте проекта.
#define STRICT
#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include "NtProcessList.h"
BOOL EnableDebugPriv(VOID);
void Win32ErrorMessage(void);
void main(int nCountArg, char *lpszArg[], char *lpszEnv[])
{
NTSTATUS NtStatus;
PROCESS_INFO ProcInfo[1024];
PPROCESS_INFO lpProcInfo;
ULONG LehgthReturned = 0;
ULONG i;
NtStatus = NtGetProcessList(ProcInfo, sizeof(ProcInfo), &LehgthReturned);
if(NtStatus == STATUS_SUCCESS)
{
lpProcInfo = ProcInfo;
EnableDebugPriv();
while(1)
{
printf("\n------------------------------------------------------\n");
printf("| ID| Name| Threads| Parent| Offset|Priority\n");
printf("------------------------------------------------------\n");
wprintf(L"%4lX|%13s|%8ld|%7lX|%7ld",
lpProcInfo->dwProcessID,
//(lpProcInfo->pszProcessName == 0 ? L"(System Idle)" : lpProcInfo->pszProcessName),
lpProcInfo->ProcessName.Buffer,
lpProcInfo->dwThreadCount,
lpProcInfo->dwParentProcessID,
lpProcInfo->dwOffset);
printf("|%4ld\n", lpProcInfo->dwBasePriority);
printf(" -------------- Threads -----------------------\n");
printf("\t| ID|Owner|State|Priority|Base Priority\n");
for(i=0; i<lpProcInfo->dwThreadCount; i++)
{
printf("\t|%4lX|%5lX|%5lX|%8X|%8X\n",
lpProcInfo->ti[i].dwThreadID,
lpProcInfo->ti[i].dwOwningPID,
lpProcInfo->ti[i].dwThreadState,
lpProcInfo->ti[i].dwCurrentPriority,
lpProcInfo->ti[i].dwBasePriority);
}
PPROCESS_DEBUG_INFORMATION lpBuf = NtRtlCreateQueryDebugBuffer();
if(lpBuf)
{
DWORD dwRes = NtRtlQueryProcessDebugInformation(lpBuf, lpProcInfo->dwProcessID);
if(!dwRes)
{
printf("\n------------------------------------------------------\n");
printf("| Modules \n");
printf("------------------------------------------------------\n");
for(i=0; i<lpBuf->lpModules->dwModuleCount; i++)
{
printf(" %s\n", lpBuf->lpModules->ModuleInfo[i].lpszModuleFileName);
}
}
dwRes = NtRtlDestroyQueryDebugBuffer(lpBuf);
}
if(lpProcInfo->dwOffset == 0) break;
lpProcInfo = (PPROCESS_INFO)((CHAR*)lpProcInfo + lpProcInfo->dwOffset);
}
}
else
printf("\nError NtQuerySystemInformation !!!");
}
BOOL EnableDebugPriv(VOID)
{
HANDLE hToken;
LUID DebugValue;
TOKEN_PRIVILEGES tkp;
//
// Retrieve a handle of the access token
//
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken)) {
Win32ErrorMessage();
printf(" OpenProcessToken failed");
return FALSE;
}
//
// Enable the SE_DEBUG_NAME privilege
//
if (!LookupPrivilegeValue((LPSTR) NULL,
SE_DEBUG_NAME,
&DebugValue)) {
Win32ErrorMessage();
printf(" LookupPrivilegeValue failed");
return FALSE;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = DebugValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,
FALSE,
&tkp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
//
// The return value of AdjustTokenPrivileges can't be tested
//
if (GetLastError() != ERROR_SUCCESS) {
Win32ErrorMessage();
printf(" AdjustTokenPrivileges failed");
return FALSE;
}
return TRUE;
"
void Win32ErrorMessage(void)
{
LPTSTR MsgBuf;
char lpMultiByteStr[1024];
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &MsgBuf,
0,
NULL
);
CharToOem(MsgBuf, lpMultiByteStr);
printf("%s", lpMultiByteStr);
LocalFree(MsgBuf);
}
///////////////////////////////////////////////////////////////////////
2) Теперь втрой вариант. Более трудный, но более быстрый.
Надо написать свой драйвер, получить через handle указатель на объект(ObReferenceObjectByHandle), далее получить указатель на заголовок объекта(по смещению - 0x18 ниже адреса объекта)
typedef struct _OBJECT_HEADER
{
/*000*/ DWORD PointerCount; // number of references
/*004*/ DWORD HandleCount; // number of open handles
/*008*/ POBJECT_TYPE ObjectType;
/*00C*/ BYTE NameOffset; // -> OBJECT_NAME
/*00D*/ BYTE HandleDBOffset; // -> OBJECT_HANDLE_DB
/*00E*/ BYTE QuotaChargesOffset; // -> OBJECT_QUOTA_CHARGES
/*00F*/ BYTE ObjectFlags; // OB_FLAG_*
/*010*/ union
{ // OB_FLAG_CREATE_INFO ? ObjectCreateInfo : QuotaBlock
/*010*/ PQUOTA_BLOCK QuotaBlock;
/*010*/ POBJECT_CREATE_INFO ObjectCreateInfo;
/*014*/ };
/*014*/ PSECURITY_DESCRIPTOR SecurityDescriptor;
/*018*/ }
OBJECT_HEADER,
* POBJECT_HEADER,
**PPOBJECT_HEADER;
далее по смещению HandleDBOffset от указателя на объект(по моему от него все отчитывают, но это легко проверить или самому или у Шрайбера почитать ) в сторону уменьшения адресов получить указатель на
typedef struct _OBJECT_HANDLE_DB
{
/*000*/ union
{
/*000*/ struct _EPROCESS *Process;
/*000*/ struct _OBJECT_HANDLE_DB_LIST *HandleDBList;
/*004*/ };
/*004*/ DWORD HandleCount;
/*008*/ }
OBJECT_HANDLE_DB,
* POBJECT_HANDLE_DB,
**PPOBJECT_HANDLE_DB;
в этой структуре если счетчик 1 то в объединение указаетль на процесс владелец, если больше единицы- указатель на
typedef struct _OBJECT_HANDLE_DB_LIST
{
/*000*/ DWORD Count;
/*004*/ OBJECT_HANDLE_DB Entries [];
/*
*/ }
OBJECT_HANDLE_DB_LIST,
* POBJECT_HANDLE_DB_LIST,
**PPOBJECT_HANDLE_DB_LIST;
которая содержит массив структур OBJECT_HANDLE_DB с указателями на процессы(вроде так). Утиочнить все это можно в книге C.Шрайбер "Недокументированные возможности Windows 2000"(до сих пор в продаже есть). У меня ее под рукой сейчас нет, могу завтра посмотреть.