Changeset 751

Show
Ignore:
Timestamp:
07/23/07 18:01:54 (1 year ago)
Author:
kindlund
Message:

sva: merging branch using tags svn+ssh://kindlund@www.honeyclient.org/home/svn/honeyclient/honeyclient/tags/exp/PRE-kindlund-firefox and svn+ssh://kindlund@www.honeyclient.org/home/svn/honeyclient/honeyclient/branches/exp/kindlund-firefox

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • honeyclient/trunk/bin/StartManager.pl

    r696 r751  
    2424# They can however supply multiple urls which will be processed in order 
    2525 
    26 my $driver = "IE"; 
    27 my $config = "/vm/master-vms/Agent.Master-22/winXPPro.cfg"; 
    28 my $maxrel = 10; 
     26# Change to 'HoneyClient::Agent::Driver::Browser::IE' or 
     27#           'HoneyClient::Agent::Driver::Browser::FF' 
     28my $driver = "HoneyClient::Agent::Driver::Browser::FF"; 
     29my $config = "/vm/master-vms/Agent.Master-23/winXPPro.cfg"; 
     30my $maxrel = 5; 
    2931my $nexturl = ""; 
    3032my $urllist= ""; 
     
    6062 
    6163my $agentState = HoneyClient::Manager->run( 
    62                     driver           => $driver, # Change to 'IE' or 'FF' 
     64                    driver           => $driver, 
    6365                    master_vm_config => $config, 
    6466                    agent_state      => encode_base64(nfreeze({ 
    65                         $driver => { # Change to 'IE' or 'FF' 
     67                        $driver => { 
    6668                            next_link_to_visit => $firsturl, 
    6769                            # Enable this line, if you want to only go to the 
  • honeyclient/trunk/etc/honeyclient.xml

    r698 r751  
    6868            9000 
    6969        </port> 
     70        <allowed_drivers description="List of implemented Drivers that the Agent is allowed to run directly."> 
     71            <name>HoneyClient::Agent::Driver::Browser::IE</name> 
     72            <name>HoneyClient::Agent::Driver::Browser::FF</name> 
     73        </allowed_drivers> 
    7074        <!-- HoneyClient::Agent::Driver Options --> 
    7175        <Driver> 
     
    122126                <IE> 
    123127                    <!-- HoneyClient::Agent::Driver::Browser::IE Options --> 
    124                     <!-- TODO: Update this. --> 
    125128                    <process_exec description="The absolute path to the Internet Explorer application process, as it sits in the VM filesystem." default="C:\Program Files\Internet Explorer\iexplore.exe"> 
    126129                        C:\Program Files\Internet Explorer\iexplore.exe 
    127130                    </process_exec> 
     131                    <process_name description="The name of the Internet Explorer executable, as it appears on the VM filesystem." default="iexplore.exe"> 
     132                        iexplore.exe 
     133                    </process_name> 
    128134                </IE> 
    129135                <FF> 
     
    132138                        C:\Program Files\Mozilla Firefox\firefox.exe 
    133139                    </process_exec> 
     140                    <process_name description="The name of the Mozilla Firefox executable, as it appears on the VM filesystem." default="firefox.exe"> 
     141                        firefox.exe 
     142                    </process_name> 
    134143                </FF> 
    135144            </Browser> 
  • honeyclient/trunk/lib/HoneyClient/Agent.pm

    r605 r751  
    7676    # Defines which functions can be called externally. 
    7777    require Exporter; 
    78     our (@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION, @DRIVERS); 
     78    our (@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION); 
    7979 
    8080    # Set our package version. 
     
    110110    $Config{useithreads} or Carp::croak "Error: Recompile Perl with ithread support, in order to use this module.\n"; 
    111111 
    112     # Registered driver list. 
    113     # TODO: Eventually, make this more dynamic, based upon the presence of HoneyClient::Agent::Driver::* elements 
    114     # within the global configuration file.  Or, feed the initialization logic through init() as part of the arguments. 
    115     @DRIVERS = ( 'IE' ); 
    116     foreach (@DRIVERS) { 
    117         eval "use HoneyClient::Agent::Driver::Browser::$_"; 
    118         if ($@) { 
    119             Carp::croak "$@"; 
    120         } 
    121     } 
    122  
    123112    $SIG{PIPE} = 'IGNORE'; # Do not exit on broken pipes. 
    124113} 
    125 our (@EXPORT_OK, $VERSION, @DRIVERS); 
     114our (@EXPORT_OK, $VERSION); 
    126115 
    127116=pod 
     
    150139use HoneyClient::Util::Config qw(getVar); 
    151140 
    152 # TODO: Change Driver::IE to Driver::Browser::IE 
    153 # Make sure HoneyClient::Agent::Driver::IE loads. 
    154 BEGIN { use_ok('HoneyClient::Agent::Driver::IE') or diag("Can't load HoneyClient::Agent::Driver::IE package.  Check to make sure the package library is correctly listed within the path."); } 
    155 require_ok('HoneyClient::Agent::Driver::IE'); 
    156 can_ok('HoneyClient::Agent::Driver::IE', 'new'); 
    157 can_ok('HoneyClient::Agent::Driver::IE', 'drive'); 
    158 can_ok('HoneyClient::Agent::Driver::IE', 'getNextLink'); 
    159 can_ok('HoneyClient::Agent::Driver::IE', 'next'); 
    160 can_ok('HoneyClient::Agent::Driver::IE', 'isFinished'); 
    161 can_ok('HoneyClient::Agent::Driver::IE', 'status'); 
    162 use HoneyClient::Agent::Driver::IE; 
     141# TODO: Include FF 
     142# Make sure HoneyClient::Agent::Driver::Browser::IE loads. 
     143BEGIN { use_ok('HoneyClient::Agent::Driver::Browser::IE') or diag("Can't load HoneyClient::Agent::Driver::Browser::IE package.  Check to make sure the package library is correctly listed within the path."); } 
     144require_ok('HoneyClient::Agent::Driver::Browser::IE'); 
     145# TODO: Update this list of function names. 
     146can_ok('HoneyClient::Agent::Driver::Browser::IE', 'new'); 
     147can_ok('HoneyClient::Agent::Driver::Browser::IE', 'drive'); 
     148can_ok('HoneyClient::Agent::Driver::Browser::IE', 'getNextLink'); 
     149can_ok('HoneyClient::Agent::Driver::Browser::IE', 'next'); 
     150can_ok('HoneyClient::Agent::Driver::Browser::IE', 'isFinished'); 
     151can_ok('HoneyClient::Agent::Driver::Browser::IE', 'status'); 
     152use HoneyClient::Agent::Driver::Browser::IE; 
    163153 
    164154# Make sure Storable loads. 
     
    241231our $DAEMON_PID     : shared = undef; 
    242232 
    243 # Global static value, to indicate if the Agent should perform 
     233# Global array, to indicate which implemented Drivers the 
     234# Agent is allowed to run. 
     235our $ALLOWED_DRIVERS = getVar(name => 'allowed_drivers')->{name}; 
     236 
     237# Global value, to indicate if the Agent should perform 
    244238# any integrity checks. 
    245239our $PERFORM_INTEGRITY_CHECKS : shared = 
     
    353347    } 
    354348 
     349    # Figure out what our list of allowed Drivers are.  
     350    $ALLOWED_DRIVERS = getVar(name => 'allowed_drivers')->{name}; 
     351 
    355352    # Acquire data lock. 
    356353    _lock(); 
     
    358355    # Initialize the $driverData shared hashtable. 
    359356    my $data = { }; 
    360     for my $driverName (@DRIVERS) { 
    361  
    362         # TODO: Figure out which drivers' data to initialize, based upon 
    363         # which driver argument hashtables were provided.  Then keep 
    364         # that list in a globally, defined array. 
    365          
     357    for my $driverName (@{$ALLOWED_DRIVERS}) { 
     358 
     359        eval "use $driverName"; 
     360        if ($@) { 
     361            $LOG->fatal($@); 
     362            Carp::croak $@; 
     363        } 
     364  
    366365        $data->{$driverName} = {  
    367366            'state'     => undef, 
     
    590589 
    591590    # Figure out the corresponding driver name. 
    592     my @package = split(/::/, ref($driver)); 
    593     my $driverName = pop(@package); 
     591    my $driverName = ref($driver); 
    594592 
    595593    # Extract the corresponding queue. 
     
    630628=pod 
    631629 
    632 =head1 EXPORT
    633  
    634 =head2 run(
     630=head1 EXTERNAL SOAP FUNCTION
     631 
     632=head2 run(driver_name => $driverName
    635633 
    636634=over 4 
    637635 
     636Runs the Agent for one cycle.  In this cycle, the following happens: 
     637 
     638=over 4 
     639 
     640=item 1) 
     641 
     642The specified Driver is driven for multiple work units, where each 
     643consecutive drive operation contacts the same network resources 
     644(aka. "targets").  The Driver ceases its operation, as soon as 
     645it has exhausted all targets or until it is ready to contact a 
     646different set of targets. 
     647 
     648=item 2) 
     649 
     650Once the specified driver has stopped, the Agent performs a corresponding 
     651Integrity check. 
     652 
     653=back  
     654 
    638655# XXX: Fill this in. 
    639656 
    640657I<Inputs>:  
    641  B<$arg> is an optional argument. 
    642 SOAP server to listen on
     658 B<$driverName> is the name of the Driver to use, when running this  
     659cycle
    643660  
    644 I<Output>: XXX: Fill this in. 
     661I<Output>: Returns true if the Agent successfully started a new cycle; 
     662returns false, if the Agent is still running an existing cycle and 
     663has not finished yet. 
     664 
     665I<Notes>: 
     666During a single run() cycle, it is expected that the driven application 
     667will only contact the same targets.  This allows the Manager to update 
     668firewall rules between cycles. 
    645669 
    646670=back 
    647671 
    648 =begin testing 
    649  
     672#=begin testing 
     673
    650674# XXX: Fill this in. 
    651 1; 
    652  
    653 =end testing 
     675
     676#=end testing 
    654677 
    655678=cut 
     
    657680sub run { 
    658681    # Extract arguments. 
     682    my ($class, %args) = @_; 
     683 
     684    # Log resolved arguments. 
     685    $LOG->debug(sub { 
     686        # Make Dumper format more terse. 
     687        $Data::Dumper::Terse = 1; 
     688        $Data::Dumper::Indent = 0; 
     689        Dumper(\%args); 
     690    }); 
     691 
     692    # Sanity check.  Make sure we get a valid argument. 
     693    my $argsExist = scalar(%args); 
     694    if (!$argsExist || 
     695        !exists($args{'driver_name'}) || 
     696        !defined($args{'driver_name'})) { 
     697 
     698        # Die if no valid argument is supplied. 
     699        $LOG->warn("No Driver name specified."); 
     700        die SOAP::Fault->faultcode(__PACKAGE__ . "->run()") 
     701                       ->faultstring("No Driver name specified."); 
     702    } 
     703 
     704    # Sanity check.  Make sure the driver name specified is 
     705    # on our allowed list. 
     706    my @drivers_found = grep(/^$args{'driver_name'}$/, @{$ALLOWED_DRIVERS}); 
     707    my $driverName = pop(@drivers_found); 
     708    unless (defined($driverName)) { 
     709        $LOG->warn("Not allowed to run Driver (" . $args{'driver_name'} . ")."); 
     710        die SOAP::Fault->faultcode(__PACKAGE__ . "->run()") 
     711                       ->faultstring("Not allowed to run Driver (" . $args{'driver_name'} . ")."); 
     712    } 
    659713 
    660714    # Temporary variable, used to hold thawed driver data. 
     
    667721    my $thread = undef; 
    668722 
    669     # TODO: Eventually, use the globally defined array 
    670     # of actual drivers used (set by init()). 
    671     for my $driverName (@DRIVERS) { 
     723    if (defined($driverName)) { 
    672724 
    673725        # Acquire data lock. 
     
    678730 
    679731# XXX: Delete this, eventually. 
    680 print "Checking TID = " . Dumper($tid) . "\n"; 
     732print $driverName . " - Checking TID = " . Dumper($tid) . "\n"; 
    681733if (defined(threads->object($tid))) { 
    682     print "Thread defined.\n"; 
     734    print $driverName . " - Thread defined.\n"; 
    683735    if (threads->object($tid)->is_running()) { 
    684         print "Thread is running.\n"; 
     736        print $driverName . " - Thread is running.\n"; 
    685737    } else { 
    686         print "Thread is NOT running.\n"; 
     738        print $driverName . " - Thread is NOT running.\n"; 
    687739    } 
    688740} else { 
    689     print "Thread NOT defined.\n"; 
     741    print $driverName . " - Thread NOT defined.\n"; 
    690742} 
    691743         
     
    702754        } else { 
    703755            # XXX: Remove this, eventually. 
    704             print "Creating a new run() child thread...\n"; 
     756            print $driverName . " - Creating a new run() child thread...\n"; 
    705757        } 
    706758 
     
    736788        if ($thread->is_running()) { 
    737789            # XXX: Debugging, remove eventually.  
    738             print "Thread ID = " . $thread->tid() . "\n"; 
     790            print $driverName . " - Thread ID = " . $thread->tid() . "\n"; 
    739791        } else { 
    740792            # XXX: Debugging, remove eventually.  
    741             print "Thread ID = " . $thread->tid() . " (NOT RUNNING)\n"; 
     793            print $driverName . " - Thread ID = " . $thread->tid() . " (NOT RUNNING)\n"; 
    742794        } 
    743795 
     
    747799 
    748800    # XXX: Debugging, remove eventually.  
    749     print "Run thread initialized.\n"; 
     801    print "Run thread(s) initialized.\n"; 
    750802 
    751803    # At this point, the driver thread is initialized and running, 
     
    801853        # Now, initialize each driver object.  
    802854        # Figure out which $driver object to use... 
    803         my $driverClass = 'HoneyClient::Agent::Driver::Browser::' . $driverName; 
     855        my $driverClass = $driverName; 
    804856 
    805857        if (!defined($data->{$driverName}->{'state'})) { 
     
    848900            # We assume $driver->next() returns defined data. 
    849901            foreach my $resource (keys %{$driver->next()->{resources}}) { 
    850                 $LOG->info("Driving To Resource: " . $resource); 
     902                $LOG->info($driverName . " - Driving To Resource: " . $resource); 
    851903                $lastResource = $resource; 
    852904            } 
     
    866918            # XXX: Delete this, eventually. 
    867919            if ($driverTargetsChanged) { 
    868                 $LOG->info("Driver targets have changed."); 
     920                $LOG->info($driverName . " - Driver targets have changed."); 
    869921                #$Data::Dumper::Terse = 0; 
    870922                #$Data::Dumper::Indent = 1; 
     
    884936        } 
    885937                 
    886         # TODO: Perform Integrity Check 
     938        # Perform Integrity Check 
     939        # XXX: We may want this logic moved out of the child thread, 
     940        # in case we ever have more than one worker thread simultaneously going. 
     941        # (We wouldn't want to have 2 worker threads simultaneously performing 
     942        # this check, as VM performance would slow to a crawl.) 
    887943        my $isCompromised = 0; 
    888944        my $changes = undef; 
     
    890946            # For now, we update a scalar called 'is_compromised' within 
    891947            # the $data->{$driverName}->{'status'} sub-hashtable. 
    892             $LOG->info("Performing Integrity Checks."); 
     948            $LOG->info($driverName . " - Performing Integrity Checks."); 
    893949            $changes = $integrity->check(); 
    894950            if (scalar(@{$changes->{registry}}) ||  
    895951                scalar(@{$changes->{filesystem}})) { 
    896                 $LOG->warn("Integrity Check: FAILED"); 
     952                $LOG->warn($driverName . " - Integrity Check: FAILED"); 
    897953                $isCompromised = 1; 
    898954                $changes->{'last_resource'} = $lastResource; 
    899955            } else { 
    900                 $LOG->info("Integrity Check: PASSED"); 
     956                $LOG->info($driverName . " - Integrity Check: PASSED"); 
    901957            } 
    902958        } 
     
    936992 
    937993        # TODO: Do proper fault queuing. 
    938         $LOG->error("FAULT: " . $@); 
     994        $LOG->error($driverName . " - FAULT: " . $@); 
    939995    } 
    940996 
    941997    # XXX: Debugging, remove eventually.  
    942     print "About to return out of child thread.\n"; 
     998    print $driverName . " - About to return out of child thread.\n"; 
    943999    if (!threads->is_detached()) { 
    9441000        threads->detach(); 
     
    9941050 
    9951051    # Figure out which driver to use. 
    996     for my $driverName (@DRIVERS) { 
     1052    for my $driverName (@{$ALLOWED_DRIVERS}) { 
    9971053   
    9981054        # If the corresponding key within the argument 
     
    10341090            # Initialize the driver object.  
    10351091            # Figure out which $driver object to use... 
    1036             my $driverClass = 'HoneyClient::Agent::Driver::Browser::' . $driverName; 
     1092            my $driverClass = $driverName; 
    10371093 
    10381094            if (!defined($data->{$driverName}->{'state'})) { 
  • honeyclient/trunk/lib/HoneyClient/Agent/Driver.pm

    r615 r751  
    306306 
    307307    # Sanity check: Make sure the supplied value is an object. 
    308     my $type = ref($self) or Carp::croak "Error: $self is not an object!\n"; 
     308    my $type = ref($self); 
     309    unless(defined($type)) { 
     310        $LOG->error("Error: $self is not an object!"); 
     311        Carp::croak "Error: $self is not an object!\n"; 
     312    } 
    309313 
    310314    # Now, get the name of the function. 
  • honeyclient/trunk/lib/HoneyClient/Agent/Driver/Browser.pm

    r696 r751  
    8787  $browser->drive(); 
    8888 
     89  # Or, we can specify the URL as an argument. 
     90  $browser->drive(url => "http://www.mitre.org"); 
     91 
    8992=head1 DESCRIPTION 
    9093 
    91 This library allows the Agent module to drive an instance of any broswer, 
     94This library allows the Agent module to drive an instance of any browser, 
    9295running inside the HoneyClient VM.  The purpose of this module is to 
    9396programmatically navigate the browser to different websites, in order to 
     
    9598 
    9699This module is object-oriented in design, retaining all state information 
    97 within itself for easy access.  A specific browser class must inherit from 
    98 Browser
    99  
    100 Fundamentally, the browser driver is initialized with a set of absolute URLs 
     100within itself for easy access.  A specific browser implementation, such as 
     101'IE' or 'FF', must inherit from this package
     102 
     103Fundamentally, the Browser driver is initialized with a set of absolute URLs 
    101104for the browser to drive to.  Upon visiting each URL, the driver collects 
    102105any B<new> links found and will attempt to drive the browser to each 
     
    105108For each top-level URL given, the driver will attempt to process all 
    106109corresponding links that are hosted on the same server, in order to 
    107 simulate a complete 'spider' of each server.  B<However>, because 
    108 URLs are added and removed from hashtables, the order of which URLs 
    109 are processed B<cannot be guaranteed nor maintained across subsequent 
    110 iterations of work>. 
    111  
    112 This means that the browser driver will try to visit all links shared by a 
    113 common server in random order before moving on to drive to other, 
    114 external links in a random fashion.  B<However>, this cannot be 
    115 guaranteed, as additional links from the same server may be found 
    116 later, after processing the contents of an external link. 
    117  
    118 As the browser driver navigates the browser to each link, it 
     110simulate a complete 'spider' of each server.   
     111 
     112URLs are added and removed from hashtables, as keys.  For each URL, a 
     113calculated "priority" (a positive integer) of the URL is assigned the 
     114value.  When the Browser is ready to go to a new link, it will always go 
     115to the next link that has the highest priority.  If two URLs have the same 
     116priority, then the Browser will chose among those two at random. 
     117 
     118Furthermore, the Browser driver will try to visit all links shared by a 
     119common server in order before moving on to drive to other, 
     120external links in an ordered fashion.  B<However>, the Browser may end 
     121up re-visiting old sites, if new links were found that the 
     122Browser has not visited yet.  
     123 
     124As the Browser driver navigates the browser to each link, it 
    119125maintains a set of hashtables that record when valid links were 
    120126visited (see L<links_visited>); when invalid links were found 
     
    625631# hashtable.  The link with the highest score is returned. 
    626632# 
    627 # 
    628 # 
    629633# Inputs: hashref 
    630634# Outputs: valid key, or undef if the hash is empty 
     
    828832} 
    829833 
     834# XXX: Is this really needed? 
    830835# Helper function designed to kill all instances of the driven 
    831836# application. 
     
    848853 
    849854    if (!$som->result) { 
     855        $LOG->warn("Failed to kill process: '" . $self->process_name . "'!"); 
    850856        Carp::carp "Failed to kill process: '" . $self->process_name . "'!\n"; 
    851857    } 
     
    966972 
    967973B<Warning>: This method will B<croak> if the Browser driver object is B<unable> 
    968 to navigate to a new link, because its list of links to visit is empty. 
     974to navigate to a new link, because its list of links to visit is empty and 
     975no new URL was supplied. 
    969976 
    970977=back 
     
    986993    # Sanity check: Make sure we've been fed an object. 
    987994    unless (ref($self)) { 
     995        $LOG->error("Error: Function must be called in reference to a " . 
     996                    __PACKAGE__ . "->new() object!"); 
    988997        Carp::croak "Error: Function must be called in reference to a " . 
    989998                    __PACKAGE__ . "->new() object!\n"; 
     
    10021011    # Sanity check: Make sure our next URL is defined. 
    10031012    unless (defined($args{'url'})) { 
    1004         Carp::croak "Error: Unable to drive browser - 'links_to_visit' " . 
    1005                     "hashtable is empty!\n"; 
     1013        $LOG->error("Error: Unable to drive browser - no links left to browse!"); 
     1014        Carp::croak "Error: Unable to drive browser - no links left to browse!\n"; 
    10061015    } 
    10071016 
     
    11521161    # Sanity check: Make sure we've been fed an object. 
    11531162    unless (ref($self)) { 
     1163        $LOG->error("Error: Function must be called in reference to a " . 
     1164                    __PACKAGE__ . "->new() object!"); 
    11541165        Carp::croak "Error: Function must be called in reference to a " . 
    11551166                    __PACKAGE__ . "->new() object!\n"; 
     
    12481259    # Sanity check: Make sure we've been fed an object. 
    12491260    unless (ref($self)) { 
     1261        $LOG->error("Error: Function must be called in reference to a " . 
     1262                    __PACKAGE__ . "->new() object!"); 
    12501263        Carp::croak "Error: Function must be called in reference to a " . 
    12511264                    __PACKAGE__ . "->new() object!\n"; 
     
    15911604    # Sanity check: Make sure we've been fed an object. 
    15921605    unless (ref($self)) { 
     1606        $LOG->error("Error: Function must be called in reference to a " . 
     1607                    __PACKAGE__ . "->new() object!"); 
    15931608        Carp::croak "Error: Function must be called in reference to a " . 
    15941609                    __PACKAGE__ . "->new() object!\n"; 
     
    16541669    # Sanity check: Make sure we've been fed an object. 
    16551670    unless (ref($self)) { 
     1671        $LOG->error("Error: Function must be called in reference to a " . 
     1672                    __PACKAGE__ . "->new() object!"); 
    16561673        Carp::croak "Error: Function must be called in reference to a " . 
    16571674                    __PACKAGE__ . "->new() object!\n"; 
     
    17351752increased. 
    17361753 
    1737 Currently we assume that the browser is configured to not cache anything 
    1738  
    1739 =head1 TODO 
    1740  
    1741 Add documentation for proper configuration of browser to not cache stuff 
     1754Lastly, we assume the driven browser has been preconfigured to 
     1755B<not cache any data>.  This ensures the browser will render the most 
     1756recent version of the content hosted at each URL. 
    17421757 
    17431758=head1 SEE ALSO 
     1759 
     1760L<HoneyClient::Agent::Driver> 
     1761 
     1762L<HoneyClient::Agent::Driver::Browser::IE> 
     1763 
     1764L<HoneyClient::Agent::Driver::Browser::FF> 
    17441765 
    17451766L<http://www.honeyclient.org/trac> 
  • honeyclient/trunk/lib/HoneyClient/Agent/Driver/Browser/FF.pm

    r605 r751  
    1 ############################################################################### 
     1####################################################################### 
    22# Created on:  May 11, 2006 
    33# Package:     HoneyClient::Agent::Driver::FF 
     
    99# CVS: $Id$ 
    1010# 
    11 # @author knwang, xkovah, kindlund, ttruong 
     11# @author knwang, ttruong, kindlund, stephenson 
    1212# 
    1313# Copyright (C) 2007 The MITRE Corporation.  All rights reserved. 
     
    2828# 02110-1301, USA. 
    2929# 
    30 ############################################################################### 
    31  
    32 package HoneyClient::Agent::Driver::FF; 
    33  
    34 # XXX: Disabled version check, Honeywall does not have Perl v5.8 installed. 
    35 #use 5.008006; 
     30
     31####################################################################### 
     32 
     33=pod 
     34 
     35=head1 NAME 
     36 
     37HoneyClient::Agent::Driver::Browser::FF - Perl extension to drive Mozilla  
     38Firefox to a given web page.  This package extends the 
     39HoneyClient::Agent::Driver::Browser package, by overridding the drive() method. 
     40 
     41=head1 VERSION 
     42 
     43This documentation refers to HoneyClient::Agent::Driver::Browser::FF version 0.97. 
     44 
     45=head1 SYNOPSIS 
     46 
     47  use HoneyClient::Agent::Driver::Browser::FF; 
     48 
     49  # Library used exclusively for debugging complex objects. 
     50  use Data::Dumper; 
     51 
     52  # Create a new FF object, initialized with a collection 
     53  # of URLs to visit. 
     54  my $browser = HoneyClient::Agent::Driver::Browser::FF->new( 
     55      links_to_visit => { 
     56          'http://www.google.com'  => 1, 
     57          'http://www.cnn.com'     => 1, 
     58      }, 
     59  ); 
     60 
     61  # If you want to see what type of "state information" is physically 
     62  # inside $browser, try this command at any time. 
     63  print Dumper($browser); 
     64 
     65  # Continue to "drive" the driver, until it is finished. 
     66  while (!$browser->isFinished()) { 
     67 
     68      # Before we drive the application to a new set of resources, 
     69      # find out where we will be going within the application, first. 
     70      print "About to contact the following resources:\n"; 
     71      print Dumper($browser->next()); 
     72 
     73      # Now, drive browser for one iteration. 
     74      $browser->drive(); 
     75 
     76      # Get the driver's progress. 
     77      print "Status:\n"; 
     78      print Dumper($browser->status()); 
     79 
     80  } 
     81 
     82  # At this stage, the driver has exhausted its collection of links 
     83  # to visit.  Let's say we want to add the URL "http://www.mitre.org" 
     84  # to the driver's list. 
     85  $browser->{links_to_visit}->{'http://www.mitre.org'} = 1; 
     86 
     87  # Now, drive the browser for one iteration. 
     88  $browser->drive(); 
     89   
     90  # Or, we can specify the URL as an argument. 
     91  $browser->drive(url => "http://www.mitre.org"); 
     92 
     93=head1 DESCRIPTION 
     94 
     95This library allows the Agent module to drive an instance of Mozilla 
     96Firefox inside the HoneyClient VM.  The purpose of this module is to 
     97programmatically navigate this browser to different websites, in order to 
     98become purposefully infected with new malware. 
     99 
     100This module is object-oriented in design, retaining all state information 
     101within itself for easy access.  This specific browser implementation inherits 
     102all code from the HoneyClient::Agent::Driver::Browser package. 
     103 
     104Fundamentally, the FF driver is initialized with a set of absolute URLs 
     105for the browser to drive to.  Upon visiting each URL, the driver collects 
     106any B<new> links found and will attempt to drive the browser to each 
     107valid URL upon subsequent iterations of work. 
     108 
     109For each top-level URL given, the driver will attempt to process all 
     110corresponding links that are hosted on the same server, in order to 
     111simulate a complete 'spider' of each server.   
     112 
     113URLs are added and removed from hashtables, as keys.  For each URL, a 
     114calculated "priority" (a positive integer) of the URL is assigned the 
     115value.  When the FF driver is ready to go to a new link, it will always go 
     116to the next link that has the highest priority.  If two URLs have the same 
     117priority, then the FF driver will chose among those two at random. 
     118 
     119Furthermore, the FF driver will try to visit all links shared by a 
     120common server in order before moving on to drive to other, 
     121external links in an ordered fashion.  B<However>, the FF driver may end 
     122up re-visiting old sites, if new links were found that the 
     123FF driver has not visited yet.  
     124 
     125As the FF driver navigates the browser to each link, it 
     126maintains a set of hashtables that record when valid links were 
     127visited (see L<links_visited>); when invalid links were found 
     128(see L<links_ignored>); and when the browser attempted to visit 
     129a link but the operation timed out (see L<links_timed_out>). 
     130By maintaining this internal history, the driver will B<never> 
     131navigate the browser to the same link twice. 
     132 
     133Lastly, it is highly recommended that for each driver B<$object>, 
     134one should call $object->isFinished() prior to making a subsequent 
     135call to $object->drive(), in order to verify that the driver has 
     136not exhausted its set of links to visit.  Otherwise, if 
     137$object->drive() is called with an empty set of links to visit, 
     138the corresponding operation will B<croak>. 
     139 
     140=cut 
     141 
     142package HoneyClient::Agent::Driver::Browser::FF; 
     143 
    36144use strict; 
    37145use warnings; 
    38 use Config; 
    39146use Carp (); 
    40147 
     
    71178    # Do not simply export all your public functions/methods/constants. 
    72179 
    73     # This allows declaration use HoneyClient::Agent::Driver::Browser::IE ':all'; 
     180    # This allows declaration use HoneyClient::Agent::Driver::Browser::FF ':all'; 
    74181    # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK 
    75182    # will save memory. 
     
    84191    @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); 
    85192 
    86 # XXX: Fix this! 
    87 # Check to make sure our OS is Windows-based. 
    88 #if ($Config{osname} !~ /^MSWin32$/) { 
    89 #    Carp::croak "Error: " . __PACKAGE__ . " will only run on Win32 platforms!\n"; 
    90 #} 
    91  
    92193    $SIG{PIPE} = 'IGNORE';    # Do not exit on broken pipes. 
    93194} 
    94195our ( @EXPORT_OK, $VERSION ); 
    95196 
    96 #TODO: Rewrite the test module 
    97  
    98197=pod 
    99198 
    100199=begin testing 
    101200 
     201# Make sure Log::Log4perl loads 
     202BEGIN { use_ok('Log::Log4perl', qw(:nowarn)) 
     203        or diag("Can't load Log::Log4perl package. Check to make sure the package library is correctly listed within the path."); 
     204        
     205        # Suppress all logging messages, since we need clean output for unit testing. 
     206        Log::Log4perl->init({ 
     207            "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     208            "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     209            "log4perl.appender.Buffer.min_level"                => "fatal", 
     210            "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     211            "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     212        }); 
     213} 
     214require_ok('Log::Log4perl'); 
     215use Log::Log4perl qw(:easy); 
     216 
     217# Make sure HoneyClient::Util::Config loads. 
     218BEGIN { use_ok('HoneyClient::Util::Config', qw(getVar)) 
     219        or diag("Can't load HoneyClient::Util::Config package.  Check to make sure the package library is correctly listed within the path.");  
     220 
     221        # Suppress all logging messages, since we need clean output for unit testing. 
     222        Log::Log4perl->init({ 
     223            "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     224            "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     225            "log4perl.appender.Buffer.min_level"                => "fatal", 
     226            "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     227            "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     228        }); 
     229         
     230} 
     231require_ok('HoneyClient::Util::Config'); 
     232can_ok('HoneyClient::Util::Config', 'getVar'); 
     233use HoneyClient::Util::Config qw(getVar); 
     234 
     235# Make sure the module loads properly, with the exportable 
     236# functions shared. 
     237BEGIN { use_ok('HoneyClient::Agent::Driver::Browser::FF') or diag("Can't load HoneyClient::Agent::Driver::Browser::FF package.  Check to make sure the package library is correctly listed within the path."); } 
     238require_ok('HoneyClient::Agent::Driver::Browser::FF'); 
     239can_ok('HoneyClient::Agent::Driver::Browser::FF', 'new'); 
     240can_ok('HoneyClient::Agent::Driver::Browser::FF', 'drive'); 
     241can_ok('HoneyClient::Agent::Driver::Browser::FF', 'isFinished'); 
     242can_ok('HoneyClient::Agent::Driver::Browser::FF', 'next'); 
     243can_ok('HoneyClient::Agent::Driver::Browser::FF', 'status'); 
     244can_ok('HoneyClient::Agent::Driver::Browser::FF', 'getNextLink'); 
     245use HoneyClient::Agent::Driver::Browser::FF; 
     246 
     247# Suppress all logging messages, since we need clean output for unit testing. 
     248Log::Log4perl->init({ 
     249    "log4perl.rootLogger"                               => "DEBUG, Buffer", 
     250    "log4perl.appender.Buffer"                          => "Log::Log4perl::Appender::TestBuffer", 
     251    "log4perl.appender.Buffer.min_level"                => "fatal", 
     252    "log4perl.appender.Buffer.layout"                   => "Log::Log4perl::Layout::PatternLayout", 
     253    "log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", 
     254}); 
     255 
     256# Make sure Win32::Job loads. 
     257BEGIN { use_ok('Win32::Job') or diag("Can't load Win32::Job package.  Check to make sure the package library is correctly listed within the path."); } 
     258require_ok('Win32::Job'); 
     259use Win32::Job; 
     260 
     261# Make sure ExtUtils::MakeMaker loads. 
     262BEGIN { use_ok('ExtUtils::MakeMaker', qw(prompt)) or diag("Can't load ExtUtils::MakeMaker package.  Check to make sure the package library is correctly listed within the path."); } 
     263require_ok('ExtUtils::MakeMaker'); 
     264can_ok('ExtUtils::MakeMaker', 'prompt'); 
     265use ExtUtils::MakeMaker qw(prompt); 
     266 
    102267=end testing 
    103268 
     
    105270 
    106271####################################################################### 
    107  
    108 #TODO: Remove any of these use statements that aren't needed 
    109272 
    110273# Include the Global Configuration Processing Library 
    111274use HoneyClient::Util::Config qw(getVar); 
    112275 
    113 # Use ISO 8601 DateTime Libraries 
    114 use DateTime::HiRes; 
    115  
    116 # Use fractional second sleeping. 
    117 # TODO: Need unit testing. 
    118 use Time::HiRes qw(sleep); 
    119  
    120 # Use Storable Library 
    121 use Storable qw(dclone); 
    122  
    123 # Use threads Library 
    124 # TODO: Need unit testing. 
    125 use threads; 
    126  
    127 # TODO: Need unit testing. 
    128 use threads::shared; 
    129  
    130 # TODO: Need unit testing. 
    131 use HoneyClient::Util::SOAP qw(getClientHandle); 
    132  
    133 # TODO: Need unit testing. 
     276# Include Win32 Job Library 
    134277use Win32::Job; 
    135278 
    136 # TODO: clean this up. 
    137 #my %PARAMS = ( 
    138 #); 
    139  
    140 ####################################################################### 
    141 # Private Methods Implemented                                         # 
    142 ####################################################################### 
    143  
    144 #sub new { 
    145 #    
    146 #    # - This function takes in an optional hashtable, 
    147 #    #   that contains various key => 'value' configuration 
    148 #    #   parameters. 
    149 #    # 
    150 #    # - For each parameter given, it overwrites any corresponding 
    151 #    #   parameters specified within the default hashtable, %PARAMS, 
    152 #    #   with custom entries that were given as parameters. 
    153 #    # 
    154 #    # - Finally, it returns a blessed instance of the 
    155 #    #   merged hashtable, as an 'object'. 
    156 
    157 #    # Get the class name. 
    158 #    my $self = shift; 
    159 
    160 #    # Get the rest of the arguments, as a hashtable. 
    161 #    # Hash-based arguments are used, since HoneyClient::Util::SOAP is unable to handle 
    162 #    # hash references directly.  Thus, flat hashtables are used throughout the code 
    163 #    # for consistency. 
    164 #    my %args = @_; 
    165 
    166 #    # Check to see if the class name is inherited or defined. 
    167 #    my $class = ref($self) || $self; 
    168 
    169 #    # Initialize default parameters. 
    170 #    my %params = %{dclone(\%PARAMS)}; 
    171 #    $self = $class->SUPER::new(); 
    172 #    @{$self}{keys %params} = values %params; 
    173 
    174 #    # Now, overwrite any default parameters that were redefined 
    175 #    # in the supplied arguments. 
    176 #    @{$self}{keys %args} = values %args; 
    177 
    178 #    # Now, assign our object the appropriate namespace. 
    179 #    bless $self, $class; 
    180 
    181 #    # Finally, return the blessed object. 
    182 #    return $self; 
    183 #} 
     279# Include Logging Library 
     280use Log::Log4perl qw(:easy); 
     281 
     282# The global logging object. 
     283our $LOG = get_logger(); 
     284 
     285####################################################################### 
     286# Public Methods Implemented                                          # 
     287####################################################################### 
     288 
     289=pod 
     290 
     291=head1 METHODS OVERRIDDEN 
     292 
     293The following functions have been overridden by the FF driver.  All other 
     294methods were implemented by the generic Browser driver.  For further 
     295information about the Browser driver, see the L<HoneyClient::Agent::Driver::Browser> 
     296documentation. 
     297 
     298=head2 $object->drive(url => $url) 
     299 
     300=over 4 
     301 
     302Drives an instance of Mozilla Firefox for one iteration, 
     303navigating either to the specified URL or to the next URL computed within 
     304the Browser driver's internal hashtables. 
     305 
     306For a description of which hashtable is consulted upon each iteration of 
     307drive(), see the B<next_link_to_visit> description of the  
     308L<HoneyClient::Agent::Driver::Browser> documentation, in the 
     309"DEFAULT PARAMETER LIST" section. 
     310 
     311Once a drive() iternation has completed, the corresponding browser process 
     312is terminated.  Thus, each call to drive() invokes a new instance of the 
     313browser. 
     314 
     315I<Inputs>: 
     316 B<$url> is an optional argument, specifying the next immediate URL the browser 
     317must drive to. 
     318 
     319I<Output>: The updated FF driver B<$object>, containing state information from driving the 
     320browser for one iteration. 
     321 
     322B<Warning>: This method will B<croak>, if the FF driver object is B<unable> 
     323to navigate to a new link, because its list of links to vist is empty and no new 
     324URL was supplied. 
     325 
     326=back 
     327 
     328=begin testing 
     329 
     330# Generate a notice, to clarify our assumptions. 
     331diag(""); 
     332diag("About to run basic FF-specific browser tests."); 
     333diag("Note: These tests *require* network connectivity and"); 
     334diag("*expect* FF to be installed at the following location."); 
     335diag(""); 
     336 
     337my $processExec = getVar(name      => "process_exec", 
     338                         namespace => "HoneyClient::Agent::Driver::Browser::FF"); 
     339my $processName = getVar(name      => "process_name", 
     340                         namespace => "HoneyClient::Agent::Driver::Browser::FF"); 
     341 
     342diag("Process Name:\t\t'" . $processName . "'"); 
     343diag("Process Location:\t'" . $processExec . "'"); 
     344diag(""); 
     345diag("If FF is installed in a different location or has a different executable name,"); 
     346diag("then please answer *NO* to the next question and update your etc/honeyclient.xml"); 
     347diag("file, changing the 'process_name' and 'process_exec' elements in the"); 
     348diag("<HoneyClient/><Agent/><Driver/><Browser/><FF/> section."); 
     349diag(""); 
     350diag("Then, once updated, re-run these tests."); 
     351diag("");