Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How to Write a Protocol Analyzer

How to Write a Protocol Analyzer

From the 2013 Bro Exchange

Vlad Grigorescu

August 07, 2013
Tweet

More Decks by Vlad Grigorescu

Other Decks in Programming

Transcript

  1. What Do Analyzers Do? • Parse the network traffic •

    Generate events 2 • Handle the events • Generate logs Friday, October 18, 13
  2. What Do Analyzers Do? • Parse the network traffic •

    Generate events 2 • Handle the events • Generate logs Core Layer Script Layer Friday, October 18, 13
  3. Parsing Traffic Goal: Convert packet payload to data structure 3

    <15>Mar  19  14:06:37  scobel-­‐113  :  debug... priority (8*facility + severity) message Friday, October 18, 13
  4. 4 Parsing Traffic struct  syslog_data  {  int      facility;

                                             int      severity;                                          char*  msg;    }; /*  Parsing  code  */ <15>Mar 19 14:06:37 scobel-113 : debug... Friday, October 18, 13
  5. binpac • A domain-specific language for protocol parsing • Build

    “types” to represent logical data structures • .pac files get processed into C++ source code 5 Friday, October 18, 13
  6. 6 Parsing Traffic type  Syslog_Message  =  record  {    

               PRI:  Syslog_Priority;                msg:  bytestring  &restofdata; }  &byteorder  =  littleendian; <15>Mar 19 14:06:37 scobel-113 : debug... Friday, October 18, 13
  7. type  Syslog_Priority  =  record  {      lt    

       :  uint8;      tmppri:  RE/[[:digit:]]+/;      gt        :  uint8; }   Parsing Traffic 7 <15>Mar 19 14:06:37 scobel-113 : debug... ; Friday, October 18, 13
  8. type  Syslog_Priority  =  record  {      lt    

       :  uint8;      tmppri:  RE/[[:digit:]]+/;      gt        :  uint8; }      &let  {      pri:  int=bytestring_to_int(tmppri,  10);       Parsing Traffic 7 <15>Mar 19 14:06:37 scobel-113 : debug... }; Friday, October 18, 13
  9. type  Syslog_Priority  =  record  {      lt    

       :  uint8;      tmppri:  RE/[[:digit:]]+/;      gt        :  uint8; }      &let  {      pri:  int=bytestring_to_int(tmppri,  10);       Parsing Traffic 7 <15>Mar 19 14:06:37 scobel-113 : debug... //  pri  ==  facility*8  +  severity facility:  int  =  pri  /  8; severity:  int  =  pri  %  8; }; Friday, October 18, 13
  10. Generating Events Whenever we see a syslog message, generate the

    syslog_message event: syslog_message(                        conn                facility                severity                          msg )   9 Friday, October 18, 13
  11. Generating Events Whenever we see a syslog message, generate the

    syslog_message event: syslog_message(                        conn                facility                severity                          msg )   9 :  connection, :  int, :  int, :  string Friday, October 18, 13
  12. 10 Generating Events event  syslog_message(%          

                       c:  connection,                facility:  int,                severity:  int,                          msg:  string %);   Friday, October 18, 13
  13. 10 Generating Events event  syslog_message(%          

                       c:  connection,                facility:  int,                severity:  int,                          msg:  string %);    √  events.bif - Defines the events Friday, October 18, 13
  14. 11 Generating Events type  Syslog_Message  =  record  {    PRI:

     Syslog_Priority;    msg:  bytestring  &restofdata; }  &byteorder  =  littleendian; type  Syslog_Priority  =  record  {    lt        :  uint8;    tmppri:  RE/[[:digit:]]+/;    gt        :  uint8; }  &let  {    pri:    int  =  bytestring_to_int(val,  10);    facility:  int  =  pri  /  8;    severity:  int  =  pri  %  8;    }; Friday, October 18, 13
  15.      function  proc_syslog_msg(facility:  count,          

                                               severity:  count,                                                      msg:  bytestring  ):       Generating Events 12 Friday, October 18, 13
  16. 13 Generating Events      function  proc_syslog_msg(facility:  count,    

                                                     severity:  count,                                                      msg:  bytestring  ):    bool  %{                %}   Friday, October 18, 13
  17. 14 Generating Events      function  proc_syslog_msg(facility:  count,    

                                                     severity:  count,                                                      msg:  bytestring  ):    bool  %{        BifEvent::generate_syslog_message(                connection()-­‐>bro_analyzer(),                connection()-­‐>bro_analyzer()-­‐>Conn(),                facility,  severity,                  bytestring_to_val(msg));                %}   Friday, October 18, 13
  18. 15 Generating Events      function  proc_syslog_msg(facility:  count,    

                                                     severity:  count,                                                      msg:  bytestring  ):    bool  %{        BifEvent::generate_syslog_message(                connection()-­‐>bro_analyzer(),                connection()-­‐>bro_analyzer()-­‐>Conn(),                facility,  severity,                  bytestring_to_val(msg));        return  true;        %}   Friday, October 18, 13
  19. 19 Generating Events refine  flow  Syslog_Flow  +=  {    function

     proc_syslog_msg(facility:  count,                                                      severity:  count,                                                      msg:  bytestring  ):    bool  %{        BifEvent::generate_syslog_message(                connection()-­‐>bro_analyzer(),                connection()-­‐>bro_analyzer()-­‐>Conn(),                facility,  severity,                  bytestring_to_val(msg));        return  true;        %} };   Friday, October 18, 13
  20. refine  typeattr  Syslog_Message  +=      &let  {    proc_syslog_message

     =        $context.flow.proc_syslog_msg(PRI.facility,                                                                    PRI.severity,                                                                    msg);    }; Generating Events 20 Friday, October 18, 13
  21. 21 Generating Events refine  flow  Syslog_Flow  +=  {    function

     proc_syslog_msg(facility:  count,  severity:  count,                                                      msg:  bytestring  ):  bool  %{        BifEvent::generate_syslog_message(            connection()-­‐>bro_analyzer(),              connection()-­‐>bro_analyzer()-­‐>Conn(),            facility,  severity,  bytestring_to_val(msg));        return  true;      %}  }; refine  typeattr  Syslog_Message  +=      &let  {  proc_syslog_message  =                $context.flow.proc_syslog_msg(PRI.facility,                                                                      PRI.severity,  msg);      }; Friday, October 18, 13
  22. 21 Generating Events refine  flow  Syslog_Flow  +=  {    function

     proc_syslog_msg(facility:  count,  severity:  count,                                                      msg:  bytestring  ):  bool  %{        BifEvent::generate_syslog_message(            connection()-­‐>bro_analyzer(),              connection()-­‐>bro_analyzer()-­‐>Conn(),            facility,  severity,  bytestring_to_val(msg));        return  true;      %}  }; refine  typeattr  Syslog_Message  +=      &let  {  proc_syslog_message  =                $context.flow.proc_syslog_msg(PRI.facility,                                                                      PRI.severity,  msg);      };  √  syslog-­‐analyzer.pac - Generates the events (and handles state) Friday, October 18, 13
  23. 22 What Do Analyzers Do? Parse the network traffic Generate

    events • Handle the events • Generate logs Core Layer Script Layer Friday, October 18, 13
  24. Handle Those Events! 23 module  Syslog; const  ports  =  {

     514/udp  }; redef  likely_server_ports  +=  {  ports  }; event  bro_init()  &priority=5      {      Analyzer::register_for_ports(                            Analyzer::ANALYZER_SYSLOG,                              ports);      } Friday, October 18, 13
  25. 24 Handle Those Events! event  syslog_message(c:  connection,      

                                         facility:  count,                                            severity:  count,                                            msg:  string)  &priority=5                {                print(fmt(“I  have  a  message!  %s”,  msg);                } Friday, October 18, 13
  26. Handle Those Events! 25 module  Syslog; const  ports  =  {

     514/udp  }; redef  likely_server_ports  +=  {  ports  }; event  bro_init()  &priority=5      {      Analyzer::register_for_ports(                            Analyzer::ANALYZER_SYSLOG,                              ports);      } event  syslog_message(c:  connection,                                            facility:  count,                                            severity:  count,                                            msg:  string)  &priority=5                {                print(fmt(“I  have  a  message!  %s”,  msg);                } Friday, October 18, 13
  27. Handle Those Events! 25 module  Syslog; const  ports  =  {

     514/udp  }; redef  likely_server_ports  +=  {  ports  }; event  bro_init()  &priority=5      {      Analyzer::register_for_ports(                            Analyzer::ANALYZER_SYSLOG,                              ports);      } event  syslog_message(c:  connection,                                            facility:  count,                                            severity:  count,                                            msg:  string)  &priority=5                {                print(fmt(“I  have  a  message!  %s”,  msg);                }  √  main.bro - Registers the analyzer, handles events, logs Friday, October 18, 13
  28. 26 Non-Standard Ports? signature  dpd_syslog  {    ip-­‐proto  ==  udp

       payload  /^<[0-­‐9][0-­‐9]?[0-­‐9]?>/    enable  "syslog" } Friday, October 18, 13
  29. 26 Non-Standard Ports? signature  dpd_syslog  {    ip-­‐proto  ==  udp

       payload  /^<[0-­‐9][0-­‐9]?[0-­‐9]?>/    enable  "syslog" }  √  dpd.sig - Defines DPD signatures Friday, October 18, 13
  30. Dealing with Errors 27 event  protocol_violation(        

         c:  connection,                atype:  Analyzer::Tag,                aid:  count,                reason:  string) Binpac  exception:  binpac  exception:      string  mismatch  at  src/analyzer/protocol/sip/ sip-­‐protocol.pac:61:      expected  pattern:  "(([^:  \t]+|\r\n))"    actual  data:  "" Friday, October 18, 13
  31. Bootstrapping Coming soon to a Github near you... 28 $

     ./start.py  tftp  “Trivial  FTP  Analyzer”  ~/bro Files  created.  TODO:  1)  src/analyzers/protocol/tftp/tftp-­‐protocol.pac  2)  src/analyzers/protocol/tftp/events.bif    3)  src/analyzers/protocol/tftp/tftp-­‐analyzer.pac  4)  scripts/base/protocols/tftp/main.bro  5)  scripts/base/protocols/tftp/dpd.sig Friday, October 18, 13
  32. 29 Extra Credit: State flow  My_Flow(is_orig:  bool)  {    %member{

           bool  server_hungry;    %}    %init{        server_hungry  =  T;    %}    function  proc_error(msg:  My_Type)  {        server_hungry  =  F; }; Friday, October 18, 13