2014-10-15 14 views
5

Ich wurde für das Modul einig Beispiel-Code-Snippet Lesen Net::Pcap::Easy, und ich kam von Code über dieses Stückperl bitweise UND und bitweise Verschiebung

my $l3protlen = ord substr $raw_bytes, 14, 1; 
my $l3prot = $l3protlen & 0xf0 >> 2; # the protocol part 
return unless $l3prot == 4; # return unless IPv4 
my $l4prot = ord substr $packet, 23, 1; 
return unless $l4prot == '7'; 

insgesamt Hex-Dump des rohen Paket $ raw_bytes Nachdem ich, ich kann sehen, dass dies ein Ethernet-Frame ist und nicht auf einem TCP/UDP-Paket. Kann jemand bitte erklären, was der obige Code tut?

Antwort

7

Um den Rahmen zu analysieren, schaute ich nach oben this page.

Nun auf die Perl ...

my $l3protlen = ord substr $raw_bytes, 14, 1; 

Extrahieren den 15. Bytes (Zeichen) von $raw_bytes und wandelt seinen Ordnungswert (zB ein Buchstabe ‚A‘ in eine Ganzzahl umgewandelt werden würde 65 (0x41), vorausgesetzt der Zeichensatz ist ASCII). So kann Perl Binärdaten verarbeiten, als wäre es eine Zeichenfolge (z. B. Übergabe an substr), aber dann können Sie die Binärwerte wieder herausholen und als Zahlen behandeln. (Aber denken Sie daran, TMTOWTDI.)

Im IPv4-Rahmen sind die ersten 14 Bytes der MAC-Header (6 Bytes für Ziel-und Quell-MAC-Adresse, gefolgt von 2-Byte-Ethertype wahrscheinlich 0x8000 - Sie hätten dies überprüfen können). Danach ist das 15. Byte der Start der Ethernet-Datennutzlast: das erste Byte enthält Version (obere 4 Byte) und Header-Länge in DWORDs (untere 4 Byte).

Jetzt sieht es für mich aus, als ob es einen Bug in der nächsten Zeile dieses Beispielcodes gibt, aber es funktioniert normalerweise gut mit einem Zufallsgenerator!

my $l3prot = $l3protlen & 0xf0 >> 2; # the protocol part 

In Perl hat >> höhere Priorität als &, so führt dies zu

my $l3prot = $l3protlen & (0xf0 >> 2); 

oder gleichwertig sein, wenn Sie

my $l3prot = $l3protlen & 0x3c; 

So bevorzugen diese extrahiert Bits 2 bis 5 aus der $l3prot Wert: Der Maskenwert 0x3c ist 0011 1100 in binär. So würde zum Beispiel ein Wert von 0x86 (in binär, 1000 0110) 0x04 werden (binär 0000 0100). Tatsächlich ist ein "normaler" IPv4-Wert 0x45, d. H. Protokolltyp 4, Headerlänge 5 dwords. Maskiere das mit 0x3c und du bekommst ... 4! Aber nur durch Zufall: Sie haben die oberen 2 Bits der Länge getestet, nicht den Protokolltyp!

sollte diese Linie sicherlich

sein
my $l3prot = ($l3protlen & 0xf0) >> 4; 

(Note Klammern für Vorrang und eine Verschiebung von 4 Bits, nicht 2). (Ich habe diesen gleichen Fehler in den CPAN documentation also denke ich, es ist wahrscheinlich ziemlich weit verbreitet.)

return unless $l3prot == 4; # return unless IPv4 

Für IPv4 wir diesen Wert erwarten 4 zu sein - wenn es nicht ist, aus der Funktion springt sofort. (So ​​der falsche Code oben gibt das Ergebnis, das dies als IPv4-Paket interpretiert werden können, sondern nur durch Glück.)

my $l4prot = ord substr $packet, 23, 1; 

nun das 24. Byte extrahieren und auf die gleiche Art und Weise zu Ordinalwertes konvertieren.Dies ist das Protokoll Byte aus den IP-Header:

return unless $l4prot == '7'; 

Wir über 7 zu erwarten - wenn es nicht sofort aus der Funktion springen. (Nach IANA, 7 ist "Core-basierte Bäume" ... aber ich denke, Sie wissen, welche Protokolle Sie interessiert sind!)

+0

Sehr gut erklärt. Ja, ich suchte speziell nach UDP, also 7. – nohup

+1

@nohup - Danke! aber UDP ist 17, nicht 7 ... Hast du das auch mit meiner vorgeschlagenen Korrektur für die "& 0xf0'" Zeile versucht? – AAT

+0

Ausgezeichnet und gut erklärt. Gute Arbeit, diese Fehler zu entdecken –