| 1 |
#!/usr/bin/perl -w |
|---|
| 2 |
|
|---|
| 3 |
use strict; |
|---|
| 4 |
use Test::More 'no_plan'; |
|---|
| 5 |
$| = 1; |
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
# =begin testing |
|---|
| 10 |
{ |
|---|
| 11 |
# Make sure Log::Log4perl loads |
|---|
| 12 |
BEGIN { use_ok('Log::Log4perl', qw(:nowarn)) |
|---|
| 13 |
or diag("Can't load Log::Log4perl package. Check to make sure the package library is correctly listed within the path."); |
|---|
| 14 |
|
|---|
| 15 |
# Suppress all logging messages, since we need clean output for unit testing. |
|---|
| 16 |
Log::Log4perl->init({ |
|---|
| 17 |
"log4perl.rootLogger" => "DEBUG, Buffer", |
|---|
| 18 |
"log4perl.appender.Buffer" => "Log::Log4perl::Appender::TestBuffer", |
|---|
| 19 |
"log4perl.appender.Buffer.min_level" => "fatal", |
|---|
| 20 |
"log4perl.appender.Buffer.layout" => "Log::Log4perl::Layout::PatternLayout", |
|---|
| 21 |
"log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", |
|---|
| 22 |
}); |
|---|
| 23 |
} |
|---|
| 24 |
require_ok('Log::Log4perl'); |
|---|
| 25 |
use Log::Log4perl qw(:easy); |
|---|
| 26 |
|
|---|
| 27 |
# Make sure the module loads properly, with the exportable |
|---|
| 28 |
# functions shared. |
|---|
| 29 |
BEGIN { use_ok('HoneyClient::Util::Config', qw(getVar setVar)) |
|---|
| 30 |
or diag("Can't load HoneyClient::Util::Config package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 31 |
require_ok('HoneyClient::Util::Config'); |
|---|
| 32 |
can_ok('HoneyClient::Util::Config', 'getVar'); |
|---|
| 33 |
can_ok('HoneyClient::Util::Config', 'setVar'); |
|---|
| 34 |
use HoneyClient::Util::Config qw(getVar setVar); |
|---|
| 35 |
|
|---|
| 36 |
# Suppress all logging messages, since we need clean output for unit testing. |
|---|
| 37 |
Log::Log4perl->init({ |
|---|
| 38 |
"log4perl.rootLogger" => "DEBUG, Buffer", |
|---|
| 39 |
"log4perl.appender.Buffer" => "Log::Log4perl::Appender::TestBuffer", |
|---|
| 40 |
"log4perl.appender.Buffer.min_level" => "fatal", |
|---|
| 41 |
"log4perl.appender.Buffer.layout" => "Log::Log4perl::Layout::PatternLayout", |
|---|
| 42 |
"log4perl.appender.Buffer.layout.ConversionPattern" => "%d{yyyy-MM-dd HH:mm:ss} %5p [%M] (%F:%L) - %m%n", |
|---|
| 43 |
}); |
|---|
| 44 |
|
|---|
| 45 |
# Make sure Data::Dumper loads |
|---|
| 46 |
BEGIN { use_ok('Data::Dumper') |
|---|
| 47 |
or diag("Can't load Data::Dumper package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 48 |
require_ok('Data::Dumper'); |
|---|
| 49 |
use Data::Dumper; |
|---|
| 50 |
|
|---|
| 51 |
# Make sure Storable loads |
|---|
| 52 |
BEGIN { use_ok('Storable', qw(dclone)) |
|---|
| 53 |
or diag("Can't load Storable package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 54 |
require_ok('Storable'); |
|---|
| 55 |
can_ok('Storable', 'dclone'); |
|---|
| 56 |
use Storable qw(dclone); |
|---|
| 57 |
|
|---|
| 58 |
# Make sure IO::Handle loads |
|---|
| 59 |
BEGIN { use_ok('IO::Handle') |
|---|
| 60 |
or diag("Can't load IO::Handle package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 61 |
require_ok('IO::Handle'); |
|---|
| 62 |
use IO::Handle; |
|---|
| 63 |
|
|---|
| 64 |
# Make sure IO::File loads |
|---|
| 65 |
BEGIN { use_ok('IO::File') |
|---|
| 66 |
or diag("Can't load IO::File package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 67 |
require_ok('IO::File'); |
|---|
| 68 |
use IO::File; |
|---|
| 69 |
|
|---|
| 70 |
# Make sure Fcntl loads |
|---|
| 71 |
BEGIN { use_ok('Fcntl') |
|---|
| 72 |
or diag("Can't load Fcntl package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 73 |
require_ok('Fcntl'); |
|---|
| 74 |
use Fcntl qw(:seek); |
|---|
| 75 |
|
|---|
| 76 |
# Make sure File::Temp loads |
|---|
| 77 |
BEGIN { use_ok('File::Temp') |
|---|
| 78 |
or diag("Can't load File::Temp package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 79 |
require_ok('File::Temp'); |
|---|
| 80 |
can_ok('File::Temp', 'tmpnam'); |
|---|
| 81 |
can_ok('File::Temp', 'unlink0'); |
|---|
| 82 |
use File::Temp qw(tmpnam unlink0); |
|---|
| 83 |
|
|---|
| 84 |
# Make sure Filesys::CygwinPaths loads |
|---|
| 85 |
BEGIN { use_ok('Filesys::CygwinPaths') |
|---|
| 86 |
or diag("Can't load Filesys::CygwinPaths package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 87 |
require_ok('Filesys::CygwinPaths'); |
|---|
| 88 |
use Filesys::CygwinPaths qw(:all); |
|---|
| 89 |
|
|---|
| 90 |
# Make sure Search::Binary loads |
|---|
| 91 |
BEGIN { use_ok('Search::Binary') |
|---|
| 92 |
or diag("Can't load Search::Binary package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 93 |
require_ok('Search::Binary'); |
|---|
| 94 |
can_ok('Search::Binary', 'binary_search'); |
|---|
| 95 |
use Search::Binary; |
|---|
| 96 |
|
|---|
| 97 |
# Make sure HoneyClient::Agent::Integrity::Registry::Parser loads |
|---|
| 98 |
BEGIN { use_ok('HoneyClient::Agent::Integrity::Registry::Parser') |
|---|
| 99 |
or diag("Can't load HoneyClient::Agent::Integrity::Registry::Parser package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 100 |
require_ok('HoneyClient::Agent::Integrity::Registry::Parser'); |
|---|
| 101 |
use HoneyClient::Agent::Integrity::Registry::Parser; |
|---|
| 102 |
|
|---|
| 103 |
# Make sure HoneyClient::Agent::Integrity::Registry loads |
|---|
| 104 |
BEGIN { use_ok('HoneyClient::Agent::Integrity::Registry') |
|---|
| 105 |
or diag("Can't load HoneyClient::Agent::Integrity::Registry package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 106 |
require_ok('HoneyClient::Agent::Integrity::Registry'); |
|---|
| 107 |
use HoneyClient::Agent::Integrity::Registry; |
|---|
| 108 |
|
|---|
| 109 |
# Make sure File::Basename loads. |
|---|
| 110 |
BEGIN { use_ok('File::Basename', qw(dirname basename fileparse)) or diag("Can't load File::Basename package. Check to make sure the package library is correctly listed within the path."); } |
|---|
| 111 |
require_ok('File::Basename'); |
|---|
| 112 |
can_ok('File::Basename', 'dirname'); |
|---|
| 113 |
can_ok('File::Basename', 'basename'); |
|---|
| 114 |
can_ok('File::Basename', 'fileparse'); |
|---|
| 115 |
use File::Basename qw(dirname basename fileparse); |
|---|
| 116 |
} |
|---|
| 117 |
|
|---|
| 118 |
|
|---|
| 119 |
|
|---|
| 120 |
# =begin testing |
|---|
| 121 |
{ |
|---|
| 122 |
diag("These tests will create temporary files in /tmp. Be sure to cleanup this directory, if any of these tests fail."); |
|---|
| 123 |
|
|---|
| 124 |
# Create a generic Registry object, with test state data. |
|---|
| 125 |
my $registry = HoneyClient::Agent::Integrity::Registry->new(test => 1, bypass_baseline => 1); |
|---|
| 126 |
is($registry->{test}, 1, "new(test => 1, bypass_baseline => 1)") or diag("The new() call failed."); |
|---|
| 127 |
isa_ok($registry, 'HoneyClient::Agent::Integrity::Registry', "new(test => 1, bypass_baseline => 1)") or diag("The new() call failed."); |
|---|
| 128 |
|
|---|
| 129 |
diag("Performing baseline check of 'HKEY_CURRENT_USER' hive; this may take some time..."); |
|---|
| 130 |
|
|---|
| 131 |
# Perform Registry baseline on HKEY_CURRENT_USER. |
|---|
| 132 |
$registry = HoneyClient::Agent::Integrity::Registry->new(hives_to_check => [ 'HKEY_CURRENT_USER' ]); |
|---|
| 133 |
isa_ok($registry, 'HoneyClient::Agent::Integrity::Registry', "new(hives_to_check => [ 'HKEY_CURRENT_USER' ])") or diag("The new() call failed."); |
|---|
| 134 |
$registry->destroy(); |
|---|
| 135 |
} |
|---|
| 136 |
|
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 |
# =begin testing |
|---|
| 140 |
{ |
|---|
| 141 |
my ($foundChanges, $expectedChanges); |
|---|
| 142 |
my $before_registry_file = $ENV{PWD} . "/" . getVar(name => "before_registry_file", |
|---|
| 143 |
namespace => "HoneyClient::Agent::Integrity::Registry::Test"); |
|---|
| 144 |
my $after_registry_file = $ENV{PWD} . "/" . getVar(name => "after_registry_file", |
|---|
| 145 |
namespace => "HoneyClient::Agent::Integrity::Registry::Test"); |
|---|
| 146 |
|
|---|
| 147 |
|
|---|
| 148 |
# Create a generic Registry object, with test state data. |
|---|
| 149 |
my $registry = HoneyClient::Agent::Integrity::Registry->new(bypass_baseline => 1); |
|---|
| 150 |
|
|---|
| 151 |
# Verify Changes |
|---|
| 152 |
$foundChanges = $registry->check(before_file => $before_registry_file, |
|---|
| 153 |
after_file => $after_registry_file); |
|---|
| 154 |
$expectedChanges = [ |
|---|
| 155 |
{ |
|---|
| 156 |
'entries' => [ |
|---|
| 157 |
{ |
|---|
| 158 |
'new_value' => undef, |
|---|
| 159 |
'name' => 'Test_Bin_1', |
|---|
| 160 |
'old_value' => 'hex:f4,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,\\ |
|---|
| 161 |
00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,f0,77,3f,00,\\ |
|---|
| 162 |
3f,00,3f,00,3f,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,78,00,1c,10,fc,\\ |
|---|
| 163 |
7f,22,14,fc,7f,b0,fe,12,00,00,00,00,00,00,00,00,00,98,23,eb,77', |
|---|
| 164 |
}, |
|---|
| 165 |
{ |
|---|
| 166 |
'new_value' => 'hex:f4,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,bc,02,00,00,00,\\ |
|---|
| 167 |
00,00,00,00,00,00,00,54,00,61,00,68,00,6f,00,6d,00,61,00,00,00,f0,77,3f,00,\\ |
|---|
| 168 |
3f,00,3f,00,3f,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,78,00,1c,10,fc,\\ |
|---|
| 169 |
7f,22,14,fc,7f,b0,fe,12,00,00,00,00,00,00,00,00,00,98,23,eb,77', |
|---|
| 170 |
'name' => 'Test_Bon_1', |
|---|
| 171 |
'old_value' => undef, |
|---|
| 172 |
} |
|---|
| 173 |
], |
|---|
| 174 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_MODIFIED, |
|---|
| 175 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 3', |
|---|
| 176 |
}, |
|---|
| 177 |
{ |
|---|
| 178 |
'entries' => [], |
|---|
| 179 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_DELETED, |
|---|
| 180 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 4', |
|---|
| 181 |
}, |
|---|
| 182 |
{ |
|---|
| 183 |
'entries' => [ |
|---|
| 184 |
{ |
|---|
| 185 |
'new_value' => 'new value', |
|---|
| 186 |
'name' => '@', |
|---|
| 187 |
'old_value' => '', |
|---|
| 188 |
} |
|---|
| 189 |
], |
|---|
| 190 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_MODIFIED, |
|---|
| 191 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 5', |
|---|
| 192 |
}, |
|---|
| 193 |
{ |
|---|
| 194 |
'entries' => [ |
|---|
| 195 |
{ |
|---|
| 196 |
'new_value' => 'hex:f5,ff,ff,ff,00,00,00,00,00,00,00,00,00,00,00,00,90,01,00,00,00,\\ |
|---|
| 197 |
00,00,00,00,00,00,00,4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,\\ |
|---|
| 198 |
20,00,53,00,61,00,6e,00,73,00,20,00,53,00,65,00,72,00,69,00,66,00,00,00,f0,\\ |
|---|
| 199 |
77,00,20,14,00,00,00,00,10,80,05,14,00,f0,1f,14,00,00,00,14,00', |
|---|
| 200 |
'name' => 'Test_Bin_3', |
|---|
| 201 |
'old_value' => undef, |
|---|
| 202 |
} |
|---|
| 203 |
], |
|---|
| 204 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_ADDED, |
|---|
| 205 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 6', |
|---|
| 206 |
}, |
|---|
| 207 |
{ |
|---|
| 208 |
'entries' => [ |
|---|
| 209 |
{ |
|---|
| 210 |
'new_value' => 'C:\\\\WINDOWSsystem32\\\\', |
|---|
| 211 |
'name' => 'InstallerLocation', |
|---|
| 212 |
'old_value' => 'C:\\\\WINDOWS\\\\system32\\\\', |
|---|
| 213 |
} |
|---|
| 214 |
], |
|---|
| 215 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_MODIFIED, |
|---|
| 216 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 6\\With\\Really\\Deep\\Nested\\Directory\\Structure', |
|---|
| 217 |
}, |
|---|
| 218 |
{ |
|---|
| 219 |
'entries' => [ |
|---|
| 220 |
{ |
|---|
| 221 |
'new_value' => '', |
|---|
| 222 |
'name' => 'C:\\\\WINDOWS\\\\Installer\\\\{6855XXXX-BDF9-48E4-B80A-80DFB96FE36C}\\\\', |
|---|
| 223 |
'old_value' => undef, |
|---|
| 224 |
}, |
|---|
| 225 |
{ |
|---|
| 226 |
'new_value' => undef, |
|---|
| 227 |
'name' => 'C:\\\\WINDOWS\\\\Installer\\\\{6855CCDD-BDF9-48E4-B80A-80DFB96FE36C}\\\\', |
|---|
| 228 |
'old_value' => '', |
|---|
| 229 |
} |
|---|
| 230 |
], |
|---|
| 231 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_MODIFIED, |
|---|
| 232 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 7', |
|---|
| 233 |
}, |
|---|
| 234 |
{ |
|---|
| 235 |
'entries' => [ |
|---|
| 236 |
{ |
|---|
| 237 |
'new_value' => undef, |
|---|
| 238 |
'name' => '000', |
|---|
| 239 |
'old_value' => 'String Value', |
|---|
| 240 |
} |
|---|
| 241 |
], |
|---|
| 242 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_DELETED, |
|---|
| 243 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 8\\{00021492-0000-0000-C000-000000000046}', |
|---|
| 244 |
}, |
|---|
| 245 |
{ |
|---|
| 246 |
'entries' => [ |
|---|
| 247 |
{ |
|---|
| 248 |
'new_value' => 'String Value', |
|---|
| 249 |
'name' => '000', |
|---|
| 250 |
'old_value' => undef, |
|---|
| 251 |
} |
|---|
| 252 |
], |
|---|
| 253 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_ADDED, |
|---|
| 254 |
'key_name' => 'HKEY_CURRENT_USER\\Testing Group 8\\{01021492-0000-0000-C000-000000000046}', |
|---|
| 255 |
}, |
|---|
| 256 |
{ |
|---|
| 257 |
'entries' => [ |
|---|
| 258 |
{ |
|---|
| 259 |
'new_value' => 'newvalue', |
|---|
| 260 |
'name' => 'newkey', |
|---|
| 261 |
'old_value' => undef, |
|---|
| 262 |
} |
|---|
| 263 |
], |
|---|
| 264 |
'status' => $HoneyClient::Agent::Integrity::Registry::STATUS_ADDED, |
|---|
| 265 |
'key_name' => 'HKEY_CURRENT_USER\\Tsting Group 9', |
|---|
| 266 |
} |
|---|
| 267 |
]; |
|---|
| 268 |
|
|---|
| 269 |
is_deeply($foundChanges, $expectedChanges, "check(before_file => '" . $before_registry_file . "', after_file => '" . $after_registry_file . "')") or diag("The check() call failed."); |
|---|
| 270 |
$registry->destroy(); |
|---|
| 271 |
} |
|---|
| 272 |
|
|---|
| 273 |
|
|---|
| 274 |
|
|---|
| 275 |
# =begin testing |
|---|
| 276 |
{ |
|---|
| 277 |
# Perform Registry baseline on HKEY_CURRENT_CONFIG. |
|---|
| 278 |
diag("Performing baseline check of 'HKEY_CURRENT_CONFIG' hive; this may take some time..."); |
|---|
| 279 |
my $registry = HoneyClient::Agent::Integrity::Registry->new(hives_to_check => [ 'HKEY_CURRENT_CONFIG' ]); |
|---|
| 280 |
my @files_created = $registry->getFilesCreated(); |
|---|
| 281 |
use Data::Dumper; |
|---|
| 282 |
my $tmpfile = tmpnam(); |
|---|
| 283 |
unlink($tmpfile); |
|---|
| 284 |
my $tmpdir = dirname($tmpfile); |
|---|
| 285 |
foreach my $file (@files_created) { |
|---|
| 286 |
like($file, qr/$tmpdir/, "getFilesCreated()") or diag("The getFilesCreated() call failed."); |
|---|
| 287 |
} |
|---|
| 288 |
$registry->destroy(); |
|---|
| 289 |
} |
|---|
| 290 |
|
|---|
| 291 |
|
|---|
| 292 |
|
|---|
| 293 |
# =begin testing |
|---|
| 294 |
{ |
|---|
| 295 |
# Perform Registry baseline on HKEY_CURRENT_CONFIG. |
|---|
| 296 |
diag("Performing baseline check of 'HKEY_CURRENT_CONFIG' hive; this may take some time..."); |
|---|
| 297 |
my $registry = HoneyClient::Agent::Integrity::Registry->new(hives_to_check => [ 'HKEY_CURRENT_CONFIG' ]); |
|---|
| 298 |
$registry->closeFiles(); |
|---|
| 299 |
my @files_created = $registry->getFilesCreated(); |
|---|
| 300 |
use Data::Dumper; |
|---|
| 301 |
my $tmpfile = tmpnam(); |
|---|
| 302 |
unlink($tmpfile); |
|---|
| 303 |
my $tmpdir = dirname($tmpfile); |
|---|
| 304 |
foreach my $file (@files_created) { |
|---|
| 305 |
like($file, qr/$tmpdir/, "closeFiles()") or diag("The closeFiles() call failed."); |
|---|
| 306 |
} |
|---|
| 307 |
$registry->destroy(); |
|---|
| 308 |
} |
|---|
| 309 |
|
|---|
| 310 |
|
|---|
| 311 |
|
|---|
| 312 |
# =begin testing |
|---|
| 313 |
{ |
|---|
| 314 |
# Perform Registry baseline on HKEY_CURRENT_CONFIG. |
|---|
| 315 |
diag("Performing baseline check of 'HKEY_CURRENT_CONFIG' hive; this may take some time..."); |
|---|
| 316 |
my $registry = HoneyClient::Agent::Integrity::Registry->new(hives_to_check => [ 'HKEY_CURRENT_CONFIG' ]); |
|---|
| 317 |
my @files_created = $registry->getFilesCreated(); |
|---|
| 318 |
$registry->destroy(); |
|---|
| 319 |
use Data::Dumper; |
|---|
| 320 |
foreach my $file (@files_created) { |
|---|
| 321 |
is(-e $file, undef, "destroy()") or diag("The destroy() call failed."); |
|---|
| 322 |
} |
|---|
| 323 |
} |
|---|
| 324 |
|
|---|
| 325 |
|
|---|
| 326 |
|
|---|
| 327 |
|
|---|
| 328 |
1; |
|---|