Fix and clean up the DCE_RPC analyzer a bit and probably broke it in some way.

This commit is contained in:
Seth Hall 2016-03-07 11:18:22 -05:00
parent ca58dc84d5
commit 12a8b8e5db
5 changed files with 251 additions and 231 deletions

View file

@ -190,7 +190,7 @@ DCE_RPC_Header::DCE_RPC_Header(analyzer::Analyzer* a, const u_char* b)
DCE_RPC_Session::DCE_RPC_Session(analyzer::Analyzer* a)
: analyzer(a),
if_uuid("00000000-0000-0000-0000-000000000000"),
uuid("00000000-0000-0000-0000-000000000000"),
if_id(BifEnum::DCE_RPC_unknown_if)
{
opnum = -1;
@ -203,7 +203,7 @@ bool DCE_RPC_Session::LooksLikeRPC(int len, const u_char* msg)
try
{
binpac::DCE_RPC_Simple::DCE_RPC_Header h;
binpac::DCE_RPC::DCE_RPC_Header h;
h.Parse(msg, msg + len);
if ( h.rpc_vers() == 5 && h.rpc_vers_minor() == 0 )
{
@ -241,20 +241,20 @@ void DCE_RPC_Session::DeliverPDU(int is_orig, int len, const u_char* data)
try
{
// TODO: handle incremental input
binpac::DCE_RPC_Simple::DCE_RPC_PDU pdu;
binpac::DCE_RPC::DCE_RPC_PDU pdu;
pdu.Parse(data, data + len);
switch ( pdu.header()->PTYPE() ) {
case binpac::DCE_RPC_Simple::DCE_RPC_BIND:
case binpac::DCE_RPC_Simple::DCE_RPC_ALTER_CONTEXT:
case binpac::DCE_RPC::DCE_RPC_BIND:
case binpac::DCE_RPC::DCE_RPC_ALTER_CONTEXT:
DeliverBind(&pdu);
break;
case binpac::DCE_RPC_Simple::DCE_RPC_REQUEST:
case binpac::DCE_RPC::DCE_RPC_REQUEST:
DeliverRequest(&pdu);
break;
case binpac::DCE_RPC_Simple::DCE_RPC_RESPONSE:
case binpac::DCE_RPC::DCE_RPC_RESPONSE:
DeliverResponse(&pdu);
break;
}
@ -265,24 +265,24 @@ void DCE_RPC_Session::DeliverPDU(int is_orig, int len, const u_char* data)
}
}
void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu)
void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC::DCE_RPC_PDU* pdu)
{
binpac::DCE_RPC_Simple::DCE_RPC_Bind* bind = pdu->body()->bind();
binpac::DCE_RPC::DCE_RPC_Bind* bind = pdu->body()->bind();
for ( int i = 0; i < bind->p_context_elem()->n_context_elem(); ++i )
for ( int i = 0; i < bind->context_list()->num_contexts(); ++i )
{
binpac::DCE_RPC_Simple::p_cont_elem_t* elem =
(*bind->p_context_elem()->p_cont_elem())[i];
binpac::DCE_RPC::ContextRequest* elem =
(*bind->context_list()->request_contexts())[i];
if_uuid = UUID(elem->abstract_syntax()->if_uuid().begin());
uuid = UUID(elem->abstract_syntax()->uuid().begin());
uuid_map_t::const_iterator uuid_it =
well_known_uuid_map().find(if_uuid);
well_known_uuid_map().find(uuid);
if ( uuid_it == well_known_uuid_map().end() )
{
#ifdef DEBUG
// conn->Weird(fmt("Unknown DCE_RPC interface %s",
// if_uuid.to_string()));
// uuid.to_string()));
#endif
if_id = BifEnum::DCE_RPC_unknown_if;
}
@ -293,7 +293,7 @@ void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu
{
val_list* vl = new val_list;
vl->append(analyzer->BuildConnVal());
vl->append(new StringVal(if_uuid.to_string()));
vl->append(new StringVal(uuid.to_string()));
// vl->append(new EnumVal(if_id, BifType::Enum::dce_rpc_if_id));
analyzer->ConnectionEvent(dce_rpc_bind, vl);
@ -301,9 +301,9 @@ void DCE_RPC_Session::DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu
}
}
void DCE_RPC_Session::DeliverRequest(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu)
void DCE_RPC_Session::DeliverRequest(const binpac::DCE_RPC::DCE_RPC_PDU* pdu)
{
binpac::DCE_RPC_Simple::DCE_RPC_Request* req = pdu->body()->request();
binpac::DCE_RPC::DCE_RPC_Request* req = pdu->body()->request();
opnum = req->opnum();
@ -328,9 +328,9 @@ void DCE_RPC_Session::DeliverRequest(const binpac::DCE_RPC_Simple::DCE_RPC_PDU*
}
}
void DCE_RPC_Session::DeliverResponse(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu)
void DCE_RPC_Session::DeliverResponse(const binpac::DCE_RPC::DCE_RPC_PDU* pdu)
{
binpac::DCE_RPC_Simple::DCE_RPC_Response* resp = pdu->body()->response();
binpac::DCE_RPC::DCE_RPC_Response* resp = pdu->body()->response();
if ( dce_rpc_response )
{
@ -353,16 +353,16 @@ void DCE_RPC_Session::DeliverResponse(const binpac::DCE_RPC_Simple::DCE_RPC_PDU*
}
void DCE_RPC_Session::DeliverEpmapperRequest(
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* /* pdu */,
const binpac::DCE_RPC_Simple::DCE_RPC_Request* /* req */)
const binpac::DCE_RPC::DCE_RPC_PDU* /* pdu */,
const binpac::DCE_RPC::DCE_RPC_Request* /* req */)
{
// DEBUG_MSG("Epmapper request opnum = %d\n", req->opnum());
// ### TODO(rpang): generate an event on epmapper request
}
void DCE_RPC_Session::DeliverEpmapperResponse(
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC_Simple::DCE_RPC_Response* resp)
const binpac::DCE_RPC::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC::DCE_RPC_Response* resp)
{
// DEBUG_MSG("Epmapper request opnum = %d\n", req->opnum());
switch ( opnum ) {
@ -374,12 +374,12 @@ void DCE_RPC_Session::DeliverEpmapperResponse(
void DCE_RPC_Session::DeliverEpmapperMapResponse(
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC_Simple::DCE_RPC_Response* resp)
const binpac::DCE_RPC::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC::DCE_RPC_Response* resp)
{
try
{
binpac::DCE_RPC_Simple::epmapper_map_resp epm_resp;
binpac::DCE_RPC::epmapper_map_resp epm_resp;
epm_resp.Parse(resp->stub().begin(), resp->stub().end(),
pdu->byteorder());
@ -387,7 +387,7 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse(
for ( unsigned int twr_i = 0;
twr_i < epm_resp.towers()->actual_count(); ++twr_i )
{
binpac::DCE_RPC_Simple::epm_tower* twr =
binpac::DCE_RPC::epm_tower* twr =
(*epm_resp.towers()->towers())[twr_i]->tower();
mapped.addr = dce_rpc_endpoint_addr();
@ -396,28 +396,28 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse(
for ( int floor_i = 0; floor_i < twr->num_floors();
++floor_i )
{
binpac::DCE_RPC_Simple::epm_floor* floor =
binpac::DCE_RPC::epm_floor* floor =
(*twr->floors())[floor_i];
switch ( floor->protocol() ) {
case binpac::DCE_RPC_Simple::EPM_PROTOCOL_UUID:
case binpac::DCE_RPC::EPM_PROTOCOL_UUID:
if ( floor_i == 0 )
mapped.uuid = UUID(floor->lhs()->data()->uuid()->if_uuid());
break;
case binpac::DCE_RPC_Simple::EPM_PROTOCOL_TCP:
case binpac::DCE_RPC::EPM_PROTOCOL_TCP:
mapped.addr.port =
floor->rhs()->data()->tcp();
mapped.addr.proto = TRANSPORT_TCP;
break;
case binpac::DCE_RPC_Simple::EPM_PROTOCOL_UDP:
case binpac::DCE_RPC::EPM_PROTOCOL_UDP:
mapped.addr.port =
floor->rhs()->data()->udp();
mapped.addr.proto = TRANSPORT_UDP;
break;
case binpac::DCE_RPC_Simple::EPM_PROTOCOL_IP:
case binpac::DCE_RPC::EPM_PROTOCOL_IP:
uint32 hostip = floor->rhs()->data()->ip();
mapped.addr.addr = IPAddr(IPv4, &hostip, IPAddr::Host);
break;

View file

@ -11,7 +11,7 @@
#include "analyzer/protocol/dce-rpc/events.bif.h"
#include "IPAddr.h"
#include "dce_rpc_simple_pac.h"
#include "dce_rpc_pac.h"
namespace analyzer { namespace dce_rpc {
@ -125,22 +125,22 @@ public:
{ return dce_rpc_message || dce_rpc_bind || dce_rpc_request; }
protected:
void DeliverBind(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu);
void DeliverRequest(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu);
void DeliverResponse(const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu);
void DeliverBind(const binpac::DCE_RPC::DCE_RPC_PDU* pdu);
void DeliverRequest(const binpac::DCE_RPC::DCE_RPC_PDU* pdu);
void DeliverResponse(const binpac::DCE_RPC::DCE_RPC_PDU* pdu);
void DeliverEpmapperRequest(
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC_Simple::DCE_RPC_Request* req);
const binpac::DCE_RPC::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC::DCE_RPC_Request* req);
void DeliverEpmapperResponse(
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC_Simple::DCE_RPC_Response* resp);
const binpac::DCE_RPC::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC::DCE_RPC_Response* resp);
void DeliverEpmapperMapResponse(
const binpac::DCE_RPC_Simple::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC_Simple::DCE_RPC_Response* resp);
const binpac::DCE_RPC::DCE_RPC_PDU* pdu,
const binpac::DCE_RPC::DCE_RPC_Response* resp);
analyzer::Analyzer* analyzer;
UUID if_uuid;
UUID uuid;
BifEnum::dce_rpc_if_id if_id;
int opnum;
struct {

View file

@ -4,131 +4,132 @@ type DCE_RPC_PDU = record {
# Set header's byteorder to little-endian (or big-endian) to
# avoid cyclic dependency.
header : DCE_RPC_Header;
frag : bytestring &length = body_length;
# TODO: bring back reassembly. It was having trouble.
#frag : bytestring &length = body_length;
body : DCE_RPC_Body(header);
auth : DCE_RPC_Auth(header);
} &let {
body_length: int =
header.frag_length - sizeof(header) - header.auth_length;
frag_reassembled: bool =
$context.flow.reassemble_fragment(frag, header.lastfrag);
body: DCE_RPC_Body(header)
withinput $context.flow.reassembled_body()
&if frag_reassembled;
#body_length : int = header.frag_length - sizeof(header) - header.auth_length;
#frag_reassembled : bool = $context.flow.reassemble_fragment(frag, header.lastfrag);
#body : DCE_RPC_Body(header)
# withinput $context.flow.reassembled_body()
# &if frag_reassembled;
} &byteorder = header.byteorder,
&length = header.frag_length; # length of the PDU
&length = header.frag_length;
connection DCE_RPC_Conn(bro_analyzer: BroAnalyzer) {
upflow = DCE_RPC_Flow(true);
downflow = DCE_RPC_Flow(false);
function get_cont_id_opnum_map(cont_id: uint16): uint16
%{
return cont_id_opnum_map[cont_id];
%}
function set_cont_id_opnum_map(cont_id: uint16, opnum: uint16): bool
%{
cont_id_opnum_map[cont_id] = opnum;
return true;
%}
%member{
map<uint16, uint16> cont_id_opnum_map;
%}
};
flow DCE_RPC_Flow(is_orig: bool) {
flowunit = DCE_RPC_PDU withcontext (connection, this);
%member{
FlowBuffer frag_reassembler_;
%}
# Fragment reassembly.
function reassemble_fragment(frag: bytestring, lastfrag: bool): bool
%{
int orig_data_length = frag_reassembler_.data_length();
frag_reassembler_.NewData(frag.begin(), frag.end());
int new_frame_length = orig_data_length + frag.length();
if ( orig_data_length == 0 )
frag_reassembler_.NewFrame(new_frame_length, false);
else
frag_reassembler_.GrowFrame(new_frame_length);
return lastfrag;
%}
function reassembled_body(): const_bytestring
%{
return const_bytestring(
frag_reassembler_.begin(),
frag_reassembler_.end());
%}
# Bind.
function process_dce_rpc_bind(bind: DCE_RPC_Bind): bool
%{
$const_def{bind_elems = bind.p_context_elem};
if ( ${bind_elems.n_context_elem} > 1 ) {
${connection.bro_analyzer}->Weird(
"DCE_RPC_bind_to_multiple_interfaces");
}
if ( dce_rpc_bind ) {
// Go over the elements, each having a UUID
for ( int i = 0; i < ${bind_elems.n_context_elem}; ++i ) {
$const_def{if_uuid =
bind_elems.p_cont_elem[i].abstract_syntax.if_uuid};
// Queue the event
BifEvent::generate_dce_rpc_bind(
${connection.bro_analyzer},
${connection.bro_analyzer}->Conn(),
bytestring_to_val(${if_uuid}));
// Set the connection's UUID
// ${connection}->set_uuid(${if_uuid});
}
}
return ${bind_elems.n_context_elem} > 0;
%}
# Request.
function process_dce_rpc_request(req: DCE_RPC_Request): bool
%{
if ( dce_rpc_request )
{
BifEvent::generate_dce_rpc_request(
${connection.bro_analyzer},
${connection.bro_analyzer}->Conn(),
${req.opnum},
bytestring_to_val(${req.stub}));
}
${connection}->set_cont_id_opnum_map(${req.p_cont_id},
${req.opnum});
return true;
%}
# Response.
function process_dce_rpc_response(resp: DCE_RPC_Response): bool
%{
if ( dce_rpc_response )
{
BifEvent::generate_dce_rpc_response(
${connection.bro_analyzer},
${connection.bro_analyzer}->Conn(),
${connection}->get_cont_id_opnum_map(${resp.p_cont_id}),
bytestring_to_val(${resp.stub}));
}
return true;
%}
};
#connection DCE_RPC_Conn(bro_analyzer: BroAnalyzer) {
# upflow = DCE_RPC_Flow(true);
# downflow = DCE_RPC_Flow(false);
#
# %member{
# map<uint16, uint16> cont_id_opnum_map;
# %}
#
# function get_cont_id_opnum_map(cont_id: uint16): uint16
# %{
# return cont_id_opnum_map[cont_id];
# %}
#
# function set_cont_id_opnum_map(cont_id: uint16, opnum: uint16): bool
# %{
# cont_id_opnum_map[cont_id] = opnum;
# return true;
# %}
#};
#
#
#flow DCE_RPC_Flow(is_orig: bool) {
# flowunit = DCE_RPC_PDU withcontext (connection, this);
#
# #%member{
# #FlowBuffer frag_reassembler_;
# #%}
#
# # Fragment reassembly.
# #function reassemble_fragment(frag: bytestring, lastfrag: bool): bool
# # %{
# # int orig_data_length = frag_reassembler_.data_length();
# #
# # frag_reassembler_.NewData(frag.begin(), frag.end());
# #
# # int new_frame_length = orig_data_length + frag.length();
# # if ( orig_data_length == 0 )
# # frag_reassembler_.NewFrame(new_frame_length, false);
# # else
# # frag_reassembler_.GrowFrame(new_frame_length);
# #
# # return lastfrag;
# # %}
#
# #function reassembled_body(): const_bytestring
# # %{
# # return const_bytestring(
# # frag_reassembler_.begin(),
# # frag_reassembler_.end());
# # %}
#
# # Bind.
# function process_dce_rpc_bind(bind: DCE_RPC_Bind): bool
# %{
# $const_def{bind_elems = bind.context_list};
#
# if ( ${bind_elems.num_contexts} > 1 )
# {
# ${connection.bro_analyzer}->Weird("DCE_RPC_bind_to_multiple_interfaces");
# }
#
# if ( dce_rpc_bind )
# {
# // Go over the elements, each having a UUID
# for ( int i = 0; i < ${bind_elems.num_contexts}; ++i )
# {
# $const_def{uuid =
# bind_elems.request_contexts[i].abstract_syntax.uuid};
#
# // Queue the event
# BifEvent::generate_dce_rpc_bind(
# ${connection.bro_analyzer},
# ${connection.bro_analyzer}->Conn(),
# bytestring_to_val(${uuid}));
#
# // Set the connection's UUID
# // ${connection}->set_uuid(${uuid});
# }
# }
#
# return ${bind_elems.num_contexts} > 0;
# %}
#
# # Request.
# function process_dce_rpc_request(req: DCE_RPC_Request): bool
# %{
# if ( dce_rpc_request )
# {
# BifEvent::generate_dce_rpc_request(
# ${connection.bro_analyzer},
# ${connection.bro_analyzer}->Conn(),
# ${req.opnum},
# bytestring_to_val(${req.stub}));
# }
#
# ${connection}->set_cont_id_opnum_map(${req.context_id},
# ${req.opnum});
#
# return true;
# %}
#
# # Response.
# function process_dce_rpc_response(resp: DCE_RPC_Response): bool
# %{
# if ( dce_rpc_response )
# {
# BifEvent::generate_dce_rpc_response(
# ${connection.bro_analyzer},
# ${connection.bro_analyzer}->Conn(),
# ${connection}->get_cont_id_opnum_map(${resp.context_id}),
# bytestring_to_val(${resp.stub}));
# }
#
# return true;
# %}
#};

View file

@ -25,15 +25,15 @@ enum dce_rpc_ptype {
type uuid = bytestring &length = 16;
type context_handle = record {
cxt_attributes: uint32;
cxt_uuid: uuid;
attrs : uint32;
uuid : bytestring &length = 16;
};
type rpc_if_id_t = record {
if_uuid : uuid;
vers_major : uint16;
vers_minor : uint16;
};
#type rpc_if_id_t = record {
# if_uuid : bytestring &length = 16;
# vers_major : uint16;
# vers_minor : uint16;
#};
type NDR_Format = record {
intchar : uint8;
@ -60,44 +60,61 @@ type DCE_RPC_Header = record {
lastfrag = (! frag) || (pfc_flags & 2);
} &byteorder = packed_drep.byteorder;
type p_context_id_t = uint16;
type p_syntax_id_t = record {
if_uuid : uuid;
if_version : uint32;
type Syntax = record {
uuid : bytestring &length = 16;
version : uint32;
};
type p_cont_elem_t = record {
p_cont_id : p_context_id_t;
n_transfer_syn : uint8;
type ContextRequest = record {
id : uint16;
num_syntaxes : uint8;
reserved : padding[1];
abstract_syntax : p_syntax_id_t;
transfer_syntaxes : p_syntax_id_t[n_transfer_syn];
abstract_syntax : Syntax;
transfer_syntaxes : Syntax[num_syntaxes];
};
type p_cont_list_t = record {
n_context_elem : uint8;
type ContextReply = record {
ack_result : uint16;
ack_reason : uint16;
syntax : Syntax;
};
type ContextList(is_request: bool) = record {
num_contexts : uint8;
reserved : padding[3];
p_cont_elem : p_cont_elem_t[n_context_elem];
req_reply : case is_request of {
true -> request_contexts : ContextRequest[num_contexts];
false -> reply_contexts : ContextReply[num_contexts];
};
};
type DCE_RPC_Bind = record {
max_xmit_frag : uint16;
max_recv_frag : uint16;
assoc_group_id : uint32;
p_context_elem : p_cont_list_t;
context_list : ContextList(1);
};
type DCE_RPC_Bind_Ack = record {
max_xmit_frag : uint16;
max_recv_frag : uint16;
assoc_group_id : uint32;
sec_addr_length : uint16;
sec_addr : bytestring &length=sec_addr_length;
pad : padding align 4;
contexts : ContextList(0);
};
type DCE_RPC_AlterContext = record {
max_xmit_frag : uint16;
max_recv_frag : uint16;
assoc_group_id : uint32;
p_context_elem : p_cont_list_t;
contexts : ContextList(0);
};
type DCE_RPC_Request = record {
alloc_hint : uint32;
p_cont_id : p_context_id_t;
context_id : uint16;
opnum : uint16;
# object : uuid;
# stub_pad_0 : padding align 8;
@ -106,7 +123,7 @@ type DCE_RPC_Request = record {
type DCE_RPC_Response = record {
alloc_hint : uint32;
p_cont_id : p_context_id_t;
context_id : uint16;
cancel_count : uint8;
reserved : uint8;
# stub_pad_0 : padding align 8;
@ -115,11 +132,10 @@ type DCE_RPC_Response = record {
type DCE_RPC_Body(header: DCE_RPC_Header) = case header.PTYPE of {
DCE_RPC_BIND -> bind : DCE_RPC_Bind;
DCE_RPC_BIND_ACK -> bind_ack : DCE_RPC_Bind_Ack;
DCE_RPC_REQUEST -> request : DCE_RPC_Request;
DCE_RPC_RESPONSE -> response : DCE_RPC_Response;
default -> other : bytestring &restofdata;
};
type DCE_RPC_Auth(header: DCE_RPC_Header) = uint8[header.auth_length];
%include epmapper.pac

View file

@ -5,10 +5,13 @@
#include "events.bif.h"
%}
analyzer DCE_RPC withcontext {
connection: DCE_RPC_Conn;
flow: DCE_RPC_Flow;
};
analyzer DCE_RPC withcontext {};
#analyzer DCE_RPC withcontext {
# connection : DCE_RPC_Conn;
# flow : DCE_RPC_Flow;
#};
%include dce_rpc-protocol.pac
%include epmapper.pac
%include dce_rpc-analyzer.pac