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
file_2.pac
Description: Binary data
file_1.pac
Description: Binary data
_______________________________________________ bro-dev mailing list bro-dev@bro.org http://mailman.icsi.berkeley.edu/mailman/listinfo/bro-dev