From 17392c995b3584143c4cbc389c2bae09dc4cc968 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Sat, 16 Mar 2002 04:39:29 +0000 Subject: [PATCH] A new type of DCERPC over SMB transport. I have captures with w2k speaking DCERPC without using the normal Transaction named pipes SMBs. Instead DCERPC is just implemented ontop of ordinary read/write calls. The smb dissector now examines TreeConnectAndX and stores the conversation/tid/type-of-share in a table for later access. All SMB requests examine that hash table to find out if TID in the header refers to a normal share or an IPC$ share. Initial support in read/write SMB calls to detect if the operations are for an IPC share and thus it assumes it must be DCERPC commands in the payload. Desegmentation/Reassembly of these types of calls are not implemented yet. svn path=/trunk/; revision=4952 --- packet-smb-pipe.c | 4 +-- packet-smb-pipe.h | 5 ++- packet-smb.c | 91 +++++++++++++++++++++++++++++++++++------------ smb.h | 12 ++++++- 4 files changed, 86 insertions(+), 26 deletions(-) diff --git a/packet-smb-pipe.c b/packet-smb-pipe.c index 7a3fad7d54..ed88de56be 100644 --- a/packet-smb-pipe.c +++ b/packet-smb-pipe.c @@ -8,7 +8,7 @@ XXX Fixme : shouldnt show [malformed frame] for long packets * significant rewrite to tvbuffify the dissector, Ronnie Sahlberg and * Guy Harris 2001 * - * $Id: packet-smb-pipe.c,v 1.70 2002/03/15 08:59:52 sahlberg Exp $ + * $Id: packet-smb-pipe.c,v 1.71 2002/03/16 04:39:28 sahlberg Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -3157,7 +3157,7 @@ proto_register_pipe_lanman(void) static heur_dissector_list_t smb_transact_heur_subdissector_list; -static gboolean +gboolean dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, guint32 fid) { diff --git a/packet-smb-pipe.h b/packet-smb-pipe.h index 7084a5d7da..6f86f91c7e 100644 --- a/packet-smb-pipe.h +++ b/packet-smb-pipe.h @@ -2,7 +2,7 @@ * Declarations of routines for SMB named pipe packet dissection * Copyright 1999, Richard Sharpe * - * $Id: packet-smb-pipe.h,v 1.9 2001/11/19 11:41:51 guy Exp $ + * $Id: packet-smb-pipe.h,v 1.10 2002/03/16 04:39:28 sahlberg Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -30,5 +30,8 @@ extern gboolean dissect_pipe_smb(tvbuff_t *sp_tvb, tvbuff_t *s_tvb, tvbuff_t *pd_tvb, tvbuff_t *p_tvb, tvbuff_t *d_tvb, const char *pipe, packet_info *pinfo, proto_tree *tree); +gboolean +dissect_pipe_dcerpc(tvbuff_t *d_tvb, packet_info *pinfo, proto_tree *parent_tree, + proto_tree *tree, guint32 fid); #endif diff --git a/packet-smb.c b/packet-smb.c index 5f12961e10..dab94f85f4 100644 --- a/packet-smb.c +++ b/packet-smb.c @@ -3,7 +3,7 @@ * Copyright 1999, Richard Sharpe * 2001 Rewrite by Ronnie Sahlberg and Guy Harris * - * $Id: packet-smb.c,v 1.219 2002/03/15 19:47:03 sharpe Exp $ + * $Id: packet-smb.c,v 1.220 2002/03/16 04:39:29 sahlberg Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -3114,8 +3114,9 @@ static int dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_tree *smb_tree) { guint32 ofs=0; - guint16 cnt=0, bc, fid; + guint16 cnt=0, bc, fid=0; guint8 wc; + smb_info_t *si = (smb_info_t *)pinfo->private_data; WORD_COUNT; @@ -3156,8 +3157,16 @@ dissect_write_file_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, COUNT_BYTES(2); if (bc != 0) { - /* file data */ - offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc); + if( (si->sip->flags&SMB_SIF_TID_IS_IPC) && (ofs==0) ){ + tvbuff_t *dcerpc_tvb; + /* dcerpc call */ + dcerpc_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), bc); + dissect_pipe_dcerpc(dcerpc_tvb, pinfo, top_tree, + tree, fid); + } else { + /* ordinary file data */ + offset = dissect_file_data(tvb, pinfo, tree, offset, bc, bc); + } bc = 0; } @@ -4775,6 +4784,7 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint8 wc, cmd=0xff; guint16 andxoffset=0, bc, datalen=0, dataoffset=0; smb_info_t *si = (smb_info_t *)pinfo->private_data; + int fid=0; WORD_COUNT; @@ -4799,7 +4809,8 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, /* If we have seen the request, then print which FID this refers to */ /* first check if we have seen the request */ if(si->sip != NULL && si->sip->frame_req>0){ - add_fid(tvb, pinfo, tree, 0, 0, (int)si->sip->extra_info); + fid=(int)si->sip->extra_info; + add_fid(tvb, pinfo, tree, 0, 0, fid); } /* remaining */ @@ -4876,9 +4887,21 @@ dissect_read_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, } } - /* file data */ - offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen); - bc = 0; + /* another way to transport DCERPC over SMB is to skip Transaction completely and just + read write */ + if(bc){ + if(si->sip->flags&SMB_SIF_TID_IS_IPC){ + tvbuff_t *dcerpc_tvb; + /* dcerpc call */ + dcerpc_tvb = tvb_new_subset(tvb, offset, tvb_length_remaining(tvb, offset), bc); + dissect_pipe_dcerpc(dcerpc_tvb, pinfo, top_tree, + tree, fid); + } else { + /* ordinary file data */ + offset = dissect_file_data(tvb, pinfo, tree, offset, bc, datalen); + } + bc = 0; + } END_OF_SMB @@ -5713,6 +5736,22 @@ dissect_tree_connect_andx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree offset, an_len, an); COUNT_BYTES(an_len); + /* Now when we know the service type, store it so that we know it for later commands down + this tree */ + if(!pinfo->fd->flags.visited){ + smb_info_t *si = (smb_info_t *)pinfo->private_data; + /* Remove any previous entry for this TID */ + if(g_hash_table_lookup(si->ct->tid_service, (void *)si->tid)){ + g_hash_table_remove(si->ct->tid_service, (void *)si->tid); + } + if(!strcmp(an,"IPC")){ + g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_IPC); + } else { + g_hash_table_insert(si->ct->tid_service, (void *)si->tid, (void *)TID_NORMAL); + } + } + + if(wc==3){ if (bc != 0) { /* @@ -12430,6 +12469,8 @@ free_hash_tables(gpointer ctarg, gpointer user_data) g_hash_table_destroy(ct->matched); if (ct->dcerpc_fid_to_frame) g_hash_table_destroy(ct->dcerpc_fid_to_frame); + if (ct->tid_service) + g_hash_table_destroy(ct->tid_service); } static void @@ -13928,7 +13969,6 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) guint32 nt_status = 0; guint8 errclass = 0; guint16 errcode = 0; - guint16 uid, pid, tid, mid; guint32 pid_mid; conversation_t *conversation; @@ -13963,11 +14003,11 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) } else { si.unicode = FALSE; } - tid = tvb_get_letohs(tvb, offset+24); - pid = tvb_get_letohs(tvb, offset+26); - uid = tvb_get_letohs(tvb, offset+28); - mid = tvb_get_letohs(tvb, offset+30); - pid_mid = (pid << 16) | mid; + si.tid = tvb_get_letohs(tvb, offset+24); + si.pid = tvb_get_letohs(tvb, offset+26); + si.uid = tvb_get_letohs(tvb, offset+28); + si.mid = tvb_get_letohs(tvb, offset+30); + pid_mid = (si.pid << 16) | si.mid; si.info_level = -1; si.info_count = -1; @@ -14007,14 +14047,17 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) si.ct->dcerpc_fid_to_frame=g_hash_table_new( smb_saved_info_hash_unmatched, smb_saved_info_equal_unmatched); + si.ct->tid_service=g_hash_table_new( + smb_saved_info_hash_unmatched, + smb_saved_info_equal_unmatched); conversation_add_proto_data(conversation, proto_smb, si.ct); } if( (si.request) - && (mid==0) - && (uid==0) - && (pid==0) - && (tid==0) ){ + && (si.mid==0) + && (si.uid==0) + && (si.pid==0) + && (si.tid==0) ){ /* this is a broadcast SMB packet, there will not be a reply. We dont need to do anything */ @@ -14192,6 +14235,10 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) sip = g_mem_chunk_alloc(smb_saved_info_chunk); sip->frame_req = pinfo->fd->num; sip->frame_res = 0; + sip->flags = 0; + if(g_hash_table_lookup(si.ct->tid_service, (void *)si.tid)){ + sip->flags |= SMB_SIF_TID_IS_IPC; + } sip->cmd = si.cmd; sip->extra_info = NULL; g_hash_table_insert(si.ct->unmatched, (void *)pid_mid, sip); @@ -14307,19 +14354,19 @@ dissect_smb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) offset += 12; /* TID */ - proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, tid); + proto_tree_add_uint(htree, hf_smb_tid, tvb, offset, 2, si.tid); offset += 2; /* PID */ - proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2, pid); + proto_tree_add_uint(htree, hf_smb_pid, tvb, offset, 2, si.pid); offset += 2; /* UID */ - proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2, uid); + proto_tree_add_uint(htree, hf_smb_uid, tvb, offset, 2, si.uid); offset += 2; /* MID */ - proto_tree_add_uint(htree, hf_smb_mid, tvb, offset, 2, mid); + proto_tree_add_uint(htree, hf_smb_mid, tvb, offset, 2, si.mid); offset += 2; pinfo->private_data = &si; diff --git a/smb.h b/smb.h index cba344da61..aed148eeeb 100644 --- a/smb.h +++ b/smb.h @@ -2,7 +2,7 @@ * Defines for smb packet dissection * Copyright 1999, Richard Sharpe * - * $Id: smb.h,v 1.35 2002/03/15 08:59:53 sahlberg Exp $ + * $Id: smb.h,v 1.36 2002/03/16 04:39:29 sahlberg Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -225,8 +225,10 @@ * The information we need to save about a request in order to show the * frame number of the request in the dissection of the reply. */ +#define SMB_SIF_TID_IS_IPC 0x0001 typedef struct { guint32 frame_req, frame_res; + guint16 flags; int cmd; void *extra_info; } smb_saved_info_t; @@ -256,6 +258,11 @@ typedef struct { #define TRANSACTION_PIPE 0 #define TRANSACTION_MAILSLOT 1 +/* these are defines used to represent different types of TIDs. + dont use the value 0 for any of these */ +#define TID_NORMAL 1 +#define TID_IPC 2 + /* this is the structure which is associated with each conversation */ typedef struct conv_tables { /* these two tables are used to match requests with responses */ @@ -263,10 +270,13 @@ typedef struct conv_tables { GHashTable *matched; /* this tables is used by DCERPC over SMB reassembly*/ GHashTable *dcerpc_fid_to_frame; + /* This table is used to track TID->services for a conversation */ + GHashTable *tid_service; } conv_tables_t; typedef struct smb_info { int cmd; + int tid, pid, uid, mid; gboolean unicode; /* Are strings in this SMB Unicode? */ gboolean request; /* Is this a request? */ gboolean unidir;