Hui Lin_Some question on Binpac


I have been working on modbus protocol analyzer by Binpac, which is an application-level protocol used in SCADA network. The protocol itself is not complex and it is not hard to express it in Binpac. However, this protocol in application level does not contain the information which can tell whether the parsing packet is a “request” or a “response”. For example, in HTTP protocol, the http header will include such information. But for this protocol, the headers for both the request and response are the same.

So if the traffic dump that I am using for the testing starts with the request, then the analyzer can properly parse it. However, if the traffic dump starts with the response, then the analyzer will not be properly parsing the packet. So I am wondering how to resolve this problem in my protocol analyzer.



tell whether the parsing packet is a "request" or a "response". For example,
in HTTP protocol, the http header will include such information.

While that's right, BinPAC/Bro is actually not using that information
to decide which side it's parsing. Generally, Bro always considers the
originator of a connection to be the client side[1], and then it
drives BinPAC parsing accordingly.

Take a look at http-procotol.pac, there's this piece:

    type HTTP_PDU(is_orig: bool) = case is_orig of {
        true -> request: HTTP_Request;
        false -> reply: HTTP_Reply;

And in http-analyzer.pac, there is:

    connection HTTP_Conn(bro_analyzer: BroAnalyzer) {
        upflow = HTTP_Flow(true);
        downflow = HTTP_Flow(false);

    flow HTTP_Flow(is_orig: bool) {
        flowunit = HTTP_PDU(is_orig) withcontext (connection, this);


When Bro passes in data, it tells BinPAC which of these flows to use.


    void HTTP_Analyzer_binpac::DeliverStream(int len, const u_char* data, bool orig)
        // orig is true here if it's originator-side data.
        interp->NewData(orig, data, data + len);

There's a skeleton Bro analyzer on the web page that's based on
binpac. If you us that skeleton, you should pretty much automatically
get this direction stuff right. See


[1] With a few additional heuristics for corner-cases.


I do follow the Binpac sample analyzer. And I also notice this part of code which use the value of is_orig to decide whether the packet is the request.

When Bro is used to parse network traffic on the network card, it is obvious to see what traffic are coming in and what traffic are going out. But i am using the traffic dump to test, so how can Binpac know which traffic is coming in and going out? I use the Wireshark and actually, wireshark can tell whether the packet is a request or response.

Also according to your logic, the Bro considers the originator of the traffic as the client and then this makes sense to my situation. Since the first packet in that dump is a response (without any request before it) and Binpac will consider the source of the packet as the client and the receiver as the server, then this can successfully fool the Binpac to think that this packet is a request. Then the exception can happen.



Yes, in general that's a problem. Here's what Bro (and thus in turn
BinPAC) is doing:

    (1) by default, the first packet of a new connection indicates the

    (2) it however also looks at well-known ports: if with (1), the
        connection would have a well-known port on the originator-side but
        not on the responder-side, it flips the direction.

Is there a well-known port for this protocol? If so, add it to
policy/server-ports.bro and it should work. If not, you can trigger
the flipping yourslef by calling Connection::FlipRoles(), but you'd
need some heuristic to decide who's the client. BinPAC doesn't have
anything built in for that (yet). Also, flipping should occur as early
as possible, as otherwise things may get mixed up.


Eek, good reminder. I need to put that back!