Проблема с DuplicateHandle

Тема в разделе "WASM.WIN32", создана пользователем Koshak, 21 фев 2006.

  1. Koshak

    Koshak New Member

    Публикаций:
    0
    Регистрация:
    21 фев 2006
    Сообщения:
    31
    Адрес:
    Russia
    Доброго времени суток всем.

    Проблема в следующем:

    хочу сделать просмотрщик открытых портов (для начала 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;

    }