mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 22:58:20 +00:00
Analyzer and bro script for RFB protocol (VNC)
This analyzer parses the Remote Frame Buffer protocol, usually referred to as the 'VNC protocol'. It supports several dialects (3.3, 3.7, 3.8) and also handles the Apple Remote Desktop variant. It will log such facts as client/server versions, authentication method used, authentication result, height, width and name of the shared screen. It also includes two testcases. Todo: Apple Remote Desktop seems to have some bytes prepended to the screen name. This is not interepreted correctly.
This commit is contained in:
parent
8650841bf5
commit
849875e8be
19 changed files with 766 additions and 0 deletions
|
@ -55,6 +55,7 @@
|
|||
@load base/protocols/pop3
|
||||
@load base/protocols/radius
|
||||
@load base/protocols/rdp
|
||||
@load base/protocols/rfb
|
||||
@load base/protocols/sip
|
||||
@load base/protocols/snmp
|
||||
@load base/protocols/smtp
|
||||
|
|
3
scripts/base/protocols/rfb/__load__.bro
Normal file
3
scripts/base/protocols/rfb/__load__.bro
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Generated by binpac_quickstart
|
||||
@load ./main
|
||||
@load-sigs ./dpd.sig
|
12
scripts/base/protocols/rfb/dpd.sig
Normal file
12
scripts/base/protocols/rfb/dpd.sig
Normal file
|
@ -0,0 +1,12 @@
|
|||
signature dpd_rfb_server {
|
||||
ip-proto == tcp
|
||||
payload /^RFB/
|
||||
requires-reverse-signature dpd_rfb_client
|
||||
enable "rfb"
|
||||
}
|
||||
|
||||
signature dpd_rfb_client {
|
||||
ip-proto == tcp
|
||||
payload /^RFB/
|
||||
tcp-state originator
|
||||
}
|
143
scripts/base/protocols/rfb/main.bro
Normal file
143
scripts/base/protocols/rfb/main.bro
Normal file
|
@ -0,0 +1,143 @@
|
|||
module Rfb;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the event happened.
|
||||
ts: time &log;
|
||||
## Unique ID for the connection.
|
||||
uid: string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id: conn_id &log;
|
||||
|
||||
client_major_version: string &log &optional;
|
||||
client_minor_version: string &log &optional;
|
||||
server_major_version: string &log &optional;
|
||||
server_minor_version: string &log &optional;
|
||||
|
||||
authentication_method: string &log &optional;
|
||||
auth: bool &log &optional;
|
||||
|
||||
share_flag: bool &log &optional;
|
||||
desktop_name: string &log &optional;
|
||||
width: count &log &optional;
|
||||
height: count &log &optional;
|
||||
|
||||
done: bool &default=F;
|
||||
};
|
||||
|
||||
global log_rfb: event(rec: Info);
|
||||
}
|
||||
|
||||
function friendly_auth_name(auth: count): string {
|
||||
switch (auth) {
|
||||
case 0:
|
||||
return "Invalid";
|
||||
case 1:
|
||||
return "None";
|
||||
case 2:
|
||||
return "VNC";
|
||||
case 16:
|
||||
return "Tight";
|
||||
case 17:
|
||||
return "Ultra";
|
||||
case 18:
|
||||
return "TLS";
|
||||
case 19:
|
||||
return "VeNCrypt";
|
||||
case 20:
|
||||
return "GTK-VNC SASL";
|
||||
case 21:
|
||||
return "MD5 hash authentication";
|
||||
case 22:
|
||||
return "Colin Dean xvp";
|
||||
case 30:
|
||||
return "Apple Remote Desktop";
|
||||
}
|
||||
return "RealVNC";
|
||||
|
||||
}
|
||||
|
||||
|
||||
redef record connection += {
|
||||
rfb_state: Info &optional;
|
||||
};
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(Rfb::LOG, [$columns=Info, $ev=log_rfb, $path="rfb"]);
|
||||
}
|
||||
|
||||
function write_log(c:connection) {
|
||||
local state = c$rfb_state;
|
||||
if ( state?$done && state$done == T) {
|
||||
return;
|
||||
}
|
||||
Log::write(Rfb::LOG, c$rfb_state);
|
||||
c$rfb_state$done = T;
|
||||
}
|
||||
|
||||
function set_session(c: connection) {
|
||||
if ( ! c?$rfb_state ) {
|
||||
local info: Info;
|
||||
info$ts = network_time();
|
||||
info$uid = c$uid;
|
||||
info$id = c$id;
|
||||
|
||||
c$rfb_state = info;
|
||||
}
|
||||
}
|
||||
|
||||
event rfb_event(c: connection)
|
||||
{
|
||||
set_session(c);
|
||||
}
|
||||
|
||||
event rfb_client_version(c: connection, major_version: string, minor_version: string)
|
||||
{
|
||||
set_session(c);
|
||||
c$rfb_state$client_major_version = major_version;
|
||||
c$rfb_state$client_minor_version = minor_version;
|
||||
}
|
||||
|
||||
event rfb_server_version(c: connection, major_version: string, minor_version: string)
|
||||
{
|
||||
set_session(c);
|
||||
c$rfb_state$server_major_version = major_version;
|
||||
c$rfb_state$server_minor_version = minor_version;
|
||||
add c$service["rfb"];
|
||||
}
|
||||
|
||||
event rfb_authentication_type(c: connection, authtype: count)
|
||||
{
|
||||
c$rfb_state$authentication_method = friendly_auth_name(authtype);
|
||||
}
|
||||
|
||||
event rfb_server_parameters(c: connection, name: string, width: count, height: count)
|
||||
{
|
||||
c$rfb_state$desktop_name = name;
|
||||
c$rfb_state$width = width;
|
||||
c$rfb_state$height = height;
|
||||
write_log(c);
|
||||
}
|
||||
|
||||
event rfb_auth_result(c: connection, result: count)
|
||||
{
|
||||
if ( result ==0 ) {
|
||||
c$rfb_state$auth = T;
|
||||
} else {
|
||||
c$rfb_state$auth = F;
|
||||
}
|
||||
}
|
||||
|
||||
event rfb_share_flag(c: connection, flag: bool)
|
||||
{
|
||||
c$rfb_state$share_flag = flag;
|
||||
}
|
||||
|
||||
event connection_state_remove(c: connection) {
|
||||
if ( c?$rfb_state ) {
|
||||
write_log(c);
|
||||
}
|
||||
}
|
|
@ -30,6 +30,7 @@ add_subdirectory(pia)
|
|||
add_subdirectory(pop3)
|
||||
add_subdirectory(radius)
|
||||
add_subdirectory(rdp)
|
||||
add_subdirectory(rfb)
|
||||
add_subdirectory(rpc)
|
||||
add_subdirectory(sip)
|
||||
add_subdirectory(snmp)
|
||||
|
|
11
src/analyzer/protocol/rfb/CMakeLists.txt
Normal file
11
src/analyzer/protocol/rfb/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Generated by binpac_quickstart
|
||||
|
||||
include(BroPlugin)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
bro_plugin_begin(Bro RFB)
|
||||
bro_plugin_cc(RFB.cc Plugin.cc)
|
||||
bro_plugin_bif(events.bif)
|
||||
bro_plugin_pac(rfb.pac rfb-analyzer.pac rfb-protocol.pac)
|
||||
bro_plugin_end()
|
25
src/analyzer/protocol/rfb/Plugin.cc
Normal file
25
src/analyzer/protocol/rfb/Plugin.cc
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Generated by binpac_quickstart
|
||||
|
||||
#include "plugin/Plugin.h"
|
||||
|
||||
#include "RFB.h"
|
||||
|
||||
namespace plugin {
|
||||
namespace Bro_RFB {
|
||||
|
||||
class Plugin : public plugin::Plugin {
|
||||
public:
|
||||
plugin::Configuration Configure()
|
||||
{
|
||||
AddComponent(new ::analyzer::Component("RFB",
|
||||
::analyzer::rfb::RFB_Analyzer::InstantiateAnalyzer));
|
||||
|
||||
plugin::Configuration config;
|
||||
config.name = "Bro::RFB";
|
||||
config.description = "Parser for rfb (VNC) analyzer";
|
||||
return config;
|
||||
}
|
||||
} plugin;
|
||||
|
||||
}
|
||||
}
|
69
src/analyzer/protocol/rfb/RFB.cc
Normal file
69
src/analyzer/protocol/rfb/RFB.cc
Normal file
|
@ -0,0 +1,69 @@
|
|||
// Generated by binpac_quickstart
|
||||
|
||||
#include "RFB.h"
|
||||
|
||||
#include "analyzer/protocol/tcp/TCP_Reassembler.h"
|
||||
|
||||
#include "Reporter.h"
|
||||
|
||||
#include "events.bif.h"
|
||||
|
||||
using namespace analyzer::rfb;
|
||||
|
||||
RFB_Analyzer::RFB_Analyzer(Connection* c)
|
||||
|
||||
: tcp::TCP_ApplicationAnalyzer("RFB", c)
|
||||
|
||||
{
|
||||
interp = new binpac::RFB::RFB_Conn(this);
|
||||
had_gap = false;
|
||||
}
|
||||
|
||||
RFB_Analyzer::~RFB_Analyzer()
|
||||
{
|
||||
delete interp;
|
||||
}
|
||||
|
||||
void RFB_Analyzer::Done()
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::Done();
|
||||
|
||||
interp->FlowEOF(true);
|
||||
interp->FlowEOF(false);
|
||||
|
||||
}
|
||||
|
||||
void RFB_Analyzer::EndpointEOF(bool is_orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
|
||||
interp->FlowEOF(is_orig);
|
||||
}
|
||||
|
||||
void RFB_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
|
||||
assert(TCP());
|
||||
if ( TCP()->IsPartial() )
|
||||
return;
|
||||
|
||||
if ( had_gap )
|
||||
// If only one side had a content gap, we could still try to
|
||||
// deliver data to the other side if the script layer can handle this.
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
interp->NewData(orig, data, data + len);
|
||||
}
|
||||
catch ( const binpac::Exception& e )
|
||||
{
|
||||
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg()));
|
||||
}
|
||||
}
|
||||
|
||||
void RFB_Analyzer::Undelivered(uint64 seq, int len, bool orig)
|
||||
{
|
||||
tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
|
||||
had_gap = true;
|
||||
interp->NewGap(orig, len);
|
||||
}
|
45
src/analyzer/protocol/rfb/RFB.h
Normal file
45
src/analyzer/protocol/rfb/RFB.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Generated by binpac_quickstart
|
||||
|
||||
#ifndef ANALYZER_PROTOCOL_RFB_RFB_H
|
||||
#define ANALYZER_PROTOCOL_RFB_RFB_H
|
||||
|
||||
#include "events.bif.h"
|
||||
|
||||
|
||||
#include "analyzer/protocol/tcp/TCP.h"
|
||||
|
||||
#include "rfb_pac.h"
|
||||
|
||||
namespace analyzer { namespace rfb {
|
||||
|
||||
class RFB_Analyzer
|
||||
|
||||
: public tcp::TCP_ApplicationAnalyzer {
|
||||
|
||||
public:
|
||||
RFB_Analyzer(Connection* conn);
|
||||
virtual ~RFB_Analyzer();
|
||||
|
||||
// Overriden from Analyzer.
|
||||
virtual void Done();
|
||||
|
||||
virtual void DeliverStream(int len, const u_char* data, bool orig);
|
||||
virtual void Undelivered(uint64 seq, int len, bool orig);
|
||||
|
||||
// Overriden from tcp::TCP_ApplicationAnalyzer.
|
||||
virtual void EndpointEOF(bool is_orig);
|
||||
|
||||
|
||||
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||
{ return new RFB_Analyzer(conn); }
|
||||
|
||||
protected:
|
||||
binpac::RFB::RFB_Conn* interp;
|
||||
|
||||
bool had_gap;
|
||||
|
||||
};
|
||||
|
||||
} } // namespace analyzer::*
|
||||
|
||||
#endif
|
50
src/analyzer/protocol/rfb/events.bif
Normal file
50
src/analyzer/protocol/rfb/events.bif
Normal file
|
@ -0,0 +1,50 @@
|
|||
## Generated for RFB event
|
||||
##
|
||||
## c: The connection record for the underlying transport-layer session/flow.
|
||||
event rfb_event%(c: connection%);
|
||||
|
||||
## Generated for RFB event authentication mechanism selection
|
||||
##
|
||||
## c: The connection record for the underlying transport-layer session/flow.
|
||||
##
|
||||
## authtype: the value of the chosen authentication mechanism
|
||||
event rfb_authentication_type%(c: connection, authtype: count%);
|
||||
|
||||
## Generated for RFB event authentication result message
|
||||
##
|
||||
## c: The connection record for the underlying transport-layer session/flow.
|
||||
##
|
||||
## result: whether or not authentication was succesful
|
||||
event rfb_auth_result%(c: connection, result: count%);
|
||||
|
||||
## Generated for RFB event share flag messages
|
||||
##
|
||||
## c: The connection record for the underlying transport-layer session/flow.
|
||||
##
|
||||
## flag: whether or not the share flag was set
|
||||
event rfb_share_flag%(c: connection, flag: bool%);
|
||||
|
||||
## Generated for RFB event client banner message
|
||||
##
|
||||
## c: The connection record for the underlying transport-layer session/flow.
|
||||
##
|
||||
## version: of the client's rfb library
|
||||
event rfb_client_version%(c: connection, major_version: string, minor_version: string%);
|
||||
|
||||
## Generated for RFB event server banner message
|
||||
##
|
||||
## c: The connection record for the underlying transport-layer session/flow.
|
||||
##
|
||||
## version: of the server's rfb library
|
||||
event rfb_server_version%(c: connection, major_version: string, minor_version: string%);
|
||||
|
||||
## Generated for RFB event server parameter message
|
||||
##
|
||||
## c: The connection record for the underlying transport-layer session/flow.
|
||||
##
|
||||
## name: name of the shared screen
|
||||
##
|
||||
## width: width of the shared screen
|
||||
##
|
||||
## height: height of the shared screen
|
||||
event rfb_server_parameters%(c: connection, name: string, width: count, height: count%);
|
193
src/analyzer/protocol/rfb/rfb-analyzer.pac
Normal file
193
src/analyzer/protocol/rfb/rfb-analyzer.pac
Normal file
|
@ -0,0 +1,193 @@
|
|||
# Generated by binpac_quickstart
|
||||
|
||||
refine flow RFB_Flow += {
|
||||
function proc_rfb_message(msg: RFB_PDU): bool
|
||||
%{
|
||||
BifEvent::generate_rfb_event(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn());
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_rfb_client_version(major: bytestring, minor: bytestring) : bool
|
||||
%{
|
||||
BifEvent::generate_rfb_client_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor));
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_rfb_version(client: bool, major: bytestring, minor: bytestring) : bool
|
||||
%{
|
||||
if (client) {
|
||||
BifEvent::generate_rfb_client_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor));
|
||||
} else {
|
||||
BifEvent::generate_rfb_server_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor));
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_rfb_share_flag(shared: bool) : bool
|
||||
%{
|
||||
BifEvent::generate_rfb_share_flag(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), shared);
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_security_types(msg: RFBSecurityTypes) : bool
|
||||
%{
|
||||
BifEvent::generate_rfb_authentication_type(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), ${msg.sectype});
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_security_types37(msg: RFBAuthTypeSelected) : bool
|
||||
%{
|
||||
BifEvent::generate_rfb_authentication_type(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), ${msg.type});
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_handle_server_params(msg:RFBServerInit) : bool
|
||||
%{
|
||||
BifEvent::generate_rfb_server_parameters(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(${msg.name}), ${msg.width}, ${msg.height});
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_handle_security_result(result : uint32) : bool
|
||||
%{
|
||||
BifEvent::generate_rfb_auth_result(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), result);
|
||||
return true;
|
||||
%}
|
||||
};
|
||||
|
||||
refine connection RFB_Conn += {
|
||||
%member{
|
||||
enum states {
|
||||
AWAITING_SERVER_BANNER = 0,
|
||||
AWAITING_CLIENT_BANNER = 1,
|
||||
AWAITING_SERVER_AUTH_TYPES = 2,
|
||||
AWAITING_SERVER_CHALLENGE = 3,
|
||||
AWAITING_CLIENT_RESPONSE = 4,
|
||||
AWAITING_SERVER_AUTH_RESULT = 5,
|
||||
AWAITING_CLIENT_SHARE_FLAG = 6,
|
||||
AWAITING_SERVER_PARAMS = 7,
|
||||
AWAITING_CLIENT_AUTH_METHOD = 8,
|
||||
AWAITING_SERVER_ARD_CHALLENGE = 9,
|
||||
AWAITING_CLIENT_ARD_RESPONSE = 10,
|
||||
AWAITING_SERVER_AUTH_TYPES37 = 11,
|
||||
AWAITING_CLIENT_AUTH_TYPE_SELECTED37 = 12,
|
||||
RFB_MESSAGE = 13
|
||||
};
|
||||
%}
|
||||
|
||||
function get_state(client: bool) : int
|
||||
%{
|
||||
return state;
|
||||
%}
|
||||
|
||||
function handle_banners(client: bool, msg: RFBProtocolVersion) : bool
|
||||
%{
|
||||
if ( client ) {
|
||||
// Set protocol version on client's version
|
||||
int minor_version = bytestring_to_int(${msg.minor},10);
|
||||
|
||||
// Apple specifies minor version "889" but talks v37
|
||||
if ( minor_version >= 7 ) {
|
||||
state = AWAITING_SERVER_AUTH_TYPES37;
|
||||
} else {
|
||||
state = AWAITING_SERVER_AUTH_TYPES;
|
||||
}
|
||||
} else {
|
||||
if ( !client ) {
|
||||
state = AWAITING_CLIENT_BANNER;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_ard_challenge() : bool
|
||||
%{
|
||||
state = AWAITING_CLIENT_ARD_RESPONSE;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_ard_response() : bool
|
||||
%{
|
||||
state = AWAITING_SERVER_AUTH_RESULT;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_auth_request() : bool
|
||||
%{
|
||||
state = AWAITING_CLIENT_RESPONSE;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_auth_response() : bool
|
||||
%{
|
||||
state = AWAITING_SERVER_AUTH_RESULT;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_security_result(msg: RFBSecurityResult) : bool
|
||||
%{
|
||||
if ( ${msg.result} == 0 ) //FIXME
|
||||
{
|
||||
state = AWAITING_CLIENT_SHARE_FLAG;
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_client_init(msg: RFBClientInit) : bool
|
||||
%{
|
||||
state = AWAITING_SERVER_PARAMS;
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_server_init(msg: RFBServerInit) : bool
|
||||
%{
|
||||
state = RFB_MESSAGE;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_security_types(msg: RFBSecurityTypes): bool
|
||||
%{
|
||||
if ( msg->sectype() == 0 ) { // No auth
|
||||
state = AWAITING_CLIENT_SHARE_FLAG;
|
||||
return true;
|
||||
}
|
||||
if ( msg->sectype() == 2 ) { //VNC
|
||||
state = AWAITING_SERVER_CHALLENGE;
|
||||
}
|
||||
return false;
|
||||
%}
|
||||
|
||||
function handle_security_types37(msg: RFBSecurityTypes37): bool
|
||||
%{
|
||||
if ( ${msg.count} == 0 ) { // No auth
|
||||
state = AWAITING_CLIENT_SHARE_FLAG;
|
||||
return true;
|
||||
}
|
||||
state = AWAITING_CLIENT_AUTH_TYPE_SELECTED37;
|
||||
return true;
|
||||
%}
|
||||
|
||||
function handle_auth_type_selected(msg: RFBAuthTypeSelected): bool
|
||||
%{
|
||||
if ( ${msg.type} == 30 ) { // Apple Remote Desktop
|
||||
state = AWAITING_SERVER_ARD_CHALLENGE;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ${msg.type} == 1 ) { // No Auth
|
||||
state = AWAITING_SERVER_AUTH_RESULT;
|
||||
} else {
|
||||
// Assume VNC
|
||||
state = AWAITING_SERVER_CHALLENGE;
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
%member{
|
||||
uint8 state = AWAITING_SERVER_BANNER;
|
||||
%}
|
||||
};
|
||||
|
||||
refine typeattr RFB_PDU += &let {
|
||||
proc: bool = $context.flow.proc_rfb_message(this);
|
||||
};
|
139
src/analyzer/protocol/rfb/rfb-protocol.pac
Normal file
139
src/analyzer/protocol/rfb/rfb-protocol.pac
Normal file
|
@ -0,0 +1,139 @@
|
|||
enum states {
|
||||
AWAITING_SERVER_BANNER = 0,
|
||||
AWAITING_CLIENT_BANNER = 1,
|
||||
AWAITING_SERVER_AUTH_TYPES = 2,
|
||||
AWAITING_SERVER_CHALLENGE = 3,
|
||||
AWAITING_CLIENT_RESPONSE = 4,
|
||||
AWAITING_SERVER_AUTH_RESULT = 5,
|
||||
AWAITING_CLIENT_SHARE_FLAG = 6,
|
||||
AWAITING_SERVER_PARAMS = 7,
|
||||
AWAITING_CLIENT_AUTH_METHOD = 8,
|
||||
AWAITING_SERVER_ARD_CHALLENGE = 9,
|
||||
AWAITING_CLIENT_ARD_RESPONSE = 10,
|
||||
AWAITING_SERVER_AUTH_TYPES37 = 11,
|
||||
AWAITING_CLIENT_AUTH_TYPE_SELECTED37 = 12,
|
||||
RFB_MESSAGE = 13
|
||||
};
|
||||
|
||||
type RFBProtocolVersion (client: bool) = record {
|
||||
header : "RFB ";
|
||||
major :bytestring &length=3;
|
||||
dot: ".";
|
||||
minor: bytestring &length=3;
|
||||
pad: uint8;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_banners(client, this);
|
||||
proc2: bool = $context.flow.proc_rfb_version(client, major, minor);
|
||||
}
|
||||
|
||||
type RFBSecurityTypes = record {
|
||||
sectype: uint32;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_security_types(this);
|
||||
proc2: bool = $context.flow.proc_security_types(this);
|
||||
};
|
||||
|
||||
type RFBSecurityTypes37 = record {
|
||||
count: uint8;
|
||||
types: uint8[count];
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_security_types37(this);
|
||||
};
|
||||
|
||||
type RFBAuthTypeSelected = record {
|
||||
type: uint8;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_auth_type_selected(this);
|
||||
proc2: bool = $context.flow.proc_security_types37(this);
|
||||
};
|
||||
|
||||
type RFBSecurityResult = record {
|
||||
result: uint32;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_security_result(this);
|
||||
proc2: bool = $context.flow.proc_handle_security_result(result);
|
||||
};
|
||||
|
||||
type RFBSecurityResultReason = record {
|
||||
len: uint32;
|
||||
reason: bytestring &length=len;
|
||||
};
|
||||
|
||||
type RFBVNCAuthenticationRequest = record {
|
||||
challenge: bytestring &length=16;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_auth_request();
|
||||
};
|
||||
|
||||
type RFBVNCAuthenticationResponse = record {
|
||||
response: bytestring &length= 16;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_auth_response();
|
||||
};
|
||||
|
||||
type RFBSecurityARDChallenge = record {
|
||||
challenge: bytestring &restofdata;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_ard_challenge();
|
||||
}
|
||||
|
||||
type RFBSecurityARDResponse = record {
|
||||
response: bytestring &restofdata;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_ard_response();
|
||||
}
|
||||
|
||||
type RFBClientInit = record {
|
||||
shared_flag: uint8;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_client_init(this);
|
||||
proc2: bool = $context.flow.proc_rfb_share_flag(shared_flag);
|
||||
}
|
||||
|
||||
type RFBServerInit = record {
|
||||
width: uint16;
|
||||
height: uint16;
|
||||
pixel_format: bytestring &length= 16;
|
||||
len : uint32;
|
||||
name: bytestring &length = len;
|
||||
} &let {
|
||||
proc: bool = $context.connection.handle_server_init(this);
|
||||
proc2: bool = $context.flow.proc_handle_server_params(this);
|
||||
};
|
||||
|
||||
type RFB_PDU_request = record {
|
||||
request: case state of {
|
||||
AWAITING_CLIENT_BANNER -> version: RFBProtocolVersion(true);
|
||||
AWAITING_CLIENT_RESPONSE -> response: RFBVNCAuthenticationResponse;
|
||||
AWAITING_CLIENT_SHARE_FLAG -> shareflag: RFBClientInit;
|
||||
AWAITING_CLIENT_AUTH_TYPE_SELECTED37 -> authtype: RFBAuthTypeSelected;
|
||||
AWAITING_CLIENT_ARD_RESPONSE -> ard_response: RFBSecurityARDResponse;
|
||||
RFB_MESSAGE -> ignore: bytestring &restofdata;
|
||||
default -> data: bytestring &restofdata;
|
||||
} &requires(state);
|
||||
} &let {
|
||||
state: uint8 = $context.connection.get_state(true);
|
||||
};
|
||||
|
||||
type RFB_PDU_response = record {
|
||||
request: case rstate of {
|
||||
AWAITING_SERVER_BANNER -> version: RFBProtocolVersion(false);
|
||||
AWAITING_SERVER_AUTH_TYPES -> auth_types: RFBSecurityTypes;
|
||||
AWAITING_SERVER_AUTH_TYPES37 -> auth_types37: RFBSecurityTypes37;
|
||||
AWAITING_SERVER_CHALLENGE -> challenge: RFBVNCAuthenticationRequest;
|
||||
AWAITING_SERVER_AUTH_RESULT -> authresult : RFBSecurityResult;
|
||||
AWAITING_SERVER_ARD_CHALLENGE -> ard_challenge: RFBSecurityARDChallenge;
|
||||
AWAITING_SERVER_PARAMS -> serverinit: RFBServerInit;
|
||||
RFB_MESSAGE -> ignore: bytestring &restofdata;
|
||||
default -> data: bytestring &restofdata;
|
||||
} &requires(rstate);
|
||||
} &let {
|
||||
rstate: uint8 = $context.connection.get_state(false);
|
||||
};
|
||||
|
||||
type RFB_PDU(is_orig: bool) = record {
|
||||
payload: case is_orig of {
|
||||
true -> request: RFB_PDU_request;
|
||||
false -> response: RFB_PDU_response;
|
||||
};
|
||||
} &byteorder = bigendian;
|
42
src/analyzer/protocol/rfb/rfb.pac
Normal file
42
src/analyzer/protocol/rfb/rfb.pac
Normal file
|
@ -0,0 +1,42 @@
|
|||
# Generated by binpac_quickstart
|
||||
|
||||
# Analyzer for Parser for rfb (VNC)
|
||||
# - rfb-protocol.pac: describes the rfb protocol messages
|
||||
# - rfb-analyzer.pac: describes the rfb analyzer code
|
||||
|
||||
%include binpac.pac
|
||||
%include bro.pac
|
||||
|
||||
%extern{
|
||||
#include "events.bif.h"
|
||||
%}
|
||||
|
||||
analyzer RFB withcontext {
|
||||
connection: RFB_Conn;
|
||||
flow: RFB_Flow;
|
||||
};
|
||||
|
||||
# Our connection consists of two flows, one in each direction.
|
||||
connection RFB_Conn(bro_analyzer: BroAnalyzer) {
|
||||
upflow = RFB_Flow(true);
|
||||
downflow = RFB_Flow(false);
|
||||
};
|
||||
|
||||
%include rfb-protocol.pac
|
||||
|
||||
# Now we define the flow:
|
||||
flow RFB_Flow(is_orig: bool) {
|
||||
|
||||
# ## TODO: Determine if you want flowunit or datagram parsing:
|
||||
|
||||
# Using flowunit will cause the anlayzer to buffer incremental input.
|
||||
# This is needed for &oneline and &length. If you don't need this, you'll
|
||||
# get better performance with datagram.
|
||||
|
||||
# flowunit = RFB_PDU(is_orig) withcontext(connection, this);
|
||||
|
||||
datagram = RFB_PDU(is_orig) withcontext(connection, this);
|
||||
|
||||
};
|
||||
|
||||
%include rfb-analyzer.pac
|
|
@ -0,0 +1,12 @@
|
|||
#separator \x09
|
||||
#set_separator ,
|
||||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#path rfb
|
||||
#open 2016-04-11-08-25-48
|
||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p client_major_version client_minor_version server_major_version server_minor_version authentication_method auth share_flag desktop_name width height
|
||||
#types time string addr port addr port string string string string string bool bool string count count
|
||||
1459148054.031382 CCvvfg3TEfuqmmG4bh 192.168.2.115 52353 192.168.2.16 5900 003 889 003 889 Apple Remote Desktop T T \x00\x00\x00\x00\x00\x02\xbf\xfe\xe7\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00MacMini SSD 1920 1080
|
||||
1459148050.685932 CjhGID4nQcgTWjvg4c 192.168.2.115 52352 192.168.2.16 5900 003 889 003 889 Apple Remote Desktop F - - - -
|
||||
1459148047.738043 CXWv6p3arKYeMETxOg 192.168.2.115 52351 192.168.2.16 5900 003 889 003 889 - - - - - -
|
||||
#close 2016-04-11-08-25-48
|
|
@ -0,0 +1,12 @@
|
|||
#separator \x09
|
||||
#set_separator ,
|
||||
#empty_field (empty)
|
||||
#unset_field -
|
||||
#path rfb
|
||||
#open 2016-04-06-13-48-56
|
||||
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p client_major_version client_minor_version server_major_version server_minor_version authentication_method auth share_flag desktop_name width height
|
||||
#types time string addr port addr port string string string string string bool bool string count count
|
||||
1459093553.334734 CsRx2w45OKnoww6xl4 192.168.2.115 49259 192.168.2.125 5901 003 003 003 008 VNC T T root's X desktop (martin-VirtualBox:1) 1024 768
|
||||
1459093548.745805 CjhGID4nQcgTWjvg4c 192.168.2.115 49256 192.168.2.125 5901 003 003 003 008 VNC - - - - -
|
||||
1459093551.559391 CCvvfg3TEfuqmmG4bh 192.168.2.115 49257 192.168.2.125 5901 003 003 003 008 VNC F - - - -
|
||||
#close 2016-04-06-13-48-56
|
BIN
testing/btest/Traces/rfb/vnc-mac-to-linux.pcap
Normal file
BIN
testing/btest/Traces/rfb/vnc-mac-to-linux.pcap
Normal file
Binary file not shown.
BIN
testing/btest/Traces/rfb/vncmac.pcap
Normal file
BIN
testing/btest/Traces/rfb/vncmac.pcap
Normal file
Binary file not shown.
|
@ -0,0 +1,4 @@
|
|||
# @TEST-EXEC: bro -C -r $TRACES/rfb/vncmac.pcap
|
||||
# @TEST-EXEC: btest-diff rfb.log
|
||||
|
||||
@load base/protocols/rfb
|
|
@ -0,0 +1,4 @@
|
|||
# @TEST-EXEC: bro -C -r $TRACES/rfb/vnc-mac-to-linux.pcap
|
||||
# @TEST-EXEC: btest-diff rfb.log
|
||||
|
||||
@load base/protocols/rfb
|
Loading…
Add table
Add a link
Reference in a new issue