Changeset 751
- Timestamp:
- 07/23/07 18:01:54 (1 year ago)
- Files:
-
- honeyclient/trunk/bin/StartManager.pl (modified) (2 diffs)
- honeyclient/trunk/etc/honeyclient.xml (modified) (3 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent.pm (modified) (22 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent/Driver.pm (modified) (1 diff)
- honeyclient/trunk/lib/HoneyClient/Agent/Driver/Browser.pm (modified) (14 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent/Driver/Browser/FF.pm (modified) (10 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent/Driver/Browser/IE.pm (modified) (8 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent/Integrity.pm (modified) (3 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent/Integrity/Filesystem.pm (modified) (1 diff)
- honeyclient/trunk/lib/HoneyClient/Agent/Integrity/Registry.pm (modified) (4 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent/Integrity/Registry/Parser.pm (modified) (8 diffs)
- honeyclient/trunk/lib/HoneyClient/Agent/Integrity/Registry/Parser.yp (modified) (8 diffs)
- honeyclient/trunk/lib/HoneyClient/Manager.pm (modified) (3 diffs)
- honeyclient/trunk/lib/HoneyClient/Manager/VM.pm (modified) (1 diff)
- honeyclient/trunk/lib/HoneyClient/Manager/VM/Clone.pm (modified) (3 diffs)
- honeyclient/trunk/t/honeyclient_agent.t (modified) (2 diffs)
- honeyclient/trunk/t/honeyclient_agent_driver_activecontent.t (copied) (copied from honeyclient/branches/exp/kindlund-firefox/t/honeyclient_agent_driver_activecontent.t)
- honeyclient/trunk/t/honeyclient_agent_driver_activecontent_flash.t (copied) (copied from honeyclient/branches/exp/kindlund-firefox/t/honeyclient_agent_driver_activecontent_flash.t)
- honeyclient/trunk/t/honeyclient_agent_driver_browser_ff.t (copied) (copied from honeyclient/branches/exp/kindlund-firefox/t/honeyclient_agent_driver_browser_ff.t)
- honeyclient/trunk/t/honeyclient_agent_driver_browser_ie.t (modified) (1 diff)
- honeyclient/trunk/t/honeyclient_agent_driver_ff.t (deleted)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
honeyclient/trunk/bin/StartManager.pl
r696 r751 24 24 # They can however supply multiple urls which will be processed in order 25 25 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' 28 my $driver = "HoneyClient::Agent::Driver::Browser::FF"; 29 my $config = "/vm/master-vms/Agent.Master-23/winXPPro.cfg"; 30 my $maxrel = 5; 29 31 my $nexturl = ""; 30 32 my $urllist= ""; … … 60 62 61 63 my $agentState = HoneyClient::Manager->run( 62 driver => $driver, # Change to 'IE' or 'FF'64 driver => $driver, 63 65 master_vm_config => $config, 64 66 agent_state => encode_base64(nfreeze({ 65 $driver => { # Change to 'IE' or 'FF'67 $driver => { 66 68 next_link_to_visit => $firsturl, 67 69 # Enable this line, if you want to only go to the honeyclient/trunk/etc/honeyclient.xml
r698 r751 68 68 9000 69 69 </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> 70 74 <!-- HoneyClient::Agent::Driver Options --> 71 75 <Driver> … … 122 126 <IE> 123 127 <!-- HoneyClient::Agent::Driver::Browser::IE Options --> 124 <!-- TODO: Update this. -->125 128 <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"> 126 129 C:\Program Files\Internet Explorer\iexplore.exe 127 130 </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> 128 134 </IE> 129 135 <FF> … … 132 138 C:\Program Files\Mozilla Firefox\firefox.exe 133 139 </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> 134 143 </FF> 135 144 </Browser> honeyclient/trunk/lib/HoneyClient/Agent.pm
r605 r751 76 76 # Defines which functions can be called externally. 77 77 require Exporter; 78 our (@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION , @DRIVERS);78 our (@ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS, $VERSION); 79 79 80 80 # Set our package version. … … 110 110 $Config{useithreads} or Carp::croak "Error: Recompile Perl with ithread support, in order to use this module.\n"; 111 111 112 # Registered driver list.113 # TODO: Eventually, make this more dynamic, based upon the presence of HoneyClient::Agent::Driver::* elements114 # 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 123 112 $SIG{PIPE} = 'IGNORE'; # Do not exit on broken pipes. 124 113 } 125 our (@EXPORT_OK, $VERSION , @DRIVERS);114 our (@EXPORT_OK, $VERSION); 126 115 127 116 =pod … … 150 139 use HoneyClient::Util::Config qw(getVar); 151 140 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. 143 BEGIN { 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."); } 144 require_ok('HoneyClient::Agent::Driver::Browser::IE'); 145 # TODO: Update this list of function names. 146 can_ok('HoneyClient::Agent::Driver::Browser::IE', 'new'); 147 can_ok('HoneyClient::Agent::Driver::Browser::IE', 'drive'); 148 can_ok('HoneyClient::Agent::Driver::Browser::IE', 'getNextLink'); 149 can_ok('HoneyClient::Agent::Driver::Browser::IE', 'next'); 150 can_ok('HoneyClient::Agent::Driver::Browser::IE', 'isFinished'); 151 can_ok('HoneyClient::Agent::Driver::Browser::IE', 'status'); 152 use HoneyClient::Agent::Driver::Browser::IE; 163 153 164 154 # Make sure Storable loads. … … 241 231 our $DAEMON_PID : shared = undef; 242 232 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. 235 our $ALLOWED_DRIVERS = getVar(name => 'allowed_drivers')->{name}; 236 237 # Global value, to indicate if the Agent should perform 244 238 # any integrity checks. 245 239 our $PERFORM_INTEGRITY_CHECKS : shared = … … 353 347 } 354 348 349 # Figure out what our list of allowed Drivers are. 350 $ALLOWED_DRIVERS = getVar(name => 'allowed_drivers')->{name}; 351 355 352 # Acquire data lock. 356 353 _lock(); … … 358 355 # Initialize the $driverData shared hashtable. 359 356 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 366 365 $data->{$driverName} = { 367 366 'state' => undef, … … 590 589 591 590 # Figure out the corresponding driver name. 592 my @package = split(/::/, ref($driver)); 593 my $driverName = pop(@package); 591 my $driverName = ref($driver); 594 592 595 593 # Extract the corresponding queue. … … 630 628 =pod 631 629 632 =head1 EX PORTS633 634 =head2 run( )630 =head1 EXTERNAL SOAP FUNCTIONS 631 632 =head2 run(driver_name => $driverName) 635 633 636 634 =over 4 637 635 636 Runs the Agent for one cycle. In this cycle, the following happens: 637 638 =over 4 639 640 =item 1) 641 642 The specified Driver is driven for multiple work units, where each 643 consecutive drive operation contacts the same network resources 644 (aka. "targets"). The Driver ceases its operation, as soon as 645 it has exhausted all targets or until it is ready to contact a 646 different set of targets. 647 648 =item 2) 649 650 Once the specified driver has stopped, the Agent performs a corresponding 651 Integrity check. 652 653 =back 654 638 655 # XXX: Fill this in. 639 656 640 657 I<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 659 cycle. 643 660 644 I<Output>: XXX: Fill this in. 661 I<Output>: Returns true if the Agent successfully started a new cycle; 662 returns false, if the Agent is still running an existing cycle and 663 has not finished yet. 664 665 I<Notes>: 666 During a single run() cycle, it is expected that the driven application 667 will only contact the same targets. This allows the Manager to update 668 firewall rules between cycles. 645 669 646 670 =back 647 671 648 =begin testing649 672 #=begin testing 673 # 650 674 # XXX: Fill this in. 651 1; 652 653 =end testing 675 # 676 #=end testing 654 677 655 678 =cut … … 657 680 sub run { 658 681 # 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 } 659 713 660 714 # Temporary variable, used to hold thawed driver data. … … 667 721 my $thread = undef; 668 722 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)) { 672 724 673 725 # Acquire data lock. … … 678 730 679 731 # XXX: Delete this, eventually. 680 print "Checking TID = " . Dumper($tid) . "\n";732 print $driverName . " - Checking TID = " . Dumper($tid) . "\n"; 681 733 if (defined(threads->object($tid))) { 682 print "Thread defined.\n";734 print $driverName . " - Thread defined.\n"; 683 735 if (threads->object($tid)->is_running()) { 684 print "Thread is running.\n";736 print $driverName . " - Thread is running.\n"; 685 737 } else { 686 print "Thread is NOT running.\n";738 print $driverName . " - Thread is NOT running.\n"; 687 739 } 688 740 } else { 689 print "Thread NOT defined.\n";741 print $driverName . " - Thread NOT defined.\n"; 690 742 } 691 743 … … 702 754 } else { 703 755 # XXX: Remove this, eventually. 704 print "Creating a new run() child thread...\n";756 print $driverName . " - Creating a new run() child thread...\n"; 705 757 } 706 758 … … 736 788 if ($thread->is_running()) { 737 789 # XXX: Debugging, remove eventually. 738 print "Thread ID = " . $thread->tid() . "\n";790 print $driverName . " - Thread ID = " . $thread->tid() . "\n"; 739 791 } else { 740 792 # XXX: Debugging, remove eventually. 741 print "Thread ID = " . $thread->tid() . " (NOT RUNNING)\n";793 print $driverName . " - Thread ID = " . $thread->tid() . " (NOT RUNNING)\n"; 742 794 } 743 795 … … 747 799 748 800 # XXX: Debugging, remove eventually. 749 print "Run thread initialized.\n";801 print "Run thread(s) initialized.\n"; 750 802 751 803 # At this point, the driver thread is initialized and running, … … 801 853 # Now, initialize each driver object. 802 854 # Figure out which $driver object to use... 803 my $driverClass = 'HoneyClient::Agent::Driver::Browser::' .$driverName;855 my $driverClass = $driverName; 804 856 805 857 if (!defined($data->{$driverName}->{'state'})) { … … 848 900 # We assume $driver->next() returns defined data. 849 901 foreach my $resource (keys %{$driver->next()->{resources}}) { 850 $LOG->info( "Driving To Resource: " . $resource);902 $LOG->info($driverName . " - Driving To Resource: " . $resource); 851 903 $lastResource = $resource; 852 904 } … … 866 918 # XXX: Delete this, eventually. 867 919 if ($driverTargetsChanged) { 868 $LOG->info( "Driver targets have changed.");920 $LOG->info($driverName . " - Driver targets have changed."); 869 921 #$Data::Dumper::Terse = 0; 870 922 #$Data::Dumper::Indent = 1; … … 884 936 } 885 937 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.) 887 943 my $isCompromised = 0; 888 944 my $changes = undef; … … 890 946 # For now, we update a scalar called 'is_compromised' within 891 947 # the $data->{$driverName}->{'status'} sub-hashtable. 892 $LOG->info( "Performing Integrity Checks.");948 $LOG->info($driverName . " - Performing Integrity Checks."); 893 949 $changes = $integrity->check(); 894 950 if (scalar(@{$changes->{registry}}) || 895 951 scalar(@{$changes->{filesystem}})) { 896 $LOG->warn( "Integrity Check: FAILED");952 $LOG->warn($driverName . " - Integrity Check: FAILED"); 897 953 $isCompromised = 1; 898 954 $changes->{'last_resource'} = $lastResource; 899 955 } else { 900 $LOG->info( "Integrity Check: PASSED");956 $LOG->info($driverName . " - Integrity Check: PASSED"); 901 957 } 902 958 } … … 936 992 937 993 # TODO: Do proper fault queuing. 938 $LOG->error( "FAULT: " . $@);994 $LOG->error($driverName . " - FAULT: " . $@); 939 995 } 940 996 941 997 # 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"; 943 999 if (!threads->is_detached()) { 944 1000 threads->detach(); … … 994 1050 995 1051 # Figure out which driver to use. 996 for my $driverName (@ DRIVERS) {1052 for my $driverName (@{$ALLOWED_DRIVERS}) { 997 1053 998 1054 # If the corresponding key within the argument … … 1034 1090 # Initialize the driver object. 1035 1091 # Figure out which $driver object to use... 1036 my $driverClass = 'HoneyClient::Agent::Driver::Browser::' .$driverName;1092 my $driverClass = $driverName; 1037 1093 1038 1094 if (!defined($data->{$driverName}->{'state'})) { honeyclient/trunk/lib/HoneyClient/Agent/Driver.pm
r615 r751 306 306 307 307 # 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 } 309 313 310 314 # Now, get the name of the function. honeyclient/trunk/lib/HoneyClient/Agent/Driver/Browser.pm
r696 r751 87 87 $browser->drive(); 88 88 89 # Or, we can specify the URL as an argument. 90 $browser->drive(url => "http://www.mitre.org"); 91 89 92 =head1 DESCRIPTION 90 93 91 This library allows the Agent module to drive an instance of any bro swer,94 This library allows the Agent module to drive an instance of any browser, 92 95 running inside the HoneyClient VM. The purpose of this module is to 93 96 programmatically navigate the browser to different websites, in order to … … 95 98 96 99 This module is object-oriented in design, retaining all state information 97 within itself for easy access. A specific browser class must inherit from98 Browser.99 100 Fundamentally, the browser driver is initialized with a set of absolute URLs100 within itself for easy access. A specific browser implementation, such as 101 'IE' or 'FF', must inherit from this package. 102 103 Fundamentally, the Browser driver is initialized with a set of absolute URLs 101 104 for the browser to drive to. Upon visiting each URL, the driver collects 102 105 any B<new> links found and will attempt to drive the browser to each … … 105 108 For each top-level URL given, the driver will attempt to process all 106 109 corresponding 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 110 simulate a complete 'spider' of each server. 111 112 URLs are added and removed from hashtables, as keys. For each URL, a 113 calculated "priority" (a positive integer) of the URL is assigned the 114 value. When the Browser is ready to go to a new link, it will always go 115 to the next link that has the highest priority. If two URLs have the same 116 priority, then the Browser will chose among those two at random. 117 118 Furthermore, the Browser driver will try to visit all links shared by a 119 common server in order before moving on to drive to other, 120 external links in an ordered fashion. B<However>, the Browser may end 121 up re-visiting old sites, if new links were found that the 122 Browser has not visited yet. 123 124 As the Browser driver navigates the browser to each link, it 119 125 maintains a set of hashtables that record when valid links were 120 126 visited (see L<links_visited>); when invalid links were found … … 625 631 # hashtable. The link with the highest score is returned. 626 632 # 627 #628 #629 633 # Inputs: hashref 630 634 # Outputs: valid key, or undef if the hash is empty … … 828 832 } 829 833 834 # XXX: Is this really needed? 830 835 # Helper function designed to kill all instances of the driven 831 836 # application. … … 848 853 849 854 if (!$som->result) { 855 $LOG->warn("Failed to kill process: '" . $self->process_name . "'!"); 850 856 Carp::carp "Failed to kill process: '" . $self->process_name . "'!\n"; 851 857 } … … 966 972 967 973 B<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. 974 to navigate to a new link, because its list of links to visit is empty and 975 no new URL was supplied. 969 976 970 977 =back … … 986 993 # Sanity check: Make sure we've been fed an object. 987 994 unless (ref($self)) { 995 $LOG->error("Error: Function must be called in reference to a " . 996 __PACKAGE__ . "->new() object!"); 988 997 Carp::croak "Error: Function must be called in reference to a " . 989 998 __PACKAGE__ . "->new() object!\n"; … … 1002 1011 # Sanity check: Make sure our next URL is defined. 1003 1012 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"; 1006 1015 } 1007 1016 … … 1152 1161 # Sanity check: Make sure we've been fed an object. 1153 1162 unless (ref($self)) { 1163 $LOG->error("Error: Function must be called in reference to a " . 1164 __PACKAGE__ . "->new() object!"); 1154 1165 Carp::croak "Error: Function must be called in reference to a " . 1155 1166 __PACKAGE__ . "->new() object!\n"; … … 1248 1259 # Sanity check: Make sure we've been fed an object. 1249 1260 unless (ref($self)) { 1261 $LOG->error("Error: Function must be called in reference to a " . 1262 __PACKAGE__ . "->new() object!"); 1250 1263 Carp::croak "Error: Function must be called in reference to a " . 1251 1264 __PACKAGE__ . "->new() object!\n"; … … 1591 1604 # Sanity check: Make sure we've been fed an object. 1592 1605 unless (ref($self)) { 1606 $LOG->error("Error: Function must be called in reference to a " . 1607 __PACKAGE__ . "->new() object!"); 1593 1608 Carp::croak "Error: Function must be called in reference to a " . 1594 1609 __PACKAGE__ . "->new() object!\n"; … … 1654 1669 # Sanity check: Make sure we've been fed an object. 1655 1670 unless (ref($self)) { 1671 $LOG->error("Error: Function must be called in reference to a " . 1672 __PACKAGE__ . "->new() object!"); 1656 1673 Carp::croak "Error: Function must be called in reference to a " . 1657 1674 __PACKAGE__ . "->new() object!\n"; … … 1735 1752 increased. 1736 1753 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 1754 Lastly, we assume the driven browser has been preconfigured to 1755 B<not cache any data>. This ensures the browser will render the most 1756 recent version of the content hosted at each URL. 1742 1757 1743 1758 =head1 SEE ALSO 1759 1760 L<HoneyClient::Agent::Driver> 1761 1762 L<HoneyClient::Agent::Driver::Browser::IE> 1763 1764 L<HoneyClient::Agent::Driver::Browser::FF> 1744 1765 1745 1766 L<http://www.honeyclient.org/trac> honeyclient/trunk/lib/HoneyClient/Agent/Driver/Browser/FF.pm
r605 r751 1 ####################################################################### ########1 ####################################################################### 2 2 # Created on: May 11, 2006 3 3 # Package: HoneyClient::Agent::Driver::FF … … 9 9 # CVS: $Id$ 10 10 # 11 # @author knwang, xkovah, kindlund, ttruong11 # @author knwang, ttruong, kindlund, stephenson 12 12 # 13 13 # Copyright (C) 2007 The MITRE Corporation. All rights reserved. … … 28 28 # 02110-1301, USA. 29 29 # 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 37 HoneyClient::Agent::Driver::Browser::FF - Perl extension to drive Mozilla 38 Firefox to a given web page. This package extends the 39 HoneyClient::Agent::Driver::Browser package, by overridding the drive() method. 40 41 =head1 VERSION 42 43 This 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 95 This library allows the Agent module to drive an instance of Mozilla 96 Firefox inside the HoneyClient VM. The purpose of this module is to 97 programmatically navigate this browser to different websites, in order to 98 become purposefully infected with new malware. 99 100 This module is object-oriented in design, retaining all state information 101 within itself for easy access. This specific browser implementation inherits 102 all code from the HoneyClient::Agent::Driver::Browser package. 103 104 Fundamentally, the FF driver is initialized with a set of absolute URLs 105 for the browser to drive to. Upon visiting each URL, the driver collects 106 any B<new> links found and will attempt to drive the browser to each 107 valid URL upon subsequent iterations of work. 108 109 For each top-level URL given, the driver will attempt to process all 110 corresponding links that are hosted on the same server, in order to 111 simulate a complete 'spider' of each server. 112 113 URLs are added and removed from hashtables, as keys. For each URL, a 114 calculated "priority" (a positive integer) of the URL is assigned the 115 value. When the FF driver is ready to go to a new link, it will always go 116 to the next link that has the highest priority. If two URLs have the same 117 priority, then the FF driver will chose among those two at random. 118 119 Furthermore, the FF driver will try to visit all links shared by a 120 common server in order before moving on to drive to other, 121 external links in an ordered fashion. B<However>, the FF driver may end 122 up re-visiting old sites, if new links were found that the 123 FF driver has not visited yet. 124 125 As the FF driver navigates the browser to each link, it 126 maintains a set of hashtables that record when valid links were 127 visited (see L<links_visited>); when invalid links were found 128 (see L<links_ignored>); and when the browser attempted to visit 129 a link but the operation timed out (see L<links_timed_out>). 130 By maintaining this internal history, the driver will B<never> 131 navigate the browser to the same link twice. 132 133 Lastly, it is highly recommended that for each driver B<$object>, 134 one should call $object->isFinished() prior to making a subsequent 135 call to $object->drive(), in order to verify that the driver has 136 not exhausted its set of links to visit. Otherwise, if 137 $object->drive() is called with an empty set of links to visit, 138 the corresponding operation will B<croak>. 139 140 =cut 141 142 package HoneyClient::Agent::Driver::Browser::FF; 143 36 144 use strict; 37 145 use warnings; 38 use Config;39 146 use Carp (); 40 147 … … 71 178 # Do not simply export all your public functions/methods/constants. 72 179 73 # This allows declaration use HoneyClient::Agent::Driver::Browser:: IE':all';180 # This allows declaration use HoneyClient::Agent::Driver::Browser::FF ':all'; 74 181 # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK 75 182 # will save memory. … … 84 191 @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); 85 192 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 92 193 $SIG{PIPE} = 'IGNORE'; # Do not exit on broken pipes. 93 194 } 94 195 our ( @EXPORT_OK, $VERSION ); 95 196 96 #TODO: Rewrite the test module97 98 197 =pod 99 198 100 199 =begin testing 101 200 201 # Make sure Log::Log4perl loads 202 BEGIN { 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 } 214 require_ok('Log::Log4perl'); 215 use Log::Log4perl qw(:easy); 216 217 # Make sure HoneyClient::Util::Config loads. 218 BEGIN { 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 } 231 require_ok('HoneyClient::Util::Config'); 232 can_ok('HoneyClient::Util::Config', 'getVar'); 233 use HoneyClient::Util::Config qw(getVar); 234 235 # Make sure the module loads properly, with the exportable 236 # functions shared. 237 BEGIN { 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."); } 238 require_ok('HoneyClient::Agent::Driver::Browser::FF'); 239 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'new'); 240 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'drive'); 241 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'isFinished'); 242 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'next'); 243 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'status'); 244 can_ok('HoneyClient::Agent::Driver::Browser::FF', 'getNextLink'); 245 use HoneyClient::Agent::Driver::Browser::FF; 246 247 # Suppress all logging messages, since we need clean output for unit testing. 248 Log::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. 257 BEGIN { 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."); } 258 require_ok('Win32::Job'); 259 use Win32::Job; 260 261 # Make sure ExtUtils::MakeMaker loads. 262 BEGIN { 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."); } 263 require_ok('ExtUtils::MakeMaker'); 264 can_ok('ExtUtils::MakeMaker', 'prompt'); 265 use ExtUtils::MakeMaker qw(prompt); 266 102 267 =end testing 103 268 … … 105 270 106 271 ####################################################################### 107 108 #TODO: Remove any of these use statements that aren't needed109 272 110 273 # Include the Global Configuration Processing Library 111 274 use HoneyClient::Util::Config qw(getVar); 112 275 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 134 277 use Win32::Job; 135 278 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 280 use Log::Log4perl qw(:easy); 281 282 # The global logging object. 283 our $LOG = get_logger(); 284 285 ####################################################################### 286 # Public Methods Implemented # 287 ####################################################################### 288 289 =pod 290 291 =head1 METHODS OVERRIDDEN 292 293 The following functions have been overridden by the FF driver. All other 294 methods were implemented by the generic Browser driver. For further 295 information about the Browser driver, see the L<HoneyClient::Agent::Driver::Browser> 296 documentation. 297 298 =head2 $object->drive(url => $url) 299 300 =over 4 301 302 Drives an instance of Mozilla Firefox for one iteration, 303 navigating either to the specified URL or to the next URL computed within 304 the Browser driver's internal hashtables. 305 306 For a description of which hashtable is consulted upon each iteration of 307 drive(), see the B<next_link_to_visit> description of the 308 L<HoneyClient::Agent::Driver::Browser> documentation, in the 309 "DEFAULT PARAMETER LIST" section. 310 311 Once a drive() iternation has completed, the corresponding browser process 312 is terminated. Thus, each call to drive() invokes a new instance of the 313 browser. 314 315 I<Inputs>: 316 B<$url> is an optional argument, specifying the next immediate URL the browser 317 must drive to. 318 319 I<Output>: The updated FF driver B<$object>, containing state information from driving the 320 browser for one iteration. 321 322 B<Warning>: This method will B<croak>, if the FF driver object is B<unable> 323 to navigate to a new link, because its list of links to vist is empty and no new 324 URL was supplied. 325 326 =back 327 328 =begin testing 329 330 # Generate a notice, to clarify our assumptions. 331 diag(""); 332 diag("About to run basic FF-specific browser tests."); 333 diag("Note: These tests *require* network connectivity and"); 334 diag("*expect* FF to be installed at the following location."); 335 diag(""); 336 337 my $processExec = getVar(name => "process_exec", 338 namespace => "HoneyClient::Agent::Driver::Browser::FF"); 339 my $processName = getVar(name => "process_name", 340 namespace => "HoneyClient::Agent::Driver::Browser::FF"); 341 342 diag("Process Name:\t\t'" . $processName . "'"); 343 diag("Process Location:\t'" . $processExec . "'"); 344 diag(""); 345 diag("If FF is installed in a different location or has a different executable name,"); 346 diag("then please answer *NO* to the next question and update your etc/honeyclient.xml"); 347 diag("file, changing the 'process_name' and 'process_exec' elements in the"); 348 diag("<HoneyClient/><Agent/><Driver/><Browser/><FF/> section."); 349 diag(""); 350 diag("Then, once updated, re-run these tests."); 351 diag("");
