Coverage Report

Created: 2026-01-02 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-dcom-remunkn.c
Line
Count
Source
1
/* packet-dcom-remunkn.c
2
 * Routines for the IRemUnknown interface
3
 * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/* see packet-dcom.c for details about DCOM */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include "packet-dcerpc.h"
18
#include "packet-dcom.h"
19
20
void proto_register_remunk(void);
21
void proto_reg_handoff_remunk(void);
22
23
static int hf_remunk_opnum;
24
25
26
static int hf_remunk_refs;
27
static int hf_remunk_iids;
28
29
/* static int hf_remunk_flags; */
30
static int hf_remunk_qiresult;
31
32
static int ett_remunk_reminterfaceref;
33
static int hf_remunk_reminterfaceref;
34
static int hf_remunk_interface_refs;
35
static int hf_remunk_public_refs;
36
static int hf_remunk_private_refs;
37
38
39
static int ett_remunk_rqi_result;
40
41
42
static int ett_remunk;
43
static e_guid_t uuid_remunk = { 0x00000131, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
44
static uint16_t ver_remunk;
45
static int proto_remunk;
46
47
static e_guid_t ipid_remunk = { 0x00000131, 0x1234, 0x5678, { 0xCA, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
48
49
/* There is a little bit confusion about the IRemUnknown2 interface UUIDs */
50
/* DCOM documentation tells us: 0x00000142 (7 methods) */
51
/* win2000 registry tells us: 0x00000142 IRemoteQI (4 methods) */
52
/* win2000 registry tells us: 0x00000143 IRemUnknown2 (7 methods) */
53
/* There is some evidence, that the DCOM documentation is wrong, so using 143 for IRemUnknown2 now. */
54
55
static int ett_remunk2;
56
static e_guid_t uuid_remunk2 = { 0x00000143, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
57
static uint16_t ver_remunk2;
58
static int proto_remunk2;
59
60
61
typedef struct remunk_remqueryinterface_call_s {
62
    unsigned     iid_count;
63
    e_guid_t    *iids;
64
} remunk_remqueryinterface_call_t;
65
66
67
static unsigned
68
dissect_remunk_remqueryinterface_rqst(tvbuff_t *tvb, unsigned offset,
69
                                      packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
70
0
{
71
0
    e_guid_t     ipid;
72
0
    uint32_t     u32Refs;
73
0
    uint16_t     u16IIDs;
74
0
    uint32_t     u32ArraySize;
75
0
    uint32_t     u32ItemIdx;
76
0
    e_guid_t     iid;
77
0
    remunk_remqueryinterface_call_t *call;
78
79
80
0
    offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
81
82
0
    offset = dissect_dcom_UUID(tvb, offset, pinfo, tree, di, drep,
83
0
                               hf_dcom_ipid, &ipid);
84
85
0
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
86
0
                                hf_remunk_refs, &u32Refs);
87
88
0
    offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep,
89
0
                               hf_remunk_iids, &u16IIDs);
90
91
0
    offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
92
0
                                            &u32ArraySize);
93
94
    /* limit the allocation to a reasonable size */
95
0
    if(u32ArraySize < 100) {
96
0
        call = (remunk_remqueryinterface_call_t *)wmem_alloc0(wmem_file_scope(), sizeof(remunk_remqueryinterface_call_t) + u32ArraySize * sizeof(e_guid_t));
97
0
        call->iid_count = u32ArraySize;
98
0
        call->iids = (e_guid_t *) (call+1);
99
0
        di->call_data->private_data = call;
100
0
    } else {
101
0
        call = NULL;
102
0
    }
103
104
0
    for (u32ItemIdx = 0; u32ArraySize != 0; u32ItemIdx++, u32ArraySize--) {
105
0
        offset = dissect_dcom_append_UUID(tvb, offset,  pinfo, tree, di, drep,
106
0
                                          hf_dcom_iid, u32ItemIdx+1, &iid);
107
0
        if(call != NULL) {
108
0
            call->iids[u32ItemIdx] = iid;
109
0
        }
110
0
    }
111
112
0
    return offset;
113
0
}
114
115
116
static unsigned
117
dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, unsigned offset,
118
                                      packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
119
0
{
120
0
    uint32_t     u32Pointer;
121
0
    uint32_t     u32ArraySize;
122
0
    uint32_t     u32ItemIdx;
123
0
    proto_item  *sub_item;
124
0
    proto_tree  *sub_tree;
125
0
    uint32_t     u32HResult;
126
0
    uint32_t     u32SubStart;
127
0
    e_guid_t     iid;
128
0
    e_guid_t     iid_null = DCERPC_UUID_NULL;
129
0
    remunk_remqueryinterface_call_t *call = (remunk_remqueryinterface_call_t *)di->call_data->private_data;
130
0
    uint64_t     oxid;
131
0
    uint64_t     oid;
132
0
    e_guid_t     ipid;
133
134
135
0
    offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);
136
137
0
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
138
0
                                         &u32Pointer);
139
0
    offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
140
0
                                            &u32ArraySize);
141
142
0
    u32ItemIdx = 1;
143
0
    while (u32ArraySize != 0) {
144
        /* add subtree */
145
0
        sub_item = proto_tree_add_item(tree, hf_remunk_qiresult, tvb, offset, 0, ENC_NA);
146
0
        sub_tree = proto_item_add_subtree(sub_item, ett_remunk_rqi_result);
147
148
        /* REMQIRESULT */
149
0
        offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
150
0
                                      &u32HResult);
151
0
        u32SubStart = offset - 4;
152
0
        offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep,
153
0
                                             &u32Pointer);
154
155
        /* try to read the iid from the request */
156
0
        if(call != NULL && u32ItemIdx <= call->iid_count) {
157
0
            iid = call->iids[u32ItemIdx-1];
158
0
        } else {
159
0
            iid = iid_null;
160
0
        }
161
162
        /* XXX - this doesn't seem to be dependent on the pointer above?!? */
163
        /*if (u32Pointer) {*/
164
0
        offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, 0 /* hfindex */,
165
0
                                        &oxid, &oid, &ipid);
166
        /*}*/
167
168
        /* add interface instance to database (we currently only handle IPv4) */
169
0
        if(pinfo->net_src.type == AT_IPv4) {
170
0
            dcom_interface_new(pinfo,
171
0
                               &pinfo->net_src,
172
0
                               &iid, oxid, oid, &ipid);
173
0
        }
174
175
        /* update subtree */
176
0
        proto_item_append_text(sub_item, "[%u]: %s",
177
0
                               u32ItemIdx,
178
0
                               val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
179
0
        proto_item_set_len(sub_item, offset - u32SubStart);
180
181
        /* update column info now */
182
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]",
183
0
                        val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"),
184
0
                        u32ItemIdx);
185
0
        u32ItemIdx++;
186
0
        u32ArraySize--;
187
0
    }
188
189
    /* HRESULT of call */
190
0
    offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
191
0
                                  &u32HResult);
192
193
    /* update column info now */
194
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
195
0
                    val_to_str(pinfo->pool, u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"));
196
197
0
    return offset;
198
0
}
199
200
201
static unsigned
202
dissect_remunk_remrelease_rqst(tvbuff_t *tvb, unsigned offset,
203
                               packet_info *pinfo, proto_tree *tree, dcerpc_info *di, uint8_t *drep)
204
0
{
205
0
    uint32_t     u32Pointer;
206
0
    uint32_t     u32IntRefs;
207
0
    uint32_t     u32ItemIdx;
208
0
    e_guid_t     ipid;
209
0
    uint32_t     u32PublicRefs;
210
0
    uint32_t     u32PrivateRefs;
211
0
    const char *pszFormat;
212
0
    proto_item  *sub_item;
213
0
    proto_tree  *sub_tree;
214
0
    uint32_t     u32SubStart;
215
216
217
0
    offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep);
218
219
0
    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
220
0
                                         &u32Pointer);
221
222
0
    offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep,
223
0
                                hf_remunk_interface_refs, &u32IntRefs);
224
225
    /* update column info now */
226
0
    if (u32IntRefs) {
227
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " Cnt=%u Refs=", u32IntRefs);
228
0
    } else {
229
0
        col_append_str(pinfo->cinfo, COL_INFO, " Cnt=0");
230
0
    }
231
232
233
0
    u32ItemIdx = 1;
234
0
    while (u32IntRefs != 0) {
235
        /* add subtree */
236
0
        sub_item = proto_tree_add_item(tree, hf_remunk_reminterfaceref, tvb, offset, 0, ENC_NA);
237
0
        sub_tree = proto_item_add_subtree(sub_item, ett_remunk_reminterfaceref);
238
0
        u32SubStart = offset;
239
240
0
        offset = dissect_dcom_UUID(tvb, offset, pinfo, sub_tree, di, drep,
241
0
                                   hf_dcom_ipid, &ipid);
242
243
0
        offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
244
0
                                    hf_remunk_public_refs, &u32PublicRefs);
245
246
0
        offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep,
247
0
                                    hf_remunk_private_refs, &u32PrivateRefs);
248
249
        /* update subtree */
250
0
        proto_item_append_text(sub_item, "[%u]: IPID=%s, PublicRefs=%u, PrivateRefs=%u",
251
0
                               u32ItemIdx,
252
0
                               guids_resolve_guid_to_str(&ipid, pinfo->pool),
253
0
                               u32PublicRefs, u32PrivateRefs);
254
0
        proto_item_set_len(sub_item, offset - u32SubStart);
255
256
        /* update column info now */
257
0
        pszFormat = "";
258
0
        if (u32ItemIdx == 1) {
259
0
            pszFormat = "%u-%u";
260
0
        } else if (u32ItemIdx < 10) {
261
0
            pszFormat = ",%u-%u";
262
0
        } else if (u32ItemIdx == 10) {
263
0
            pszFormat = ",...";
264
0
        }
265
0
        col_append_fstr(pinfo->cinfo, COL_INFO, pszFormat, u32PublicRefs, u32PrivateRefs);
266
267
0
        u32ItemIdx++;
268
0
        u32IntRefs--;
269
0
    }
270
271
0
    return offset;
272
0
}
273
274
275
/* sub dissector table of IRemUnknown interface */
276
static const dcerpc_sub_dissector remunk_dissectors[] = {
277
    { 0, "QueryInterface", NULL, NULL },
278
    { 1, "AddRef", NULL, NULL },
279
    { 2, "Release", NULL, NULL },
280
281
    { 3, "RemQueryInterface", dissect_remunk_remqueryinterface_rqst, dissect_remunk_remqueryinterface_resp },
282
    { 4, "RemAddRef", NULL, NULL },
283
    { 5, "RemRelease", dissect_remunk_remrelease_rqst, dissect_dcom_simple_resp },
284
    { 0, NULL, NULL, NULL }
285
};
286
287
/* sub dissector table of IRemUnknown2 interface */
288
static const dcerpc_sub_dissector remunk2_dissectors[] = {
289
    { 0, "QueryInterface", NULL, NULL },
290
    { 1, "AddRef", NULL, NULL },
291
    { 2, "Release", NULL, NULL },
292
293
    { 3, "RemQueryInterface", dissect_remunk_remqueryinterface_rqst, dissect_remunk_remqueryinterface_resp },
294
    { 4, "RemAddRef", NULL, NULL },
295
    { 5, "RemRelease", dissect_remunk_remrelease_rqst, dissect_dcom_simple_resp },
296
297
    { 6, "RemQueryInterface2", NULL, NULL },
298
    { 0, NULL, NULL, NULL }
299
};
300
301
302
303
void
304
proto_register_remunk (void)
305
14
{
306
14
    static hf_register_info hf_remunk_rqi_array[] = {
307
14
        { &hf_remunk_opnum,
308
14
          { "Operation", "remunk.opnum", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
309
310
14
        { &hf_remunk_refs,
311
14
          { "Refs", "remunk.refs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
312
14
        { &hf_remunk_iids,
313
14
          { "IIDs", "remunk.iids", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
314
14
        { &hf_remunk_qiresult,
315
14
          { "QIResult", "remunk.qiresult", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
316
#if 0
317
        { &hf_remunk_flags,
318
          { "Flags", "remunk.flags",  FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }},
319
#endif
320
14
        { &hf_remunk_public_refs,
321
14
          { "PublicRefs", "remunk.public_refs",  FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
322
14
        { &hf_remunk_reminterfaceref,
323
14
          { "RemInterfaceRef", "remunk.reminterfaceref",  FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
324
14
        { &hf_remunk_interface_refs,
325
14
          { "InterfaceRefs", "remunk.int_refs",  FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
326
14
        { &hf_remunk_private_refs,
327
14
          { "PrivateRefs", "remunk.private_refs",  FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}
328
14
    };
329
330
14
    static int *ett_remunk_array[] = {
331
14
        &ett_remunk,
332
14
        &ett_remunk_rqi_result,
333
14
        &ett_remunk2,
334
14
        &ett_remunk_reminterfaceref
335
14
    };
336
337
14
    proto_remunk = proto_register_protocol ("IRemUnknown", "IRemUnknown", "remunk");
338
14
    proto_register_field_array (proto_remunk, hf_remunk_rqi_array, array_length (hf_remunk_rqi_array));
339
340
14
    proto_remunk2 = proto_register_protocol ("IRemUnknown2", "IRemUnknown2", "remunk2");
341
342
14
    proto_register_subtree_array (ett_remunk_array, array_length (ett_remunk_array));
343
14
}
344
345
void
346
proto_reg_handoff_remunk (void)
347
14
{
348
349
    /* Register the IPID */
350
14
    guids_add_guid(&ipid_remunk, "IPID-IRemUnknown");
351
352
    /* Register the interfaces */
353
14
    dcerpc_init_uuid(proto_remunk, ett_remunk,
354
14
                     &uuid_remunk, ver_remunk,
355
14
                     remunk_dissectors, hf_remunk_opnum);
356
357
14
    dcerpc_init_uuid(proto_remunk2, ett_remunk2,
358
14
                     &uuid_remunk2, ver_remunk2,
359
14
                     remunk2_dissectors, hf_remunk_opnum);
360
14
}
361
362
/*
363
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
364
 *
365
 * Local variables:
366
 * c-basic-offset: 4
367
 * tab-width: 8
368
 * indent-tabs-mode: nil
369
 * End:
370
 *
371
 * vi: set shiftwidth=4 tabstop=8 expandtab:
372
 * :indentSize=4:tabSize=8:noTabs=true:
373
 */