Доброго времени суток всем. Проблема в следующем: хочу сделать просмотрщик открытых портов (для начала TCP), алгоритм следующий: 1. получаю все хэндлы в системе через NtQuerySystemInformation 2. по каждому хэндлу делаю запрос в драйвер (самопальный), который мне возвращает имя устройства, ассоциированного с объектом данного хэндла 3. Если имя устройства "Тср", то копирую хэндл в свой процесс (с помощью DuplicateHandle), пытаюсь вызвать getsockname для этого хэндла, ВСЕГДА выпадает ошибка 10038 (WSAENOTSOCK - An operation was attempted on something that is not a socket.). Я считаю, что сокет - это обычный хэндл (как это декларируется во всех учебниках и документациях), следовательно и копировать его надо как хэндл (например так http://www.compdoc.ru/prog/cpp/socket_transfer/) Если же вместо попытки выполнить getsockname вызвать волшебную функцию DeviceIoControl, передав ей хэндл, полученный от DuplicateHandle, и магический IOCTL код 0x00210012 (почему магический - потому что не знаю что он обозначает, и в интернете на нашёл описания что это), а также указать адрес буфера для получения информации (TDI_CONNECTION_OUT), то из этого буфера можем извлечь номер открытого локального порта (Это по мотивам "Как стать невидимым в Windows NT" от http://www.RootKit.com) причём номер открытого порта правильный (проверил по нормальному монитору открытых портов). Следовательно хэндл-то валидный!!! Пока думаю, что неправильно отрабатывает DuplicateHandle, что-то она не делает (не так делает) для сокетов. Если кто наступал на подобные грабли напишите плиз. исходный код на С++ прилагаю. Заголовочный файл и файл драйвера если кто заинтересуется выложу. #include "stdafx.h" #include "test.h" #include "Winioctl.h" #include "stdlib.h" #define IOCTL_READ_OBJ_INFO CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct { // в драйвер передаём адрес объекта, которого хотим прощупать PVOID ObjAddr; } RMD_IN; typedef struct { // имя устройства ассоциированного с объектом char Name[256]; } RMD_OUT; int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow){ SYSTEM_HANDLE_INFORMATION_EX *system_handles=0; int len=0; HANDLE ExtProc; HANDLE TestHANDLE=0; UINT i; DWORD CurPID=GetCurrentProcessId(); DWORD ProcMemSize=0x4000; HANDLE CUR_PROC=GetCurrentProcess(); NtQuerySystemInformation=(NQSI)GetProcAddress(LoadLibrary("NTDLL.DLL" ),"NtQuerySystemInformation"); NtDuplicateObject=(NDO)GetProcAddress(LoadLibrary("NTDLL.DLL"),"NtDup licateObject"); /* получение отладочных привилегий */ HANDLE hToken; LUID DebugNameValue; TOKEN_PRIVILEGES Privileges; DWORD dwRet; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken); LookupPrivilegeValue(NULL,"SeDebugPrivilege",&DebugNameValue); Privileges.PrivilegeCount=1; Privileges.Privileges[0].Luid=DebugNameValue; Privileges.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken,FALSE,&Privileges,sizeof(Privileges),NULL,&dwRet); CloseHandle(hToken); /**************************************/ /* запуск драйвера (он Legacy) */ SERVICE_STATUS SS; SC_HANDLE Service; SC_HANDLE scm=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); Service=OpenService( scm, "GetDeviceName", SERVICE_ALL_ACCESS ); StartService(Service,0,NULL); CloseServiceHandle(Service); CloseServiceHandle(scm); HANDLE HDrv=CreateFile("\\\\.\\GetDeviceName",GENERIC_ALL,0,NULL,OPEN_EXISTIN G,NULL,NULL); /********************************/ /* инициализация WinSock */ struct sockaddr SA; WSADATA wsaData; WSAStartup(WINSOCK_VERSION, &wsaData); /*************************/ system_handles=(SYSTEM_HANDLE_INFORMATION_EX*)calloc(1,ProcMemSize); while(NtQuerySystemInformation(16,system_handles,ProcMemSize,&ProcMemSize)!=0) system_handles=(SYSTEM_HANDLE_INFORMATION_EX*)realloc(system_handles,ProcMemSize); ExtProc=INVALID_HANDLE_VALUE; for(i=0;i<system_handles->NumberOfHandles-1;i++){ if(ExtProc!=INVALID_HANDLE_VALUE) CloseHandle(ExtProc); ExtProc=OpenProcess(PROCESS_DUP_HANDLE,0,system_handles->Information .ProcessId); if( (ExtProc!=0)&&(ExtProc!=INVALID_HANDLE_VALUE)&& (system_handles->Information.ProcessId!=CurPID)) { RMD_IN rmd_in; RMD_OUT rmd_out; ULONG LBytesRecvd; rmd_in.ObjAddr=(PVOID)system_handles->Information.Object; DeviceIoControl(HDrv,IOCTL_READ_OBJ_INFO,&rmd_in,sizeof(RMD_IN),&rmd_out,sizeof(RMD_OUT),&LBytesRecvd,NULL); if( (strcmp(rmd_out.Name,"Tcp")==0)){ if(DuplicateHandle(ExtProc,(HANDLE)system_handles->Information. Handle, CUR_PROC,&TestHANDLE,0,0,DUPLICATE_SAME_ACCESS)!=0){ int a=getsockname((SOCKET)TestHANDLE,&SA,&len); a=GetLastError(); if(a!=10038){ // сюда управление НИКОГДА не попадает // и никак не могу его заставить попасть сюда. // Скоро начну биться головой об угол... } } } } } WSACleanup(); /* выгрузка драйвера */ scm=OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS); Service=OpenService( scm, "GetDeviceName", SERVICE_ALL_ACCESS ); ControlService(Service,SERVICE_CONTROL_STOP,&SS); CloseServiceHandle(Service); CloseServiceHandle(scm); /***********************/ /* понижение привилегий */ OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken); LookupPrivilegeValue(NULL,"SeDebugPrivilege",&DebugNameValue); Privileges.PrivilegeCount=1; Privileges.Privileges[0].Luid=DebugNameValue; Privileges.Privileges[0].Attributes=SE_PRIVILEGE_REMOVED; AdjustTokenPrivileges(hToken,FALSE,&Privileges,sizeof(Privileges), NULL,&dwRet); CloseHandle(hToken); /************************/ return 0; }