diff options
Diffstat (limited to 'epan/dissectors/packet-dcom-remunkn.c')
-rw-r--r-- | epan/dissectors/packet-dcom-remunkn.c | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dcom-remunkn.c b/epan/dissectors/packet-dcom-remunkn.c new file mode 100644 index 00000000..3e020d39 --- /dev/null +++ b/epan/dissectors/packet-dcom-remunkn.c @@ -0,0 +1,371 @@ +/* packet-dcom-remunkn.c + * Routines for the IRemUnknown interface + * Copyright 2004, Jelmer Vernooij <jelmer@samba.org> + * + * Wireshark - Network traffic analyzer + * By Gerald Combs <gerald@wireshark.org> + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* see packet-dcom.c for details about DCOM */ + +#include "config.h" + +#include <epan/packet.h> +#include "packet-dcerpc.h" +#include "packet-dcom.h" + +void proto_register_remunk(void); +void proto_reg_handoff_remunk(void); + +static int hf_remunk_opnum = -1; + + +static int hf_remunk_refs = -1; +static int hf_remunk_iids = -1; + +/* static int hf_remunk_flags = -1; */ +static int hf_remunk_qiresult = -1; + +static gint ett_remunk_reminterfaceref = -1; +static int hf_remunk_reminterfaceref = -1; +static int hf_remunk_interface_refs = -1; +static int hf_remunk_public_refs = -1; +static int hf_remunk_private_refs = -1; + + +static gint ett_remunk_rqi_result = -1; + + +static gint ett_remunk = -1; +static e_guid_t uuid_remunk = { 0x00000131, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; +static guint16 ver_remunk = 0; +static int proto_remunk = -1; + +static e_guid_t ipid_remunk = { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; + +/* There is a little bit confusion about the IRemUnknown2 interface UUIDs */ +/* DCOM documentation tells us: 0x00000142 (7 methods) */ +/* win2000 registry tells us: 0x00000142 IRemoteQI (4 methods) */ +/* win2000 registry tells us: 0x00000143 IRemUnknown2 (7 methods) */ +/* There is some evidence, that the DCOM documentation is wrong, so using 143 for IRemUnknown2 now. */ + +static gint ett_remunk2 = -1; +static e_guid_t uuid_remunk2 = { 0x00000143, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; +static guint16 ver_remunk2 = 0; +static int proto_remunk2 = -1; + + +typedef struct remunk_remqueryinterface_call_s { + guint iid_count; + e_guid_t *iids; +} remunk_remqueryinterface_call_t; + + +static int +dissect_remunk_remqueryinterface_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + e_guid_t ipid; + guint32 u32Refs; + guint16 u16IIDs; + guint32 u32ArraySize; + guint32 u32ItemIdx; + e_guid_t iid; + remunk_remqueryinterface_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, di, drep, + hf_dcom_ipid, &ipid); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_remunk_refs, &u32Refs); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_remunk_iids, &u16IIDs); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* limit the allocation to a reasonable size */ + if(u32ArraySize < 100) { + call = (remunk_remqueryinterface_call_t *)wmem_alloc0(wmem_file_scope(), sizeof(remunk_remqueryinterface_call_t) + u32ArraySize * sizeof(e_guid_t)); + call->iid_count = u32ArraySize; + call->iids = (e_guid_t *) (call+1); + di->call_data->private_data = call; + } else { + call = NULL; + } + + for (u32ItemIdx = 0; u32ArraySize--; u32ItemIdx++) { + offset = dissect_dcom_append_UUID(tvb, offset, pinfo, tree, di, drep, + hf_dcom_iid, u32ItemIdx+1, &iid); + if(call != NULL) { + call->iids[u32ItemIdx] = iid; + } + } + + return offset; +} + + +static int +dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32ItemIdx; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32HResult; + guint32 u32SubStart; + e_guid_t iid; + e_guid_t iid_null = DCERPC_UUID_NULL; + remunk_remqueryinterface_call_t *call = (remunk_remqueryinterface_call_t *)di->call_data->private_data; + guint64 oxid; + guint64 oid; + e_guid_t ipid; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32ItemIdx = 1; + while (u32ArraySize--) { + /* add subtree */ + sub_item = proto_tree_add_item(tree, hf_remunk_qiresult, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_remunk_rqi_result); + + /* REMQIRESULT */ + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult); + u32SubStart = offset - 4; + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + + /* try to read the iid from the request */ + if(call != NULL && u32ItemIdx <= call->iid_count) { + iid = call->iids[u32ItemIdx-1]; + } else { + iid = iid_null; + } + + /* XXX - this doesn't seem to be dependent on the pointer above?!? */ + /*if (u32Pointer) {*/ + offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, 0 /* hfindex */, + &oxid, &oid, &ipid); + /*}*/ + + /* add interface instance to database (we currently only handle IPv4) */ + if(pinfo->net_src.type == AT_IPv4) { + dcom_interface_new(pinfo, + &pinfo->net_src, + &iid, oxid, oid, &ipid); + } + + /* update subtree */ + proto_item_append_text(sub_item, "[%u]: %s", + u32ItemIdx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"), + u32ItemIdx); + u32ItemIdx++; + } + + /* HRESULT of call */ + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)")); + + return offset; +} + + +static int +dissect_remunk_remrelease_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32IntRefs; + guint32 u32ItemIdx; + e_guid_t ipid; + guint32 u32PublicRefs; + guint32 u32PrivateRefs; + const gchar *pszFormat; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_remunk_interface_refs, &u32IntRefs); + + /* update column info now */ + if (u32IntRefs) { + col_append_fstr(pinfo->cinfo, COL_INFO, " Cnt=%u Refs=", u32IntRefs); + } else { + col_append_str(pinfo->cinfo, COL_INFO, " Cnt=0"); + } + + + u32ItemIdx = 1; + while (u32IntRefs--) { + /* add subtree */ + sub_item = proto_tree_add_item(tree, hf_remunk_reminterfaceref, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_remunk_reminterfaceref); + u32SubStart = offset; + + offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep, + hf_dcom_ipid, &ipid); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_remunk_public_refs, &u32PublicRefs); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_remunk_private_refs, &u32PrivateRefs); + + /* update subtree */ + proto_item_append_text(sub_item, "[%u]: IPID=%s, PublicRefs=%u, PrivateRefs=%u", + u32ItemIdx, + guids_resolve_guid_to_str(&ipid, pinfo->pool), + u32PublicRefs, u32PrivateRefs); + proto_item_set_len(sub_item, offset - u32SubStart); + + /* update column info now */ + pszFormat = ""; + if (u32ItemIdx == 1) { + pszFormat = "%u-%u"; + } else if (u32ItemIdx < 10) { + pszFormat = ",%u-%u"; + } else if (u32ItemIdx == 10) { + pszFormat = ",..."; + } + col_append_fstr(pinfo->cinfo, COL_INFO, pszFormat, u32PublicRefs, u32PrivateRefs); + + u32ItemIdx++; + } + + return offset; +} + + +/* sub dissector table of IRemUnknown interface */ +static dcerpc_sub_dissector remunk_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "RemQueryInterface", dissect_remunk_remqueryinterface_rqst, dissect_remunk_remqueryinterface_resp }, + { 4, "RemAddRef", NULL, NULL }, + { 5, "RemRelease", dissect_remunk_remrelease_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL } +}; + +/* sub dissector table of IRemUnknown2 interface */ +static dcerpc_sub_dissector remunk2_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "RemQueryInterface", dissect_remunk_remqueryinterface_rqst, dissect_remunk_remqueryinterface_resp }, + { 4, "RemAddRef", NULL, NULL }, + { 5, "RemRelease", dissect_remunk_remrelease_rqst, dissect_dcom_simple_resp }, + + { 6, "RemQueryInterface2", NULL, NULL }, + { 0, NULL, NULL, NULL } +}; + + + +void +proto_register_remunk (void) +{ + static hf_register_info hf_remunk_rqi_array[] = { + { &hf_remunk_opnum, + { "Operation", "remunk.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + + { &hf_remunk_refs, + { "Refs", "remunk.refs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_remunk_iids, + { "IIDs", "remunk.iids", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_remunk_qiresult, + { "QIResult", "remunk.qiresult", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, +#if 0 + { &hf_remunk_flags, + { "Flags", "remunk.flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, +#endif + { &hf_remunk_public_refs, + { "PublicRefs", "remunk.public_refs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_remunk_reminterfaceref, + { "RemInterfaceRef", "remunk.reminterfaceref", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_remunk_interface_refs, + { "InterfaceRefs", "remunk.int_refs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_remunk_private_refs, + { "PrivateRefs", "remunk.private_refs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }} + }; + + static gint *ett_remunk_array[] = { + &ett_remunk, + &ett_remunk_rqi_result, + &ett_remunk2, + &ett_remunk_reminterfaceref + }; + + proto_remunk = proto_register_protocol ("IRemUnknown", "IRemUnknown", "remunk"); + proto_register_field_array (proto_remunk, hf_remunk_rqi_array, array_length (hf_remunk_rqi_array)); + + proto_remunk2 = proto_register_protocol ("IRemUnknown2", "IRemUnknown2", "remunk2"); + + proto_register_subtree_array (ett_remunk_array, array_length (ett_remunk_array)); +} + +void +proto_reg_handoff_remunk (void) +{ + + /* Register the IPID */ + guids_add_uuid(&ipid_remunk, "IPID-IRemUnknown"); + + /* Register the interfaces */ + dcerpc_init_uuid(proto_remunk, ett_remunk, + &uuid_remunk, ver_remunk, + remunk_dissectors, hf_remunk_opnum); + + dcerpc_init_uuid(proto_remunk2, ett_remunk2, + &uuid_remunk2, ver_remunk2, + remunk2_dissectors, hf_remunk_opnum); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ |