Re: Sctp Decoding using libcrafter

89 views
Skip to first unread message

Esteban Pellegrino

unread,
Aug 21, 2013, 8:29:29 PM8/21/13
to libcr...@googlegroups.com
Hello, to achieve this you'll have to code the SCTP::ParseLayerData(ParseInfo* info) method (also on the chunk layers). Basically, that methods tells the libcrafter "engine" which layer comes next when is decoding a packet.

Right now, that function is not doing anything, so after the SCTP layer libcrafter don't know which layer should create (that's why you see a RawLayer at the end of the packet). The ParseInfo* info structure is defined on the Layer.h header:

        /* Structure with information about the parsing of layers */
        struct ParseInfo {
            /* READ ONLY inside ParseData */
            /* Pointer to the original data, this should be set only once at the begging*/
            const byte* raw_data;
            /* Total length of the data */
            size_t total_size;

            /* UPDATE DATA inside ParseData */
            /* Current offset to read data on the raw pointer */
            size_t offset;
            /* Next layer to be pushed on the Packet stack */
            Layer* next_layer;
            /* Additional information that a layer may need to communicate to other layer */
            void* extra_info;
            /* Reach top of the packet */
            byte top;
            /* Constructor */
            ParseInfo() : raw_data(0), total_size(0), offset(0), next_layer(0), extra_info(0), top(0) {};
        };



In your case, you don't need the "extra_info" member. The raw_data pointer is the data of the entire packet, from the first layer to the top, and the offset member is the current position of libcrafter's parser. With that information, you should be able to create a new layer and put a pointer to it next_layer on the member. You should use the member total_size to check consistency of the data and the amount of bytes. To signal the parser that the top layer was founded, you should set next_layer to NULL or put a one 1 on top.

In your case,

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |   Chunk Type  | Chunk  Flags  |        Chunk Length           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       \                                                               \
       /                          Chunk Value                          /
       \                                                               \
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

void SCTP::ParseLayerData(ParseInfo* info) {

 /* This will point to the first byte of the SCTP layer*/
 byte* sctp_layer = info->raw_data + info->offset;

 /* This will point to the first chunk after the SCTP layer */
 byte* sctp_chunk = (sctp_layer + GetSize());

 /* You know that the first byte is the type of chunk (Chunk Type), and the 3rd and 4th byte is the Chunk Lenght */
 int chunk_type = sctp_chunk[0];
 int chunk_lenght = ((short_word*)sctp_chunk)[1];

 if(chunk_type == SOME_CHUNK) {
  info->next_layer = new SCTPSomeChunkLayer;
 } else if (chunk_type == SOME_OTHER_CHUNK) {
  info->next_layer = new SCTPSomeOtherChunkLayer(chunk_length); /* probably some chunks will need the lenght on the constructor... */
 }
  /* .... etc ... */
}

Hope this help :-) You should do basically the same thing on that method for each SCTP chunk implementation.

Best,
Esteban


On Mon, Aug 19, 2013 at 7:34 AM, Rana Umar <umar....@ebryx.com> wrote:
Dear Pellegre

I was able to form a sctp packet i just implemented SCTP and SCTP Data chunk  


   Crafter::IP ip;

    Crafter::SCTP sctp;

    Crafter::SCTPChunkData sctp_data;

    Crafter::SCTPChunk sctp_chunk;

    Packet pck = ip / sctp /sctp_data;

    pck.HexDump();

    pck.Print();



output is

45000030 00004000 40843A4B 00000000  E..0..@.@.:K.... 00000000
  00000000 00000050 00000000 0000F886  .......P........ 00000010
  03000088 00000100 01010000 00000100  ................ 00000020
< IP (20 bytes) :: Version = 4 , HeaderLength = 5 , DiffServicesCP = 0 , ExpCongestionNot = 0 , TotalLength = 48 , Identification = 0x0 , Flags = 2 , FragmentOffset = 0 , TTL = 64 , Protocol = 0x84 , CheckSum = 0x3a4b , SourceIP = 0.0.0.0 , DestinationIP = 0.0.0.0 , >
< SCTP (12 bytes) :: SrcPort = 0 , DstPort = 80 , VerTag = 0 , CheckSum = 63622 , >
< SCTPChunkData (16 bytes) :: ChunkType = 3 , ChunkFlags = 0 , ChunkLength = 136 , TSN = 256 , StreamIdentifier = 257 , StreamSequnceNumber = 256 , PayloadProtocolIdentifier = 256 , >



but i am unable to decode SCTP packet as raw layer (instead of SCTPChunkData) appears just after SCTP layer .



00270E34 CA590024 217F809B 08004500  .'.4.Y.$!.....E. 00000000
  00A80000 40004084 B38CC0A8 027DC0A8  ....@.@......}.. 00000010
  02780B59 0B59196B 25290000 D38C0003  .x.Y.Y.k%)...... 00000020
  0088250F 66250001 00080000 00030100  ..%.f%.......... 00000030
  01010000 00780006 00080000 00010210  .....x.......... 00000040
  00650000 00030000 00010303 00000901  .e.............. 00000050
  03050902 42910443 03000847 64454904  ....B..C...GdEI. 00000060
  00020800 6B262824 06070011 86050101  ....k&($........ 00000070
  01A01961 17A10906 07040000 01002603  ...a..........&. 00000080
  A2030201 00A305A1 03020100 6C15A213  ............l... 00000090
  02010130 0E020153 30090407 012CB570  ...0...S0....,.p 000000A0
  34D02700 0000                        4.'...           000000B0
< Ethernet (14 bytes) :: DestinationMAC = 00:27:0e:34:ca:59 , SourceMAC = 00:24:21:7f:80:9b , Type = 0x800 , >
< IP (20 bytes) :: Version = 4 , HeaderLength = 5 , DiffServicesCP = 0 , ExpCongestionNot = 0 , TotalLength = 168 , Identification = 0x0 , Flags = 2 , FragmentOffset = 0 , TTL = 64 , Protocol = 0x84 , CheckSum = 0xb38c , SourceIP = 192.168.2.125 , DestinationIP = 192.168.2.120 , >
< SCTP (12 bytes) :: SrcPort = 2905 , DstPort = 2905 , VerTag = 426452265 , CheckSum = 54156 , >
< RawLayer (136 bytes) :: Payload = \x0\x3\x0\x88\x25\xf\x66\x25\x0\x1\x0\x8\x0\x0\x0\x3\x1\x0\x1\x1\x0\x0\x0\x78\x0\x6\x0\x8\x0\x0\x0\x1\x2\x10\x0\x65\x0\x0\x0\x3\x0\x0\x0\x1\x3\x3\x0\x0\x9\x1\x3\x5\x9\x2\x42\x91\x4\x43\x3\x0\x8\x47\x64\x45\x49\x4\x0\x2\x8\x0\x6b\x26\x28\x24\x6\x7\x0\x11\x86\x5\x1\x1\x1\xa0\x19\x61\x17\xa1\x9\x6\x7\x4\x0\x0\x1\x0\x26\x3\xa2\x3\x2\x1\x0\xa3\x5\xa1\x3\x2\x1\x0\x6c\x15\xa2\x13\x2\x1\x1\x30\xe\x2\x1\x53\x30\x9\x4\x7\x1\x2c\xb5\x70\x34\xd0\x27\x0\x0\x0>



i need your kind help in decoding it

High Regards
Umar

--
You received this message because you are subscribed to the Google Groups "libcrafter" group.
To unsubscribe from this group and stop receiving emails from it, send an email to libcrafter+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Esteban Pellegrino

unread,
Aug 21, 2013, 8:37:07 PM8/21/13
to libcr...@googlegroups.com
Sorry, I made I mistake... Actually, the offset member points to the first byte after the current parsed layer (i.e. the data after the SCTP layer, which will be the chunk). So, the code will be:

void SCTP::ParseLayerData(ParseInfo* info) {

 /* This will point to the first byte of the SCTP layer*/
 byte* sctp_chunk = info->raw_data + info->offset;

Rana Umar

unread,
Aug 26, 2013, 1:32:19 AM8/26/13
to libcr...@googlegroups.com
hello

Dear i want to know which architectural and design(s) pattern does libcrafter use / follows ?

Regards 

Esteban Pellegrino

unread,
Aug 26, 2013, 7:03:49 PM8/26/13
to libcr...@googlegroups.com
Hi,

libcrafter architecture is pretty simple. The most important classes are "Layer" and "Packet". Each Layer (i.e. protocols) is registered in a factory and the packet decoder instantiate the concrete layer in the parsing process (and the result is a decoded packet).

The packet crafting is more simple, each layer has a virtual method to write the bytes on a raw buffer (which is put on the wire).

Best,
Esteban

Rana Umar

unread,
Aug 27, 2013, 8:25:01 AM8/27/13
to libcr...@googlegroups.com

Hi

Any hint regarding how to decode layers having variable length header . if this feature is not supported what changes should i made to make this feature work

regards

Esteban Pellegrino

unread,
Aug 28, 2013, 8:40:18 PM8/28/13
to libcr...@googlegroups.com
You will have to create a new type of Field with variable size (you can derive from FieldInfo, see below), and derive from Layer a" DynamicLayer" class where the internal buffer is grown on demand when fields are added to the layer (right now is defined on the constructor with a fixed size).

In this folder you have examples of different fields : https://github.com/pellegre/libcrafter/tree/master/libcrafter/crafter/Fields

A Layer have a field container as a member where all fields are pushed. Each field has its own method to parse and write data to/from the wire. If you want to make it dynamic, you will have to peek the raw bytes on the packet and look for the amount of bytes of the field. Then, you set that information on the Field, push it into the DymamicLayer, and the layer decoder will now how much bytes should parse for each field.

Best,
Esteban
Reply all
Reply to author
Forward
0 new messages