zeek/policy.old/summaries/smb-summary.bro
2011-03-01 10:51:44 -05:00

251 lines
6.2 KiB
Text

@load app-summary
redef capture_filters += {
["netbios-dgm"] = "udp port 138",
["netbios-ssn"] = "tcp port 139",
["microsft-ds"] = "tcp port 445",
};
module SMB_summary;
global smb_log = open_log_file("smb-summary") &redef;
global chris_log = open_log_file("chris-summary") &redef;
#const smb_transaction_func = {
# ["SMB_COM_TRANSACTION", 0x0 ] = "\\PIPE\\LANMAN\\",
# ["SMB_COM_TRANSACTION", 0x1 ] = "\\MAILSLOT\\",
# ["SMB_COM_TRANSACTION", 0x54] = "CallNamedPipe",
# ["SMB_COM_TRANSACTION", 0x53] = "WaitNamedPipe",
# ["SMB_COM_TRANSACTION", 0x26] = "TransactNmPipe",
#
# ["SMB_COM_TRANSACTION2", 0x0] = "TRANS2_OPEN2",
# ["SMB_COM_TRANSACTION2", 0x1] = "TRANS2_FIND_FIRST2",
# ["SMB_COM_TRANSACTION2", 0x2] = "TRANS2_FIND_NEXT2",
# ["SMB_COM_TRANSACTION2", 0x3] = "TRANS2_QUERY_FS_INFORMATION",
# ["SMB_COM_TRANSACTION2", 0x5] = "TRANS2_QUERY_PATH_INFORMATION",
# ["SMB_COM_TRANSACTION2", 0x6] = "TRANS2_SET_PATH_INFORMATION",
# ["SMB_COM_TRANSACTION2", 0x7] = "TRANS2_QUERY_FILE_INFORMATION",
# ["SMB_COM_TRANSACTION2", 0x8] = "TRANS2_SET_FILE_INFORMATION",
# ["SMB_COM_TRANSACTION2", 0x0d] = "TRANS2_CREATE_DIRECTORY",
# ["SMB_COM_TRANSACTION2", 0x0e] = "TRANS2_SESSION_SETUP",
# ["SMB_COM_TRANSACTION2", 0x10] = "TRANS2_GET_DFS_REFERRAL",
#} &default = function(cmd: string, subcmd: count): string
# {
# return fmt("%s/%d", cmd, subcmd);
# };
type smb_req_resp: record {
connection_id: conn_id;
conn_start: time;
func: string;
cmd: string;
start: time;
num_req: count;
req_size: count;
num_resp: count;
resp_size: count;
};
type smb_req_reply_group: record {
trans: table[count] of smb_req_resp;
first_req: count;
last_req: count;
};
global smb_trans_table: table[conn_id] of smb_req_reply_group;
function lookup_smb_req_reply_group(id: conn_id, create: bool): smb_req_reply_group
{
if ( id !in smb_trans_table )
{
if ( create )
{
local trans: table[count] of smb_req_resp;
smb_trans_table[id] = [
$trans = trans, $first_req = 1, $last_req = 0];
}
else
print fmt("SMB req_reply_group not found: %s",
conn_id_string(id));
}
return smb_trans_table[id];
}
function new_smb_req_resp(c: connection, cmd: string): smb_req_resp
{
local id = c$id;
local g = lookup_smb_req_reply_group(id, T);
if( is_udp_port(id$orig_p) || is_udp_port(id$resp_p) )
print fmt("%.6f %s a new req_resp was triggered on a UDP connection!: %s",
network_time(), conn_id_string(id), cmd);
local t = [
$connection_id = id, $conn_start = c$start_time,
$cmd = cmd, $func = cmd,
$start = network_time(),
$num_req = 0, $req_size = 0,
$num_resp = 0, $resp_size = 0
];
++g$last_req;
g$trans[g$last_req] = t;
return g$trans[g$last_req];
}
function end_smb_req_resp(t: smb_req_resp)
{
print_app_summary(smb_log, t$connection_id, t$conn_start,
t$func, t$start,
t$num_req, t$req_size,
t$num_resp, t$resp_size,
fmt("cmd %s", t$cmd));
}
function lookup_smb_req_resp(c: connection, is_orig: bool, cmd: string): smb_req_resp
{
local id = c$id;
local g = lookup_smb_req_reply_group(id, T);
if( is_udp_port(id$orig_p) || is_udp_port(id$resp_p) )
print fmt("%.6f %s a lookup was triggered on a UDP connection!: %s",
network_time(), conn_id_string(id), cmd);
if ( g$first_req > g$last_req )
{
print fmt("%.6f %s request missing: %s",
network_time(), conn_id_string(id), cmd);
return new_smb_req_resp(c, cmd);
}
if ( is_orig )
{
return g$trans[g$last_req];
}
else if ( cmd == "(current)" )
{
return g$trans[g$first_req];
}
else
{
local t = g$trans[g$first_req];
if ( g$first_req < g$last_req )
{
end_smb_req_resp(t);
++g$first_req;
t = g$trans[g$first_req];
}
if ( t$cmd != cmd )
{
if ( g$first_req < g$last_req )
return lookup_smb_req_resp(c, is_orig, cmd);
print fmt("%.6f %s SMB command-reply mismatch",
network_time(), conn_id_string(id));
}
return t;
}
}
event smb_message(c: connection, hdr: smb_hdr, is_orig: bool, cmd:
string, body_length: count, body : string)
{
print chris_log, fmt("%.6f %s %s", network_time(), conn_id_string(c$id), cmd);
local t: smb_req_resp;
if ( is_udp_port( c$id$orig_p ) || is_udp_port ( c$id$resp_p ) )
{
# dont need to keep track of UDP smb commands
print_app_summary(smb_log, c$id, network_time(),
cmd, network_time(),
0, 0, 0, 0,
fmt("cmd %s", cmd));
}
else if ( is_orig )
{
t = new_smb_req_resp(c, cmd);
++t$num_req;
t$req_size = t$req_size + body_length;
}
else
{
t = lookup_smb_req_resp(c, is_orig, cmd);
++t$num_resp;
t$resp_size = t$resp_size + body_length;
}
}
event smb_error(c: connection, hdr: smb_hdr, cmd: count, cmd_str: string, data: string)
{
print chris_log, fmt("%.6f %s SMB_ERROR:%s", network_time(), conn_id_string(c$id), cmd_str);
}
event dce_rpc_bind(c: connection, uuid: string)
{
local id = c$id;
if ( id !in smb_trans_table )
return;
local t = lookup_smb_req_resp(c, T, "(current)");
t$func = "DCE_RPC_BIND";
}
event dce_rpc_request(c: connection, opnum: count, stub: string)
{
local id = c$id;
if ( id !in smb_trans_table )
return;
local t = lookup_smb_req_resp(c, T, "(current)");
t$func = "DCE_RPC_CALL";
}
event dce_rpc_response(c: connection, opnum: count, stub: string)
{
local id = c$id;
if ( id !in smb_trans_table )
return;
local t = lookup_smb_req_resp(c, F, "(current)");
t$func = "DCE_RPC_CALL";
}
event smb_com_transaction(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool)
{
if ( is_orig && !is_udp_port( c$id$orig_p ) )
{
local t = lookup_smb_req_resp(c, T, "(current)");
}
}
event smb_com_transaction2(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool)
{
if ( is_orig && !is_udp_port( c$id$orig_p ) )
{
local t = lookup_smb_req_resp(c, T, "(current)");
}
}
function end_smb_req_reply_group(g: smb_req_reply_group, index: count)
{
if ( index > g$last_req )
return;
if ( index >= g$first_req && index in g$trans )
end_smb_req_resp(g$trans[index]);
if( index in g$trans )
{
delete g$trans[index];
end_smb_req_reply_group(g, index + 1);
}
}
event connection_state_remove(c: connection)
{
local id = c$id;
if ( !is_udp_port( id$orig_p ) && id in smb_trans_table )
{
local g = smb_trans_table[id];
end_smb_req_reply_group(g, 1);
}
}