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 {