Wireshark-dev: Re: [Wireshark-dev] [RFC] Vendor-specific dissector extension for EtherNet/IP
From: Michael Mann <mmann78@xxxxxxxxxxxx>
Date: Mon, 4 Sep 2017 14:26:48 -0400
Hopefully inlining comments will work...
 
 
-----Original Message-----
From: Samuel GROOT <groot.samuel@xxxxxxxxx>
To: Developer support list for Wireshark <wireshark-dev@xxxxxxxxxxxxx>
Cc: Michael Mann <mmann78@xxxxxxxxxxxx>
Sent: Thu, Aug 31, 2017 8:58 am
Subject: Re: [Wireshark-dev] [RFC] Vendor-specific dissector extension for EtherNet/IP

Hi,

I was already looking at CCO and the heuristic function when I received
your last email.
After some reading of the C dissector and some tests I arrived at the
same conclusions, I will see now what I will implement, and how.

> In the CIP specs, they focus on <identifier> being an object class and
> instance, but
> for some Rockwell PLCs, the <identifier> is just a string (and there is
> no class in the message).
> That's what I mean when I refer to "classless" requests.

I never encountered this case but indeed this notion of segment is
present in the CIP documentation, I didn't read it enough!
 
 
I believe the only time you will encounter this is with Rockwell PLCs and its use is starting to go towards "legacy"
status (not deprecated I'm guessing just because of backwards compatibility), so I wouldn't worry about it too much. 
 
 

> >> 2. If you want to add vendor specific services to already supported
> >> objects, that would be more difficult to do in Lua because there isn't a
> >> dissector table hook for them.  I'm not sure there would be a way to
> >> handle the "general" case of registering service + class into a
> >> dissector table, but you could add dissector tables (patching
> >> packet-cip.c) for specific objects (Identity, ConnectionManager, etc)
> >> and submit just that part as a patch for inclusion in base Wireshark
> code.
> This is where I started to steer you incorrectly.  The heuristic
> functionality should
> be able to handle this case without issue.

I think in this case it would be the dissector, since the heuristic only
triggers for common services (and we want to support vendor-specific
services for common objects).
 
 
I believe what you want is:
1. A dissector for each vendor specific object
2. A (single) heuristic dissector for all vendor specific objects that use common services.
I thought I could simplify the existing CIP dissector and only use one heuristic dissector (and just use a switch
statement for the object IDs), but the "built in" objects have a way to list their attributes so they can be dissected
by the common service dissection routines (GAA, GAS, GAL, etc).  I think part of the reason I never added an
"external" interface for the attribute lists was I wasn't sure how to make it generic enough to fit into existing
Wireshark APIs.
Your 1 heuristic dissection function should look like dissect_class_cco_heur(), but have a switch statement for
calling each of the object classes after you've parsed the EPATH for a request.  A "response" should be handled
exactly like the CCO object (but I'm not sure how all of that would translate to Lua, trying to directly access a
C structure from p_get_proto_data)
 


> I think the intent of the cip.data_segment.iface dissector table was to
> handle the "string"
> identifiers I mentioned with the Rockwell PLCs.  It's probably something
> that should actually
> be removed from the dissector.

It makes sense. Why remove it though, since it can be used to support
"classless" services?
 
 
 
Architecturally it seems simpler to have a heuristic function that registers with "cip.sc" table and dissects the EPATH
for the "classless" services to determine if they are truly "classless".  Again, the only ones that use this is Rockwell
PLCs and because the information isn't in the CIP specs, I consider it proprietary, much like vendor-specific objects.


> >> 4. I believe Lua will "override" any value registered to a dissector
> >> table, so you could write the "vendor specific" portion, for say the
> >> Identity object, but then you'd have to duplicate all of the dissection
> >> currently being done for it in your Lua script.
> > I did test with setting a lua dissector for Identity in the
> cip.class.iface, and on packets
> > with common services it wasn't triggered (I didn't have packets with
> vendor-specific
> > services call for Identity).  So apparently it does not override the
> default dissector
> > with the lua one (at least with a common service).
> Again, this issue can be handled with the heuristic dissection mentioned
> above.

True in this case.


So to clarify I could now cover the following cases:
- Vendor-specific class, vendor-specific services with a dissector (one
per class)
- Vendor-specific class, common services with a heuristic (to handle the
epath and attributes)
- Common class, vendor-specific services with a dissector (again, one
per class)

An implementation in lua seems extremely tedious, since I will have to
re-write most of the dissection code already present in C (status,
epath, and attribute-related services).
 
 
 
I hope you can simplify some of the dissection with the single heuristic function and a switch statement.
But yes, you would have to rewrite (copy/paste) the value_strings used in the dissector.
There is also the option of writing a C plugin (which I've done before and I know others have), but that is
typically tied to a Wireshark release version (because APIs aren't guaranteed to stay the same between
major releases)
In general, I would discourage adding vendor specific object code to the Wireshark source base because
of the high probability of collision (with another vendor's objects).  Unless you're one of the large PLC
manufacturers, you probably only have a handful of objects, and like most vendors you probably started
at the bottom with 0x7F.