Hi , I am very glad to write this email . I am a user of bro and recently I 
start to use BinPAC which is a subcomponent of bro . After learning the syntax 
of BinPAC , I wrote some simple BinPAC programs and tested them . I got a 
problem during the test and it really confused me . So I am writing to you and 
hope to get your help . I will describe my problem below .





My BinPAC version is 0.47 .




In the test I have two machines , A and B . One process on machine A sends 
messages to another process on machine B once per second . the message is in 
this format :

la(uint32) + lb (uint32) + s(a random string whose length is not fixed)

In the message , "la" and "lb" are both the length of the string "s" . For 
example , la = 26 , lb = 26 , s = "abcdefghijklmnopqrstuvwxyz" . Another 
example , la = 10 , lb = 10 , s = "helloworld" . So I wrote a BinPAC program 
(see file_1.pac in attachment) and it worked as expected . But when I made a 
small change to the BinPAC program (see file_2.pac in attachment), a bug 
existed .


In the first case , I defined a type "header" which contains "la : unint32" and 
"lb : uint32" and I defined another type "body" which only contains "s : 
bytestring" . And I defined a high-level type which contains "header" and 
"body" . Then I print out "la" and the length of "s" . It showed that the 
program worked properly , the output is like this :

238 238
309 309
311 311
339 339
344 344
252 252
290 290
312 312
298 298
300 300
281 281
...

That is what I want . The first number in each line is "la" and the second 
number is the length of "s" .



But when I didn't define the "header" type but wrote "la : uint32 ; lb : 
uint32" in the high-level type directly instead , it failed to work , I mean , 
nothing was printed out .




In "file_2.pac" , I wrote like this :

type trans_pdu(is_orig: bool) = record {
    la: uint32 &byteorder=bigendian;
    lb: uint32 &byteorder=bigendian;
    body: trans_body(x) &requires(x);
} &let{
    x = la;
} &length = x + 8;


I read the file generated by binpac ("file_2.cc") , and I added 2 lines into 
"file_2.cc" to debug it to see what would happen (the additional codes just 
print out buffering state , the address of "t_begin_of_data" , the address of 
"t_end_of_data" and "throw") . The following is part of the code of "file_2.cc" 
. Only the two "printf" sentences are added by me .

bool trans_pdu::ParseBuffer(flow_buffer_t t_flow_buffer, Contexttrans * 
t_context)
    {
    bool t_val_parsing_complete;
    t_val_parsing_complete = false;
    const_byteptr t_begin_of_data = t_flow_buffer->begin();
    const_byteptr t_end_of_data = t_flow_buffer->end();
           printf("buffering state: %d  t_begin_of_data: %d  t_end_of_data: %d 
\n" , buffering_state_ , (void*)t_begin_of_data , (void*)t_end_of_data);
    switch ( buffering_state_ )
        {
        case 0:
            if ( buffering_state_ == 0 )
                {
                t_flow_buffer->NewFrame(4, false);
                buffering_state_ = 1;
                }
            buffering_state_ = 1;
            break;
        case 1:
            {
            buffering_state_ = 2;
            // Checking out-of-bound for "trans_pdu:lb"
            if ( (t_begin_of_data + 4) + (4) > t_end_of_data || 
(t_begin_of_data + 4) + (4) < (t_begin_of_data + 4) )
                {
                               printf("throw\n");
                // Handle out-of-bound condition
                throw binpac::ExceptionOutOfBound("trans_pdu:lb",
                    (4) + (4),
                    (t_end_of_data) - (t_begin_of_data));
                }
            // Parse "la"
            la_ = FixByteOrder(bigendian, *((uint32 const *) 
(t_begin_of_data)));
            // Evaluate 'let' and 'withinput' fields
            x_ = la();
            t_flow_buffer->GrowFrame(x() + 8);
            }
            break;
        case 2:
            BINPAC_ASSERT(t_flow_buffer->ready());
            if ( t_flow_buffer->ready() )
                {
                
                // Parse "lb"
                lb_ = FixByteOrder(bigendian, *((uint32 const *) 
((t_begin_of_data + 4))));
                // Evaluate 'let' and 'withinput' fields
                
                // Parse "body"
                body_ = new trans_body(x());
                int t_body__size;
                t_body__size = body_->Parse((t_begin_of_data + 8), 
t_end_of_data);
                // Evaluate 'let' and 'withinput' fields
                
                t_val_parsing_complete = true;
                if ( t_val_parsing_complete )
                    {
                    // Evaluate 'let' and 'withinput' fields
                    proc_ = t_context->flow()->proc_sample_message(this);
                    }
                BINPAC_ASSERT(t_val_parsing_complete);
                buffering_state_ = 0;
                }
            break;
        default:
            BINPAC_ASSERT(buffering_state_ <= 2);
            break;
        }
    return t_val_parsing_complete;


    }




void trans_flow::NewData(const_byteptr t_begin_of_data, const_byteptr 
t_end_of_data)

    {

        ......

        ......


        while ( ! t_dataunit_parsing_complete && flow_buffer_->ready() )
                {
                const_byteptr t_begin_of_data = flow_buffer()->begin();
                const_byteptr t_end_of_data = flow_buffer()->end();
                t_dataunit_parsing_complete = 
dataunit_->ParseBuffer(flow_buffer(), context_);
                if ( t_dataunit_parsing_complete )
                    {
                    // Evaluate 'let' and 'withinput' fields
                    }
                }


        ......

        ......


    }



and the following is the output :

buffering state: 0  t_begin_of_data: 44665856  t_end_of_data: 44665856
buffering state: 1  t_begin_of_data: 44665856  t_end_of_data: 44665860
throw
buffering state: 0  t_begin_of_data: 44669328  t_end_of_data: 44669328
buffering state: 1  t_begin_of_data: 44669328  t_end_of_data: 44669332
throw
buffering state: 0  t_begin_of_data: 44687568  t_end_of_data: 44687568
buffering state: 1  t_begin_of_data: 44687568  t_end_of_data: 44687572
throw
buffering state: 0  t_begin_of_data: 44688176  t_end_of_data: 44688176
buffering state: 1  t_begin_of_data: 44688176  t_end_of_data: 44688180
throw
...








I guess that in " case 0 " , the sentence " t_flow_buffer->NewFrame(4, false) " 
is used to create a 4-byte frame to parse "la" , since "la" occupies the first 
4 bytes of the message and BinPAC need it evaluate the length of the message ? 
After this operation , "t_begin_of_data " points to the begin of the message 
and "t_end_of_data" points to the end of "la" .  But then " case 1 " will take 
place . "lb" will be checked whether out-of-bound . "t_begin_of_data + 4" is 
the begin of "lb" ,  " 4 " is the length of "lb" , but "t_end_of_data" still 
points to the end of la . So  "(t_begin_of_data + 4) + (4) > t_end_of_data"  
was met , and the program didn't go ahead . However , that is only the direct 
reason but not the source reason . I guess the source reason is that I didn't 
write the BinPAC code in the correct way somewhere or maybe there is a small 
bug in BinPAC .




I really really hope to use BinPAC to deal with some protocol analysis . I 
tried to read the source code of BinPAC but failed to understand . I don't know 
what to do and I really want to get your help !

Wish to get your reply !




Good luck !

Yunchao Chen

2018.2.27

Attachment: file_2.pac
Description: Binary data

Attachment: file_1.pac
Description: Binary data

_______________________________________________
bro-dev mailing list
bro-dev@bro.org
http://mailman.icsi.berkeley.edu/mailman/listinfo/bro-dev

Reply via email to