This is a static archive of our old Q&A Site. Please post any new questions and answers at ask.wireshark.org.

SSL Lua dissector - how?

0

I have a protocol that is over SSL that I'd like to dissect. I'm having a hard time just conceptually figuring out how one goes about doing this. I've created a dissector for the right port that gets a reference to the ssl dissector and then calls it. I've also tried registering it as a post-dissector. In both cases the SSL dissector seems to work a-ok (I have a client-random/master key file set up in the SSL protocol preferences) and I can see my protocol's raw data in the Follow SSL Stream window. But I'd like to dissect that protocol and get at the decrypted data.

I'm guessing that what I'm supposed to do is get a reference to one of the fields populated by the SSL dissector like ssl.segment, ssl.segment.data, ssl.reassembled.data, etc and then work with that. But whether I call the ssl dissector explicitly or use a post-dissector, those variables are always nil.

protocol_foo = Proto("foo", "Foo protocol")
port = 4172

g_field_segment = Field.new("ssl.segment") g_field_segment_data = Field.new("ssl.segment.data") g_field_segments = Field.new("ssl.segments") g_field_reassembled_data = Field.new("ssl.reassembled.data")

function protocol_foo.dissector(tvb, pinfo, root)

print("====== protocol_foo")

for k,v in pairs({ g_field_segment, g_field_segment_data, g_field_segments, g_field_reassembled_data }) do
    if v() ~= nil then
        print("Field " .. v.name .. " is NOT nil")
    else
        print("Field " .. v.name .. " is nil")
    end
end

end

– post-dissector registration local ssl_dissector = Dissector.get("ssl") local dissector_table_tcp = DissectorTable.get("tcp.port") dissector_table_tcp:add(port, ssl_dissector) register_postdissector(protocol_foo)

or calling explicitly …

protocol_foo = Proto("foo", "Foo protocol")
port = 4172

g_field_segment = Field.new("ssl.segment") g_field_segment_data = Field.new("ssl.segment.data") g_field_segments = Field.new("ssl.segments") g_field_reassembled_data = Field.new("ssl.reassembled.data")

function protocol_foo.dissector(tvb, pinfo, root)

print("====== protocol_foo")

local ssl_dissector = Dissector.get("ssl")
ssl_dissector:call(tvb, pinfo, root)

for k,v in pairs({ g_field_segment, g_field_segment_data, g_field_segments, g_field_reassembled_data }) do
    if v() ~= nil then
        print("Field " .. v.name .. " is NOT nil")
    else
        print("Field " .. v.name .. " is nil")
    end
end

end

– dissector registration local dissector_table_tcp = DissectorTable.get("tcp.port") dissector_table_tcp:add(port, protocol_foo)

Other fields, like ssl.handshake.* seem to be populated well enough, but not the ones I want. Am I just going about this the wrong way?

Update: I can appreciate that this seems like an elementary question, but I can’t find any examples on the wireshark site, on the web, or in any of the questions and answers in this forum or on SO that do this - I can’t find an example of how to dissect the decrypted output of the ssl dissector (although I’ve read many questions on this forum that seem to indicate that people are in fact doing this successfully).

asked 19 Dec ‘16, 19:56

tedmiddleton's gravatar image

tedmiddleton
6114
accept rate: 0%

edited 21 Dec ‘16, 16:49


2 Answers:

3

I think you're going about it backwards. Rather than calling SSL from your dissector I'd suggest:

  1. Write your dissector as a normal dissector (named foo).
  2. Configure the SSL dissector to decode your port as foo (in the same place where you specify the IP address and key file)

Your protocol dissector will now be called with a TVB containing the (decrypted) data. Your dissector can, at this point, be unaware that SSL was even involved.

answered 03 Jan '17, 15:09

JeffMorriss's gravatar image

JeffMorriss ♦
6.2k572
accept rate: 27%

I'm a bit confused - when you say, "in the same place where you specify the IP address and key file," do you mean the Wireshark SSL protocol preferences? Because that's where I've configured the master key file I'm using. I don't seem to see an option for sub-dissection in those preferences?

(10 Jan '17, 16:18) tedmiddleton

In that case see the answer to this question.

Though @koundi's answer is probably the better way (if your port number is constant).

(11 Jan '17, 06:24) JeffMorriss ♦

2

You should consider redesigning your flow. If your protocol works on top of SSl, then the ssl dissector should be called first. Let the TCP dissector worry about that.

All you need to do while registering proto_foo is to add it to the dissector table using ssl.port.

Instead of

local dissector_table_tcp = DissectorTable.get("tcp.port") dissector_table_tcp:add(port, protocol_foo)

you can do

local dissector_table_ssl = DissectorTable.get("ssl.port") dissector_table_ssl:add(port, protocol_foo)

and not worry about calling the ssl dissector altogether. Now the decrypted data if available will be passed on to the foo dissector where you will do your processing.

answered 11 Jan '17, 04:37

koundi's gravatar image

koundi
9791119
accept rate: 0%

"bad argument #1 to 'get' (DissectorTable_get: no such dissector_table)". Wireshark doesn't seem to like "ssl.port"?

(17 Jan '17, 09:37) tedmiddleton
1

Well it didn't always support ssl.port. I'm guessing you're using 2.0.x or earlier? In that case you'll need to use the solution described in my answer (or just upgrade :-)).

(17 Jan '17, 10:54) JeffMorriss ♦

Yup - I was using 2.0.x. I've upgraded to 2.2 and I no longer get the "no such dissector_table" error with ssl.port. But wireshark/tshark still isn't decoding those packets as SSL or my protocol; at least not on first encounter (when I load the .pcap file). I have to tell wireshark to "decode as..." SSL before it tries decoding and decrypting the packets; even then, it doesn't hand the result off to my dissector.

(25 Jan '17, 15:42) tedmiddleton

The Decode-As bit will still be necessary. Registering yourself for ssl.port X does not cause the SSL dissector to register for tcp.port X.

I don't know why your dissector wouldn't be called though. Are you sure you registered it for the appropriate port? Is any other dissector registered on that port? You can check by looking at the View->Internals->Dissector Tables dialog. Look in the Integer table for SSL TCP dissector. You should see your Lua dissector there under port X.

(25 Jan '17, 17:49) JeffMorriss ♦