ANNOUNCEMENT: Live Wireshark University & Allegro Packets online APAC Wireshark Training Session
July 17th, 2024 | 10:00am-11:55am SGT (UTC+8) | Online

Ethereal-dev: [Ethereal-dev] Partial patch to packet-dcerpc-remact.c - call for assistance

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Yaniv Kaul <ykaul@xxxxxxxxxxxx>
Date: Thu, 18 Sep 2003 00:06:51 +0200
With all the noise around DCOM over DCE-RPC, no one bothered to dissect it properly.
I've began adding proper dissection to it.
However, due to lack of time, lack of GOOD (read: not exploits) traffic captures, and lack of normal documentation of this protocol, I'm unable to complete the dissector properly.
I'll be happy if someone can pick it up and finish it or help me a bit.
Once this is done, it'll be  trivial to do SystemActivator over DCE-RPC.

Attached please find my uncomplete patch. (Do NOT check in). Pay attention to the FIXME notes in it.

TIA,
Y.
/* packet-dcerpc-remact.c
 * Routines for DCOM Remote Activation
 * Copyright 2001, Todd Sabin <tas@xxxxxxxxxxx>
 *
 * $Id: packet-dcerpc-remact.c,v 1.7 2003/06/26 04:30:28 tpot Exp $
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

/* Information taken from:
 * http://www.globecom.net/ietf/draft/draft-brown-dcom-v1-spec-03.html
 * http://www.microsoft.com/msj/0398/dcom.aspx
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif


#include <string.h>

#include <glib.h>
#include <epan/packet.h>
#include "packet-dcerpc.h"

typedef struct tagCOMVERSION
    {
        guint16 MajorVersion; 
        guint16 MinorVersion;
    } COMVERSION;

typedef struct tagORPC_EXTENT
    {
        e_uuid_t id; 
        guint32 size;
        guint8 data; /* wrong - should be data[] */
    } ORPC_EXTENT;

typedef struct tagORPC_EXTENT_ARRAY
    {
        guint32 size;    
        guint32 reserved; 
        ORPC_EXTENT **extent; 
    } ORPC_EXTENT_ARRAY;

typedef struct tagORPCTHIS {
    COMVERSION version;  
    guint32 flags; 
    guint32 reserved1; 
    e_uuid_t  cid;                
    ORPC_EXTENT_ARRAY *extensions;
 } ORPCTHIS;

typedef struct tagMInterfacePointer {
    guint32 ulCntData; 
    guint8 abData;  /* wrong - should be abData[] */
 } MInterfacePointer,  *PMInterfacePointer;

typedef struct tagORPCTHAT {
    guint32 flags;
    ORPC_EXTENT_ARRAY *extensions; 
 } ORPCTHAT;

static int proto_remact = -1;

static gint ett_orpcthis_tree = -1;
static int hf_opnum = -1;
static int hf_COMVERSION_MjrVer = -1;
static int hf_COMVERSION_MnrVer = -1;
static int hf_ORPCTHIS_flags = -1;
static int hf_ORPCTHIS_reserved1 = -1;
static int hf_ORPCTHIS_cid = -1;
static int hf_ORPCTHIS_extensions = -1;
static int hf_ORPCTHAT_flags = -1;
static int hf_GUID = -1;
static int hf_ObjectName = -1;
static int hf_mptr_ulcntdata = -1;
static int hf_ClientImpLevel = -1;
static int hf_Mode = -1;
static int hf_Interfaces = -1;
static int hf_Interface = -1;
static int hf_fixme = -1;
static int hf_cRequestedProtseqs = -1;
static int hf_RequestedProtseqs = -1;
static int hf_Oxid = -1;
static int hf_wNumEntries = -1;
static int hf_wSecurityOffset = -1;
static int hf_ipid = -1;
static int hf_pAuthHint = -1;
static int hf_HRESULT = -1;

static gint ett_remact = -1;

static e_uuid_t uuid_remact = { 0x4d9f4ab8, 0x7d1c, 0x11cf, { 0x86, 0x1e, 0x00, 0x20, 0xaf, 0x6e, 0x7c, 0x57 } };
static guint16  ver_remact = 0;

static int
remact_dissect_rqst(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char *drep)
{
	proto_item *orpcthis_hdr;
	proto_tree *orpcthis_tree;
	ORPCTHIS orpcthis;
	e_uuid_t GUID, Interface;
	guint32 ext_ptr;
	char uuid_str[DCERPC_UUID_STR_LEN];
	int uuid_str_len, Object_strlen, i;
	MInterfacePointer Mptr;
	guint32 ClientImpLevel, Mode, Interfaces;
	guint16 cRequestedProtseqs, RequestedProtseqs;
	unsigned char fixme[8];

	orpcthis_hdr = proto_tree_add_text(tree, tvb, offset, 64, "ORPCTHIS structure");
	orpcthis_tree = proto_item_add_subtree(orpcthis_hdr, 0);
	dissect_dcerpc_uint16(tvb, offset, pinfo, orpcthis_tree, drep, hf_COMVERSION_MjrVer, &orpcthis.version.MajorVersion);
	offset += sizeof(orpcthis.version.MajorVersion);
	
	dissect_dcerpc_uint16(tvb, offset, pinfo, orpcthis_tree, drep, hf_COMVERSION_MnrVer,&orpcthis.version.MinorVersion);
	offset += sizeof(orpcthis.version.MinorVersion);

	dissect_dcerpc_uint32(tvb, offset, pinfo, orpcthis_tree, drep, hf_ORPCTHIS_flags, &orpcthis.flags);
	offset += sizeof(orpcthis.flags);

	dissect_dcerpc_uint32(tvb, offset, pinfo, orpcthis_tree, drep, hf_ORPCTHIS_reserved1, &orpcthis.reserved1);
	offset += sizeof(orpcthis.reserved1);
	
	dcerpc_tvb_get_uuid(tvb, offset, drep, &orpcthis.cid);
	uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", orpcthis.cid.Data1, orpcthis.cid.Data2, orpcthis.cid.Data3,orpcthis.cid.Data4[0], orpcthis.cid.Data4[1],orpcthis.cid.Data4[2], orpcthis.cid.Data4[3], orpcthis.cid.Data4[4], orpcthis.cid.Data4[5], orpcthis.cid.Data4[6], orpcthis.cid.Data4[7]);

	if(uuid_str_len >= DCERPC_UUID_STR_LEN)
		memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
	proto_tree_add_string_format(orpcthis_tree, hf_ORPCTHIS_cid, tvb, offset, sizeof(orpcthis.cid), uuid_str,"ORPCTHIS CID: %s", uuid_str);
	offset += sizeof(orpcthis.cid);

	dissect_dcerpc_uint32(tvb, offset, pinfo, orpcthis_tree, drep, hf_ORPCTHIS_extensions, &ext_ptr);
	offset += sizeof(ext_ptr);
	
	dcerpc_tvb_get_uuid(tvb, offset, drep, &GUID);
	uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", GUID.Data1, GUID.Data2, GUID.Data3, GUID.Data4[0], GUID.Data4[1], GUID.Data4[2], GUID.Data4[3], GUID.Data4[4], GUID.Data4[5], GUID.Data4[6], GUID.Data4[7]);
	
	if (uuid_str_len >= DCERPC_UUID_STR_LEN)
		memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
	proto_tree_add_string_format(tree, hf_GUID, tvb, offset, sizeof(GUID), uuid_str, "GUID: %s", uuid_str);
	offset += sizeof(GUID);

/*** FIXME: The object name is in Unicode - need to do tvb_get_unicode... ***/	
	Object_strlen = tvb_strsize(tvb, offset);
	if(Object_strlen == 1)
		Object_strlen = 4;
 	proto_tree_add_item(tree, hf_ObjectName, tvb, offset, Object_strlen, FALSE);
	offset += Object_strlen;

	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_mptr_ulcntdata, &Mptr.ulCntData); 
	offset += sizeof(Mptr.ulCntData);	

	/***FIXME: For the time being, skip the MInterfacePointer data */
	offset += Mptr.ulCntData;
	
	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_ClientImpLevel, &ClientImpLevel);
	offset += sizeof(ClientImpLevel);

	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_Mode, &Mode);
	offset += sizeof(Mode);
	
	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_Interfaces, &Interfaces);
	offset += sizeof(Interfaces);
	
	dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, hf_fixme, fixme);	
	offset += sizeof(fixme);
	for (i=0; i!= (int)Interfaces; i++)
	{
		dcerpc_tvb_get_uuid(tvb, offset, drep, &Interface);
		uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Interface.Data1, Interface.Data2, Interface.Data3, Interface.Data4[0], Interface.Data4[1], Interface.Data4[2], Interface.Data4[3], Interface.Data4[4], Interface.Data4[5], Interface.Data4[6], Interface.Data4[7]);
		if (uuid_str_len >= DCERPC_UUID_STR_LEN)
                	memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
        	proto_tree_add_string_format(tree, hf_Interface, tvb, offset, sizeof(Interface), uuid_str, "Interface %d: %s", i, uuid_str);
		offset += sizeof(Interface);
	}
	
	dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_cRequestedProtseqs, &cRequestedProtseqs);
	offset += sizeof(cRequestedProtseqs);	

	for(i=0; i!= (int)cRequestedProtseqs; i++)
	{
		dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_RequestedProtseqs, &RequestedProtseqs);
		offset += sizeof(RequestedProtseqs);
	}
    	
	return offset;
}

static int
remact_dissect_rply(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, char *drep) {
        ORPCTHAT orpcthat;
	unsigned char Oxid[8];
        guint16 wNumEntries, wSecurityOffset;
	e_uuid_t ipid;
        char uuid_str[DCERPC_UUID_STR_LEN];
        int uuid_str_len;
	guint32 pAuthHint, ext_ptr, HRESULT;
	COMVERSION repver;
        
	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_ORPCTHAT_flags, &orpcthat.flags);
	offset += sizeof(orpcthat.flags);

	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_ORPCTHIS_extensions, &ext_ptr);
        offset += sizeof(ext_ptr);

	dissect_dcerpc_uint64(tvb, offset, pinfo, tree, drep, hf_Oxid, Oxid);
        offset += sizeof(Oxid);
	
	dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_wNumEntries, &wNumEntries);
	offset += sizeof(wNumEntries);
	
	dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_wSecurityOffset, &wSecurityOffset);
	offset += sizeof(wSecurityOffset);

	offset += (sizeof(unsigned short)*wNumEntries);

	dcerpc_tvb_get_uuid(tvb, offset, drep, &ipid);
        uuid_str_len = snprintf(uuid_str, DCERPC_UUID_STR_LEN, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", ipid.Data1, ipid.Data2, ipid.Data3, ipid.Data4[0], ipid.Data4[1], ipid.Data4[2], ipid.Data4[3], ipid.Data4[4], ipid.Data4[5], ipid.Data4[6], ipid.Data4[7]);
        if (uuid_str_len >= DCERPC_UUID_STR_LEN)
        	memset(uuid_str, 0, DCERPC_UUID_STR_LEN);
        proto_tree_add_string_format(tree, hf_ipid, tvb, offset, sizeof(ipid), uuid_str, "IPID: %s", uuid_str);
        offset += sizeof(ipid);
	
	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pAuthHint, &pAuthHint);
	offset += sizeof(pAuthHint);

	dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_COMVERSION_MjrVer, &repver.MajorVersion);
	offset += sizeof(repver.MajorVersion);
	
	 dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_COMVERSION_MnrVer, &repver.MinorVersion);
        offset += sizeof(repver.MinorVersion);

	dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_HRESULT, &HRESULT);
	offset += sizeof(HRESULT);

	return offset;
}
static dcerpc_sub_dissector remact_dissectors[] = {
    { 0, "RemoteActivation", remact_dissect_rqst, remact_dissect_rply },
};

void
proto_register_remact (void)
{
	static hf_register_info hf[] = {
		{ &hf_opnum,
		  { "Operation", "remact.opnum", FT_UINT16, BASE_DEC,
		    NULL, 0x0, "", HFILL }},
		{ &hf_COMVERSION_MjrVer,
		  { "COM Major Version", "remact.com_mjr_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_COMVERSION_MnrVer,
		  { "COM Minor Version", "remact.com_mnr_ver", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_ORPCTHIS_flags,
		  { "Flags", "remact.orpcthis_flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
		{ &hf_ORPCTHIS_reserved1,
		  { "reserved1 (should be 0)", "remact.orpcthis_res1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_ORPCTHIS_cid,
		  { "CID", "remact.orpcthis_cid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
		{ &hf_ORPCTHIS_extensions,
		  { "Extensions pointer", "remact.orpcthis_extnesions", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
		{ &hf_ORPCTHAT_flags,
		  { "ORPCTHAT Flags", "remact.orpcthat_flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
		{ &hf_GUID,
		  { "GUID", "remact.guid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
		{ &hf_ObjectName,
		  { "ObjectName", "remact.objectname", FT_STRINGZ, BASE_NONE, NULL, 0x0, "", HFILL }},
		{ &hf_mptr_ulcntdata,
		  { "MInterfacePointer Length", "remact.MinterfacePointer_ulCntData", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_ClientImpLevel,
		  { "Client Implementation Level", "remact.ClientImpLevel", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_Mode,
		  { "Mode", "remact.mode", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
		{ &hf_Interfaces,
		  { "Interfaces", "remact.interfaces", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }}, 
		{ &hf_fixme,
		  { "FIXME", "remact.fixme", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL }},
		{ &hf_Interface,
		  {" Interface", "remact.interface", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
		{ &hf_cRequestedProtseqs,
		  { "cRequestedProtseqs", "remact.cRequestedProtseqs", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_RequestedProtseqs, 
		  { "RequestedProtseqs", "remact.RequestedProtseqs", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_Oxid,
		  {"Oxid", "remact.Oxid", FT_UINT64, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_wNumEntries,
		  { "wNumEntries", "remact.wNumEntries", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_wSecurityOffset,
		  { "wSecurityOffset", "remact.wSecurityOffset", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_ipid,
		  { "ipid", "remact.ipid", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }},
		{ &hf_pAuthHint,
		  { "pAuthHint", "remact.pAuthHint", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
		{ &hf_HRESULT,
		  { "HRESULT", "remact.HRESULT", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }},
	};
	static gint *ett[] = {
		&ett_remact
	};
	proto_remact = proto_register_protocol ("DCOM Remote Activation", "REMACT", "remact");
	proto_register_field_array (proto_remact, hf, array_length (hf));
	proto_register_subtree_array (ett, array_length (ett));
}

void
proto_reg_handoff_remact (void)
{
	header_field_info *hf_info;

	/* Register the protocol as dcerpc */
	dcerpc_init_uuid (proto_remact, ett_remact, &uuid_remact, ver_remact, remact_dissectors, hf_opnum);

	/* Set opnum strings from subdissector list */

	hf_info = proto_registrar_get_nth(hf_opnum);
	hf_info->strings = value_string_from_subdissectors(
		remact_dissectors, array_length(remact_dissectors));
}