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
This commit is contained in:
Ronnie Sahlberg 2002-03-16 04:39:29 +00:00
parent 54fa1d944a
commit 17392c995b
4 changed files with 86 additions and 26 deletions

View 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)
{

View 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

View 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;

12
smb.h
View File

@ -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>
@ -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;