Код (Text): #define MAX_PACKET_SIZE 65525 #define BIND2IP "10.20.3.119" //Put you'r IP in her #include <stdio.h> #include <winsock2.h> #include <mstcpip.h> #include <ws2tcpip.h> typedef struct iphdr { unsigned char VerIHL; //Version and IP Header Length unsigned char Tos; unsigned short Total_len; unsigned short ID; unsigned short Flags_and_Frags; //Flags 3 bits and Fragment offset 13 bits unsigned char TTL; unsigned char Protocol; unsigned short Checksum; unsigned long SrcIP; unsigned long DstIP; //unsigned long Options_and_Padding; } IpHeader; typedef struct port { unsigned short SrcPort; unsigned short DstPort; } TcpUdpPort; void ProcessPacket(char* Buffer, int Size) { IpHeader *iphdr; TcpUdpPort *port; struct sockaddr_in SockAddr; unsigned short iphdrlen; char C; iphdr = (IpHeader *)Buffer; iphdrlen = (iphdr->VerIHL << 4); memcpy(&C, &iphdrlen, 1); iphdrlen = (C >> 4) * 4; //20 memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = iphdr->SrcIP; printf("Packet From: %s ", inet_ntoa(SockAddr.sin_addr)); memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = iphdr->DstIP; printf("To: %s ", inet_ntoa(SockAddr.sin_addr)); switch (iphdr->Protocol) { case 1: printf("Protocol: ICMP "); break; case 2: printf("Protocol: IGMP "); break; case 6: printf("Protocol: TCP "); if (Size > iphdrlen) { port = (TcpUdpPort *)(Buffer + iphdrlen); printf("From Port: %i To Port: %i ", ntohs(port->SrcPort), ntohs(port->DstPort)); } break; case 17: printf("Protocol: UDP "); if (Size > iphdrlen) { port = (TcpUdpPort *)(Buffer + iphdrlen); printf("From Port: %i To Port: %i ", ntohs(port->SrcPort), ntohs(port->DstPort)); } break; default: printf("Protocol: %i ", iphdr->Protocol); } printf("\n"); } void StartSniffing(SOCKET Sock) { char *RecvBuffer = (char *)malloc(MAX_PACKET_SIZE + 1); int BytesRecv, FromLen; struct sockaddr_in From; if (RecvBuffer == NULL) { printf("malloc() failed.\n"); exit(-1); } FromLen = sizeof(From); do { memset(RecvBuffer, 0, MAX_PACKET_SIZE + 1); memset(&From, 0, sizeof(From)); BytesRecv = recvfrom(Sock, RecvBuffer, MAX_PACKET_SIZE, 0, (sockaddr *)&From, &FromLen); if (BytesRecv > 0) { ProcessPacket(RecvBuffer, BytesRecv); } else { printf( "recvfrom() failed.\n"); } } while (BytesRecv > 0); free(RecvBuffer); } int main() { WSAData wsaData; SOCKET Sock; struct sockaddr_in SockAddr; DWORD BytesReturned; int I = 1; try { if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("WSAStartup() failed.\n"); exit(-1); } Sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP); if (Sock == INVALID_SOCKET) { printf("socket() failed.\n"); exit(-1); } memset(&SockAddr, 0, sizeof(SockAddr)); SockAddr.sin_addr.s_addr = inet_addr(BIND2IP); SockAddr.sin_family = AF_INET; SockAddr.sin_port = 0; if (bind(Sock, (sockaddr *)&SockAddr, sizeof(SockAddr)) == SOCKET_ERROR) { printf("bind(%s) failed.\n", BIND2IP); exit(-1); } if (WSAIoctl(Sock, SIO_RCVALL, &I, sizeof(I), NULL, NULL, &BytesReturned, NULL, NULL) == SOCKET_ERROR) { printf("WSAIoctl() failed.\n"); exit(-1); } StartSniffing(Sock); } catch (...) { printf("CRASH\n"); } closesocket(Sock); WSACleanup(); return 0; } Пробовал вот так, но(!) если ip впн интерфейса отлавливаю только ваходящие, как с этим справиться? PS код не мой, но я прочитал его несколько раз. И почти уверен что это не ошибка в программе а именно какое то ограничение.
если поставить SockAddr.sin_addr.s_addr = INADDR_ANY;//inet_addr(BIND2IP); то WSAIoctl возвращает ошибку, если использовать ioctlsocket то проходят редкие пакеты с протоколом 47.
Одним словом чуть чуть начал разбираться. Встал вопрос выбора на что сделать упор. Мне как я уже говорил нужно просто отслеживание трафика (без его изменения). Как я понял для этого мс рекомендует NDIS Intermediate Driver, какие еще есть варианты? какой пример из ддк лучше изучить? (можно даже так "какому примеру следует придать больше внимания"). И если не сложно то какой пример к какой технологии относиться. Одним словом необходимо снова выбрать куда идти дальше. Желательна аргументация советов, но буду благодарен за все.
http://www.wasm.ru/article.php?article=netfilter ЗЫ гугл рулит .. следующие слова были удалены модератором, во избежании флейма. Предупреждение
Для просто перехвата подойдёт Ndis Protocol Driver, пример DDK-WDK ndisuio или ndisprot, как модифицировать - тут:http://ndis.com.
Нырыл в процессе изучения , но вот что мне не понятно откуда берутся ошибки: Ошибка 1 error C2061: syntax error : identifier 'IPAddr' c:\winddk\7600.16385.0\inc\ddk\pfhook.h 44 и главное что с ними делать. Я бы уже и забил на этот пример, но мне прям интересно стало что за фигня ) И так уже не могу заснуть, пробовал всяко на ошибку глянуть, но пока безуспешно. Код (Text): extern "C" { #include <ntddk.h> #include <pfhook.h> }; void spSniffUnload(IN PDRIVER_OBJECT DriverObject); #ifdef __cplusplus extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); #endif TCHAR drvsmbl[]=TEXT("\\Device\\IPFILTERDRIVER"); NTSTATUS Status=STATUS_SUCCESS; PFILE_OBJECT fileobject=NULL; PDEVICE_OBJECT devobject=NULL; PF_SET_EXTENSION_HOOK_INFO hook_info; IO_STATUS_BLOCK isb; PIRP myirp=NULL; VOID Unload(IN PDRIVER_OBJECT DriverObject); PF_FORWARD_ACTION hook_fn(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN IPAddr RecvLinkNextHop, IN IPAddr SendLinkNextHop}; NTSTATUS Set_Hook(PacketFilterExtensionPtr hook_fn); //=================================================================================== NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { DbgPrint("DriverEntry()\n"); Status=Set_Hook(hook_fn); if(Status!=STATUS_SUCCESS) return Status; DriverObject->DriverUnload=Unload; return Status; } //=================================================================================== VOID Unload(IN PDRIVER_OBJECT DriverObject) { Set_Hook(0); } //=================================================================================== NTSTATUS Set_Hook(PacketFilterExtensionPtr hook_fn) { NTSTATUS status=IoGetDeviceObjectPointer(drvsmbl,STANDART_RIGHTS_ALL, &fileopject,&devobject); if(status!=STATUS_SUCCESS) return status; hook_info.ExtensionPointer=hook_fn; myirp=IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,devobject,&hook_info, sizeof(hook_info),NULL,0,FALSE,NULL,&isb); status=IoCallDriver(devobject,myirp); return status; } //=================================================================================== PF_FORWARD_ACTION hook_fn(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN IPAddr RecvLinkNextHop, IN IPAddr SendLinkNextHop} { return PF_DROP; } //===================================================================================
Может я не о том, но в этом варианте можно снимать с Afd, посредством перехвата NtDeviceIoControlFile из ntdll.dll
Стоп!! WinPCAP работает с NDIS и значит, все чем рулит NDIS доступно и WinPCAP. Ну протокол VPN как уж своими силами разбирать!
Что ты понимаешь под словом "работает". Для расшифровки пакетов нужен ключ. Ключ для исходящих пакетов известен только на сервере. Т.е. ловить нужно выше, до использования ВПН при посылке или после расшифровки на приеме. ВПН и был сделан для того, чтобы сниффер не мог смотреть трафик.
valterg но коментс, ведь мы на текущей машине хотим сниферить. А это значит что как минимум можно перехватить send/recv мы же говорим не про сниферинг в лок сети. И впн не для этого был создан. Для чего у него в названии "виртуальная частная сеть"
ОПА! Так тебе не снифер нужен а ХУК на send/recv. Но ВПН? Незнаю-незнаю, скорей всиво send/recv работают с RAW сокетами, и оправляют\принимают зашыврованые пакеты!!!