Ethereal-dev: [Ethereal-dev] [PATCH] packet-dcerpc.c: clamp to tvb length and display multiple
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Charles Levert <chuck@xxxxxxxxxxxxxxxx>
Date: Fri, 12 Nov 2004 03:02:31 -0500
Hi. When displaying strings inside "UDP/DCE RPC/Microsoft Messenger Service" packets (such as that lovely spam promoting www.windowspatch.net), the "actual character count" was taken at face value and not checked against the total size of the tvb; an intentional overflow (or exception) could have been provoked by a carefully crafted packet. Also, the message string can be quite long and its display on a single line ends up being truncated. Since this is UDP, the "Follow TCP Stream" feature cannot be used to view the message in ASCII lines. Therefore, it is useful to add a subtree that displays each line individually (when there is more than one), instead of having to rely solely on the "packet octets pane". Keep in mind that the string content could have been (maliciously?) crafted in an unusual way such that it contains printable characters beyond the first NUL; therefore, it is a good idea to check if lines can still be displayed past that point. When the message is in wide (16-bit) characters, it is less confusing and more consistent with the "Follow TCP Stream" display to substitute a '.' for code points beyond the 8-bit range, rather than the character that happens to have the same lower 8 bits (possibly NUL or another control character). Also, a check for endianness was missing. [ Edited with ude, the unified-format diff-output ("unidiff") editor, version 0.1 of 2004-11-03. ] --- epan/tvbuff.c.svn-11796 2004-10-31 01:40:41 -0400 +++ epan/tvbuff.c 2004-11-11 20:34:05 -0500 @@ -12 +12 @@ * $Id: tvbuff.c 11796 2004-08-22 00:31:58Z guy $ @@ -1645,7 +1645,7 @@ tvb_fake_unicode(tvbuff_t *tvb, int offs for (i = 0; i < len; i++) { character = little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset); - buffer[i] = character & 0xff; + buffer[i] = character < 256 ? character : '.'; offset += 2; } --- epan/dissectors/packet-dcerpc.c.svn-12128 2004-10-30 00:37:33 -0400 +++ epan/dissectors/packet-dcerpc.c 2004-11-12 01:43:46 -0500 @@ -6 +6 @@ * $Id: packet-dcerpc.c 12128 2004-09-29 00:06:36Z guy $ @@ -33,6 +33,7 @@ #include <glib.h> #include <epan/packet.h> +#include <epan/strutil.h> #include <epan/dissectors/packet-dcerpc.h> #include <epan/conversation.h> #include <epan/prefs.h> @@ -413,6 +414,7 @@ static gint ett_dcerpc_dg_flags2 = -1; static gint ett_dcerpc_pointer_data = -1; static gint ett_dcerpc_string = -1; +static gint ett_dcerpc_line = -1; static gint ett_dcerpc_fragments = -1; static gint ett_dcerpc_fragment = -1; static gint ett_dcerpc_krb5_auth_verf = -1; @@ -1242,7 +1244,7 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int proto_item *string_item; proto_tree *string_tree; guint32 len, buffer_len; - char *s; + char *s, *s1; header_field_info *hfinfo; di=pinfo->private_data; @@ -1251,7 +1253,7 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int return offset; } - if (add_subtree) { + if (tree && add_subtree) { string_item = proto_tree_add_text(tree, tvb, offset, -1, "%s", proto_registrar_get_name(hfindex)); string_tree = proto_item_add_subtree(string_item, ett_dcerpc_string); @@ -1277,9 +1279,15 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int if (offset % size_is) offset += size_is - (offset % size_is); + len = tvb_length_remaining(tvb, offset); + if (len < buffer_len) + buffer_len = len; + + s1 = NULL; + if (size_is == sizeof(guint16)) { /* XXX - use drep to determine the byte order? */ - s = tvb_fake_unicode(tvb, offset, buffer_len / 2, TRUE); + s = tvb_fake_unicode(tvb, offset, buffer_len / 2, drep[0] & 0x10); /* * XXX - we don't support a string type with Unicode * characters, so if this is a string item, we make @@ -1291,8 +1299,7 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int proto_tree_add_string(string_tree, hfindex, tvb, offset, buffer_len, s); } else { - proto_tree_add_item(string_tree, hfindex, tvb, offset, - buffer_len, drep[0] & 0x10); + s1 = s; } } } else { @@ -1306,10 +1313,48 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int */ s = tvb_get_string(tvb, offset, buffer_len); if (tree && buffer_len) - proto_tree_add_item(string_tree, hfindex, tvb, offset, - buffer_len, drep[0] & 0x10); + s1 = s; } + if (s1) { + proto_item *line_item; + char *s2; + char *end = s + buffer_len / size_is; + + line_item = proto_tree_add_item(string_tree, hfindex, tvb, offset, + buffer_len, drep[0] & 0x10); + s2 = strchr(s1, '\n'); + if (s2) + s2++; + else + s2 = s1 + strlen(s1); + if (s2 < end) { + proto_tree *line_tree; + + line_tree = proto_item_add_subtree(line_item, ett_dcerpc_line); + for (;;) { + len = s2 - s1; + if (!len) { + while (s2 < end && !*s2) + s2++; + len = s2 - s1; + } + proto_tree_add_text(line_tree, tvb, + offset + (s1 - s) * size_is, + len * size_is, + "%s", format_text(s1, len)); + if (s2 >= end) + break; + s1 = s2; + s2 = strchr(s1, '\n'); + if (s2) + s2++; + else + s2 = s1 + strlen(s1); + } + } + } + if (string_item != NULL) proto_item_append_text(string_item, ": %s", s); @@ -4835,6 +4880,7 @@ proto_register_dcerpc (void) &ett_dcerpc_dg_flags2, &ett_dcerpc_pointer_data, &ett_dcerpc_string, + &ett_dcerpc_line, &ett_dcerpc_fragments, &ett_dcerpc_fragment, &ett_dcerpc_krb5_auth_verf,
- Follow-Ups:
- Prev by Date: RE: [Ethereal-dev] Conversion of @foo@ macros in config.h.win32
- Next by Date: Re: [Ethereal-dev] Patch to packet-acse.c
- Previous by thread: Re: [Ethereal-dev] captures on FreeBSD hang UI (potential patch)
- Next by thread: Re: [Ethereal-dev] [PATCH] packet-dcerpc.c: clamp to tvb length and display multiple lines
- Index(es):