Nutzdaten von einem TCP/IP Paket?
-
hi, und zwar arbeite ich mich gerade in die pcap lib ein. Soweit funktioniert auch alles wunderbar. NUr hab ich gerade noch ein paar verständnisprobleme, beim erhalten der Nutzdaten:
// base pointer const u_char *packet = (const u_char*)ppacket; // ehternet-pointer //ether_header *eptr = (ether_header *) packet; // compute ip-header sniff_ip *ip = (sniff_ip*) (packet + SIZE_ETHERNET ); u_int size_ip = IP_HL(ip)*4; // compute tcp-header data sniff_tcp *tcp = (sniff_tcp*)( packet + SIZE_ETHERNET + size_ip ); u_int size_tcp = TH_OFF(tcp)*4; long data_length = (ip->ip_len - ( SIZE_ETHERNET + size_ip + size_tcp )); printf("\nProcess (new) tcp/ip package %i, length %i", (int)packet_counter, (int)data_length); // (*) HIER const u_char* payload = (u_char*)(packet + SIZE_ETHERNET + size_ip + size_tcp ); memcpy( temp_buffer, payload, data_length ); temp_buffer[data_length] = 0; printf("\n%s", payload );
1. über data_length erhalte ich einen Wert von etwa. 14.000 ...(sollte eig. in ordnung sein)
2. Wenn ich port 80 abhöre, dann hab ich das Problem, dass ich keinen ascii code erhalte. Ich erhalte immer das mime protokoll und der rest ist "komisch"
Ich kann mir vorstellen, dass bei (*) das problem begaben liegt ... evt. findet jemand einen Fehler?
-
Vergleiche deine Werte einfach mit den Werten, die Wireshark reportet. Wenn du Glück hast, können beide Tools gleichzeitig lauschen.
-
hi ist evt. ne super idee, das würde jedoch durchaus viel zeit in anspruch nehmen das ganze zu tracken...
Hat keiner eine Idee?
-
für die data_length ziehst du vom wert im ip header auch SIZE_ETHERNET ab. ich glaub, das is falsch. im ip header wird nur die länge des ip pakets aufgezeichnet. sind 14.000 14 oder 14000? 14000 wäre viel zu viel.
-
Ich denke das ist richtig. Von einer analogen IP-Tracker lib. wird die länge wie folgt berechnet: (winplfilter)
DWORD dwDataLength = PacketBuffer.m_Length - (sizeof(ether_header) + pIpHeader->ip_hl*4 + pTcpHeader->th_off*4);
Das funktioniert perfekt unter Windows XP (lib: winpkfilter)
-
14.000 sind 14000, (in bytes) entspricht ca. 14 gb. sollte in ordnung sein,o?
-
ethernet-pakete haben maximal 1536 bytes, also das mit den 14000 kann schon mal nicht stimmen. der ethernet-header (bei eth-1 frames) selber ist 14 bytes gross, ip und tcp-header haben jeweils 20 bytes. bleiben also 1536-14-20-20 = 1482 bytes für die nutzdaten. der aufbau von einem tcp/ip-paket in einem ethernet-frame sieht so aus:
1. 6 bytes empfängeradresse
2. 6 bytes absenderadresse
3. 2 bytes protocol-id (oder längenangabe wenn <= 0x600)
4. 20 bytes ip-header
5. 20 bytes tcp-header
4. 0...1482 bytes nutzdaten
davor und dahinter befinden sich noch informationen, die aber nur für die hardware interessant sind. die bekommt meistens noch nicht mal der treiber zu sehen.
-
JayJay1 schrieb:
DWORD dwDataLength = PacketBuffer.m_Length - (sizeof(ether_header) + pIpHeader->ip_hl*4 + pTcpHeader->th_off*4);
das stimmt bestimmt, aber PacketBuffer.m_Length scheint eher die länge des gesamten ethernet frames zu sein und nicht nur die des ip pakets. das ip paket hat keine ahnung, in welcher art hardware-frame es transportiert wird.
14000 bytes wären nicht 14 gb sondern 14 kb. aber auch 14 kb is wohl zu viel. bei loopback wäre das aber noch möglich. die mtu von lo ist 16 kib.
-
Also generell kann das wirklich nicht stimmen. 14000 ist zu viel, max. müsste 1452 bytes sein.
Wenn ich jedoch den ethernet header auch abziehe, dann wird es weniger, ansonsten ist es größer... Die Frage, was genau ist hier falsch
-
jayjay1 schrieb:
Die Frage, was genau ist hier falsch
geh mal mit 'nem debugger durch und schau dir die einzelnen längen an. vielleicht ein alignment-fehler. sowas kann passieren, wenn du irgendwelche struct-pointer auf die rohdaten draufcastest.
-
hi, okay mach ich. Also sämtliche anderen daten stimmen ... (ip,port..etc). was heißen lässt, dass grundlegent was stimmt
-
Eigentlich müsste es wie folgt aussehen. Ich bekomm einen pointer auf mein ethernet paket.
Ich hab mir mal (ip->ip_len) ausgeben lassen. Das hat immer eine größe von > 10000.
d.h. hier müsste schon ein problem vor liegen:sniff_ip *ip = (sniff_ip*) (packet + SIZE_ETHERNET );
Hier noch meine definition vom ip-header:
/* IP header */ struct sniff_ip { u_char ip_vhl; /* version << 4 | header length >> 2 */ u_char ip_tos; /* type of service */ u_short ip_len; /* total length */ u_short ip_id; /* identification */ u_short ip_off; /* fragment offset field */ #define IP_RF 0x8000 /* reserved fragment flag */ #define IP_DF 0x4000 /* dont fragment flag */ #define IP_MF 0x2000 /* more fragments flag */ #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ u_char ip_ttl; /* time to live */ u_char ip_p; /* protocol */ u_short ip_sum; /* checksum */ struct in_addr ip_src,ip_dst; /* source and dest address */ }; #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f) #define IP_V(ip) (((ip)->ip_vhl) >> 4)
// base pointer const u_char *packet = (const u_char*)ppacket; // ehternet-pointer //ether_header *eptr = (ether_header *) packet; // compute ip-header sniff_ip *ip = (sniff_ip*) (packet + SIZE_ETHERNET ); u_int size_ip = IP_HL(ip)*4; // compute tcp-header data sniff_tcp *tcp = (sniff_tcp*)( packet + SIZE_ETHERNET + size_ip ); u_int size_tcp = TH_OFF(tcp)*4; long data_length = (ip->ip_len - ( size_ip + size_tcp )); printf("\nProcess (new) tcp/ip package %i, length %i", (int)packet_counter, (int)data_length);
-
Für alle die Lösung:
Das Problem nennt sich Most Significant Byte first. Eine Bestimmung in der Netzwerktechnik.ntohs ist in diesem Falle das Zauberwort!
Besteht ein Wert[*] aus mehreren Bytes, wird auf 80x86 Prozessoren das niederwertige Byte vorangestellt (Least Significant Byte first), während man sich im Internet auf die umgekehrte Byteordnung geeinigt hat (Most Significant Byte first). Um von Rechner- auf Netzwerk-Ordnung zu konvertieren, benutzt man die htons() bzw. htonl() Funktionen; umgekehrt benutzt man die ntohs() bzw. ntohl() Funktionen.
htons() und ntohs() konvertieren short integer, die beiden anderen Funktionen konvertieren long integer.unsigned long int htonl( unsigned long int hostlong );
unsigned short int htons( unsigned short int hostshort );
unsigned long int ntohl( unsigned long int netlong );
unsigned short int ntohs( unsigned short int netshort );unter linux im header netinet/in.h
// base pointer const u_char *packet = (const u_char*)ppacket; // ehternet-pointer //ether_header *eptr = (ether_header *) packet; // compute ip-header sniff_ip *ip = (sniff_ip*) (packet + SIZE_ETHERNET ); u_int size_ip = IP_HL(ip)*4; // compute tcp-header data sniff_tcp *tcp = (sniff_tcp*)( packet + SIZE_ETHERNET + size_ip ); u_int size_tcp = TH_OFF(tcp)*4; long data_length = (ntohs(ip->ip_len) - ( size_ip + size_tcp )); printf("\nProcess (new) tcp/ip package %i, length %i", (int)packet_counter, (int)data_length);
PS: Für den Port braucht ihr das Ebenfalls. ntohs(tcp->th_sport) / ntohs(tcp->th_dport).
Gruß jayjay