From e489df5024acc86b0bd3c9f41844b06ff7560d24 Mon Sep 17 00:00:00 2001 From: Michael Mann Date: Thu, 18 Sep 2014 22:40:49 -0400 Subject: [PATCH] Don't assert that values fit in 32 bits if the NDR64 flag is set. For now, this just pacifies fuzz-testing. If real world examples have this, there needs to be a drastic overhaul to support fields that could be either 32 or 64-bit values. Bug:9329 Change-Id: I3e28808ca0291868a5f84258b0ee1e2a922703c2 Reviewed-on: https://code.wireshark.org/review/4189 Reviewed-by: Michael Mann --- epan/dissectors/packet-dcerpc-ndr.c | 6 +-- epan/dissectors/packet-dcerpc.c | 67 +++++++++++++++++++------- epan/dissectors/packet-dcerpc.h | 2 +- epan/dissectors/packet-dcom-oxid.c | 4 +- plugins/profinet/packet-dcerpc-pn-io.c | 13 +++-- 5 files changed, 65 insertions(+), 27 deletions(-) diff --git a/epan/dissectors/packet-dcerpc-ndr.c b/epan/dissectors/packet-dcerpc-ndr.c index 4f8b293ceb..cabf6f3686 100644 --- a/epan/dissectors/packet-dcerpc-ndr.c +++ b/epan/dissectors/packet-dcerpc-ndr.c @@ -355,7 +355,7 @@ dissect_ndr_duint32(tvbuff_t *tvb, gint offset, packet_info *pinfo, offset += 4 - (offset % 4); } return dissect_dcerpc_uint64(tvb, offset, pinfo, - tree, drep, hfindex, pdata); + tree, di, drep, hfindex, pdata); } /* uint64 : hyper @@ -383,7 +383,7 @@ dissect_ndr_uint64(tvbuff_t *tvb, gint offset, packet_info *pinfo, offset += padding; } return dissect_dcerpc_uint64(tvb, offset, pinfo, - tree, drep, hfindex, pdata); + tree, di, drep, hfindex, pdata); } int @@ -402,7 +402,7 @@ PIDL_dissect_uint64_val(tvbuff_t *tvb, gint offset, packet_info *pinfo, offset += 8 - (offset % 8); } offset = dissect_dcerpc_uint64(tvb, offset, pinfo, - tree, drep, hfindex, &val); + tree, di, drep, hfindex, &val); if (param&PIDL_SET_COL_INFO) { header_field_info *hf_info; diff --git a/epan/dissectors/packet-dcerpc.c b/epan/dissectors/packet-dcerpc.c index d643926294..15c9fd983f 100644 --- a/epan/dissectors/packet-dcerpc.c +++ b/epan/dissectors/packet-dcerpc.c @@ -571,7 +571,8 @@ static int hf_dcerpc_array_max_count = -1; static int hf_dcerpc_array_offset = -1; static int hf_dcerpc_array_actual_count = -1; static int hf_dcerpc_op = -1; -static int hf_dcerpc_referent_id = -1; +static int hf_dcerpc_referent_id32 = -1; +static int hf_dcerpc_referent_id64 = -1; static int hf_dcerpc_fragments = -1; static int hf_dcerpc_fragment = -1; static int hf_dcerpc_fragment_overlap = -1; @@ -1557,7 +1558,7 @@ dissect_dcerpc_time_t(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, int dissect_dcerpc_uint64(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, - proto_tree *tree, guint8 *drep, + proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, guint64 *pdata) { guint64 data; @@ -1583,7 +1584,9 @@ dissect_dcerpc_uint64(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, proto_tree_add_int64(tree, hfindex, tvb, offset, 8, data); break; default: - DISSECTOR_ASSERT(data <= G_MAXUINT32); + /* The value is truncated to 32bits. 64bit values have only been + seen on fuzz-tested files */ + DISSECTOR_ASSERT((di->call_data->flags & DCERPC_IS_NDR64) || (data <= G_MAXUINT32)); proto_tree_add_uint(tree, hfindex, tvb, offset, 8, (guint32)data); } } @@ -1980,7 +1983,8 @@ dissect_ndr_cvstring(tvbuff_t *tvb, int offset, packet_info *pinfo, offset = dissect_ndr_uint3264(tvb, offset, pinfo, string_tree, di, drep, hf_dcerpc_array_actual_count, &len); - DISSECTOR_ASSERT(len <= G_MAXUINT32); + /* The value is truncated to 32bits. 64bit values have only been + seen on fuzztested files */ buffer_len = size_is * (guint32)len; /* Adjust offset */ @@ -2523,8 +2527,9 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo, goto after_ref_id; } - /* see if we have seen this pointer before */ - DISSECTOR_ASSERT(id <= G_MAXUINT32); + /* see if we have seen this pointer before + The value is truncated to 32bits. 64bit values have only been + seen on fuzz-tested files */ idx = find_pointer_index((guint32)id); /* we have seen this pointer before */ @@ -2540,8 +2545,13 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo, pointer_size, "%s", text); tr = proto_item_add_subtree(item,ett_dcerpc_pointer_data); - proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, - offset-pointer_size, pointer_size, (guint32)id); + if (di->call_data->flags & DCERPC_IS_NDR64) { + proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb, + offset-pointer_size, pointer_size, id); + } else { + proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb, + offset-pointer_size, pointer_size, (guint32)id); + } add_pointer_to_list(pinfo, tr, item, di, fnct, (guint32)id, hf_index, callback, callback_args); goto after_ref_id; @@ -2565,13 +2575,17 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo, } /* new pointer */ - DISSECTOR_ASSERT(id <= G_MAXUINT32); item = proto_tree_add_text(tree, tvb, offset-pointer_size, pointer_size, "%s", text); tr = proto_item_add_subtree(item,ett_dcerpc_pointer_data); - proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, + if (di->call_data->flags & DCERPC_IS_NDR64) { + proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb, + offset-pointer_size, pointer_size, id); + } else { + proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb, offset-pointer_size, pointer_size, (guint32)id); + } add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff, hf_index, callback, callback_args); goto after_ref_id; @@ -2592,9 +2606,13 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo, pointer_size, "%s",text); tr = proto_item_add_subtree(item,ett_dcerpc_pointer_data); - DISSECTOR_ASSERT(id <= G_MAXUINT32); - proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, + if (di->call_data->flags & DCERPC_IS_NDR64) { + proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb, + offset-pointer_size, pointer_size, id); + } else { + proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb, offset-pointer_size, pointer_size, (guint32)id); + } add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff, hf_index, callback, callback_args); goto after_ref_id; @@ -2623,9 +2641,13 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo, pointer_size, "%s",text); tr = proto_item_add_subtree(item,ett_dcerpc_pointer_data); - DISSECTOR_ASSERT(id <= G_MAXUINT32); - proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, + if (di->call_data->flags & DCERPC_IS_NDR64) { + proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb, + offset-pointer_size, pointer_size, id); + } else { + proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb, offset-pointer_size, pointer_size, (guint32)id); + } add_pointer_to_list(pinfo, tr, item, di, fnct, 0xffffffff, hf_index, callback, callback_args); goto after_ref_id; @@ -2650,8 +2672,9 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo, goto after_ref_id; } - /* see if we have seen this pointer before */ - DISSECTOR_ASSERT(id <= G_MAXUINT32); + /* see if we have seen this pointer before + The value is truncated to 32bits. 64bit values have only been + seen on fuzztested files */ idx = find_pointer_index((guint32)id); /* we have seen this pointer before */ @@ -2667,8 +2690,13 @@ dissect_ndr_pointer_cb(tvbuff_t *tvb, gint offset, packet_info *pinfo, pointer_size, "%s", text); tr = proto_item_add_subtree(item,ett_dcerpc_pointer_data); - proto_tree_add_uint(tr, hf_dcerpc_referent_id, tvb, + if (di->call_data->flags & DCERPC_IS_NDR64) { + proto_tree_add_uint64(tr, hf_dcerpc_referent_id64, tvb, + offset-pointer_size, pointer_size, id); + } else { + proto_tree_add_uint(tr, hf_dcerpc_referent_id32, tvb, offset-pointer_size, pointer_size, (guint32)id); + } add_pointer_to_list(pinfo, tr, item, di, fnct, (guint32)id, hf_index, callback, callback_args); goto after_ref_id; @@ -5931,9 +5959,12 @@ proto_register_dcerpc(void) { &hf_dcerpc_response_in, { "Response in frame", "dcerpc.response_in", FT_FRAMENUM, BASE_NONE, NULL, 0, "This packet will be responded in the packet with this number", HFILL }}, - { &hf_dcerpc_referent_id, + { &hf_dcerpc_referent_id32, { "Referent ID", "dcerpc.referent_id", FT_UINT32, BASE_HEX, NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }}, + { &hf_dcerpc_referent_id64, + { "Referent ID", "dcerpc.referent_id", FT_UINT64, BASE_HEX, + NULL, 0, "Referent ID for this NDR encoded pointer", HFILL }}, { &hf_dcerpc_ver, { "Version", "dcerpc.ver", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_dcerpc_ver_minor, diff --git a/epan/dissectors/packet-dcerpc.h b/epan/dissectors/packet-dcerpc.h index f10463f892..5d63a7cc13 100644 --- a/epan/dissectors/packet-dcerpc.h +++ b/epan/dissectors/packet-dcerpc.h @@ -217,7 +217,7 @@ int dissect_dcerpc_uint32 (tvbuff_t *tvb, gint offset, packet_info *pinfo, int hfindex, guint32 *pdata); WS_DLL_PUBLIC int dissect_dcerpc_uint64 (tvbuff_t *tvb, gint offset, packet_info *pinfo, - proto_tree *tree, guint8 *drep, + proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex, guint64 *pdata); int dissect_dcerpc_float (tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, diff --git a/epan/dissectors/packet-dcom-oxid.c b/epan/dissectors/packet-dcom-oxid.c index 45799bbb8a..4a0d84a7d4 100644 --- a/epan/dissectors/packet-dcom-oxid.c +++ b/epan/dissectors/packet-dcom-oxid.c @@ -259,13 +259,13 @@ dissect_oxid_server_alive2_resp(tvbuff_t *tvb, int offset, packet_info *pinfo, offset = dissect_dcom_COMVERSION(tvb, offset, pinfo, tree, di, drep, &u16VersionMajor, &u16VersionMinor); /* XXX - understand what those 8 bytes mean! don't skip'em!*/ - dissect_dcerpc_uint64(tvb , offset, pinfo, tree, drep, hf_oxid_Unknown1, NULL); + dissect_dcerpc_uint64(tvb, offset, pinfo, tree, di, drep, hf_oxid_Unknown1, NULL); offset += 8; offset = dissect_dcom_DUALSTRINGARRAY(tvb, offset, pinfo, tree, di, drep, hf_oxid_ds_array, NULL); /* unknown field 2 */ - dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, hf_oxid_Unknown2, NULL); + dissect_dcerpc_uint64(tvb, offset, pinfo, tree, di, drep, hf_oxid_Unknown2, NULL); offset += 8; return offset; } diff --git a/plugins/profinet/packet-dcerpc-pn-io.c b/plugins/profinet/packet-dcerpc-pn-io.c index 95588554a8..f8ebf4c1c6 100644 --- a/plugins/profinet/packet-dcerpc-pn-io.c +++ b/plugins/profinet/packet-dcerpc-pn-io.c @@ -6659,7 +6659,8 @@ dissect_LogData_block(tvbuff_t *tvb, int offset, guint64 u64LocaltimeStamp; e_uuid_t aruuid; guint32 u32EntryDetail; - + dcerpc_info di; /* fake dcerpc_info struct */ + dcerpc_call_value call_data; if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { expert_add_info_format(pinfo, item, &ei_pn_io_block_version, @@ -6667,8 +6668,14 @@ dissect_LogData_block(tvbuff_t *tvb, int offset, return offset; } + di.conformant_run = 0; + /* we need di->call_data->flags.NDR64 == 0 */ + call_data.flags = 0; + di.call_data = &call_data; + di.dcerpc_procedure_name = ""; + /* ActualLocalTimeStamp */ - offset = dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, tree, &di, drep, hf_pn_io_actual_local_time_stamp, &u64ActualLocaltimeStamp); /* NumberOfLogEntries */ offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, @@ -6676,7 +6683,7 @@ dissect_LogData_block(tvbuff_t *tvb, int offset, while (u16NumberOfLogEntries--) { /* LocalTimeStamp */ - offset = dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, tree, &di, drep, hf_pn_io_local_time_stamp, &u64LocaltimeStamp); /* ARUUID */ offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep,