Aujourd'hui j'essaye de sniffer les données qui transitent sur mon PC. Pour cela j'ai réadapté un code trouvé ici: http://www.purebasic.fr/english/viewtop ... it=sniffer . Mais voilà, problème il y a ...
Il se trouve que pour sniffer de simples pages web, il n'y a aucun problème. Le problème survient quand il y a un gros débit de données à sniffer (comme pour une musique ou une video). En effet, le traitement des données prend beaucoup trop de temps et je perds des paquets en cours de route. Pour palier a ce problème, j'ai conçu 2 threads: l'un s'occupant seulement de récupérer les données et de les mettre dans une file et le deuxième qui se charge de traiter les données de la file lorsqu'il y en a. Cette technique a plutot bien marché puisque je perds moins de données mais ... j'ai toujours des pertes ... Et je ne sais pas comment régler cela.
Je vous laisse un code. Pour le tester, il faut compiler avec les droits d'administrateur, se rendre sur le site de grooveshark (http://grooveshark.com) et charger un titre. Normalement le programme est censé enregistrer le titre (avec pour nom gdxxxxx) dans le dossier de l’exécutable. Le problème, c'est qu'il manque certaines données (ca s'entend d'ailleurs ...)
Code : Tout sélectionner
#BufferSize = 4096
#WSA_VER = $202
#SIO_RCVALL=$98000001
Structure IpHeader
IhlVersion.b
typeOfService.b
totalLength.w
ID.w
flagOffset.b
fragOffset.b
timeToLive.b
protocol.b
checksum.w
source.l
destination.l
EndStructure
Structure TcpHeader
portSource.w
portDestination.w
seqNum.l
ackNum.l
dataOffset.b
flags.a
window.w
checksum.w
urgentPointer.w
EndStructure
Structure PortToFile
file.i
port.l
received.i
EndStructure
Structure Memory
buffer.i
size.l
EndStructure
Structure ProcessData
List dataQueue.Memory()
mutex.i
semaphore.i
EndStructure
Procedure sniff(*processFunction)
Protected ip.i, wsaData.WSADATA, sock.i, sin.SOCKADDR_IN, promiscuous_mode.l, size.l, mutex.i, semaphore.i, processData.ProcessData
promiscuous_mode = 1
;ip du client
ExamineIPAddresses()
ip = NextIPAddress()
If WSAStartup_(#WSA_VER, @wsaData) And *processFunction
WSACleanup_()
ProcedureReturn 0
EndIf
;creation du socket
sock = SOCKET_(#AF_INET, #SOCK_RAW, #IPPROTO_IP)
If sock = #INVALID_SOCKET
WSACleanup_()
ProcedureReturn 0
EndIf
sin\sin_family = #AF_INET
sin\sin_addr = ip
;mode sniffing
If bind_(sock, @sin, SizeOf(SOCKADDR_IN))
WSACleanup_()
ProcedureReturn 0
EndIf
If ioctlsocket_(sock, #SIO_RCVALL, @promiscuous_mode)
WSACleanup_()
ProcedureReturn 0
EndIf
mutex = CreateMutex()
semaphore = CreateSemaphore()
processData\mutex = mutex
processData\semaphore = semaphore
CreateThread(*processFunction, @processData)
*buffer = AllocateMemory(#BufferSize) ;allocation de la memoire de reception
Repeat
size = recv_(sock, *buffer, #BufferSize, 0)
If size > 40 ;en-tete TCP/IP complet
;Ajout des données à la file
LockMutex(mutex)
LastElement(processData\dataQueue())
AddElement(processData\dataQueue())
processData\dataQueue()\buffer = *buffer
processData\dataQueue()\size = size
UnlockMutex(mutex)
SignalSemaphore(semaphore) ;on envoi un signal à l'autre thread pour qu'il traite les données
*buffer = AllocateMemory(#BufferSize) ;on alloue une nouvelle zone de mémoire (l'ancienne étant dans la file, il ne faut pas la remplacer)
EndIf
ForEver
FreeMutex(mutex)
FreeSemaphore(semaphore)
EndProcedure
Procedure processData(*processData.ProcessData)
Protected save.i, httpHeader.s, file.i, *buffer, *datas, size.l, dataSize.i, ipData.IpHeader, tcpData.TcpHeader
Static i.i, j
Static NewList files.PortToFile() ;liste contenant la liste associant les ports à ecouter et les fichiers de sauvegarde
Repeat
WaitSemaphore(*processData\semaphore) ;attente d'un traitement
;récupération des infos de la file (threadsafe)
LockMutex(*processData\mutex)
FirstElement(*processData\dataQueue())
*buffer = *processData\dataQueue()\buffer
size = *processData\dataQueue()\size
DeleteElement(*processData\dataQueue())
UnlockMutex(*processData\mutex)
;séparation des données
CopyMemory(*buffer, @ipData, SizeOf(IpHeader))
CopyMemory(*buffer+SizeOf(IpHeader), @tcpData, SizeOf(TcpHeader))
dataSize = size - SizeOf(IpHeader) - SizeOf(TcpHeader)
*datas = AllocateMemory(dataSize)
CopyMemory(*buffer+SizeOf(IpHeader)+SizeOf(TcpHeader), *datas, dataSize)
FreeMemory(*buffer) ;on libere la memoire allouée par le processus de sniff
;on regarde si le paquet doit etre enregistré ou non
save = 0
ForEach files()
If files()\port = tcpData\portSource Or files()\port = tcpData\portDestination
save = @files()
Break
EndIf
Next
;ce paquet nous interesse
If save
ChangeCurrentElement(files(), save)
If files()\port = tcpData\portDestination ;paquet en reception: il doit etre enregistré
test + 1
WriteData(files()\file, *datas, dataSize)
EndIf
If tcpData\flags & 1 ;signal FIN
CloseFile(files()\file)
DeleteElement(files())
Debug "Fin du download"
EndIf
Else ;le paquet n'est pas dans la liste
httpHeader = PeekS(*datas, dataSize)
;Ce paquet provient de grooveshark
If Left(httpHeader, Len("POST /stream.php HTTP/1.1")) = "POST /stream.php HTTP/1.1" And FindString(httpHeader, "grooveshark.com", 1)
file = CreateFile(#PB_Any, "gd"+Str(ElapsedMilliseconds()))
If file
Debug "Ajout d'un fichier"
AddElement(files()) ;ajout du port à écouter
files()\file = file
files()\port = tcpData\portSource
EndIf
EndIf
EndIf
FreeMemory(*datas) ;liberation de la memoire allouée pour stocker les données
ForEver
EndProcedure
InitNetwork()
thread = CreateThread(@sniff(), @processData())
Debug ThreadPriority(thread, 31)
OpenConsole()
Repeat
Input()
ForEver
