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

Avatar for Vlad Grigorescu

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