Changeset 123

Show
Ignore:
Timestamp:
12/17/06 15:39:43 (4 years ago)
Author:
kindlund
Message:

Completed alpha version of bug fix. Still have to test it out on our test VM network.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • honeyclient/branches/bug/42/bin/StartAgent.pl

    r122 r123  
    3737    print "Watchdog fault detected, recovering Agent daemon.\n"; 
    3838    # XXX: Reenable this, eventually. 
    39 #    Carp::carp __PACKAGE__ . "->_watchdogFaultHandler(): Error occurred during processing.\n" . $errMsg; 
     39    #Carp::carp __PACKAGE__ . "->_watchdogFaultHandler(): Error occurred during processing.\n" . $errMsg; 
    4040 
    4141 
  • honeyclient/branches/bug/42/bin/TestRegistry.pl

    r122 r123  
    2929my $registry = HoneyClient::Agent::Integrity::Registry->new(); 
    3030 
     31print "\n"; 
    3132print "Baseline check complete.  Perform normal allowable actions\n" . 
    3233      "on the system (i.e., browse benign web pages).\n\n" . 
     
    5758    $Data::Dumper::Indent = 1; 
    5859    print $fh Dumper($changes); 
    59     print "\nDone!\n"; 
     60    print "\n"; 
     61    print "Done!\n"; 
    6062    print "Detailed registry changes were written to: " . $file . "\n"; 
    6163} 
  • honeyclient/branches/bug/42/etc/honeyclient.xml

    r119 r123  
    4949    <!-- Note: This timeout should be long enough so that the Agent watchdog code will properly let the integrity checking code finish, before detecting a faulty timeout in processing. --> 
    5050    <timeout description="Default timeout used for all communications between each module (in seconds)." default="900"> 
    51         900 
     51        1800 
    5252    </timeout> 
    5353    <log_config description="The global Log4perl configuration file, used throughout all modules.  This setting should not need to be changed." default="etc/honeyclient_log.conf"> 
     
    121121            <!-- Files which are read in only. --> 
    122122            <!-- TODO: Update this. --> 
    123             <file_checklist description="The file containing the list of files and directories to check during filesystem checking."
    124                 ../../../etc/file_checklist.txt 
     123            <file_checklist description="The file containing the list of files and directories to check during filesystem checking." default="none"
     124                etc/file_checklist.txt 
    125125            </file_checklist> 
    126126            <!-- TODO: Update this. --> 
    127             <file_exclude description="The file containing the list of files or directories to exclude if found in subdirectories during filesystem checking."
     127            <file_exclude description="The file containing the list of files or directories to exclude if found in subdirectories during filesystem checking." default="none"
    128128                ../../../etc/file_exclude.txt 
    129129            </file_exclude> 
    130             <!-- TODO: Update this. --> 
    131             <reg_exclude_file description="The file containing the list of regular expressions specifying registry keys to exclude during registry checking."> 
    132                 ../../../etc/reg_exclude.txt 
    133             </reg_exclude_file> 
    134             <!-- TODO: Update this. --> 
    135             <reg_list_to_check description="The file containing the list of registry keys to check."> 
    136                 ../../../etc/reg_list_to_check.txt 
    137             </reg_list_to_check> 
    138130            <!-- Files which are written out only. --> 
    139131            <!-- TODO: Update this. --> 
     
    146138            </change_file> 
    147139            <!-- Files to read and write. --> 
    148             <!-- TODO: Update this. --> 
    149             <clean_reg description="Stores baseline for the registry.  Always appended with a number."> 
    150                 clean.reg 
    151             </clean_reg> 
    152             <!-- TODO: Update this. --> 
    153             <current_reg description="Stores the current state of the register to check against the clean state."> 
    154                 current.reg 
    155             </current_reg> 
    156             <!-- TODO: Update this. --> 
    157             <diffs description="The file for the diff command to redirect its output to.  Always appended with a number."> 
    158                 differences.out 
    159             </diffs> 
    160140            <!-- TODO: Update this. --> 
    161141            <test_dir description="If you're testing integrity checks, this is the directory that you can specify to minimize testing time. Only the files in this directory will be part of the integrity check."> 
  • honeyclient/branches/bug/42/lib/HoneyClient/Agent.pm

    r96 r123  
    210210# TODO: Update unit tests to include 'dclone' 
    211211use Storable qw(nfreeze thaw dclone); 
     212$Storable::Deparse = 1; 
     213$Storable::Eval = 1; 
    212214 
    213215# Include Base64 Libraries 
     
    366368 
    367369    # Perform initial integrity baseline check. 
    368     my $integrity = undef; 
    369     if ($PERFORM_INTEGRITY_CHECKS) { 
    370         print "Initializing Integrity Check...\n"; 
    371         # TODO: Initialize Integrity Checks 
    372         $integrity = HoneyClient::Agent::Integrity->new(); 
    373         $integrity->initAll(); 
    374    
    375     $integrityState = nfreeze($integrity); 
     370    #my $integrity = undef; 
     371    #if ($PERFORM_INTEGRITY_CHECKS) { 
     372    #    print "Initializing Integrity Check...\n"; 
     373    #    # TODO: Initialize Integrity Checks 
     374    #    $integrity = HoneyClient::Agent::Integrity->new(); 
     375    #    $integrity->initAll(); 
     376    #
     377    #$integrityState = $integrity->serialize(); 
    376378 
    377379    # Release data lock. 
     
    721723                    # As such, do NOT try to call integrity checks on multiple, simultaneous 
    722724                    # asynchronous threaded drivers. 
    723                     $integrity = thaw($integrityState); 
     725                    #$integrity = thaw($integrityState); 
     726                    # Perform initial integrity baseline check. 
     727                    print "Initializing Integrity Check...\n"; 
     728                    # TODO: Initialize Integrity Checks 
     729                    $integrity = HoneyClient::Agent::Integrity->new(); 
     730                    $integrity->initAll(); 
     731 
     732                    # TODO: Delete this. 
     733                    #$Data::Dumper::Indent = 1; 
     734                    #$Data::Dumper::Terse = 1; 
     735                    #print "Integrity: " . Dumper($integrity) . "\n"; 
    724736                } 
    725737 
  • honeyclient/branches/bug/42/lib/HoneyClient/Agent/Integrity.pm

    r96 r123  
    104104can_ok('HoneyClient::Agent::Integrity', 'initFileSystem'); 
    105105can_ok('HoneyClient::Agent::Integrity', 'checkFileSystem'); 
    106 can_ok('HoneyClient::Agent::Integrity', 'initRegistry'); 
    107 can_ok('HoneyClient::Agent::Integrity', 'checkRegistry'); 
    108 use HoneyClient::Agent::Integrity qw(initAll checkAll initRegistry checkRegistry initFileSystem checkFileSystem); 
     106use HoneyClient::Agent::Integrity qw(initAll checkAll initFileSystem checkFileSystem); 
    109107 
    110108# Make sure HoneyClient::Util::Config loads. 
     
    133131 
    134132# Make sure Storable loads. 
    135 BEGIN { use_ok('Storable', qw(dclone)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
     133BEGIN { use_ok('Storable', qw(dclone nfreeze thaw)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
    136134require_ok('Storable'); 
    137135can_ok('Storable', 'dclone'); 
    138 use Storable qw(dclone); 
     136can_ok('Storable', 'nfreeze'); 
     137can_ok('Storable', 'thaw'); 
     138use Storable qw(dclone nfreeze thaw); 
    139139 
    140140###Testing Globals### 
     
    158158# Include Global Configuration Processing Library 
    159159use HoneyClient::Util::Config qw(getVar); 
     160use HoneyClient::Agent::Integrity::Registry; 
    160161use File::Find qw(find); 
    161162#use Win32::TieRegistry; 
    162163use Digest::MD5; 
    163164use MIME::Base64; 
    164 use Switch; 
    165 use Storable qw(dclone); 
     165use Storable qw(nfreeze thaw dclone); 
     166$Storable::Deparse = 1; 
     167$Storable::Eval = 1; 
    166168use Data::Dumper; 
    167169use File::Basename qw(dirname); 
     
    178180 
    179181    # Symbols to export on request 
    180     @EXPORT = qw(new initAll checkAll initRegistry checkRegistry initFileSystem checkFileSystem); 
     182    @EXPORT = qw(new initAll checkAll); 
    181183 
    182184    # Items to export into callers namespace by default. Note: do not export 
     
    208210#Used *for now* to signal whether any changes occured (if they == 1) 
    209211my $g_fs_changes = 0; 
    210 my $g_reg_changes = 0; 
    211  
    212 #Used to initialize a default registry space to check if they don't specify anything when creating the object 
    213 my @default_reg_check_array = ("HKEY_LOCAL_MACHINE", "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_USERS", "HKEY_CURRENT_CONFIG"); 
    214  
    215 #I have no idea why slashes need to be triple-slashes since it's single quoted, but that's what works... 
    216 #also, of course [ and ] and any other special characters you find need to be escaped 
    217 my @default_reg_exclude_array = ( 
    218     '\[HKEY_LOCAL_MACHINE\\\SOFTWARE\\\Microsoft\\\Cryptography\\\RNG\]',  
    219     '\[HKEY_CURRENT_USER\\\SessionInformation\]', 
    220     '\[HKEY_USERS\\\.+\\\SessionInformation\]',  
    221     '\[HKEY_LOCAL_MACHINE\\\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\WindowsUpdate\\\Auto Update\]',  
    222     '\[HKEY_USERS\\\.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\UserAssist\\\.*\\\Count\]',  
    223     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\CurrentControlSet\\\Services\\\.+\\\Parameters\\\Tcpip\]', 
    224     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\CurrentControlSet\\\Services\\\Tcpip\\\Parameters\\\Interfaces\\\.+\]', 
    225     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\CurrentControlSet\\\Services\\\Dhcp\\\Parameters\]', 
    226     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\ControlSet.+\\\Services\\\.+\\\Parameters\\\Tcpip\]', 
    227     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\ControlSet.+\\\Services\\\Tcpip\\\Parameters\\\Interfaces\\\.+\]', 
    228     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\ControlSet.+\\\Services\\\Dhcp\\\Parameters\]', 
    229     '\[HKEY_LOCAL_MACHINE\\\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\BITS]', 
    230     '\[HKEY_USERS\\\.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\UserAssist\\\.+\\\Count\]', 
    231     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\UserAssist\\\.+\\\Count\]', 
    232     '\[HKEY_LOCAL_MACHINE\\\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\Group Policy\\\State\\\Machine\\\Extension-List\\\.+\]', 
    233     '\[HKEY_LOCAL_MACHINE\\\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\Group Policy\\\State\\\.+\\\Extension-List\\\.+\]', 
    234     '\[HKEY_USERS\\\.+\\\Software\\\Microsoft\\\Windows\\\ShellNoRoam\\\BagMRU\]', 
    235     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\ShellNoRoam\\\BagMRU\]', 
    236     '\[HKEY_CURRENT_USER\\\Volatile Environment\]', 
    237     '\[HKEY_USERS\\\.+\\\UNICODE Program Groups\]', 
    238     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\ControlSet.+\\\Services\\\SharedAccess\\\Epoch\]', 
    239     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\CurrentControlSet\\\Services\\\SharedAccess\\\Epoch\]', 
    240     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\CurrentControlSet\\\Services\\\Eventlog\\\Application\\\ESENT\]', 
    241     '\[HKEY_LOCAL_MACHINE\\\SYSTEM\\\ControlSet001\\\Services\\\Eventlog\\\Application\\\ESENT\]', 
    242     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Internet Settings\\\Connections\]', 
    243     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Ext\\\Stats\\\.*\\\iexplore\]', 
    244     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MenuOrder\\\Favorites\\\Links\]', 
    245     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Internet Settings\\\Connections\]', 
    246     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Ext\\\Stats\\\.*\\\iexplore\]', 
    247     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MenuOrder\\\Favorites\\\Links\]', 
    248     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MenuOrder\\\Favorites\\\Links\]', 
    249     '\[HKEY_LOCAL_MACHINE\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\WindowsUpdate\\\.*\]', 
    250     '\[HKEY_LOCAL_MACHINE\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\WindowsUpdate\\\Reporting\\\.*\]', 
    251     '\[HKEY_LOCAL_MACHINE\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\WindowsUpdate\\\Reporting\\\EventCache\\\.*\]', 
    252     '\[HKEY_LOCAL_MACHINE\SOFTWARE\\\Microsoft\\\Windows\\\CurrentVersion\\\WindowsUpdate\\\Reporting\\\EventCache\\\.+\]', 
    253     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MountPoints2\\\CPC\\\Volume\]', 
    254     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MountPoints2\\\CPC\\\Volume\\\.*\]', 
    255     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MountPoints2\\\CPC\\\Volume\]', 
    256     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MountPoints2\\\CPC\\\Volume\\\.*\]', 
    257     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\ShellNoRoam\\\MUICache\]', 
    258     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Internet Settings\\\5.0\\\Cache\]', 
    259     '\[HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Internet Settings\\\5.0\\\Cache\\\.*\]', 
    260     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\ShellNoRoam\\\MUICache\]', 
    261     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Internet Settings\\\5.0\\\Cache\]', 
    262     '\[HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Internet Settings\\\5.0\\\Cache\\\.*\]', 
    263 ); 
    264212 
    265213# XXX: All dirs must NEVER end in a trailing slash. 
     
    290238    '/cygdrive/c/Program Files/Mozilla Firefox/updates.xml', 
    291239    '/cygdrive/c/WINDOWS/SoftwareDistribution/WuRedir', 
     240    '/cygdrive/c/WINDOWS/SYSTEM32/config/SecEvent.Evt', 
     241    '/cygdrive/c/WINDOWS/SYSTEM32/config/SysEvent.Evt', 
     242    '/cygdrive/c/WINDOWS/SYSTEM32/wbem/Repository/FS/INDEX.BTR', 
     243    '/cygdrive/c/WINDOWS/SYSTEM32/wbem/Repository/FS/INDEX.MAP', 
     244    '/cygdrive/c/WINDOWS/SYSTEM32/wbem/Repository/FS/MAPPING.VER', 
     245    '/cygdrive/c/WINDOWS/SYSTEM32/wbem/Repository/FS/MAPPING2.MAP', 
     246    '/cygdrive/c/WINDOWS/SYSTEM32/wbem/Repository/FS/OBJECTS.DATA', 
     247    '/cygdrive/c/WINDOWS/SYSTEM32/wbem/Repository/FS/OBJECTS.MAP', 
    292248); 
    293249 
     
    295251my %PARAMS = ( 
    296252 
    297     ### Files which are read in only ### 
    298     # List of files and directories to check during filesystem checking 
    299     file_checklist => getVar(name => "file_checklist", namespace => "HoneyClient::Agent::Integrity"), 
     253    # Contains the Registry object, once initialized. 
     254    _registry => undef, 
     255 
     256    # XXX: Clean the rest of these variables up. 
     257    ### Files which are read in only ### 
     258    # List of files and directories to check during filesystem checking 
     259    file_checklist => getVar(name => "file_checklist", namespace => "HoneyClient::Agent::Integrity"), 
    300260     
    301261    # List of files or directories to exclude if found in subdirs during 
    302262    # filesystem check. 
    303     file_exclude => getVar(name => "file_exclude", namespace => "HoneyClient::Agent::Integrity"), 
    304      
    305     # List of registry keys to check 
    306     reg_list_to_check   => getVar(name => "reg_list_to_check", namespace => "HoneyClient::Agent::Integrity"), 
    307  
    308     # List of registry keys to exclude 
    309     reg_exclude_file => getVar(name => "reg_exclude_file", namespace => "HoneyClient::Agent::Integrity"), 
     263    file_exclude => getVar(name => "file_exclude", namespace => "HoneyClient::Agent::Integrity"), 
    310264     
    311265    ### Files to write and read ### 
    312266    # File to store hashes for files selected during the baseline 
    313    clean_file => getVar(name => "clean_file", namespace => "HoneyClient::Agent::Integrity"), 
     267    clean_file => getVar(name => "clean_file", namespace => "HoneyClient::Agent::Integrity"), 
    314268     
    315269    # File to write any found changes to 
    316    change_file => getVar(name => "change_file", namespace => "HoneyClient::Agent::Integrity"), 
     270    change_file => getVar(name => "change_file", namespace => "HoneyClient::Agent::Integrity"), 
    317271     
    318     # Stores baseline for the registry. Always appended with a number 
    319     clean_reg => getVar(name => "clean_reg", namespace => "HoneyClient::Agent::Integrity"), 
     272    #vars 
     273    file_exclude_hash => undef, #hash, holds files to exclude 
     274    file_list => undef, #list, files to check when checking filesystem 
    320275     
    321     # Stores the current state of the registry to check against the 
    322     # clean state 
    323     current_reg => getVar(name => "current_reg", namespace => "HoneyClient::Agent::Integrity"), 
    324      
    325     # The file for the diff command to redirect it's output to. 
    326     # Always appended with a number. 
    327     diffs => getVar(name => "diffs", namespace => "HoneyClient::Agent::Integrity"), 
    328  
    329     #vars 
    330     file_exclude_hash => undef, #hash, holds files to exclude 
    331     file_list => undef, #list, files to check when checking filesystem 
    332     reg1 => undef,      #list,  holds entire contents of first file to diff 
    333     reg2 => undef,      #list, holds entire contents of second file to diff 
    334      
    335     #array that holds the locations in the registry to check 
    336     reg_check_array => undef, 
    337     #array that holds the registry locations that should be excluded from the detected changes 
    338     reg_exclude_array => undef,  
    339  
    340276    #works exactly like the reg_exclude_array, and is initialized in a similar way 
    341     file_exclude_array => undef, 
    342  
    343     changes => undef,   #multi-dimensional array used for holding individual instances of a diff output 
    344     g_count => -1,  #highest level index for, each $g_count will be a different instance of a diff grouping 
     277    file_exclude_array => undef, 
     278 
     279    changes => undef,   #multi-dimensional array used for holding individual instances of a diff output 
    345280); 
    346281 
     
    409344 
    410345sub initAll { 
    411 my $self = shift; 
     346    my $self = shift; 
    412347    # XXX: initRegistry() MUST be called before initFileSystem, since initRegistry 
    413348    # creates new files that must exist to be added to the exclusion list for 
    414349    # initFileSystem. 
    415     $self->initRegistry(); 
     350    $self->{'_registry'} = HoneyClient::Agent::Integrity::Registry->new(); 
    416351    $self->initFileSystem(); 
    417352} 
     
    428363 
    429364sub checkAll { 
    430 my $self = shift; 
    431 my $retval; 
    432  
    433     #Add any new created checks here 
    434   
    435     $self->startCheckProcesses();   #currently a dummy method that just returns 
     365    my $self = shift; 
     366    my $retval; 
     367 
    436368    # If at all possible we want the (faster) registry checks to short circut 
    437369    # the overall checks so we don't have to do the very slow filesystem checks. 
    438     $retval = $self->checkRegistry(); 
    439 # TODO: Re-enable this block. 
    440 #   if($retval){ 
    441 #       return $retval; 
    442 #   } 
    443     $retval = $self->checkFileSystem(); 
     370    my $changes = $self->{'_registry'}->check(); 
     371    if (scalar(@{$changes})) { 
     372        print "Registry has changed:\n"; 
     373        foreach my $change (@{$changes}) { 
     374            print $change->{'key'} . " (" . $change->{'status'} . ")\n"; 
     375        } 
     376        open CHANGES, ">>$self->{change_file}" or die "Cannot open $self->{change_file}: $!\n";      
     377        $Data::Dumper::Terse = 1; 
     378        $Data::Dumper::Indent = 1; 
     379        print CHANGES Dumper($changes); 
     380        close CHANGES; 
     381        return $changes; 
     382    } 
     383    print "No registry changes have occurred.\n"; 
     384    $retval = $self->checkFileSystem(); 
    444385 
    445386    return $retval; 
    446  
    447  
    448 
     387
     388 
     389# TODO: Comment this. 
     390sub serialize { 
     391    my $self = shift; 
     392 
     393    if (defined($self->{'_registry'})) { 
     394        $self->{'_registry'}->closeFiles(); 
     395    } 
     396 
     397    return nfreeze($self); 
     398
     399 
    449400################################################################################ 
    450401 
     
    513464    $g_hack = $self->{file_list}; 
    514465    $g_ex_hash = (); 
     466    my $file; 
    515467     
    516468    my @checkdirs = $self->_get_directories_to_check(); 
     
    528480    } 
    529481 
    530     foreach my $file (@{$self->{file_exclude_array}}){ 
     482    $/ = "\n"; 
     483    foreach $file (@{$self->{file_exclude_array}}){ 
    531484        chomp $file; 
    532485        if(-f $file){ 
     
    547500 
    548501    print "Finding Files in initFileSystem...Be Patient.\n"; 
    549     foreach my $checkdir(@checkdirs) { 
     502    foreach my $checkdir (@checkdirs) { 
    550503        find (\&_found, "$checkdir");   #this will populate @{$self->{file_list}} 
    551504    } 
     
    553506    $self->{file_list} = $g_hack; 
    554507    $self->{file_exclude_hash} = $g_ex_hash; 
    555 ###   print "file_exclude_hash in init\n" . Dumper($self->{file_exclude_hash}) . "\n"; 
     508##    print "file_exclude_hash in init\n" . Dumper($self->{file_exclude_hash}) . "\n"; 
    556509 
    557510    print "Hashing Files in initFileSystem...Be Patient\n"; 
    558511    open CLEANFILE, ">$self->{clean_file}" or die "Cannot open $self->{clean_file}: $!\n"; 
    559     foreach my $file (@{$self->{file_list}}) { 
     512    foreach $file (@{$self->{file_list}}) { 
    560513#       print "hashing $file\n"; 
    561514        if(open HASHFILE, "$file") { 
     
    638591sub checkFileSystem { 
    639592 
    640 my $self = shift;   #Object 
    641 %{$self->{clean_file_hash}} = (); 
    642 %{$self->{changed_file_hash}} = (); 
    643 my %current_file_hash = (); 
    644 my %new_file_hash = (); 
    645 my %del_file_hash = (); 
    646 my @checkdirs; 
    647 my $standalone_test = 0; 
     593    my $self = shift;   #Object 
     594    %{$self->{clean_file_hash}} = (); 
     595    %{$self->{changed_file_hash}} = (); 
     596    my %current_file_hash = (); 
     597    my %new_file_hash = (); 
     598    my %del_file_hash = (); 
     599    my @checkdirs; 
     600    my $standalone_test = 0; 
     601    my $file; 
     602    my $key; 
    648603 
    649604### print "file_exclude_hash in check\n" . Dumper($self->{file_exclude_hash}) . "\n"; 
     
    655610    #open file to create hash of values for clean files 
    656611    open CLEANFILE, "$self->{clean_file}" or die "Cannot open $self->{clean_file}: $!\n"; 
     612    $/ = "\n"; 
    657613    while(<CLEANFILE>) { 
    658614        my $line = $_; 
     
    691647        } 
    692648     
    693         foreach my $file (@{$self->{file_exclude_array}}){ 
     649        $/ = "\n"; 
     650        foreach $file (@{$self->{file_exclude_array}}){ 
    694651            chomp $file; 
    695652            if(-f $file){ 
     
    721678    #also detects new files 
    722679    print "Hashing Files in checkFileSystem...Be Patient\n"; 
    723     foreach my $file (@{$self->{file_list}}) { 
    724       if(open HASHFILE, "$file") { 
     680    foreach $file (@{$self->{file_list}}) { 
     681      if(open HASHFILE, "$file") { 
    725682            my $md5ctx = Digest::MD5->new(); 
    726683            # If this call fails, an exception will be generated. 
     
    739696 
    740697    #check for deleted files 
    741     foreach my $key (keys %{$self->{clean_file_hash}}) { 
     698    foreach $key (keys %{$self->{clean_file_hash}}) { 
    742699        if(!($current_file_hash{$key})) { 
    743700            $del_file_hash{$key} = $self->{clean_file_hash}->{$key}; 
     
    751708 
    752709        print CHANGES "Files deleted:\n"; 
    753         foreach my $key (sort keys %del_file_hash) { 
     710        foreach $key (sort keys %del_file_hash) { 
    754711            print CHANGES "$key\n"; 
    755712        } 
    756713        print CHANGES "\n\n"; 
    757714        print CHANGES "Files added:\n"; 
    758         foreach my $key (sort keys %new_file_hash) { 
     715        foreach $key (sort keys %new_file_hash) { 
    759716            print CHANGES "$key\n"; 
    760717        } 
    761718        print CHANGES "\n\n"; 
    762719        print CHANGES "Files modified:\n"; 
    763         foreach my $key (sort keys %{$self->{changed_file_hash}}) { 
     720        foreach $key (sort keys %{$self->{changed_file_hash}}) { 
    764721            print CHANGES "$key\n"; 
    765722        } 
     
    784741 
    785742    #Sets the VERY hardcoded default for now (late addition for ease of use, not clean code) 
    786    push @checkdirs, "/cygdrive/c/"; 
     743    push @checkdirs, "/cygdrive/c/"; 
    787744 
    788745    #Can override the default by creating this file (for now, eventually put directly into XML) 
     
    793750         "Please see the POD documentation for more information.\n"; 
    794751        @checkdirs = (); 
     752        $/ = "\n"; 
    795753        while(<CHECK>) { 
    796754            chomp; 
     
    814772         
    815773    my $foundfile = $File::Find::name; 
     774     
    816775    if (-f $foundfile) { 
    817776        if (exists($g_ex_hash->{$foundfile})) { 
     
    845804sub _recursive_exclude{ 
    846805     
    847    my $foundfile = $File::Find::name; 
     806   my $foundfile = $File::Find::name; 
    848807    if (-f $foundfile) { 
    849808        $g_ex_hash->{$foundfile} = 1; 
    850 #       print "\t _recursive_exclude()d $foundfile\n"; 
    851     } 
    852 
    853 ################################################################################ 
    854  
    855 =pod 
    856  
    857 =head1 
    858  
    859 initRegistry() : Takes no input. Optionally reads in a one-per-line list of  
    860 registry keys to check, as stored in $self->reg_list_to_check. If such a list is not 
    861 present, uses the values hardcoded in the @{$self->{reg_check_array}}. Uses a system() call to 
    862 have regedit export the keys and sub-keys beginning at the specified location.  
    863 Individual files are postfixed with their array index for uniqueness. Therefore 
    864 creates a number of files such as clean.reg0, clean.reg1, etc.  
    865  
    866 =begin testing 
    867  
    868  
    869 #Testing initRegistry() 
    870 my $ob = HoneyClient::Agent::Integrity->new(); 
    871  
    872 system("regedit.exe /s noTEST.reg"); 
    873 system("regedit.exe /s /c $test_dir/t1a.reg"); 
    874 $ob->initRegistry("HKEY_LOCAL_MACHINE\\HARDWARE\\TEST"); 
    875 open (DIFF, "diff $test_dir/t1a.reg clean.reg0 |") or die "Can't check the changes files\n"; 
    876 @result = <DIFF>; 
    877 close DIFF; 
    878 #Bad test because it will be empty in the case of an error anyway? 
    879 is(scalar(@result), 0, 'initRegistry: General Test'); 
    880  
    881 =end testing 
    882  
    883 =cut 
    884  
    885 sub initRegistry { 
    886 my $self = shift; 
    887  
    888     #If we're given function input, use it. 
    889     if(scalar(@_) > 0){ 
    890         print "given input for reg_check_array in the parameters\n"; 
    891         @{$self->{reg_check_array}} = @_; 
    892     } 
    893     else { 
    894         #otherwise, if we're given input via file, use it 
    895         if(-f "$self->{reg_list_to_check}"){ 
    896             open REGDIRS, "$self->{reg_list_to_check}" or die "Cannot open $self->{reg_list_to_check}: $!\n"; 
    897             #wipe out any hardcoded ones 
    898             @{$self->{reg_check_array}} = (); 
    899             while(<REGDIRS>){ 
    900                 push @{$self->{reg_check_array}}, $_; 
    901             } 
    902         } 
    903         #otherwise, it will use the default array. 
    904         else{ 
    905             $self->{reg_check_array} = \@default_reg_check_array; 
    906         } 
    907     } 
    908     my $tmp = $self->{clean_reg}; 
    909     print "clean_reg in initRegistry $tmp\n"; 
    910     print "reg_check_array in initRegistry @{$self->{reg_check_array}}\n"; 
    911     my $var = 0; 
    912     foreach my $key_to_check (@{$self->{reg_check_array}}){ 
    913         print "exporting $key_to_check to $self->{clean_reg}$var\n"; 
    914         print "regedit /a \"$self->{clean_reg}$var\" \"$key_to_check\" \n"; 
    915         system("regedit.exe /a \"$self->{clean_reg}$var\" \"$key_to_check\""); 
    916         # XXX: We touch the current and differences files first, even though they are empty. 
    917         # This is to make sure that these files get properly excluded during filesystem initialization, 
    918         # since they would not have existed otherwise, until after a registry check occurs. 
    919         system("touch \"$self->{current_reg}$var\""); 
    920         system("touch \"$self->{diffs}$var\""); 
    921         $var++; 
    922     } 
    923  
    924         if(-f $self->{reg_exclude_file}){ 
    925         open REGEXCLUDE, "$self->{reg_exclude_file}" or die "Cannot open $self->{reg_exclude_file}: $!\n"; 
    926         #wipe out any hardcoded ones 
    927         @{$self->{reg_exclude_file}} = (); 
    928         while(<REGEXCLUDE>){ 
    929             push @{$self->{reg_exclude_array}}, $_; 
    930         } 
    931     } 
    932     else{ 
    933         $self->{reg_exclude_array} = \@default_reg_exclude_array; 
    934     } 
    935 
    936 ################################################################################ 
    937  
    938 =pod 
    939  
    940 =head1 
    941  
    942 checkRegistry() : Takes no input. Responsible for dumping the current state of 
    943 each of the registry locations in @{$self->{reg_check_array}} and comparing it against that 
    944 which was exported to the filesystem in initRegistry() by using the command line 
    945 utility diff. If differences are detected it parses the diff file and consults 
    946 the original and new file as necessary to determine exactly what changed. 
    947  
    948 =begin testing 
    949  
    950  
    951 my $ob = HoneyClient::Agent::Integrity->new(); 
    952  
    953 reg_test($ob, 1, "checkRegistry: case 1 Multi-line addition changes."); 
    954 reg_test($ob, 2, "checkRegistry: case 2 Single-line addition changes."); 
    955 reg_test($ob, 3, "checkRegistry: case 3 Multi-line deletion changes."); 
    956 reg_test($ob, 4, "checkRegistry: case 4 Single-line deletion changes."); 
    957 reg_test($ob, 5, "checkRegistry: case 5 Simple multi-line to multi-line changes."); 
    958 is(6, 6, "checkRegistry: case 6 - SKIPPING (currently can't recreate conditions for test)"); 
    959 #reg_test($ob, 6, "checkRegistry: case 6 Complicated multi-line to multi-line changes."); 
    960 reg_test($ob, 7, "checkRegistry: case 7 Simple multi-line to single-line changes."); 
    961 reg_test($ob, 8, "checkRegistry: case 8 Complicated multi-line to single-line changes."); 
    962 reg_test($ob, 9, "checkRegistry: case 9 Simple single-line to multi-line changes."); 
    963 reg_test($ob, 10, "checkRegistry: case 10 Complicated single-line to multi-line changes."); 
    964 reg_test($ob, 11, "checkRegistry: case 11 Simple single-line to single-line changes."); 
    965 reg_test($ob, 12, "checkRegistry: case12 Complicated single-line to single-line changes."); 
    966  
    967 sub reg_test{ 
    968 my $ob = shift; 
    969 my $num = shift; 
    970 my $string = shift; 
    971  
    972     #for safety 
    973     if(-e "temp_reg_export.reg"){ 
    974         system("mv temp_reg_export.reg temp_reg_export.reg.CBL"); 
    975     } 
    976     system('regedit.exe /a temp_reg_export.reg "HKEY_LOCAL_MACHINE\HARDWARE\TEST"'); 
    977  
    978     system("regedit.exe /s noTEST.reg"); 
    979     system("regedit.exe /s /c $test_dir/t" . "$num" . "a.reg"); 
    980     $ob->initRegistry("HKEY_LOCAL_MACHINE\\HARDWARE"); 
    981     system("regedit.exe /s noTEST.reg"); 
    982     system("regedit.exe /s /c $test_dir/t" . "$num" . "b.reg"); 
    983     $ob->checkRegistry("HKEY_LOCAL_MACHINE\\HARDWARE"); 
    984     open (DIFF, "diff $test_dir/t" . "$num" . "changes.txt changes.txt |") or die "Can't check the changes files\n"; 
    985     @result = <DIFF>; 
    986     close DIFF; 
    987     #Bad test because it will be empty in the case of an error anyway? 
    988     is(scalar(@result), 0, "$string"); 
    989  
    990     #for safety/cleanup 
    991     if(-e "temp_reg_export.reg"){ 
    992         system("regedit.exe /s noTEST.reg"); 
    993         system("regedit.exe /s /c temp_reg_export.reg"); 
    994         system("rm temp_reg_export.reg"); 
    995         if(-e "temp_reg_export.reg.CBL"){ 
    996             system("mv temp_reg_export.reg.CBL temp_reg_export.reg"); 
    997         } 
    998     } 
    999      
    1000 
    1001  
    1002 =end testing 
    1003  
    1004 =cut 
    1005  
    1006 sub checkRegistry { 
    1007 my $self = shift; 
    1008  
    1009         #************************* 
    1010         #XXXY: delete me eventually 
    1011         #if(-f "$self->{change_file}") {system("rm $self->{change_file}");} 
    1012         #************************* 
    1013  
    1014  
    1015 #$var is used to create different files for different registry exports 
    1016 my $var = 0; 
    1017 #This foreach is what allows it to check multiple keys in the registry 
    1018 foreach my $key_to_check (@{$self->{reg_check_array}}){  
    1019  
    1020     #First we want @reg1 to hold the clean registry state 
    1021     print "reading in existing state for $key_to_check\n"; 
    1022     open REG, "$self->{clean_reg}$var"  or die "Cannot open $self->{clean_reg}$var: $!\n"; 
    1023     @{$self->{reg1}} = <REG>; 
    1024     close REG; 
    1025  
    1026     #Then we want @reg2 to hold the current registry state 
    1027     print "getting current state for $key_to_check\n"; 
    1028     system("regedit /a \"$self->{current_reg}$var\" \"$key_to_check\""); #More useful for debugging 
    1029     open REG2, "$self->{current_reg}$var" or die "Cannot open $self->{current_reg}$var: $!\n"; 
    1030 #   open REG2, "regedit /a \"$self->{current_reg}$var\" \"$key_to_check\" |"  or die "Problem with combo speed hack: $!\n"; #future speed hack 
    1031     @{$self->{reg2}} = <REG2>; 
    1032     close REG2; 
    1033  
    1034  
    1035  
    1036     print "diffing\n"; 
    1037     #Code to split the entries into chunks in a multi-dimensional array 
    1038     #This list is what everything else uses to differentiate different diffs ;) 
    1039     system("diff -a $self->{clean_reg}$var $self->{current_reg}$var > $self->{diffs}$var"); #More useful for debugging 
    1040     open DIFZ, "$self->{diffs}$var" or die "Cannot open $self->{diffs}$var: $!\n"; 
    1041 #   open DIFZ, "diff -a $self->{clean_reg}$var $self->{current_reg}$var |" or die "Problem with combo speed hack: $!\n"; #future speed hack 
    1042     my $inner_count=0; #inner index for the multi-dimensional array for holding diff entries 
    1043     @{$self->{changes}} = (); 
    1044     while(<DIFZ>){ 
    1045         #get rid of the nulls embedded by the export 
    1046         #NOTE: This will need to change when dealing with the  
    1047         # inaccessible special NULL registry key name case 
    1048         $_ =~ s/\0//g; 
    1049 #       print $_; 
    1050         #if the line starts with numbers then it's a new diff entry 
    1051         if($_ =~ /^[0-9]/){ 
    1052             $inner_count = 0; 
    1053             $self->{g_count}++; 
    1054             $self->{changes}->[$self->{g_count}][$inner_count] = $_; 
    1055         } 
    1056         else{ 
    1057             #otherwise it's just an entry in our current diff 
    1058             $inner_count++; 
    1059             $self->{changes}->[$self->{g_count}][$inner_count] = $_; 
    1060         } 
    1061     } 
    1062     close DIFZ; 
    1063     #Print the total number of individual diffs which will need to be parsed 
    1064     #NOTE: because "change" entries can include multiple events, this is an  
    1065     # underestimate of how many actual changes there will be 
    1066     #ALSO NOTE: The prefix ++ on the count. That's just an array index vs number 
    1067     # of elements off by one thing to make it print right. 
    1068     print ++$self->{g_count} . " diff blocks put into the changes list for parsing\n"; 
    1069     $self->{g_count}--; 
    1070  
    1071     #This while loop steps through each of the individual diffs in the multi-dimensional 
    1072     # list, parsing one at a time. 
    1073     while($self->{g_count} >= 0){ 
    1074         my $holder = $self->{changes}->[$self->{g_count}][0]; 
    1075     #   print $holder; 
    1076         my $first_start = 0; 
    1077         my $first_end = 0; 
    1078         my $second_start = 0; 
    1079         my $second_end = 0; 
    1080      
    1081         #XXX: NESTED SWITCHES CAUSE STRANGE PROBLEMS. Try to use the least nested switches as possible 
    1082         #$holder is always the first line of a diff, which is the line that contains the 
    1083         # line numbers for where in the two files the adds/deletes/changes are being made. 
    1084         #First it splits them into cases and subcases based on whether it's a an add, delete, or the 
    1085         # much more complicated change. 
    1086         switch($holder){ 
    1087             case /a/ { 
    1088      
    1089                 ############################################ 
    1090                 #Case of multi-line addition. 
    1091                 ############################################ 
    1092                  
    1093                 #TEST 1 
    1094                 if($holder =~ /([0-9]+)a([0-9]+),([0-9]+)/) { 
    1095                     $first_start = $1; 
    1096                     $second_start = $2; 
    1097                     $second_end = $3; 
    1098                     my $quick_count = $3-$2+1; 
    1099                     #We need an extra \ in the 2nd regex when used in a string 
    1100                     #The regexes tell it to only look at lines that start with 
    1101                     # the > because those are the lines represending added stuff 
    1102                     #Use parser because a multi-line addition can inlcude the addition 
    1103                     # of keys, not just name/data pairs. 
    1104                     _parser($self, "a", "(^> )(.*)", "^> \\[", $quick_count, $first_start, 1, undef); 
    1105                 } 
    1106                 else{ ############################################ 
    1107                     #Case of single name/data pair addition 
    1108                     ############################################ 
    1109                                  
    1110                     #TEST 2 
    1111                     if($holder =~ /([0-9]+)a([0-9]+)/) { 
    1112                         #In this case, there can not be any new keys because that would take 
    1113                         # at least 2 lines because diff inlcudes the blank line. But that does 
    1114                         # mean we have to go to the original file to find the name of the  
    1115                         # existing key. 
    1116                         _moonwalk_and_print($self, $first_start, "(^> )(.*)", "New values for existing key\n", 2, ($self->{changes}->[$self->{g_count}][1])); 
    1117                     } 
    1118                     else {print "WARNING: some strange case in add\n";} 
    1119                  
    1120                 }    
    1121             } 
    1122      
    1123                      
    1124             case /d/ { 
    1125                 ############################################ 
    1126                 #Case of multi-line deletion. 
    1127                 ############################################ 
    1128                              
    1129                 #TEST 3 
    1130                 if($holder =~ /([0-9]+),([0-9]+)d([0-9]+)/) { 
    1131                     $first_start = $1; 
    1132                     $first_end = $2; 
    1133                     $second_start = $3; 
    1134                     my $quick_count = $2-$1+1; 
    1135                     #need an extra \ in the 2nd regex when used in a string 
    1136                     #The regexes tell it to only look at lines that start with 
    1137                     # the < because those are the lines represending deleted stuff 
    1138                     #Use parser because a multi-line addition can inlcude the deletion 
    1139                     # of keys, not just name/data pairs. 
    1140                     _parser($self, "d", "(^< )(.*)", "^< \\[", $quick_count, $first_start, 1, undef); 
    1141      
    1142                 } 
    1143                 else {  ############################################ 
    1144                     #Case of single name/data pair deletion 
    1145                     ############################################ 
    1146                                  
    1147                     #TEST 4 
    1148                     if($holder =~ /([0-9]+)d([0-9]+)/) { 
    1149                         #We know that this can only be a name/data pair that was deleted because 
    1150                         # a deletion of a key takes at least 2 lines because diff includes the  
    1151                         # blank line separating it from the other keys 
    1152                         _moonwalk_and_print($self, $first_start, "(^< )(.*)", "Deletion of name/data from existing key\n", 1,($self->{changes}->[$self->{g_count}][1])); 
    1153                     } 
    1154                     else {print "WARNING: some strange case in delete\n";} 
    1155                 } 
    1156             } 
    1157              
    1158             case /c/ { 
    1159      
    1160                 #Note about the change case: 
    1161                 #First of all as mentioned elsewhere "change" diffs can (and do) include multiple 
    1162                 # actions into a single grouping of change instructions. If this was simply parsed  
    1163                 # and dealt with without going to either of the diffed files, this can easily 
    1164                 # be exploited to hide some registry entries (it would still show an entry, but 
    1165                 # for every entry added there can be an additional hidden one). Therefore as a 
    1166                 # tradeoff, generally I always check the *last* entry from both the top and  
    1167                 # bottom section (except where it can be proven to be a simple change) against. 
    1168                 # the first and second file respectively. While I have not found cases that  
    1169                 # necessitate this for every change subcase, it is currently done for safety 
    1170                 # and simplicity because it can be done by reusing the _top_half and _bottom_half 
    1171                 # code. 
    1172      
    1173                 switch($holder){ 
    1174                     #the cases have to be in this order ;) 
    1175                     case /([0-9]+),([0-9]+)c([0-9]+),([0-9]+)/ { 
    1176                         #XXX: BUG!!! need to do again (cause of nested switches?) 
    1177                         $holder =~ /([0-9]+),([0-9]+)c([0-9]+),([0-9]+)/; 
    1178                         $first_start = $1; 
    1179                         $first_end = $2; 
    1180                         $second_start = $3; 
    1181                         $second_end = $4; 
    1182      
    1183     #                   print "1234 = $1:$2:$3:$4\n"; 
    1184      
    1185                         ##first check to make sure there are no keys 
    1186                         my @full_diff = @{$self->{changes}->[$self->{g_count}]}; 
    1187                         my $simple = 1; 
    1188                         my @before; 
    1189                         my @after; 
    1190                         foreach (@full_diff){ 
    1191                             if(/^[<>] \[/){$simple = 0;} 
    1192                             if(/^< .*/){ 
    1193                                 push @before, $_; 
    1194                             } 
    1195                             if(/^> .*/){ 
    1196                                 push @after, $_; 
    1197                             } 
    1198                         } 
    1199      
    1200                         #TEST 5 
    1201                         ############################## 
    1202                         # simple multi-line to multi-line change 
    1203                         ############################## 
    1204                         if($simple){ 
    1205                             #case where it's only multi-line changes 
    1206                             my @fake_array = ("> Old Value:", @before, "> New Value:", @after); 
    1207                             _moonwalk_and_print($self, $first_start, "(^[<>] )(.*)", "Changed: \n", 1, @fake_array); 
    1208                         } 
    1209                         else{ 
    1210                             #TEST 6 
    1211                             ############################## 
    1212                             # the most complicated (multi-line to multi-line) changes ;) 
    1213                             ############################## 
    1214  
    1215                             #Haven't been able to recreate this case naturally... punting. 
    1216                             print("If you got here, please save the $self->{clean_reg}$var and $self->{current_reg}$var and send them to us\n"); 
    1217                             exit(); 
    1218      
    1219                             #parses the output of the diff before and after the "---"  
    1220                             # divider independently 
    1221                             _top_half($self,$first_start, $first_end, @before); 
    1222                             _bottom_half($self, $second_start, $second_end, @after); 
    1223                         } 
    1224                          
    1225                          
    1226                     } 
    1227                     case /([0-9]+),([0-9]+)c([0-9]+)/ { 
    1228                         #XXX: BUG!!! need to do again (cause of nested switches?) 
    1229                         $holder =~ /([0-9]+),([0-9]+)c([0-9]+)/;                 
    1230                         $first_start = $1; 
    1231                         $first_end = $2; 
    1232                         $second_start = $3; 
    1233                         my $quick_count = $2-$1+1; 
    1234      
    1235     #                   print "123 = $1:$2:$3\n"; 
    1236      
    1237                         #first check to see if it is the trivial case of 
    1238                         # ONLY changing name/data pairs (i.e. should not 
    1239                         # find any keys (i.e. lines starting with "> ["  
    1240                         # or "< [") 
    1241                         my @full_diff = @{$self->{changes}->[$self->{g_count}]}; 
    1242                         my $simple = 1; 
    1243                         my @before; 
    1244                         my @after; 
    1245                         foreach (@full_diff){ 
    1246                             if(/^[<>] \[/){$simple = 0;} 
    1247                             if(/^< .*/){ 
    1248                                 push @before, $_; 
    1249                             } 
    1250                             if(/^> .*/){ 
    1251                                 push @after, $_; 
    1252                             } 
    1253                         } 
    1254                          
    1255                         #TEST 7 
    1256                         ############################## 
    1257                         # simple multi-line to single-line change 
    1258                         ############################## 
    1259                         if($simple){ 
    1260                             #case where it's only multi-line changes 
    1261                             my @fake_array = ("> Old Value:", @before, "> New Value:", @after); 
    1262                             _moonwalk_and_print($self, $first_start, "(^[<>] )(.*)", "Changed: \n", 1, @fake_array); 
    1263                         } 
    1264      
    1265                         else{ 
    1266                             #TEST 8 
    1267                             ############################## 
    1268                             # complicated multi-line to single-line change 
    1269                             ############################## 
    1270                             _top_half($self, $first_start, $first_end, @before); 
    1271                             _bottom_half($self, $second_start, $second_start, @after); 
    1272      
    1273                         } 
    1274                          
    1275      
    1276                     } 
    1277                     case /([0-9]+)c([0-9]+),([0-9]+)/ { 
    1278                         #XXX: BUG!!! need to do again (cause of nested switches?) 
    1279                         $holder =~ /([0-9]+)c([0-9]+),([0-9]+)/; 
    1280                         $first_start = $1; 
    1281                         $second_start = $2; 
    1282                         $second_end = $3; 
    1283      
    1284                         my $quick_count = $3-$2+3; 
    1285      
    1286     #                   print "123 = $1:$2:$3\n"; 
    1287      
    1288                         ##first check to make sure there are no keys 
    1289                         my @full_diff = @{$self->{changes}->[$self->{g_count}]}; 
    1290                         my $simple = 1; 
    1291                         my @before; 
    1292                         my @after; 
    1293                         foreach (@full_diff){ 
    1294                             if(/^[<>] \[/){$simple = 0;} 
    1295                             if(/^< .*/){ 
    1296                                 push @before, $_; 
    1297                             } 
    1298                             if(/^> .*/){ 
    1299                                 push @after, $_; 
    1300                             } 
    1301                         } 
    1302      
    1303                         #TEST 9 
    1304                         ############################## 
    1305                         # simple single-line to multi-line change 
    1306                         ############################## 
    1307                         if($simple){ 
    1308                             my @fake_array = ("> Old Value:", @before,"> New Value:", @after); 
    1309                             _moonwalk_and_print($self, $first_start, "(^[<>] )(.*)", "Changed: \n", 1, @fake_array); 
    1310                         } 
    1311      
    1312      
    1313                         else{ 
    1314                             #TEST 10 
    1315                             ############################## 
    1316                             # complicated single-line to multi-line change 
    1317                             ############################## 
    1318                             _top_half($self, $first_start, $first_start, @before); 
    1319                             _bottom_half($self, $second_start, $second_end, @after); 
    1320                         } 
    1321                          
    1322                     } 
    1323                     case /([0-9]+)c([0-9]+)/ { 
    1324                         #XXX: BUG!!! need to do again (cause of nested switches?) 
    1325                         $holder =~ /([0-9]+)c([0-9]+)/; 
    1326                         $first_start = $1; 
    1327                         $second_start = $2; 
    1328      
    1329                         my @full_diff = @{$self->{changes}->[$self->{g_count}]}; 
    1330                         my $simple = 1; 
    1331                         my @before; 
    1332                         my @after; 
    1333                         foreach (@full_diff){ 
    1334                             if(/^[<>] \[/){$simple = 0;} 
    1335                             if(/^< .*/){ 
    1336                                 push @before, $_; 
    1337                             } 
    1338                             if(/^> .*/){ 
    1339                                 push @after, $_; 
    1340                             } 
    1341                         } 
    1342                                      
    1343                         #TEST 11 
    1344                         ############################## 
    1345                         # simple single-line to single-line change 
    1346                         ############################## 
    1347                         if($simple){ 
    1348                             my @fake_array = ("> Old Value:", @before,"> New Value:", @after); 
    1349                             _moonwalk_and_print($self, $first_start, "(^[<>] )(.*)", "Changed: \n", 1, @fake_array); 
    1350                         } 
    1351                         else{ 
    1352                             #TEST 12 
    1353                             ############################## 
    1354                             # complicated single-line to single-line change 
    1355                             ############################## 
    1356                             _top_half($self, $first_start, $first_start, @before); 
    1357                             _bottom_half($self, $second_start, $second_start, @after); 
    1358                         } 
    1359                     } 
    1360                 } 
    1361             } 
    1362             else { 
    1363                 print "holder = $holder matched none of the cases, serious problem!\n"; 
    1364             } 
    1365         }#end switch 
    1366          
    1367         $self->{g_count}--; 
    1368     } #end big while 
    1369  
    1370     $var++; 
    1371 } #end big foreach 
    1372 return $g_reg_changes; 
    1373  
    1374 } #end checkRegistry 
    1375 ################################################################################ 
    1376  
    1377  
    1378 # A very important function which is responsible for looping through a list which 
    1379 # is given to it, and treating extra registry keys as adds or deletes with  
    1380 # possible adds, deletes, or changes as the "leftover" elements which get passed 
    1381 # to _moonwalk_and_print. Originally this function only operated on a chunk of  
    1382 # the @{$self->{changes}} array, therefore to maintain compatibility for now, if no array  
    1383 # is given, it will instead use the @{$self->{changes}} array.  
    1384  
    1385 # The general logic is that if it finds something in an array it pushes it into 
    1386 # a temporary one. At such time as it pushes a line starting with > [ or < [  
    1387 # that means that there was a registry key included in the array and therefore 
    1388 # we know which key the name/data pairs belong to and therefore we won't need  
    1389 # to consult the disk because we have everything we need to know about that  
    1390 # event. If there are still things in the temporary array when we finish looping 
    1391 # through the given/changes array then that is something leftover which we will 
    1392 # have to consult either the current or clean registry state about, to determine 
    1393 # which key the name/data pair belongs to. That's _moonwalk_and_print()'s job. 
    1394  
    1395 # TODO: Check to make sure the function generates appriopriate exceptions, when failures 
    1396 # occur. 
    1397 sub _parser{ 
    1398 my $self = shift; 
    1399 my $type = shift; 
    1400 my $regex = shift; 
    1401 my $regex2 = shift; 
    1402 my $quick_count = shift; 
    1403 my $start_line = shift; 
    1404 my $offset = shift; 
    1405 my @custom_array = @_; 
    1406 my @holding_array; 
    1407  
    1408     open CHANGES, ">>$self->{change_file}" or die "Cannot open $self->{change_file} (1): $!\n"; 
    1409          
    1410     #start to step (backwards) through the output of the diff 
    1411     my $tmp; 
    1412     while($quick_count >= $offset){ 
    1413         if (defined $custom_array[$quick_count]){ 
    1414             $tmp = $custom_array[$quick_count]; 
    1415         } 
    1416         else{ 
    1417             $tmp = $self->{changes}->[$self->{g_count}][$quick_count]; 
    1418         } 
    1419                      
    1420         #If the line starts with '> [' it's a registry key 
    1421         #If this case is detected it means it's a new key 
    1422         # (possibly with name/data pairs, possibly without) and it 
    1423         # will just dump this to the CHANGES file because 
    1424         # it doesn't have to consult the original registry 
    1425         # dump in order to know which key/names/values is added. 
    1426         if($tmp =~ /$regex2/){ 
    1427             push @holding_array, $tmp; 
    1428             @holding_array = reverse (@holding_array); 
    1429             switch($type){ 
    1430                 case /a/ { 
    1431                     if(scalar(@holding_array) > 1){ 
    1432                         print CHANGES "\nAdded key and name/data: \n" or die "Can't write to changefile!\n"; 
    1433                     } 
    1434                     else { 
    1435                         print CHANGES "\nAdded empty key: \n" or die "Can't write to changefile!\n"; 
    1436                     } 
    1437                 } 
    1438                 case /d/ { 
    1439                     if(scalar(@holding_array) > 1){ 
    1440                         print CHANGES "\nDeleted key and name/data: \n" or die "Can't write to changefile!\n"; 
    1441                     } 
    1442                     else { 
    1443                         print CHANGES "\nDeleted empty key: \n" or die "Can't write to changefile!\n"; 
    1444                     } 
    1445                 } 
    1446                 else{die "Unknown type in _parser() switch\n";} 
    1447             } 
    1448  
    1449             foreach my $line (@holding_array){ 
    1450                 $line =~ /$regex/; 
    1451                 #discard $1 which is formatting from diff 
    1452                 print CHANGES "$2\n" or die "Can't write to changefile!\n"; 
    1453             } 
    1454             print CHANGES "\n" or die "Can't write to changefile!\n"; 
    1455             @holding_array = (); 
    1456  
    1457         } 
    1458         else{ 
    1459             #Push anything else (except empty line), as it will be included 
    1460             # in whatever key it was found in 
    1461             if($tmp !~ /^[<>] \r\n/){ 
    1462                 push @holding_array, $tmp; 
    1463             } 
    1464         } 
    1465         $quick_count--; 
    1466     } 
    1467     $g_reg_changes = 1; 
    1468     close CHANGES or warn "Can't close changefile!\n"; 
    1469  
    1470     #Anything left over in @holding_array after that loop 
    1471     # is a name/data pair which did not have a new key 
    1472     # being created, and therefore is the modification of 
    1473     # an existing key. Thus we must consult the original 
    1474     # file to clean up stragglers if any. 
    1475     if(scalar(@holding_array) > 0){ 
    1476         @holding_array = reverse (@holding_array); 
    1477         my $string; 
    1478         my $case; 
    1479         switch($type){ 
    1480             case "a" { 
    1481                 $string = "Added name/data for existing key\n"; 
    1482                 $case = 2; 
    1483             } 
    1484             case "d" { 
    1485                 $string = "Deleted name/data for existing key\n"; 
    1486                 $case = 1; 
    1487             } 
    1488             case /c/ { 
    1489                 #$string = "Changed name/data for existing key\n"; 
    1490                 return @holding_array; 
    1491                 $case = 1; 
    1492             } 
    1493             else{die "Unknown type in 2nd _parser() switch\n";} 
    1494         }        
    1495  
    1496         _moonwalk_and_print($self, $start_line, $regex, $string, $case, @holding_array); 
    1497     } 
    1498  
    1499 
    1500 ################################################################################ 
    1501  
    1502 # Given a line number to start at in $moonwalk, this 
    1503 # function walks backwards trying to find the enclosing 
    1504 # registry key, and then prints the results to the 
    1505 # CHANGES file. 
    1506 # NOTE that most of this functionality has been passed off to _find_enclosing_key() 
    1507 # such that this primarily just prints now. It has been left in place for now  
    1508 # simply to maintain current code. 
    1509  
    1510 # TODO: Check to make sure the function generates appriopriate exceptions, when failures 
    1511 # occur. 
    1512 sub _moonwalk_and_print { 
    1513 my $self = shift;   #Object 
    1514 my $start_line = shift; #The line to start walking backwards from 
    1515 my $regex = shift;  #regular expression to use to get rid of diff formatting on lines 
    1516 my $string = shift; #String to print when  
    1517 my $case = shift;       #Add/delete/change case (1 for delete/change, 2 for add) 
    1518 my @holding_array = @_; 
    1519  
    1520     #walk backwards looking for the registry key 
    1521     # which contains us. 
    1522     my $enclosing_key = _find_enclosing_key($self, $start_line, $case); 
    1523  
    1524     print "Searching for excludes matching: $enclosing_key\n"; 
    1525     foreach my $exclude_key (@{$self->{reg_exclude_array}}){ 
    1526 ###     print "trying to match $enclosing_key against exclude key $exclude_key\n"; 
    1527         if($enclosing_key =~ /$exclude_key/){ 
    1528             print "SUCCESS! I'm outta here!\n"; 
    1529             print "Exclude: $exclude_key\n"; 
    1530             return $start_line; 
    1531         } 
    1532     } 
    1533  
    1534     open CHANGES, ">>$self->{change_file}" or die "Cannot open $self->{change_file} (2): $!\n";      
    1535     print CHANGES "\n$string" or die "Can't write to changefile!\n"; 
    1536     print CHANGES $enclosing_key or die "Can't write to changefile!\n"; 
    1537     foreach my $line (@holding_array){ 
    1538         $line =~ /$regex/; 
    1539         #discard $1 which is formatting from diff 
    1540         print CHANGES "$2\n" or die "Can't write to changefile!\n"; 
    1541     } 
    1542     $g_reg_changes = 1; 
    1543     close CHANGES or warn "Error closing changefile!\n"; 
    1544     #for use by changed case to avoid another walk 
    1545     return $start_line; 
    1546 
    1547 ################################################################################ 
    1548  
    1549  
    1550 #This is now what's actually doing the moonwalking due to some code rearrangement ;) 
    1551 #Steps backwards from the passed in line number in the passed in case 
    1552 # representing an array (representing a file) you want to use. @{$self->{reg1}} is the first 
    1553 # file given to the diff (should be the clean file) and @{$self->{reg2}} is therefore the  
    1554 # second file (the current state). 
    1555  
    1556 # TODO: Check to make sure the function generates appriopriate exceptions, when failures 
    1557 # occur. 
    1558 sub _find_enclosing_key{ 
    1559 my $self = shift;   #Object 
    1560 my $start_line = shift; # 
    1561 my $case = shift; 
    1562  
    1563     #This is the delete or change case so it checks the clean registry file (reg1) 
    1564     # (because a key which is deleted for instance can only be found in the orignal 
    1565     # not the current) 
    1566     if($case == 1){ 
    1567         while($self->{reg1}->[$start_line] !~ /^\[/){ 
    1568             $start_line--; 
    1569         } 
    1570         return $self->{reg1}->[$start_line]; 
    1571     } 
    1572     else{ 
    1573         #This is the add case so it checks the current registry file (reg2) 
    1574         # (because a key which is deleted for instance can only be found in  
    1575         #the orignal not the clean) 
    1576         if($case == 2){ 
    1577             while($self->{reg2}->[$start_line] !~ /^\[/){ 
    1578                 $start_line--; 
    1579             } 
    1580             return $self->{reg2}->[$start_line]; 
    1581         } 
    1582         else{ 
    1583             die "Invalid value for case in _find_enclosing_key\n"; 
    1584         } 
    1585     } 
    1586 
    1587  
    1588 ################################################################################ 
    1589  
    1590 # Because changes can be ambiguous this function (and _bottom_half) were created 
    1591 # to first deal with the ambigious case and then pass the rest into _parser(). 
    1592 # Based on the way that diff works and testing, it seems that ambiguous cases 
    1593 # can only manifest themselves in the last entry in the top half (the stuff 
    1594 # immediately before the "---" line when reading from top to bottom). Similarly 
    1595 # it can only manifest in the last entry of the bottom half. Therefore if it is 
    1596 # deal with in this code, the remainder of the array representing changes in the 
    1597 # top or bottom half should be safe to parse with _parser(). 
    1598  
    1599 sub _top_half{ 
    1600 my $self = shift; 
    1601 my $first_start = shift; 
    1602 my $first_end = shift; 
    1603 my @before = @_; 
    1604 my $num_lines = scalar(@before)-1; 
    1605 my @tmp_array; 
    1606 my $walk = $first_end; 
    1607  
    1608     ############################## 
    1609     # treat the top half like *deletes*  
    1610     # BUT first go to file for the last one and check its contents! 
    1611     ############################## 
    1612  
    1613 #   print "BEFORE walk = $walk\n"; 
    1614     #walk backwards to find how many lines from the end to start at 
    1615     while($num_lines >= 0 && $before[$num_lines] !~ /^< \[/){ 
    1616         $num_lines--; 
    1617     } 
    1618                      
    1619     my $lcount = scalar(@before)-1 - $num_lines; 
    1620     #walk is where to start walking *forward* in the clean reg file 
    1621     $walk = $first_end - $lcount; 
    1622  
    1623 #   print "BEFORE lcount = $lcount, walk = $walk\n"; 
    1624  
    1625     while($self->{reg1}->[$walk] !~ /^\[/){ 
    1626         if($self->{reg1}->[$walk] !~ /^\r\n/){ 
    1627 #           print "pushing $self->{reg1}->[$walk]"; 
    1628             push @tmp_array, $self->{reg1}->[$walk];     
    1629         } 
    1630         $walk++; 
    1631     } 
    1632                      
    1633     open CHANGES, ">>$self->{change_file}" or die "Cannot open $self->{change_file} (3): $!\n"; 
    1634     if(scalar(@tmp_array) > 0){ 
    1635         print CHANGES "\nDeleted key and name/data: \n"; 
    1636         my $enclosing_key = _find_enclosing_key($self, $first_end, 1); 
    1637 #       print "enclosing $enclosing_key"; 
    1638         print CHANGES $enclosing_key; 
    1639         foreach (@tmp_array){ 
    1640             print CHANGES; 
    1641             print "in da top $_"; 
    1642         } 
    1643     } 
    1644     else{ 
    1645         print CHANGES "\nDeleted empty key: \n"; 
    1646         $walk = $first_end - $lcount-1; 
    1647         print CHANGES "$self->{reg1}->[$walk]\n"; 
    1648         print "in da top $self->{reg1}->[$walk]\n"; 
    1649  
    1650     } 
    1651     $g_reg_changes = 1; 
    1652     close CHANGES; 
    1653  
    1654     #the +1 is because we want to delete the extra empty line from the array 
    1655     $lcount++; 
    1656  
    1657 #   print "before before: @before"; 
    1658      
    1659     while($lcount > 0){ 
    1660         pop @before; 
    1661         $lcount--; 
    1662     } 
    1663  
    1664 #   print "before after: @before"; 
    1665      
    1666     ############################## 
    1667     #now the array is safe to be treated as a normal change+deletion array 
    1668     ############################### 
    1669     if(scalar(@before) > 0){ 
    1670 #       print "BEFORE\n @before BEFORE\n"; 
    1671         _parser($self, "cd", "(^< )(.*)", "^< \\[", scalar(@before)-1, $first_start, 0, @before); 
    1672     } 
    1673  
    1674 
    1675 ################################################################################ 
    1676  
    1677 # Because changes can be ambiguous this function (and _top_half) were created 
    1678 # to first deal with the ambigious case and then pass the rest into _parser(). 
    1679 # Based on the way that diff works and testing, it seems that ambiguous cases 
    1680 # can only manifest themselves in the last entry in the top half (the stuff 
    1681 # immediately before the "---" line when reading from top to bottom). Similarly 
    1682 # it can only manifest in the last entry of the bottom half. Therefore if it is 
    1683 # deal with in this code, the remainder of the array representing changes in the 
    1684 # top or bottom half should be safe to parse with _parser(). 
    1685  
    1686  
    1687 sub _bottom_half{ 
    1688 my $self = shift; 
    1689  
    1690 my $second_start = shift; 
    1691 my $second_end = shift; 
    1692 my @after = @_; 
    1693 my $num_lines = scalar(@after)-1; 
    1694 my @tmp_array; 
    1695 my $walk = $second_end; 
    1696      
    1697     ############################## 
    1698     #treat the bottom like *adds*  
    1699     #BUT first go to file for the last one and check its contents! 
    1700     ############################## 
    1701  
    1702 #   print "AFTER walk = $walk\n"; 
    1703     #walk backwards to find how many lines from the end to start at 
    1704     while($num_lines >= 0 && $after[$num_lines] !~ /^> \[/){ 
    1705         $num_lines--; 
    1706     } 
    1707              
    1708     my $lcount = scalar(@after)-1 - $num_lines; 
    1709     #walk is where to start walking *forward* in the clean reg file 
    1710     $walk = $second_end - $lcount; 
    1711  
    1712  
    1713 #   print "AFTER lcount = $lcount, walk = $walk\n"; 
    1714  
    1715     while($self->{reg2}->[$walk] !~ /^\[/){ 
    1716                          
    1717         if($self->{reg2}->[$walk] !~ /^\r\n/){ 
    1718 #           print "AFTER pushing $self->{reg2}->[$walk]"; 
    1719             push @tmp_array, $self->{reg2}->[$walk];     
    1720         } 
    1721         $walk++; 
    1722     } 
    1723                      
    1724     open CHANGES, ">>$self->{change_file}" or die "Cannot open $self->{change_file} (4): $!\n"; 
    1725     if(scalar(@tmp_array) > 0){ 
    1726                          
    1727         print CHANGES "\nAdded key and name/data: \n"; 
    1728         my $enclosing_key = _find_enclosing_key($self, $second_end, 2); 
    1729 #       print "AFTER enclosing $enclosing_key"; 
    1730         print CHANGES $enclosing_key; 
    1731         foreach (@tmp_array){ 
    1732             print CHANGES; 
    1733 #           print "in da bottom $_"; 
    1734         } 
    1735     } 
    1736     else{ 
    1737         print CHANGES "\nAdded empty key: \n"; 
    1738         $walk = $second_end - $lcount-1; 
    1739         print CHANGES "$self->{reg2}->[$walk]\n"; 
    1740 #       print "in da bottom $self->{reg2}->[$walk]\n"; 
    1741  
    1742     } 
    1743     $g_reg_changes = 1; 
    1744     close CHANGES; 
    1745  
    1746     #the +1 is because we want to delete the extra empty line from the array 
    1747     $lcount++; 
    1748  
    1749 #   print "after before: @after\n"; 
    1750      
    1751     while($lcount > 0){ 
    1752         pop @after; 
    1753         $lcount--; 
    1754     } 
    1755  
    1756 #   print "after after: @after"; 
    1757      
    1758     ############################## 
    1759     #now the array is safe to be treated as a normal change+addition array 
    1760     ############################### 
    1761     if(scalar(@after) > 0){ 
    1762 #       print "AFTER\n @after AFTER\n"; 
    1763         _parser($self, "ca", "(^> )(.*)", "^> \\[", scalar(@after)-1, $second_start, 0, @after); 
    1764     } 
    1765  
    1766 
    1767  
    1768  
    1769  
    1770  
    1771 ################################################################################ 
    1772  
    1773 =pod 
    1774  
    1775 =head1 
    1776  
    1777 startCheckProcesses() : Currently just a placeholder incase we put Thanh's  
    1778 real-time checking here. 
    1779  
    1780 =cut 
    1781  
    1782 #Holder incase we put Thanh's stuff in here 
    1783 sub startCheckProcesses { 
    1784     return; 
     809##      print "\t _recursive_exclude()d $foundfile\n"; 
     810    } 
    1785811} 
    1786812 
     
    1845871# we can simply leave the garbage collection up to Perl's internal 
    1846872# mechanism. 
    1847 sub DESTROY { 
    1848 
     873#sub DESTROY { 
     874#
    1849875################################################################################ 
    1850876 
  • honeyclient/branches/bug/42/lib/HoneyClient/Agent/Integrity/Registry.pm

    r122 r123  
    376376        '^HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Internet Explorer\\\TypedURLs$', 
    377377        '^HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MenuOrder\\\Favorites\\\Links.*$', 
     378        '^HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MenuOrder\\\Start Menu2\\\Programs.*$', 
    378379        '^HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MountPoints2\\\CPC\\\Volume.*$', 
    379380        '^HKEY_CURRENT_USER\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\UserAssist\\\.+\\\Count.*$', 
     
    401402        '^HKEY_USERS\\\.+\\\Software\\\Microsoft\\\Windows\\\ShellNoRoam\\\BagMRU.*$', 
    402403        '^HKEY_USERS\\\.+\\\UNICODE Program Groups.*$', 
     404        '^HKEY_USERS\\\S.+\\\SessionInformation$', 
    403405        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Internet Explorer\\\Main$', 
    404406        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Internet Explorer\\\Security\\\AntiPhishing.*$', 
    405407        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Internet Explorer\\\TypedURLs$', 
    406408        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MenuOrder\\\Favorites\\\Links.*$', 
     409        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MenuOrder\\\Start Menu2\\\Programs.*$', 
    407410        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Explorer\\\MountPoints2\\\CPC\\\Volume.*$', 
    408411        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\CurrentVersion\\\Ext\\\Stats\\\.+\\\iexplore.*$', 
     
    411414        '^HKEY_USERS\\\S.+\\\Software\\\Microsoft\\\Windows\\\ShellNoRoam\\\MUICache.*$', 
    412415    ], 
    413  
    414416 
    415417    # When set to 1, the object will forgo any type of initial baselining 
     
    473475            $LOG->debug("Deleting baseline of hive '" . $hive . "' in '" . 
    474476                        $fname . "'."); 
    475             if (!unlink0($parser->getFileHandle(), $fname)) { 
     477            if (!unlink($fname)) { 
    476478                $LOG->fatal("Error: Unable to unlink '" . $hive . "' hive data in '" . $fname ."'."); 
    477479                Carp::croak("Error: Unable to unlink '" . $hive . "' hive data in '" . $fname ."'."); 
     
    485487            $LOG->debug("Deleting checkpoint of hive '" . $hive . "' in '" . 
    486488                        $fname . "'."); 
    487             if (!unlink0($parser->getFileHandle(), $fname)) { 
     489            if (!unlink($fname)) { 
    488490                $LOG->fatal("Error: Unable to unlink '" . $hive . "' hive data in '" . $fname ."'."); 
    489491                Carp::croak("Error: Unable to unlink '" . $hive . "' hive data in '" . $fname ."'."); 
     
    525527        _cleanup($fname_tmp); 
    526528 
    527         $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file   => $fname, 
    528                                                                         index_groups => 1); 
     529        $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file    => $fname, 
     530                                                                        index_groups  => 1, 
     531                                                                        show_progress => 0); 
    529532 
    530533        $parser_collection->{$hive} = $parser; 
     
    15461549} 
    15471550 
     1551=pod 
     1552 
     1553=head2 $object->closeFiles() 
     1554 
     1555=over 4 
     1556 
     1557Closes any temporary files that have been created by the 
     1558Registry B<$object>.  By performing this operation, the  
     1559Registry B<$object> can become serializable. 
     1560 
     1561=back 
     1562 
     1563=begin testing 
     1564 
     1565# Perform Registry baseline on HKEY_CURRENT_CONFIG. 
     1566diag("Performing baseline check of 'HKEY_CURRENT_CONFIG' hive; this may take some time..."); 
     1567my $registry = HoneyClient::Agent::Integrity::Registry->new(hives_to_check => [ 'HKEY_CURRENT_CONFIG' ]); 
     1568$registry->closeFiles(); 
     1569my @files_created = $registry->getFilesCreated(); 
     1570use Data::Dumper; 
     1571my $tmpfile = tmpnam(); 
     1572unlink($tmpfile);  
     1573my $tmpdir = dirname($tmpfile); 
     1574foreach my $file (@files_created) { 
     1575    like($file, qr/$tmpdir/, "closeFiles()") or diag("The closeFiles() call failed."); 
     1576} 
     1577 
     1578=end testing 
     1579 
     1580=cut 
     1581 
     1582sub closeFiles { 
     1583    # Extract arguments. 
     1584    my ($self, %args) = @_; 
     1585 
     1586    # Log resolved arguments. 
     1587    # Make Dumper format more terse. 
     1588    $Data::Dumper::Terse = 1; 
     1589    $Data::Dumper::Indent = 0; 
     1590    $LOG->debug(Dumper(\%args)); 
     1591 
     1592    # Close any temporary files created. 
     1593    my $parser = undef; 
     1594    foreach my $hive (@{$self->{hives_to_check}}) { 
     1595        $parser = $self->{_baseline_parsers}->{$hive}; 
     1596        if (defined($parser)) { 
     1597            $parser->closeFileHandle(); 
     1598        } 
     1599        $parser = $self->{_checkpoint_parsers}->{$hive}; 
     1600        if (defined($parser)) { 
     1601            $parser->closeFileHandle(); 
     1602        } 
     1603    } 
     1604} 
     1605 
    154816061; 
    15491607 
  • honeyclient/branches/bug/42/lib/HoneyClient/Agent/Integrity/Registry/Parser.pm

    r119 r123  
    597597    $LOG->debug("Resetting parser."); 
    598598 
    599     my $fh = $self->YYData->{'file_handle'}; 
     599    $self->YYData->{'file_handle'} = undef; 
     600 
     601    my $fh = new IO::File($self->YYData->{'filename'}, "r"); 
     602    if (!defined($fh)) { 
     603        $LOG->fatal("Error: Unable to read file '" . $self->YYData->{'filename'} . "'!"); 
     604        Carp::croak("Error: Unable to read file '" . $self->YYData->{'filename'} . "'!"); 
     605    } 
     606 
     607    $self->YYData->{'file_handle'} = $fh; 
    600608 
    601609    # Check the offset. 
     
    806814    } 
    807815 
     816    # Save the file name. 
     817    $parser->YYData->{'filename'} = $args{'input_file'}; 
     818 
    808819    # Save the file handle. 
    809820    $parser->YYData->{'file_handle'} = $fh; 
     
    10121023    $LOG->debug(Dumper(\%args)); 
    10131024 
     1025    # Reopen the file_handle, if it's been closed. 
     1026    if (!defined($self->YYData->{'file_handle'})) { 
     1027        $self->_reset();    
     1028    } 
     1029 
    10141030    if ($self->YYData->{'input_pos'} == 0) { 
    10151031        $LOG->debug("Beginning parse of input stream."); 
     
    11621178 
    11631179    return $self->YYData->{'file_handle'};  
     1180} 
     1181 
     1182=pod 
     1183 
     1184=head2 $object->getFilename() 
     1185 
     1186=over 4 
     1187 
     1188Returns the file name associated with the current Parser B<$object>. 
     1189 
     1190I<Output>: Returns the file name in use. 
     1191 
     1192=back 
     1193 
     1194=begin testing 
     1195 
     1196my ($filename); 
     1197my $test_registry_file = $ENV{PWD} . "/" . getVar(name      => "registry_file", 
     1198                                                  namespace => "HoneyClient::Agent::Integrity::Registry::Parser::Test"); 
     1199 
     1200# Create a generic Parser object, with test state data. 
     1201my $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file => $test_registry_file); 
     1202 
     1203$filename = $parser->getFilename(); 
     1204 
     1205is($filename, $test_registry_file, "getFilename()") or diag("The getFilename() call failed."); 
     1206 
     1207=end testing 
     1208 
     1209=cut 
     1210 
     1211sub getFilename { 
     1212    # Extract arguments. 
     1213    my ($self, %args) = @_; 
     1214 
     1215    # Log resolved arguments. 
     1216    # Make Dumper format more terse. 
     1217    $Data::Dumper::Terse = 1; 
     1218    $Data::Dumper::Indent = 0; 
     1219    $LOG->debug(Dumper(\%args)); 
     1220 
     1221    return $self->YYData->{'filename'};  
     1222} 
     1223 
     1224=pod 
     1225 
     1226=head2 $object->closeFileHandle() 
     1227 
     1228=over 4 
     1229 
     1230Closes the file handle associated with the current Parser B<$object>. 
     1231 
     1232=back 
     1233 
     1234=begin testing 
     1235 
     1236my ($handle); 
     1237my $test_registry_file = $ENV{PWD} . "/" . getVar(name      => "registry_file", 
     1238                                                  namespace => "HoneyClient::Agent::Integrity::Registry::Parser::Test"); 
     1239 
     1240# Create a generic Parser object, with test state data. 
     1241my $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file => $test_registry_file); 
     1242$parser->closeFileHandle(); 
     1243 
     1244# Verify Test Group #1 
     1245my $nextGroup = $parser->nextGroup(); 
     1246my $expectedGroup = { 
     1247    key     => 'HKEY_CURRENT_USER\]Testing Group 1[', 
     1248    entries => [ { 
     1249        name  => '@', 
     1250        value => 'Default', 
     1251    }, { 
     1252        name  => 'Foo', 
     1253        value => 'Bar', 
     1254    }, ], 
     1255}; 
     1256is_deeply($nextGroup, $expectedGroup, "closeFileHandle()") or diag("The closeFileHandle() call failed."); 
     1257 
     1258=end testing 
     1259 
     1260=cut 
     1261 
     1262sub closeFileHandle { 
     1263    # Extract arguments. 
     1264    my ($self, %args) = @_; 
     1265 
     1266    # Log resolved arguments. 
     1267    # Make Dumper format more terse. 
     1268    $Data::Dumper::Terse = 1; 
     1269    $Data::Dumper::Indent = 0; 
     1270    $LOG->debug(Dumper(\%args)); 
     1271 
     1272    $self->YYData->{'file_handle'} = undef;  
    11641273} 
    11651274 
  • honeyclient/branches/bug/42/lib/HoneyClient/Agent/Integrity/Registry/Parser.yp

    r119 r123  
    442442    $LOG->debug("Resetting parser."); 
    443443 
    444     my $fh = $self->YYData->{'file_handle'}; 
     444    $self->YYData->{'file_handle'} = undef; 
     445 
     446    my $fh = new IO::File($self->YYData->{'filename'}, "r"); 
     447    if (!defined($fh)) { 
     448        $LOG->fatal("Error: Unable to read file '" . $self->YYData->{'filename'} . "'!"); 
     449        Carp::croak("Error: Unable to read file '" . $self->YYData->{'filename'} . "'!"); 
     450    } 
     451 
     452    $self->YYData->{'file_handle'} = $fh; 
    445453 
    446454    # Check the offset. 
     
    651659    } 
    652660 
     661    # Save the file name. 
     662    $parser->YYData->{'filename'} = $args{'input_file'}; 
     663 
    653664    # Save the file handle. 
    654665    $parser->YYData->{'file_handle'} = $fh; 
     
    857868    $LOG->debug(Dumper(\%args)); 
    858869 
     870    # Reopen the file_handle, if it's been closed. 
     871    if (!defined($self->YYData->{'file_handle'})) { 
     872        $self->_reset();    
     873    } 
     874 
    859875    if ($self->YYData->{'input_pos'} == 0) { 
    860876        $LOG->debug("Beginning parse of input stream."); 
     
    10071023 
    10081024    return $self->YYData->{'file_handle'};  
     1025} 
     1026 
     1027=pod 
     1028 
     1029=head2 $object->getFilename() 
     1030 
     1031=over 4 
     1032 
     1033Returns the file name associated with the current Parser B<$object>. 
     1034 
     1035I<Output>: Returns the file name in use. 
     1036 
     1037=back 
     1038 
     1039=begin testing 
     1040 
     1041my ($filename); 
     1042my $test_registry_file = $ENV{PWD} . "/" . getVar(name      => "registry_file", 
     1043                                                  namespace => "HoneyClient::Agent::Integrity::Registry::Parser::Test"); 
     1044 
     1045# Create a generic Parser object, with test state data. 
     1046my $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file => $test_registry_file); 
     1047 
     1048$filename = $parser->getFilename(); 
     1049 
     1050is($filename, $test_registry_file, "getFilename()") or diag("The getFilename() call failed."); 
     1051 
     1052=end testing 
     1053 
     1054=cut 
     1055 
     1056sub getFilename { 
     1057    # Extract arguments. 
     1058    my ($self, %args) = @_; 
     1059 
     1060    # Log resolved arguments. 
     1061    # Make Dumper format more terse. 
     1062    $Data::Dumper::Terse = 1; 
     1063    $Data::Dumper::Indent = 0; 
     1064    $LOG->debug(Dumper(\%args)); 
     1065 
     1066    return $self->YYData->{'filename'};  
     1067} 
     1068 
     1069=pod 
     1070 
     1071=head2 $object->closeFileHandle() 
     1072 
     1073=over 4 
     1074 
     1075Closes the file handle associated with the current Parser B<$object>. 
     1076 
     1077=back 
     1078 
     1079=begin testing 
     1080 
     1081my ($handle); 
     1082my $test_registry_file = $ENV{PWD} . "/" . getVar(name      => "registry_file", 
     1083                                                  namespace => "HoneyClient::Agent::Integrity::Registry::Parser::Test"); 
     1084 
     1085# Create a generic Parser object, with test state data. 
     1086my $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file => $test_registry_file); 
     1087$parser->closeFileHandle(); 
     1088 
     1089# Verify Test Group #1 
     1090my $nextGroup = $parser->nextGroup(); 
     1091my $expectedGroup = { 
     1092    key     => 'HKEY_CURRENT_USER\]Testing Group 1[', 
     1093    entries => [ { 
     1094        name  => '@', 
     1095        value => 'Default', 
     1096    }, { 
     1097        name  => 'Foo', 
     1098        value => 'Bar', 
     1099    }, ], 
     1100}; 
     1101is_deeply($nextGroup, $expectedGroup, "closeFileHandle()") or diag("The closeFileHandle() call failed."); 
     1102 
     1103=end testing 
     1104 
     1105=cut 
     1106 
     1107sub closeFileHandle { 
     1108    # Extract arguments. 
     1109    my ($self, %args) = @_; 
     1110 
     1111    # Log resolved arguments. 
     1112    # Make Dumper format more terse. 
     1113    $Data::Dumper::Terse = 1; 
     1114    $Data::Dumper::Indent = 0; 
     1115    $LOG->debug(Dumper(\%args)); 
     1116 
     1117    $self->YYData->{'file_handle'} = undef;  
    10091118} 
    10101119 
  • honeyclient/branches/bug/42/t/honeyclient_agent_integrity.t

    r96 r123  
    1717can_ok('HoneyClient::Agent::Integrity', 'initFileSystem'); 
    1818can_ok('HoneyClient::Agent::Integrity', 'checkFileSystem'); 
    19 can_ok('HoneyClient::Agent::Integrity', 'initRegistry'); 
    20 can_ok('HoneyClient::Agent::Integrity', 'checkRegistry'); 
    21 use HoneyClient::Agent::Integrity qw(initAll checkAll initRegistry checkRegistry initFileSystem checkFileSystem); 
     19use HoneyClient::Agent::Integrity qw(initAll checkAll initFileSystem checkFileSystem); 
    2220 
    2321# Make sure HoneyClient::Util::Config loads. 
     
    4644 
    4745# Make sure Storable loads. 
    48 BEGIN { use_ok('Storable', qw(dclone)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
     46BEGIN { use_ok('Storable', qw(dclone nfreeze thaw)) or diag("Can't load Storable package.  Check to make sure the package library is correctly listed within the path."); } 
    4947require_ok('Storable'); 
    5048can_ok('Storable', 'dclone'); 
    51 use Storable qw(dclone); 
     49can_ok('Storable', 'nfreeze'); 
     50can_ok('Storable', 'thaw'); 
     51use Storable qw(dclone nfreeze thaw); 
    5252 
    5353###Testing Globals### 
     
    160160 
    161161 
    162 # =begin testing 
    163 { 
    164 #Testing initRegistry() 
    165 my $ob = HoneyClient::Agent::Integrity->new(); 
    166  
    167 system("regedit.exe /s noTEST.reg"); 
    168 system("regedit.exe /s /c $test_dir/t1a.reg"); 
    169 $ob->initRegistry("HKEY_LOCAL_MACHINE\\HARDWARE\\TEST"); 
    170 open (DIFF, "diff $test_dir/t1a.reg clean.reg0 |") or die "Can't check the changes files\n"; 
    171 @result = <DIFF>; 
    172 close DIFF; 
    173 #Bad test because it will be empty in the case of an error anyway? 
    174 is(scalar(@result), 0, 'initRegistry: General Test'); 
    175 } 
    176  
    177  
    178  
    179 # =begin testing 
    180 { 
    181 my $ob = HoneyClient::Agent::Integrity->new(); 
    182  
    183 reg_test($ob, 1, "checkRegistry: case 1 Multi-line addition changes."); 
    184 reg_test($ob, 2, "checkRegistry: case 2 Single-line addition changes."); 
    185 reg_test($ob, 3, "checkRegistry: case 3 Multi-line deletion changes."); 
    186 reg_test($ob, 4, "checkRegistry: case 4 Single-line deletion changes."); 
    187 reg_test($ob, 5, "checkRegistry: case 5 Simple multi-line to multi-line changes."); 
    188 is(6, 6, "checkRegistry: case 6 - SKIPPING (currently can't recreate conditions for test)"); 
    189 #reg_test($ob, 6, "checkRegistry: case 6 Complicated multi-line to multi-line changes."); 
    190 reg_test($ob, 7, "checkRegistry: case 7 Simple multi-line to single-line changes."); 
    191 reg_test($ob, 8, "checkRegistry: case 8 Complicated multi-line to single-line changes."); 
    192 reg_test($ob, 9, "checkRegistry: case 9 Simple single-line to multi-line changes."); 
    193 reg_test($ob, 10, "checkRegistry: case 10 Complicated single-line to multi-line changes."); 
    194 reg_test($ob, 11, "checkRegistry: case 11 Simple single-line to single-line changes."); 
    195 reg_test($ob, 12, "checkRegistry: case12 Complicated single-line to single-line changes."); 
    196  
    197 sub reg_test{ 
    198 my $ob = shift; 
    199 my $num = shift; 
    200 my $string = shift; 
    201  
    202     #for safety 
    203     if(-e "temp_reg_export.reg"){ 
    204         system("mv temp_reg_export.reg temp_reg_export.reg.CBL"); 
    205     } 
    206     system('regedit.exe /a temp_reg_export.reg "HKEY_LOCAL_MACHINE\HARDWARE\TEST"'); 
    207  
    208     system("regedit.exe /s noTEST.reg"); 
    209     system("regedit.exe /s /c $test_dir/t" . "$num" . "a.reg"); 
    210     $ob->initRegistry("HKEY_LOCAL_MACHINE\\HARDWARE"); 
    211     system("regedit.exe /s noTEST.reg"); 
    212     system("regedit.exe /s /c $test_dir/t" . "$num" . "b.reg"); 
    213     $ob->checkRegistry("HKEY_LOCAL_MACHINE\\HARDWARE"); 
    214     open (DIFF, "diff $test_dir/t" . "$num" . "changes.txt changes.txt |") or die "Can't check the changes files\n"; 
    215     @result = <DIFF>; 
    216     close DIFF; 
    217     #Bad test because it will be empty in the case of an error anyway? 
    218     is(scalar(@result), 0, "$string"); 
    219  
    220     #for safety/cleanup 
    221     if(-e "temp_reg_export.reg"){ 
    222         system("regedit.exe /s noTEST.reg"); 
    223         system("regedit.exe /s /c temp_reg_export.reg"); 
    224         system("rm temp_reg_export.reg"); 
    225         if(-e "temp_reg_export.reg.CBL"){ 
    226             system("mv temp_reg_export.reg.CBL temp_reg_export.reg"); 
    227         } 
    228     } 
    229      
    230 } 
    231 } 
    232  
    233  
    234  
    235162 
    2361631; 
  • honeyclient/branches/bug/42/t/honeyclient_agent_integrity_registry.t

    r122 r123  
    288288 
    289289 
     290# =begin testing 
     291{ 
     292# Perform Registry baseline on HKEY_CURRENT_CONFIG. 
     293diag("Performing baseline check of 'HKEY_CURRENT_CONFIG' hive; this may take some time..."); 
     294my $registry = HoneyClient::Agent::Integrity::Registry->new(hives_to_check => [ 'HKEY_CURRENT_CONFIG' ]); 
     295$registry->closeFiles(); 
     296my @files_created = $registry->getFilesCreated(); 
     297use Data::Dumper; 
     298my $tmpfile = tmpnam(); 
     299unlink($tmpfile);  
     300my $tmpdir = dirname($tmpfile); 
     301foreach my $file (@files_created) { 
     302    like($file, qr/$tmpdir/, "closeFiles()") or diag("The closeFiles() call failed."); 
     303} 
     304} 
     305 
     306 
     307 
    290308 
    2913091; 
  • honeyclient/branches/bug/42/t/honeyclient_agent_integrity_registry_parser.t

    r116 r123  
    297297# =begin testing 
    298298{ 
     299my ($filename); 
     300my $test_registry_file = $ENV{PWD} . "/" . getVar(name      => "registry_file", 
     301                                                  namespace => "HoneyClient::Agent::Integrity::Registry::Parser::Test"); 
     302 
     303# Create a generic Parser object, with test state data. 
     304my $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file => $test_registry_file); 
     305 
     306$filename = $parser->getFilename(); 
     307 
     308is($filename, $test_registry_file, "getFilename()") or diag("The getFilename() call failed."); 
     309} 
     310 
     311 
     312 
     313# =begin testing 
     314{ 
     315my ($handle); 
     316my $test_registry_file = $ENV{PWD} . "/" . getVar(name      => "registry_file", 
     317                                                  namespace => "HoneyClient::Agent::Integrity::Registry::Parser::Test"); 
     318 
     319# Create a generic Parser object, with test state data. 
     320my $parser = HoneyClient::Agent::Integrity::Registry::Parser->init(input_file => $test_registry_file); 
     321$parser->closeFileHandle(); 
     322 
     323# Verify Test Group #1 
     324my $nextGroup = $parser->nextGroup(); 
     325my $expectedGroup = { 
     326    key     => 'HKEY_CURRENT_USER\]Testing Group 1[', 
     327    entries => [ { 
     328        name  => '@', 
     329        value => 'Default', 
     330    }, { 
     331        name  => 'Foo', 
     332        value => 'Bar', 
     333    }, ], 
     334}; 
     335is_deeply($nextGroup, $expectedGroup, "closeFileHandle()") or diag("The closeFileHandle() call failed."); 
     336} 
     337 
     338 
     339 
     340# =begin testing 
     341{ 
    299342my ($handle); 
    300343my $test_registry_file = $ENV{PWD} . "/" . getVar(name      => "registry_file",