A new type of DCERPC over SMB transport.
authorsahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 16 Mar 2002 04:39:29 +0000 (04:39 +0000)
committersahlberg <sahlberg@f5534014-38df-0310-8fa8-9805f1628bb7>
Sat, 16 Mar 2002 04:39:29 +0000 (04:39 +0000)
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.

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@4952 f5534014-38df-0310-8fa8-9805f1628bb7

packet-smb-pipe.c
packet-smb-pipe.h
packet-smb.c
smb.h

index 7a3fad7d549ad9fdcea7914a28136d91a19a02d2..ed88de56be039350622b84b4e60cd191fe9ca1b7 100644 (file)
@@ -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 <gerald@ethereal.com>
@@ -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)
 {
index 7084a5d7da6792ba257e74e0312b90906b3699db..6f86f91c7e3c2febce4adb0dffc78d26de6551bb 100644 (file)
@@ -2,7 +2,7 @@
  * Declarations of routines for SMB named pipe packet dissection
  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
  *
- * $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 <gerald@ethereal.com>
@@ -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
index 5f12961e10dae4ef9b025dbea4fb745c639c7d46..dab94f85f408db225b387a228f1bb69a8aada739 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
  * 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 <gerald@ethereal.com>
@@ -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 cba344da615dbd467f884d0247481b0db0bf597f..aed148eeeba28e311e0998348e8e2ea728c9de9d 100644 (file)
--- a/smb.h
+++ b/smb.h
@@ -2,7 +2,7 @@
  * Defines for smb packet dissection
  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
  *
- * $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 <gerald@ethereal.com>
  * 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;