OVH Cloud OVH Cloud

Socket RAW sous W98

6 réponses
Avatar
Nicof
Bonjour,

Est-il possible d'utiliser les sockets raw sous Windows 98? Mon projet
consiste a programmer un sniffer reseau. L'initialisation du socket se passe
correctement, mais lorsque je veux passer le socket en mode promiscious, la
fonction WSAIoctl échoue...
Cette opération est-elle réalisable sous 98 ? J'utilise pourtant ws2_32.lib.

Merci,

Nicolas

6 réponses

Avatar
Cyrille \cns\ Szymanski
> Est-il possible d'utiliser les sockets raw sous Windows 98?



Oui. Avec Winsock2 pas de problème. Consulter le site FAQ winsock (wsk
machin) pour plus d'infos.

Mon projet
consiste a programmer un sniffer reseau. L'initialisation du socket se
passe correctement, mais lorsque je veux passer le socket en mode
promiscious, la fonction WSAIoctl échoue...



Au niveau de winsock tu devrais pouvoir faire ça. Sans nous montrer ton
code ni nous donner le message/code d'erreur c'est difficile de répondre.


Tu peux aussi écrire un driver NDIS qui offre plus de souplesse et de
performance.

La bibliothèque winpcap fait tout ça pour toi, inutile de réinventer la
roue.

--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/
Avatar
Thierry
Bonjour,

Cyrille "cns" Szymanski a écrit :

Est-il possible d'utiliser les sockets raw sous Windows 98?



Oui. Avec Winsock2 pas de problème. Consulter le site FAQ winsock (wsk
machin) pour plus d'infos.



En sortie, oui. En reception il me semble que les trames seront filtrées
par les differentes couches gerant les differents protocole et qu'il faut
alors passer par un driver NDIS (c'est ce que font tous les sniffers que
j'ai vu, dont Ethereal).

--
"MOI JE VEUX JOUER DE L'HELICON (PON PON PON PON)"
Avatar
Cyrille \cns\ Szymanski
> En sortie, oui. En reception il me semble que les trames seront
filtrées par les differentes couches gerant les differents protocole
et qu'il faut alors passer par un driver NDIS (c'est ce que font tous
les sniffers que j'ai vu, dont Ethereal).



Pour forger des packets il n'y a effectivement aucun problème.

Mais maintenant que tu le dis, tu me mets le doute. Il me semble que les
sniffers utilisent un driver NDIS parce qu'il est plus performant : plus
rapide, plus souple, et surtout permet de capturer les packets au niveau
Ethernet et non IP comme Winsock est condamné à le faire.

Je ne suis pas certain qu'on ne puisse pas programmer de sniffer en
winsock2.

Je vais rechercher ça et je vous tiens au courant.

--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/
Avatar
Cyrille \cns\ Szymanski
> En sortie, oui. En reception il me semble que les trames seront
filtrées par les differentes couches gerant les differents protocole
et qu'il faut alors passer par un driver NDIS (c'est ce que font tous
les sniffers que j'ai vu, dont Ethereal).



Non, il est effectivement possible d'utiliser des raw sockets winsock2
pour créer un sniffer. Le code suivant que je vous ai concocté affiche
les paires ip expéditeur/destinataire des packets vus par l'interface.

L'inconvénient de cette méthode est effectivement comme je l'ai déjà dit,
que la capture winsock se situe au niveau IP.

Enjoy !



#include <stdio.h>
#include <conio.h>

#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)

#define BUF_LEN 100

#pragma pack(push,1)

typedef struct iphdr {
unsigned char verlen; /* version du protocol IP + la longeur de
l'en tète */
unsigned char tos; /* type de service */
unsigned short tot_len; /* longueur totale du datagramme */
unsigned short id; /* identification */
unsigned short offset; /* décalage */
unsigned char ttl; /* durée de vie du paquet */
unsigned char protocol; /* protocole */
unsigned short checksum; /* somme de contrôle */
unsigned int saddr; /* adresse IP source */
unsigned int daddr; /* adresse IP destinataire */
} IP_HDR;

typedef struct tcphdr
{
unsigned short sport; /* port source */
unsigned short dport; /* port de destination */
unsigned int seqnum; /* numéro de séquence */
unsigned int acknum; /* accusé de réception */
unsigned char dataoffset; /* décalage des données (data offset) */
unsigned char flags; /* flags */
unsigned short windows; /* fenêtre */
unsigned short checksum; /* checksum */
unsigned short urgpointer; /* pointeur de données urgentes */
} TCP_HDR;

typedef struct icmphdr
{
unsigned char type; /* type ICMP */
unsigned char code; /* code ICMP */
unsigned short checksum; /* checksum */
unsigned short id; /* id, utilisé lors de la reconnaissance
entre programmes des paquets ICMP */
unsigned short sequence; /* séquence */
unsigned long timestamp; /* timestamp */
} ICMP_HDR;

#pragma pack(pop)


int main()
{
int err;


// init winsock
WSADATA wsaData;
err = WSAStartup( MAKEWORD(2,2), &wsaData );
if( err!=0 ) {
fprintf( stderr, "WSAStartup() error %dn", err );
goto cleanup;
}


// get host name
char host_name[BUF_LEN];
err = gethostname( host_name, BUF_LEN );
if( err!=0 ) {
fprintf( stderr, "gethostname() error %dn", WSAGetLastError() );
goto cleanup;
}
printf( "host_name: %sn", host_name );


// get host info
struct hostent *he;
he = gethostbyname( host_name );
if( he==0 ) {
fprintf( stderr, "gethostbyname() error %dn", WSAGetLastError()
);
goto cleanup;
}


// save local address
struct sockaddr_in sin;
sin.sin_addr = *((LPIN_ADDR)*he->h_addr_list);
printf( "sin_addr: %sn", inet_ntoa( sin.sin_addr ) );


// create raw socket
// must be AF_INET, SOCK_RAW, IPPROTO_IP, bound to explicit interface
SOCKET s;
s = socket( AF_INET, SOCK_RAW, IPPROTO_IP );


// bind
struct sockaddr_in sa;
memset( &sa, 0, sizeof(sa) );
//sa.sin_addr = inet_addr("");
sa.sin_addr = sin.sin_addr; // ip to sniff
sa.sin_family = AF_INET;
sa.sin_port = 0;

err = bind( s, (PSOCKADDR)&sa, sizeof(sa));
if( err!=0 )
{
fprintf( stderr, "bind() error %dn", WSAGetLastError() );
goto cleanup;
}


// put in promiscuous mode
DWORD dwBytesReturned;
DWORD InBuffer;
DWORD OutBuffer;
InBuffer=1;
dwBytesReturned = 0;
err = WSAIoctl( s, SIO_RCVALL, &InBuffer, sizeof(InBuffer),
&OutBuffer, sizeof(OutBuffer), &dwBytesReturned, NULL, NULL);
if( err==SOCKET_ERROR )
{
fprintf( stderr, "WSAIoctl() error %dn", WSAGetLastError() );
goto cleanup;
}


// capture packets
// 8192 bytes should be ok !
char packet[8192];
while( !kbhit() )
{
int rcv;
struct sockaddr_in sa_from;
int sa_from_len = sizeof( sa_from );
IP_HDR *iph;
struct in_addr addr;

rcv = recvfrom( s, packet, 8192, 0, (PSOCKADDR)&sa_from,
&sa_from_len );
if( rcv==0 || rcv==SOCKET_ERROR )
{
fprintf( stderr, "recvfrom() error %dn", WSAGetLastError()
);
continue;
}

iph = (IP_HDR*)packet;
addr.S_un.S_addr = iph->saddr;
printf("%16s", inet_ntoa( addr ) );
addr.S_un.S_addr = iph->daddr;
printf(" -> %16sn", inet_ntoa( addr ) );
}

cleanup:

WSACleanup();

return 0;
}

--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/
Avatar
Thierry
Bonjour,

Cyrille "cns" Szymanski a écrit :

Enjoy !



Sympa (note a benets : faut être admin pour SOCK_RAW).

--
"MOI JE VEUX JOUER DE L'HELICON (PON PON PON PON)"
Avatar
Cyrille \cns\ Szymanski
> Bonjour,

Cyrille "cns" Szymanski a écrit :

Enjoy !



Sympa (note a benets : faut être admin pour SOCK_RAW).




Et avoir windows2000 ou plus. Encore une raison qui justifie l'utilisation
de drivers NDIS.

MSDN :
Setting this ioctl requires Administrator privilege on the local computer.
SIO_RCVALL is available in Windows 2000 and later versions of Windows.

--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/