This operation is divided in three steps:
More information about PDF, DFF, IFF files can be found into the Protocol definition Section.
This Section will provide an example of the steps needed to add new protocols. We will add three protocols in order to explain these steps:
We will modify the protocol configuration files (PDF file, DFF file, IFF file) in order to add these protocols. Initial PDF, DFF and IFF files have been kept quite small in order not to increase the difficulties of the task.
All the instructions used in these files are described by their relative grammars.
Instructions devoted to retrieve information about the packet (for example the value of a particular field) are resolved by means of a virtual machine that reads the packet.
Protocol Definition File: default.pdf
The MAC protocol definition is embedded between the key words PROTOCOL and ENDPR; For example, Ethernet v.2.0 header can be written as:
PROTOCOL MAC WORD DS1 /* DSAP */ WORD DS2 WORD DS3 WORD SS1 /* SSAP */ WORD SS2 WORD SS3 WORD LEN_TYPE /* Data Length or Protocol Type */ ENDPR
MAC protocol is used also to determine which is next protocol. Instructions that allows doing that are case and else. For instance:
case LEN_TYPE<=1500: LLC else UNSUPPORTED
The, it follow the LLC protocol definition:
PROTOCOL LLC BYTE DSAP BYTE SSAP BYTE CONTROL ENDPR
Instruction case is not compulsory; vice versa instruction else does:
else UNSUPPORTED
The following rows define a fake protocol called 'Unsupported'; this protocol does not really exist but it is used to exit from the analysis. The instruction skip means "skip the following N bytes, then restart parsing the remaining part of the packet". In order to finish the analysis, 'skip' instruction has to be followed by a very large number (bigger than the biggest packet size of the network) in order to be sure that end of packet has been reached. The instruction 'else' is followed by the name of the same fake protocol.
The keyword virtual prevents the user from using the protocol fields (which do not even exist in this case) in the expressions; virtual protocols cannot be used in DFF and IFF files.
VIRTUAL PROTOCOL UNSUPPORTED ENDPR skip: 20000 else UNSUPPORTED
Protocol Description File: default.dff
The file default.dff contains six functions definitions:
PartialFrame(){...}
Main(){...}
DATA(){...}
UNSUPPORTED(){...} //correspondent to unsupported protocols
MAC (){...} //correspondent to MAC protocol
LLC (){...} //correspondent to LLC protocol
The last three functions are relative to the protocols defined in default.pdf; in fact each protocol must have a relative function, declared in PDF file, which is called when its protocol is parsed.
When a packet has to be displayed, function main is called first that prints general information. Detailed information are printed by other functions, whose name coincides with the one defined into the PDF file. For instance, defining a protocol called MAC in default.pdf, we have to define a function MAC in default.dff and default.iff in order to print information about this level. Whem a protocol is located by the PDF definition the correspondant DFF/IFF function is called; if the function does not exist the content of the fields defined in the PDF is displayed. Such a function has the visibility of its own-defined variables and fields defined in the PDF; this functions can read, print and to modify these fields like standard variables.
PartialFrame()
It is invoked by the 'main' function. It prints the available bytes number and the length of the packet read from the disk. Both value are obtained through the call of the function GetVmVar(). printf() behaves like the homonymous C function.
DWORD PartialFrame() { title ("Description"); printf( "Item type: Partial frame, %u bytes available", GetVMVar ("FrameAvail")); printf( "Frame size is %u (%X hex) bytes",GetVMVar ("FrameSize"),GetVMVar ("FrameSize"));
Main()
It prints some general information about the packet; it is similar to the homonymous C function:
DWORD Main() { title("General"); printf("Item number %u, position in logfile %u%%",GetVMVar ("ItemNumber"),GetVMVar ("Position")); if (GetVmVar("FrameSecs")==0) printf("Timestamp: 00h:00m:00s:%06dus",GetVMVar ("FrameUSecs")); else printf( "Timestamp: %02dh:%02dm:%02ds:%06dus",(GetVMVar ("FrameSecs")%86400)/3600+2, (GetVMVar ("FrameSecs")%3600)/60,GetVMVar ("FrameSecs")%60,GetVMVar ("FrameUSecs")); PartialFrame(); }
Data()
It prints two values obtained by invoking GetVMVar() function. In this example data() is called as soon as the LLC analysis finishes, because no other protocols are defined after LLC. Whether current packet does not have an LLC level then the analysis goes to the UNSUPPORTED protocol; so function Unsupported is called and the analysis ends without calling the data function.
DWORD DATA() { DWORD s,t; s=GetVMVar ("SizeNotInt"); t=GetVMVar ("FrameSize"); if (s) { printf("----- Data ----- [%d-%d]",t-s,t-1); printf( "[%u byte(s) of data]",s); } }
Unsupported()
It prints two values obtained invoking GetVmVar:
SizeNotInt: the number of bytes (belonging to the packet actually read) not yet interpreted.
FrameSize: packet length (actually read) expressed in byte.
DWORD UNSUPPORTED() { DWORD s,t; s=GetVMVar ("SizeNotInt"); t=GetVMVar ("FrameSize"); if (s) { printf("----- NOT SUPPORTED ----- [%d-%d]",t-s,t-1); printf( "[%u byte(s) of data]",s); } } |
MAC()
We notice the instruction 'offset' which returns the offset of the specified field.
DWORD MAC () { // MAC analysis if (LEN_TYPE<=1500) title( "IEEE 802.3 MAC Header"); else title("Ethernet v.2.0 MAC Header"); printf( "Destination = %04X%02X-%02X%04X",DS1,DS2>>8,DS2&0xFF,DS3); printf( "Source = %04X%02X-%02X%04X", SS1,SS2>>8,SS2&0xFF,SS3); if(LEN_TYPE<=1500) { // IEEE 802.3 format DWORD padding; printf( "Packet Length = %u bytes",LEN_TYPE); padding=GetVMVar ("FrameSize")-(LEN_TYPE+14); if(padding!=0)printf("Padding bytes %u (before data)",padding); } else // Ethernet format (DIX) printf( "Ethertype = %04Xh (%p)",LEN_TYPE,offsetof(LEN_TYPE)); } |
LLC()
DWORD LLC () { //continues analysis of a IEEE 802.3 frame with the LLC level title( "LLC Header"); printf( "DSAP = %02Xh (%l)",DSAP,offsetof(DSAP)); printf( "SSAP = %02Xh (%l)",SSAP,offsetof(SSAP)); //analysing control field if (CONTROL==0 || CONTROL==1) //information frame printf( "Control = Information frame"); else if (CONTROL==2) //supervisory frame printf( "Control = Supervisory frame"); else if (CONTROL==3) //unnumbered frame printf( "Control = Unnumbered frame"); } |
Protocol Index File: default.iff
As you can read in Protocol codification in Analyzer this file defines the packets index print; so it is an abstract of the DFF file, in fact it generates the print of the packet information which are considered essential. The language is the same used in DFF file.
DWORD Main() { if (GetVmVar("FrameSecs")==0) printf("00h:00m:00s:%06dus",GetVMVar ("FrameUSecs")); else printf( "%02dh:%02dm:%02ds:%06dus",(GetVMVar ("FrameSecs")%86400)/3600+2, (GetVMVar ("FrameSecs")%3600)/60,GetVMVar ("FrameSecs")%60,GetVMVar ("FrameUSecs")); } DWORD MAC () { // MAC analysis printf( "%04X%02X-%02X%04X", DS1,DS2>>8,DS2&0xFF,DS3); printf( "%04X%02X-%02X%04X", SS1,SS2>>8,SS2&0xFF,SS3); } |
To see the output produced by Analyzer using these three files, set them in window protocol definition and open a capture file.
The following modification have to be implemented:
We have to modify the default PDF file. Steps are:
Here it is the IPX protocol structure:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Checksum | Length | ||||||||||||||||||||||||||||||
Transport Control | Packet Type | Dest. Network Address | |||||||||||||||||||||||||||||
Dest. Network Address | Dest. Node Address | ||||||||||||||||||||||||||||||
Dest. Node Address | |||||||||||||||||||||||||||||||
Dest. Socket | Source Network Address | ||||||||||||||||||||||||||||||
Source Network Address | Source Node Address | ||||||||||||||||||||||||||||||
Source Node Address | |||||||||||||||||||||||||||||||
Source Socket | ... | ||||||||||||||||||||||||||||||
Data (0-546 byte) |
The inclusion of the IPX protocol is done adding these rows:
PROTOCOL IPX WORD Checksum WORD PLen BYTE TControl BYTE PType DWORD DNet WORD DNode1 WORD DNode2 WORD DNode3 WORD DSocket DWORD SNet WORD SNode1 WORD SNode2 WORD SNode3 WORD SSocket ENDPR else UNSUPPORTED |
The row "else UNSUPPORTED" at the end of IPX means that no further protocols are recognized after IPX. We can notice that in IPX protocol the fields Source Node and Destination node are 6 bytes long; however PDF files allows only 1 or 2 or 4 bytes long fields. The solution is given by breaking these 6 bytes long fields: we can get three 2 bytes long fields (WORD), one 4 bytes long (DWORD) and one 2 bytes long ( WORD). These two solutions are equivalent for the analysis engine.
For instance, if we want to locate all packets with Source Node field = 123456789ABC (hexadecimal value), the discriminative expression will be:
First solution: SNode1=0x1234 && SNode2=0x5678 && SNode3=0x9ABC Second solution: SNode12=0x12345678 && SNode3=0x9ABC |
For integrating completely the IPX protocol we have to modify also definitions of MAC and LLC protocols (we don't consider proprietary solution which insert IPX in 802.3 payload). MAC level indicates an IPX packet whether field LEN_TYPE == 0x8137 or 0x8138. Then we have to add 2 rows in MAC protocol definition before string "else UNSUPPORTED":
PROTOCOL MAC WORD DS1 /* DSAP */ WORD DS2 WORD DS3 WORD SS1 /* SSAP */ WORD SS2 WORD SS3 WORD LEN_TYPE /* Data Length or Protocol Type */ ENDPR case LEN_TYPE<=1500: LLC case LEN_TYPE=0x8137: IPX case LEN_TYPE=0x8138: IPX else UNSUPPORTED |
In the LLC header we have to test the field DSAP; if DSAP is equal to 0xe0, next protocol will be IPX:
PROTOCOL LLC BYTE DSAP BYTE SSAP BYTE CONTROL ENDPR case DSAP=0xe0: IPX else UNSUPPORTED |
We still do not add CASE instructions in IPX definition because there are not protocols (among the defined ones) which succeed to the IPX protocol.
We insert a function (DWORD IPX()) in DFF file in order to show the content of IPX packet. This function is composed by a series of printf() and a single instruction title(). Last instruction is used to print the string and create a new section of the packet in order to keep packet information logically organized.
//IPX packet Interpretation DWORD IPX () { title("IPX Header"); printf( "Checksum 0x%X",Checksum); printf( "Packet length %u",PLen); printf( "Transport control %u",TControl); printf( "Packet type 0x%X (%r)",PType,offsetof(PType)); printf( "Destination network 0x%08X",DNet); printf( "Destination node %04X%02X-%02X%04X (Vendor: %v)", DNode1,(DNode2>>8),DNode2&0xff,DNode3,offsetof(DNode1)); printf( "Destination socket 0x%04X (%n)",DSocket,offsetof(DSocket)); printf( "Source network 0x%08X",SNet); printf( "Source node %04X%02X-%02X%04X (Vendor: %v)", SNode1,SNode2>>8,SNode2&0xff,SNode3,Offsetof(SNode1)); printf( "Source socket 0x%04X (%n)",SSocket,offsetof(SSocket)); } |
We can take the function added in DFF file, eliminate the unnecessary parts and insert it in IFF file. In fact in the index only the main information are shown. Character ":|:" that is printed at the ed of the function tells Analyzer that next printed information must be inserted in the next column (index view is made up of several columns).
//IPX packet Interpretation DWORD IPX () { printf("IPX: "); printf( "0x%08X.0x%04X",SNet,SSocket); printf("=>"); printf( "0x%08X.0x%04X :|:",DNet,DSocket); } |
In the definition we did not consider that the IPX header can be contained in the IEEE 802.3 header. In this solution IPX protocol replace LLC protocol.
We can distinguish if the next protocol is IPX or LLC thanks to these two observations:
Then we insert a 'virtual' protocol, called LLC_IPX; this virtual protocol is called if the field 'Data Length or Protocol Type' is less than 1500 (i.e. type is 802.3). In this case the next two bytes are stored in the word PCHECK and they are checked to decide if the next protocol is LLC or IPX. The instruction SKIP -2 is inserted in order to go two bytes back in the packet parsing in order to allow these two bytes being reinterpreted by the following protocol definition. The number after SKIP indicates how many bytes are skipped: 'SKIP N' the reading point goes N bytes on, 'SKIP -N' the reading point goes N bytes back.
VIRTUAL PROTOCOL LLC_IPX WORD PCHECK ENDPR skip: -2 case PCHECK=0xFFFF: IPX else LLC |
We modify also MAC definition:
PROTOCOL MAC WORD DS1 /* DSAP */ WORD DS2 WORD DS3 WORD SS1 /* SSAP */ WORD SS2 WORD SS3 WORD LEN_TYPE /* Data Length or Protocol Type */ ENDPR case LEN_TYPE<=1500: LLC_IPX case LEN_TYPE=0x8137: IPX case LEN_TYPE=0x8138: IPX else UNSUPPORTED |
Now the IPX protocol definition is completed. You can try to set these three files in Analyzer using the dialog window Analyzer setup (menu Setup / analyzer); the objects files will be named default.pdo/dfo/ifo and they will be stored in folder Objects.
Default.pdf
PROTOCOL MAC WORD DS1 /* DSAP */ WORD DS2 WORD DS3 WORD SS1 /* SSAP */ WORD SS2 WORD SS3 WORD LEN_TYPE /* Data Length or Protocol Type */ ENDPR case LEN_TYPE<=1500: LLC_IPX case LEN_TYPE=0x8137: IPX case LEN_TYPE=0x8138: IPX else UNSUPPORTED VIRTUAL PROTOCOL LLC_IPX WORD PCHECK ENDPR skip: -2 case PCHECK=0xFFFF: IPX else LLC PROTOCOL LLC BYTE DSAP BYTE SSAP BYTE CONTROL ENDPR case DSAP=0xe0: IPX else UNSUPPORTED PROTOCOL IPX WORD Checksum WORD PLen BYTE TControl BYTE PType DWORD DNet WORD DNode1 WORD DNode2 WORD DNode3 WORD DSocket DWORD SNet WORD SNode1 WORD SNode2 WORD SNode3 WORD SSocket ENDPR else UNSUPPORTED |
Default.dff
DWORD PartialFrame() { title ("Description"); printf( "Item type: Partial frame, %u bytes available", GetVMVar ("FrameAvail")); printf( "Frame size is %u (%X hex) bytes",GetVMVar ("FrameSize"), GetVMVar ("FrameSize")); } DWORD Main() { title("General"); printf("Item number %u, position in logfile %u%%",GetVMVar ("ItemNumber"), GetVMVar ("Position")); if (GetVmVar("FrameSecs")==0) printf("Timestamp: 00h:00m:00s:%06dus", GetVMVar ("FrameUSecs")); else printf( "Timestamp: %02dh:%02dm:%02ds:%06dus", (GetVMVar ("FrameSecs")%86400)/3600+2, (GetVMVar ("FrameSecs")%3600)/60,GetVMVar ("FrameSecs")%60, GetVMVar ("FrameUSecs")); PartialFrame(); } DWORD DATA() { DWORD s,t; s=GetVMVar ("SizeNotInt"); t=GetVMVar ("FrameSize"); if (s) { printf("----- Data ----- [%d-%d]",t-s,t-1); printf( "[%u byte(s) of data]",s); } } DWORD UNSUPPORTED() { DWORD s,t; s=GetVMVar ("SizeNotInt"); t=GetVMVar ("FrameSize"); if (s) { printf("----- NOT SUPPORTED ----- [%d-%d]",t-s,t-1); printf( "[%u byte(s) of data]",s); } } DWORD MAC () { // MAC analysis if (LEN_TYPE<=1500) title( "IEEE 802.3 MAC Header"); else title("Ethernet v.2.0 MAC Header"); printf( "Destination = %04X%02X-%02X%04X",DS1,DS2>>8,DS2&0xFF,DS3); printf( "Source = %04X%02X-%02X%04X", SS1,SS2>>8,SS2&0xFF,SS3); if(LEN_TYPE<=1500) { // IEEE 802.3 format DWORD padding; printf( "Packet Length = %u bytes",LEN_TYPE); padding=GetVMVar ("FrameSize")-(LEN_TYPE+14); if(padding!=0)printf("Padding bytes %u (before data)",padding); } else // Ethernet format (DIX) printf( "Ethertype = %04Xh (%p)",LEN_TYPE,offsetof(LEN_TYPE)); } DWORD LLC_IPX () { if (PCHECK == 65535) printf("IPX on 802.3"); } DWORD LLC () { //continues analysis of a IEEE 802.3 frame with the LLC level title( "LLC Header"); printf( "DSAP = %02Xh (%l)",DSAP,offsetof(DSAP)); printf( "SSAP = %02Xh (%l)",SSAP,offsetof(SSAP)); //analysing control field if (CONTROL==0 || CONTROL==1) //information frame printf( "Control = Information frame"); else if (CONTROL==2) //supervisory frame printf( "Control = Supervisory frame"); else if (CONTROL==3) //unnumbered frame printf( "Control = Unnumbered frame"); } //IPX packet Interpretation DWORD IPX () { title("IPX Header"); printf( "Checksum 0x%X",Checksum); printf( "Packet length %u",PLen); printf( "Transport control %u",TControl); printf( "Packet type 0x%X (%r)",PType,offsetof(PType)); printf( "Destination network 0x%08X",DNet); printf( "Destination node %04X%02X-%02X%04X (Vendor: %v)", DNode1,(DNode2>>8),DNode2&0xff,DNode3,offsetof(DNode1)); printf( "Destination socket 0x%04X (%n)",DSocket,offsetof(DSocket)); printf( "Source network 0x%08X",SNet); printf( "Source node %04X%02X-%02X%04X (Vendor: %v)", SNode1,SNode2>>8,SNode2&0xff,SNode3,Offsetof(SNode1)); printf( "Source socket 0x%04X (%n)",SSocket,offsetof(SSocket)); } |
Default.iff
DWORD Main() { if (GetVmVar("FrameSecs")==0) printf("00h:00m:00s:%06dus",GetVMVar ("FrameUSecs")); else printf( "%02dh:%02dm:%02ds:%06dus",(GetVMVar ("FrameSecs")%86400)/3600+2, (GetVMVar ("FrameSecs")%3600)/60,GetVMVar ("FrameSecs")%60, GetVMVar ("FrameUSecs")); } DWORD MAC () { // MAC analysis printf( "%04X%02X-%02X%04X", DS1,DS2>>8,DS2&0xFF,DS3); printf( "%04X%02X-%02X%04X", SS1,SS2>>8,SS2&0xFF,SS3); } //IPX packet Interpretation DWORD IPX () { printf("IPX: "); printf( "0x%08X.0x%04X",SNet,SSocket); printf("=>"); printf( "0x%08X.0x%04X :|:",DNet,DSocket); } |
Now we want add the IPv4 protocol. Let's examine the IPv4 header:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Version | Header len. | Type Of Service | Total length | ||||||||||||||||||||||||||||
Identification | Flags | Fragment Offset | |||||||||||||||||||||||||||||
Next Protocol | Time To Live | Header Checksum | |||||||||||||||||||||||||||||
Source Address | |||||||||||||||||||||||||||||||
Destination Address | |||||||||||||||||||||||||||||||
Option | Padding |
If the 'Length' field in the MAC protocol is equal to 0x0800 then the next protocol can be IPv4 or IPv6. So we have to add a virtual protocol called IP4_6 that determines the next protocol by reading the field 'Version'.
In the MAC protocol we add a line that manages the call to the virtual protocol:
CASE (LEN_TYPE=2048) : IP4_6
Then we add the virtual protocol:
VIRTUAL PROTOCOL IP4_6 BYTE VLEN { BITS VERSION (4,7) BITS HLEN (0,3) } ENDPR SKIP: (-1) CASE (VERSION=4) : IP ELSE UNSUPPORTED |
The SKIP instruction brings one byte back the point where the parser arrived to read the packet. So the byte containing the fields 'version' and 'header length' will be considered by the next protocol instructions. If we added also IPv6 we had to add the line:
CASE (VERSION=6) : IP6 |
The IP protocol definition:
PROTOCOL IP BYTE VLEN { BITS VERSION (4,7) BITS HLEN (0,3) } BYTE TOS WORD TLEN WORD IDENTIFICATION WORD FFO { BITS FLAGS (12,15) BITS FRAGMENTOFFSET (0,11) } BYTE TTL BYTE NEXTPROTOCOL WORD HCHECKSUM DWORD SADDRESS DWORD DADDRESS ENDPR SKIP: ((HLEN*4)-20) CASE ((NEXTPROTOCOL=6)&&(FRAGMENTOFFSET=0)) : TCP ELSE UNSUPPORTED |
The instruction SKIP sets the 'reading sign' after the field 'Option' whose
length is expressed by the field 'hlen'.
DWORD IP () { //IP packet Interpretation if(Version!=4) return -1; title( "IPv4 Header"); ResetLog(offsetof(vlen),offsetof(vlen)+1,1); printf( "Version = %u",Version); ResetLog(offsetof(vlen),offsetof(vlen)+1,1); printf( "Header length = %u bytes",HLEN); printf( "Type of service = %02Xh",TOS); ResetLog(offsetof(TOS),offsetof(TOS)+1,1); printf( " %3b. .... = priority %u",TOS>>5,TOS>>5); ResetLog(offsetof(TOS),offsetof(TOS)+1,1); if (TOS&0x10) printf( " ...1 .... = low delay"); else printf( " ...0 .... = normal delay"); ResetLog(offsetof(TOS),offsetof(TOS)+1,1); if (TOS & 0x08) printf( " .... 1... = high throughput"); else printf( " .... 0... = normal throughput"); ResetLog(offsetof(TOS),offsetof(TOS)+1,1); if(TOS & 0x04) printf( " .... .1.. = high reliability"); else printf( " .... .0.. = normal reliability"); ResetLog(offsetof(TOS),offsetof(TOS)+1,1); if(TOS & 0x02) printf( " .... ..1. = low monetary cost"); else printf( " .... ..0. = normal monetary cost"); printf( "Total length = %u bytes",TLen); printf( "Identification = %u", Identification); ResetLog(offsetof(Flags),offsetof(Flags)+1,1); printf( "Flags = %01Xh",Flags); ResetLog(offsetof(Flags),offsetof(Flags)+1,1); if(Flags&0x8) printf( " 1... .... = error: must be 0"); else printf( " 0... .... = must be 0"); ResetLog(offsetof(Flags),offsetof(Flags)+1,1); if(Flags&0x4) printf( " .1.. .... = do not fragment"); else printf( " .0.. .... = may fragment"); ResetLog(offsetof(Flags),offsetof(Flags)+1,1); if(Flags&0x2) printf( " ..1. .... = more fragment"); else printf( " ..0. .... = last fragment"); printf( "Fragment offset = %u bytes",FragmentOffset*8); printf( "Time to live = %u seconds/hops",TTL); printf( "Protocol = %u (%i)",NextProtocol,offsetof(NextProtocol)); printf( "Header chechsum = %04Xh",HCHECKSUM); printf( "Source address = [%u.%u.%u.%u]", SAddress>>24&0xFF, SAddress>>16&0xFF, SAddress>>8&0xFF,SAddress&0xFF); printf( "Destination address = [%u.%u.%u.%u]", DAddress>>24&0xFF, DAddress>>16&0xFF, DAddress>>8&0xFF,DAddress&0xFF); ResetLog(); if(HLEN>20) printf( "Options = %u bytes",HLEN-20); else printf( "No IP options"); } |
This function is used to modify the packet hexdump view (Analyzer's third panel). Each time Analyzer finds a printf() in the DFF file, it supposes that the user wants to print information about the next field defined into the PDF file. It follows that each printf() must coincide with a single field (multiple printf() for a single field lead to a wrong display in the third panel). By the way, Analyzer starts a new line in the packet details each time it finds a new printf().
ResetLog() is a function that can be used to change the way hexdump is highlightened. Function has three different forms:
ResetLog (StartOffset,EndOffset): it indicates that following printf() must highlight selected portion of the dumpfile
ResetLog (StartOffset,EndOffset,RedColor):same significate as before; when RedColor is positive, the interval is printed with the red color. Such a color means that the selected field is smaller than one byte; whether RedColor=0 Analyzer shows the data with the green color
ResetLog():it deletes the intervals set automatically by the analysis engine.
DWORD IP () { //IP packet Interpretation if(Version!=4) return -1; printf("IP: "); printf( "%u.%u.%u.%u", SAddress>>24&0xFF,SAddress>>16&0xFF, SAddress>>8&0xFF,SAddress&0xFF); printf("=>"); printf( "%u.%u.%u.%u", DAddress>>24&0xFF,DAddress>>16&0xFF, DAddress>>8&0xFF,DAddress&0xFF); printf( " (%u) :|:", TLen); } |
TCP header:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Source Port | Destination Port | ||||||||||||||||||||||||||||||
Sequence Number | |||||||||||||||||||||||||||||||
Acknowledgement Number | |||||||||||||||||||||||||||||||
Data Offset | Res | Control | Window | ||||||||||||||||||||||||||||
Checksum | Urgent Pointer | ||||||||||||||||||||||||||||||
Options | Padding |
In the IP definition we have added the line:
CASE ((NEXTPROTOCOL=6)&&(FRAGMENTOFFSET=0)) : TCP |
Then we add the TCP protocol definition:
PROTOCOL TCP WORD SPORT WORD DPORT DWORD SNUMBER DWORD ACKNUMBER BYTE W1 { BITS RES (0,3) BITS DATAOFFSET (4,7) } BYTE CONTROL WORD WINDOW WORD CHECKSUM WORD URGENTPTR ENDPR SKIP: ((DATAOFFSET*4)-20) ELSE DATA |
The instruction SKIP sets the reading sign where the next protocols should start. Anyway we do not add any CASE instructions because we do not add protocols that follow TCP. So all the bytes following the TCP header are considered as data. In our definition TCP options are not supported.
In the TCP definition function we notice these new instructions:
//TCP packet Interpretation DWORD TCP () { DWORD headerLength; resetlog(offsetof(sport),offsetof(sport)+DataOffset*4); printf ("----- TCP Header -----"); printf( "Source port = %u (%t)",SPort,offsetof(SPort)); printf( "Destination port = %u (%t)",DPort,offsetof(DPort)); printf( "Sequence number = %u" ,SNumber); printf( "Acknowledgement number = %u" ,AckNumber); CHECK(13); headerLength=DataOffset*4; ResetLog(offsetof(DataOffset),offsetof(DataOffset)+1,1); printf( "Header length = %u bytes",headerLength); printf( "Flags = %02Xh" ,Control ); ResetLog(offsetof(Control),offsetof(Control)+1,1); if(Control &0x20) printf( " ..1. .... = Urgent pointer"); else printf( " ..0. .... = No urgent pointer"); ResetLog(offsetof(Control),offsetof(Control)+1,1); if (Control & 0x10) printf( " ...1 .... = Acknowledgement"); else printf( " ...0 .... = No acknowledgement"); ResetLog(offsetof(Control),offsetof(Control)+1,1); if (Control & 0x08) printf( " .... 1... = Push"); else printf( " .... 0... = No push"); ResetLog(offsetof(Control),offsetof(Control)+1,1); if (Control & 0x04) printf( " .... .1.. = Reset"); else printf( " .... .0.. = No reset"); ResetLog(offsetof(Control),offsetof(Control)+1,1); if (Control & 0x02) printf( " .... ..1. = SYN"); else printf( " .... ..0. = No SYN"); ResetLog(offsetof(Control),offsetof(Control)+1,1); if (Control & 0x01) printf( " .... ...1 = FIN"); else printf( " .... ...0 = No FIN"); printf( "Window = %u",Window); printf( "Checksum = %04Xh" ,Checksum); printf( "Urgent pointer = %u",UrgentPtr); if (headerLength>20) { DWORD pos,tmp,tmp2; tmp2=headerLength-20; resetlog(offsetof(UrgentPtr)+2,offsetof(UrgentPtr)+2+tmp2); printf( "Options = %u bytes" ,tmp2); pos=GetVmVar("SizeInt")+20; check(pos); tmp=CONV16(pos); if (tmp==0x204) { printf( " Code = %X (MSS)" ,tmp); printf( " Required MSS: %u",conv16(pos+1)); tmp2=tmp2-4; } if (tmp2>0) printf(" Other Options"); } else printf( "No TCP options" ); } |
Interestingly, DFF file is able to recognize some options, even if the DFF does not support them. This is clearly a dirty way of doing that. However, it works.
//TCP packet Interpretation DWORD TCP () { printf("TCP: "); printf( "Port (%u => %u) ",SPort,Dport); printf( "Data (SN %u, ACK %u) ", SNumber,AckNumber); } |