Ethereal-dev: [Ethereal-dev] ntlmssp decoding
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Devin Heitmueller <dheitmueller@xxxxxxxxxxx>
Date: 05 Jul 2002 23:30:35 -0400
I now have a newfound appreciation for how much work goes into writing dissectors. I have made a few changes to further decode the DCERPC bind message to show ntlmssp fields. It has taken me about four hours to add three or four fields. I suspect this is either because I am doing something seriously wrong, or I am still in the learning curve. Would it be possible for someone to review my attached changes, and provide feedback? In particular, I am interested in knowing if I am using the correct primitives to decode the various data types, etc (for example, I still can't figure out how to display strings). I am very interested in going further, but I would appreciate a sanity check on what I have done thus far, so my patches do not get rejected. Any feedback would be greatly appreciated. Thanks, -- Devin Heitmueller Senior Software Engineer Netilla Networks Inc
Index: packet-dcerpc.c =================================================================== RCS file: /cvsroot/ethereal/packet-dcerpc.c,v retrieving revision 1.64 diff --unified -r1.64 packet-dcerpc.c --- packet-dcerpc.c 2002/06/24 09:23:39 1.64 +++ packet-dcerpc.c 2002/07/06 03:21:26 @@ -99,6 +99,34 @@ { 0, NULL } }; +static const value_string ntlmssp_message_types[] = { + { 1, "NTLMSSP_NEGOTIATE" }, + { 2, "NTLMSSP_CHALLENGE" }, + { 3, "NTLMSSP_AUTH" }, + { 4, "NTLMSSP_UNKNOWN" } +}; + +/* + * NTLMSSP negotiation flags + * Taken from Samba-TNG rpc_ntlmssp.h + */ +#define NTLMSSP_NEGOTIATE_UNICODE 0x00000001 +#define NTLMSSP_NEGOTIATE_OEM 0x00000002 +#define NTLMSSP_REQUEST_TARGET 0x00000004 +#define NTLMSSP_NEGOTIATE_SIGN 0x00000010 +#define NTLMSSP_NEGOTIATE_SEAL 0x00000020 +#define NTLMSSP_NEGOTIATE_LM_KEY 0x00000080 +#define NTLMSSP_NEGOTIATE_00000100 0x00000100 +#define NTLMSSP_NEGOTIATE_NTLM 0x00000200 +#define NTLMSSP_NEGOTIATE_00000400 0x00000400 +#define NTLMSSP_NEGOTIATE_00001000 0x00001000 +#define NTLMSSP_NEGOTIATE_00002000 0x00002000 +#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x00008000 +#define NTLMSSP_NEGOTIATE_NTLM2 0x00080000 +#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x00800000 +#define NTLMSSP_NEGOTIATE_128 0x20000000 +#define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000 + /* * Protection levels. */ @@ -381,6 +409,25 @@ static int hf_dcerpc_fragment_multiple_tails = -1; static int hf_dcerpc_fragment_too_long_fragment = -1; static int hf_dcerpc_fragment_error = -1; +static int hf_dcerpc_auth_ntlmssp = -1; +static int hf_ntlmssp_message_type = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_01 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_02 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_04 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_10 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_20 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_80 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_100 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_200 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_400 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_1000 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_2000 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_8000 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_80000 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_800000 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_20000000 = -1; +static int hf_dcerpc_ntlmssp_negotiate_flags_40000000 = -1; static gint ett_dcerpc = -1; static gint ett_dcerpc_cn_flags = -1; @@ -390,6 +437,7 @@ static gint ett_dcerpc_pointer_data = -1; static gint ett_dcerpc_fragments = -1; static gint ett_dcerpc_fragment = -1; +static gint ett_dcerpc_negotiate_flags = -1; fragment_items dcerpc_frag_items = { &ett_dcerpc_fragments, @@ -1298,6 +1346,89 @@ } static int +dissect_dcerpc_ntlmssp_negotiate (tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *dcerpc_tree, + e_dce_cn_common_hdr_t *hdr) +{ + guint32 negotiate_flags; + proto_tree *negotiate_flags_tree = NULL; + proto_item *tf = NULL; + + // NTLMSSP Negotiate Flags + negotiate_flags = tvb_get_letohs (tvb, offset); + tf = proto_tree_add_uint (dcerpc_tree, + hf_dcerpc_ntlmssp_negotiate_flags, + tvb, offset, 4, negotiate_flags); + negotiate_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_01, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_02, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_04, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_10, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_20, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_80, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_100, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_200, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_400, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_1000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_2000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_8000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_80000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_800000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_20000000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_40000000, tvb, offset, 4, negotiate_flags); + + offset +=4; + + + return offset; +} + +static int +dissect_dcerpc_ntlmssp_challenge (tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *dcerpc_tree, + e_dce_cn_common_hdr_t *hdr) +{ + guint32 negotiate_flags; + proto_tree *negotiate_flags_tree = NULL; + proto_item *tf = NULL; + + // Skip over the two unknown fields + offset += 8; + + // NTLMSSP Negotiate Flags + negotiate_flags = tvb_get_letohs (tvb, offset); + tf = proto_tree_add_uint (dcerpc_tree, + hf_dcerpc_ntlmssp_negotiate_flags, + tvb, offset, 4, negotiate_flags); + negotiate_flags_tree = proto_item_add_subtree (tf, ett_dcerpc_negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_01, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_02, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_04, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_10, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_20, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_80, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_100, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_200, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_400, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_1000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_2000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_8000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_80000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_800000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_20000000, tvb, offset, 4, negotiate_flags); + proto_tree_add_boolean (negotiate_flags_tree, hf_dcerpc_ntlmssp_negotiate_flags_40000000, tvb, offset, 4, negotiate_flags); + + offset +=4; + + proto_tree_add_text (dcerpc_tree, tvb, offset, 8, "NTLM Challenge"); + offset += 8; + proto_tree_add_text (dcerpc_tree, tvb, offset, 8, "Reserved"); + offset += 8; + + return offset; +} + +static int dissect_dcerpc_cn_auth (tvbuff_t *tvb, packet_info *pinfo, proto_tree *dcerpc_tree, e_dce_cn_common_hdr_t *hdr, int *auth_level_p) { @@ -1339,8 +1470,22 @@ offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep, hf_dcerpc_auth_ctx_id, NULL); - proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, "Auth Data"); + // proto_tree_add_text (dcerpc_tree, tvb, offset, hdr->auth_len, "Auth Data"); + // djh debug + /* NTLMSSP constant (skip over the string) */ + offset += 8; + + // NTLMSSP Message Type + hdr->ntlmssp_message_type = tvb_get_letohs (tvb, offset); + offset = dissect_dcerpc_uint32 (tvb, offset, pinfo, dcerpc_tree, hdr->drep, + hf_ntlmssp_message_type, NULL); + + if (hdr->ntlmssp_message_type == 1) + offset = dissect_dcerpc_ntlmssp_negotiate (tvb, offset, pinfo, dcerpc_tree, &hdr); + else if (hdr->ntlmssp_message_type == 2) + offset = dissect_dcerpc_ntlmssp_challenge (tvb, offset, pinfo, dcerpc_tree, &hdr); + /* figure out where the auth padding starts */ offset = hdr->frag_len - (hdr->auth_len + 8 + auth_pad_len); if (offset > 0 && auth_pad_len) { @@ -3427,6 +3572,46 @@ { &hf_dcerpc_fragment_error, { "Defragmentation error", "dcerpc.fragment.error", FT_NONE, BASE_NONE, NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }}, + { &hf_dcerpc_auth_ntlmssp, + { "NTLMSSP identifier", "dcerpc.auth_ntlmssp", FT_STRING, BASE_NONE, NULL, 0x0, "NTLMSSP Identifier", HFILL }}, + + { &hf_ntlmssp_message_type, + { "NTLM Message Type", "dcerpc.ntlmssp.messagetype", FT_UINT32, BASE_HEX, VALS(ntlmssp_message_types), 0x0, "", HFILL }}, + + { &hf_dcerpc_ntlmssp_negotiate_flags, + { "NTLM SSP Negotiate Flags", "dcerpc.negotiateflags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_01, + { "Negotiate UNICODE", "dcerpc.ntlmssp.negotiateunicode", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_UNICODE, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_02, + { "Negotiate OEM", "dcerpc.ntlmssp.negotiateoem", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_OEM, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_04, + { "Request Target", "dcerpc.ntlmssp.requesttarget", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_REQUEST_TARGET, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_10, + { "Negotiate Sign", "dcerpc.ntlmssp.negotiatesign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SIGN, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_20, + { "Negotiate Seal", "dcerpc.ntlmssp.negotiateseal", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_SEAL, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_80, + { "Negotiate Lan Manager Key", "dcerpc.ntlmssp.negotiatelmkey", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_LM_KEY, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_100, + { "Negotiate 0x00000100", "dcerpc.ntlmssp.negotiate00000100", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000100, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_200, + { "Negotiate NTLM key", "dcerpc.ntlmssp.negotiatentlm", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_400, + { "Negotiate 0x00000400", "dcerpc.ntlmssp.negotiate00000400", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00000400, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_1000, + { "Negotiate 0x00001000", "dcerpc.ntlmssp.negotiate00001000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00001000, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_2000, + { "Negotiate 0x00002000", "dcerpc.ntlmssp.negotiate00002000", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_00002000, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_8000, + { "Negotiate Always Sign", "dcerpc.ntlmssp.negotiatealwayssign", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_ALWAYS_SIGN, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_80000, + { "Negotiate NTLM2 key", "dcerpc.ntlmssp.negotiatentlm2", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_NTLM2, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_800000, + { "Negotiate Target Info", "dcerpc.ntlmssp.negotiatetargetinfo", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_TARGET_INFO, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_20000000, + { "Negotiate 128", "dcerpc.ntlmssp.negotiate128", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_128, "", HFILL }}, + { &hf_dcerpc_ntlmssp_negotiate_flags_40000000, + { "Negotiate Key Exchange", "dcerpc.ntlmssp.negotiatekeyexch", FT_BOOLEAN, 32, TFS (&flags_set_truth), NTLMSSP_NEGOTIATE_KEY_EXCH, "", HFILL }}, }; static gint *ett[] = { &ett_dcerpc, @@ -3437,6 +3622,7 @@ &ett_dcerpc_pointer_data, &ett_dcerpc_fragments, &ett_dcerpc_fragment, + &ett_dcerpc_negotiate_flags, }; module_t *dcerpc_module; Index: packet-dcerpc.h =================================================================== RCS file: /cvsroot/ethereal/packet-dcerpc.h,v retrieving revision 1.18 diff --unified -r1.18 packet-dcerpc.h --- packet-dcerpc.h 2002/06/24 00:03:18 1.18 +++ packet-dcerpc.h 2002/07/06 03:21:26 @@ -48,6 +48,7 @@ guint16 frag_len; guint16 auth_len; guint32 call_id; + guint32 ntlmssp_message_type; } e_dce_cn_common_hdr_t; typedef struct _e_dce_dg_common_hdr_t {
- Follow-Ups:
- Re: [Ethereal-dev] ntlmssp decoding
- From: Ronnie Sahlberg
- Re: [Ethereal-dev] ntlmssp decoding
- From: Tim Potter
- Re: [Ethereal-dev] ntlmssp decoding
- Prev by Date: Re: [Ethereal-dev] How to cd to non-8.3 dirs in Win2K?
- Next by Date: [Ethereal-dev] User Info (0x10 == 16) is an ACB struct.
- Previous by thread: Re: [Ethereal-dev] How to cd to non-8.3 dirs in Win2K?
- Next by thread: Re: [Ethereal-dev] ntlmssp decoding
- Index(es):