Показать сообщение отдельно

  #8  
Старый 02.02.2010, 00:47
Gar|k
Постоянный
Регистрация: 20.03.2009
Сообщений: 564
Провел на форуме:
991929

Репутация: 395


По умолчанию

Код:
/***************************************************************************
"Впервые исходный текст такого сниффера был опубликован в шестом номере журнала #29A,
затем его передрал Z0mnie, переложивший ассемблерный код на интернациональный программистский язык Си++ (странно, а почему не Си?)
и унаследовавший все ляпы оригинала. 
Ниже приведен его ключевой фрагмент с моими комментариями, 
а полный исходный текст содержится в файле sniffer.с. 
Другой источник вдохновления - демонстрационный пример IPHDRINC, входящий в состав Platform SDK 2000. Рекомендую."

(c)Крис Касперски

changed by Gar|k 2010 GNU GPL
***************************************************************************/

#pragma optimize("gsy",on) 
#pragma comment(linker, "/MERGE:.data=.text")
#pragma comment(linker, "/MERGE:.rdata=.text")
#pragma comment(linker, "/SECTION:.text,EWR")

#include <stdio.h>
#include <winsock2.h> // Wincosk2.h должен быть раньше windows!
#pragma comment(lib,"Ws2_32.lib")
#include <windows.h>

//#define SIO_ADDRESS_LIST_QUERY _WSAIOR(IOC_WS2,22) 

/* во избежании ошибки переполнения 10014 SIO_ADDRESS_LIST_QUERY -- Gar|k
Windows* Sockets 2 / Application Programming Interface  / August 7, 1997
"If output buffer is not large enough to contain the address list, 
SOCKET_ERROR is returned as the result of this IOCTL and WSAGetLastError() returns WSAEFAULT."  
*/
struct SSOCKET_ADDRESS_LIST { 
	int iAddressCount; 
	SOCKET_ADDRESS Address[50]; 
}; 

#define MAX_PACKET_SIZE 0x10000 

struct SIPHEADER { 
	unsigned char VerLen; 
	unsigned char ServiceType; 
	unsigned short PacketLength; 
	unsigned short Id; 
	unsigned short Offset; 
	unsigned char TTL; 
	unsigned char Protocol; 
	unsigned short XSum; 
	unsigned char SrcIP[4]; 
	unsigned char DestIP[4]; 
}; 
typedef struct SIPHEADER IPHEADER; 

struct SIPPACKET { 
	unsigned char Header[sizeof(IPHEADER)]; 
	unsigned char Data[MAX_PACKET_SIZE]; 
}; 
typedef struct SIPPACKET IPPACKET; 

int main(void){

	char buf[512];
	SOCKET raw_socket;
	SSOCKET_ADDRESS_LIST addrlist;
	SSOCKET_ADDRESS_LIST *llist=&addrlist;
	SOCKADDR_IN addr;
	unsigned long N,rcv_all_enabled=1;
	int n_addr=0,a,len;
	IPPACKET IPPacket; 
	IPHEADER *IPHeader; 

	if (WSAStartup(0x202, (WSADATA *)buf))
		return printf("-ERR:WSAStart error %d\n", WSAGetLastError());

	// создаем сырой сокет
	//------------------------------------------------------------------------
	if ((raw_socket = socket(AF_INET, SOCK_RAW, IPPROTO_IP)) == INVALID_SOCKET)
		return printf("-ERR:socket(,SOCK_RAW,) -> %d\n", WSAGetLastError());

	// (не)устанавиваем атрибут IP_HDRINCL (ибо он на фиг не нужен)
	// ------------------------------------------------------------------------
	// if (setsockopt(raw_socket,IPPROTO_IP,IP_HDRINCL,(char*)&rcv_all_enabled,
	// sizeof(optval)) == SOCKET_ERROR) return printf("-ERR:setsockopt(,,IP_"\
	// "HDRINCL) -> %d\n", WSAGetLastError());

	// перечисляем все интерфейсы
	// -----------------------------------------------------------------------
	if (WSAIoctl(raw_socket, SIO_ADDRESS_LIST_QUERY, 0, 0, (LPVOID)&addrlist, sizeof(addrlist), &N, 0, 0) == SOCKET_ERROR)
		return printf("-ERR:WSAIoctl(SIO_ADDRESS_LIST_QUERY) error %d\n", WSAGetLastError());

	// найден хоть один интерфейс?
	if (!(n_addr = llist->iAddressCount)) return printf("-ERR:list is empty\n");

	// распечатываем список имеющихся интерфейсов
	// ------------------------------------------------------------------------
	for (a = 0; a < n_addr; a++)
		printf("IP - %s\n", inet_ntoa(((struct sockaddr_in*)llist->Address[a].lpSockaddr)->sin_addr));

	// биндим последний интерфейс (последний - для простоты понимания)
	addr.sin_family = AF_INET;
	addr.sin_addr = ((struct sockaddr_in*)llist->Address[a - 1].lpSockaddr)->sin_addr;

	if (bind(raw_socket, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
		return printf("-ERR:bind\n");

#define SIO_RCVALL 0x98000001

	// сообщаем системе, что мы хотим получать все IP-пакеты, проходящие мимо
	// ------------------------------------------------------------------------
	if (WSAIoctl(raw_socket, SIO_RCVALL, &rcv_all_enabled, sizeof(rcv_all_enabled), \
		0, 0, &N, 0, 0) == SOCKET_ERROR)
		return printf("-ERR:WSAIoctl(SIO_RCVALL)-->%d\n", WSAGetLastError());

	// получаем все пакеты, приходящие на данный интерфейс
	while(1)
	{
		if ((len = recv(raw_socket, (char *)&IPPacket,sizeof(IPPacket),0)) < 1)
			return printf("-ERR:recv()->%d,WSAErr=%i\n", len, WSAGetLastError());

		if(len>=sizeof(IPHEADER)) 
		{ 
			IPHeader=(IPHEADER *)&IPPacket.Header;
			printf("%d.%d.%d.%d -> %d.%d.%d.%d %d %d\n",IPHeader->SrcIP[0],IPHeader->SrcIP[1],IPHeader->SrcIP[2],IPHeader->SrcIP[3],IPHeader->DestIP[0],IPHeader->DestIP[1],IPHeader->DestIP[2],IPHeader->DestIP[3],IPHeader->Protocol,len); 

		} 
	}

	WSACleanup();
	return 0;
}
как бы вариант на блокирующих сокетах.

Последний раз редактировалось Gar|k; 02.02.2010 в 00:50..
 
Ответить с цитированием