45 | 45 |
use File::Basename;
|
46 | 46 |
use Data::Dumper;
|
47 | 47 |
use Scalar::Util qw(tainted);
|
48 | |
|
49 | |
my $VERSION="0.8.9";
|
|
48 |
use Term::ANSIColor;
|
|
49 |
|
|
50 |
my $VERSION="0.9.1";
|
50 | 51 |
my $verbose = 0;
|
51 | 52 |
my $debug = 0;
|
|
53 |
my $aggressive = 0;
|
52 | 54 |
my $global_fail_limit = 1000; # no command line option yet
|
53 | 55 |
my $global_search_until_fail = 0; # no command line option yet
|
54 | 56 |
my $heighest_rid = 999999;
|
55 | |
my $global_workgroup = undef;
|
|
57 |
my $global_workgroup = '';
|
56 | 58 |
my $global_username = '';
|
57 | 59 |
my $global_password = '';
|
58 | 60 |
my $global_dictionary = 0;
|
59 | |
my $global_filename = undef;
|
60 | |
my $global_share_file = undef;
|
|
61 |
my $global_filename = '';
|
|
62 |
my $global_share_file = '';
|
61 | 63 |
my $global_detailed = 0;
|
62 | 64 |
my $global_passpol = 0;
|
63 | 65 |
my $global_rid_range = "500-550,1000-1050";
|
64 | 66 |
my $global_known_username_string = "administrator,guest,krbtgt,domain admins,root,bin,none";
|
65 | 67 |
my @dependent_programs = qw(nmblookup net rpcclient smbclient);
|
66 | |
my @optional_dependent_programs = qw(polenum.py ldapsearch);
|
|
68 |
my @optional_dependent_programs = qw(polenum ldapsearch);
|
67 | 69 |
my %odp_present = ();
|
68 | 70 |
my $null_session_test = 0;
|
69 | 71 |
my %opts;
|
|
155 | 157 |
|
156 | 158 |
Additional options:
|
157 | 159 |
-a Do all simple enumeration (-U -S -G -P -r -o -n -i).
|
158 | |
This opion is enabled if you don't provide any other options.
|
|
160 |
This option is enabled if you don't provide any other options.
|
159 | 161 |
-h Display this help message and exit
|
160 | 162 |
-r enumerate users via RID cycling
|
161 | 163 |
-R range RID ranges to enumerate (default: $global_rid_range, implies -r)
|
|
172 | 174 |
-w wrkg Specify workgroup manually (usually found automatically)
|
173 | 175 |
-n Do an nmblookup (similar to nbtstat)
|
174 | 176 |
-v Verbose. Shows full commands being run (net, rpcclient, etc.)
|
|
177 |
-A Aggressive. Do write checks on shares etc
|
175 | 178 |
|
176 | 179 |
RID cycling should extract a list of users from Windows \(or Samba\) hosts
|
177 | 180 |
which have RestrictAnonymous set to 1 \(Windows NT and 2000\), or \"Network
|
|
208 | 211 |
$ENV{'PATH'} =~ s/^\.://;
|
209 | 212 |
$ENV{'PATH'} =~ s/:\.//;
|
210 | 213 |
|
211 | |
getopts('UMNSPGlLDu:dp:f:rR:s:k:vow:hnaiPK:', \%opts);
|
|
214 |
getopts('UMNSPGlLDu:dp:f:rR:s:k:vAow:hnaiPK:', \%opts);
|
212 | 215 |
|
213 | 216 |
# Print help message if required
|
214 | 217 |
if ($opts{'h'}) {
|
|
218 | 221 |
|
219 | 222 |
# Read host and untaint
|
220 | 223 |
my $global_target = shift or die $usage;
|
221 | |
if ($global_target =~ /^([a-zA-Z0-9\._-]+)$/) {
|
|
224 |
if ($global_target =~ /^([a-zA-Z0-9\._\-]+)$/) {
|
222 | 225 |
$global_target = $1;
|
223 | 226 |
} else {
|
224 | 227 |
print "ERROR: Target hostname \"$global_target\" contains some illegal characters\n";
|
|
258 | 261 |
$global_known_username_string = $opts{'k'} if $opts{'k'};
|
259 | 262 |
$global_workgroup = $opts{'w'} if $opts{'w'};
|
260 | 263 |
$verbose = $opts{'v'} if $opts{'v'};
|
|
264 |
$aggressive = 1 if $opts{'A'};
|
261 | 265 |
$opts{'r'} = 1 if $opts{'R'};
|
262 | 266 |
|
263 | 267 |
$global_search_until_fail = 1 if defined($opts{'K'});
|
|
273 | 277 |
print "ERROR: $prog is not in your path. Check that samba package is installed\n";
|
274 | 278 |
$dependency_error = 1;
|
275 | 279 |
} else {
|
276 | |
print "[V] Dependent program \"$prog\" found in $which_output\n" if $verbose;
|
|
280 |
print_verbose("Dependent program \"$prog\" found in $which_output\n") if $verbose;
|
277 | 281 |
}
|
278 | 282 |
}
|
279 | 283 |
foreach my $prog (@optional_dependent_programs) {
|
|
283 | 287 |
print "WARNING: $prog is not in your path. Check that package is installed and your PATH is sane.\n";
|
284 | 288 |
$odp_present{$prog} = 0;
|
285 | 289 |
} else {
|
286 | |
print "[V] Dependent program \"$prog\" found in $which_output\n" if $verbose;
|
|
290 |
print_verbose("Dependent program \"$prog\" found in $which_output\n") if $verbose;
|
287 | 291 |
$odp_present{$prog} = 1;
|
288 | 292 |
}
|
289 | 293 |
}
|
|
295 | 299 |
|
296 | 300 |
# Untaint workgroup if supplied on command line
|
297 | 301 |
if (defined($global_workgroup)) {
|
298 | |
if ($global_workgroup =~ /^([a-zA-Z0-9\.-_]*)$/) {
|
|
302 |
if ($global_workgroup =~ /^([a-zA-Z0-9\.\-_]*)$/) {
|
299 | 303 |
$global_workgroup = $1;
|
300 | 304 |
} else {
|
301 | |
print "ERROR: Workgroup \"$global_workgroup\"contains some illegal characters\n";
|
|
305 |
print "ERROR: Workgroup \"$global_workgroup\" contains some illegal characters\n";
|
302 | 306 |
exit 1;
|
303 | 307 |
}
|
304 | 308 |
}
|
|
308 | 312 |
foreach my $known_username (@global_known_usernames) {
|
309 | 313 |
$known_username =~ s/'/'\''/g; ($known_username) = $known_username =~ /(.*)/;
|
310 | 314 |
}
|
311 | |
$global_username =~ s/'/'\''/g; ($global_username) = $global_username =~ /(.*)/;
|
312 | |
$global_password =~ s/'/'\''/g; ($global_password) = $global_password =~ /(.*)/;
|
|
315 |
$global_username =~ s/'/'\\''/g; ($global_username) = $global_username =~ /(.*)/;
|
|
316 |
$global_password =~ s/'/'\\''/g; ($global_password) = $global_password =~ /(.*)/;
|
313 | 317 |
|
314 | 318 |
# Output message about options used
|
315 | 319 |
print "Starting enum4linux v$VERSION ( http://labs.portcullis.co.uk/application/enum4linux/ ) on " . scalar(localtime) . "\n";
|
|
356 | 360 |
sub get_domain_sid {
|
357 | 361 |
print_heading("Getting domain SID for $global_target");
|
358 | 362 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' $global_target -c 'lsaquery' 2>&1";
|
359 | |
print "[V] Attempting to get domain SID with command: $command\n" if $verbose;
|
|
363 |
print_verbose("Attempting to get domain SID with command: $command\n") if $verbose;
|
360 | 364 |
my $domain_sid_text = `$command`;
|
361 | 365 |
chomp $domain_sid_text;
|
362 | 366 |
print $domain_sid_text;
|
363 | 367 |
print "\n";
|
364 | 368 |
if ($domain_sid_text =~ /Domain Sid: S-0-0/) {
|
365 | |
print "[+] Host is part of a workgroup (not a domain)\n";
|
|
369 |
print_plus("Host is part of a workgroup (not a domain)\n");
|
366 | 370 |
} elsif ($domain_sid_text =~ /Domain Sid: S-\d+-\d+-\d+-\d+-\d+-\d+/) {
|
367 | |
print "[+] Host is part of a domain (not a workgroup)\n";
|
368 | |
} else {
|
369 | |
print "[+] Can't determine if host is part of domain or part of a workgroup\n";
|
|
371 |
print_plus("Host is part of a domain (not a workgroup)\n");
|
|
372 |
} else {
|
|
373 |
print_plus("Can't determine if host is part of domain or part of a workgroup\n");
|
370 | 374 |
}
|
371 | 375 |
}
|
372 | 376 |
|
373 | 377 |
# Get workgroup from nbstat info - we need this for lots of rpcclient calls
|
374 | 378 |
sub get_workgroup {
|
375 | 379 |
print_heading("Enumerating Workgroup/Domain on $global_target");
|
376 | |
print "[V] Attempting to get domain name with command: nmblookup -A '$global_target'\n" if $verbose;
|
|
380 |
print_verbose("Attempting to get domain name with command: nmblookup -A '$global_target'\n") if $verbose;
|
377 | 381 |
|
378 | 382 |
# Workgroup might already be known - e.g. from command line or from get_os_info()
|
379 | 383 |
unless ($global_workgroup) {
|
|
381 | 385 |
$global_workgroup = `nmblookup -A '$global_target'`; # Global var. Erg!
|
382 | 386 |
($global_workgroup) = $global_workgroup =~ /\s+(\S+)\s+<00> - <GROUP>/s;
|
383 | 387 |
unless (defined($global_workgroup)) {
|
384 | |
print "[E] Can\'t find workgroup/domain\n";
|
385 | |
print "\n";
|
386 | |
return undef;
|
387 | |
}
|
388 | |
unless (defined($global_workgroup) and $global_workgroup =~ /^[A-Za-z0-9_\.-]+$/) {
|
389 | |
print "ERROR: Workgroup \"$global_workgroup\"contains some illegal characters\n";
|
|
388 |
# dc.example.org. hostmaster.example.org. 1 900 600 86400 3600
|
|
389 |
$global_workgroup = `dig +short 0.in-addr.arpa`;
|
|
390 |
($global_workgroup) = $global_workgroup =~ /.*\. hostmaster\.(.*?)\. .*/s;
|
|
391 |
if (defined($global_workgroup)) {
|
|
392 |
print "[+] Domain guessed: $global_workgroup\n";
|
|
393 |
} else {
|
|
394 |
$global_workgroup = "WORKGROUP";
|
|
395 |
print_error("Can\'t find workgroup/domain\n");
|
|
396 |
print "\n";
|
|
397 |
return;
|
|
398 |
}
|
|
399 |
}
|
|
400 |
unless (defined($global_workgroup) and $global_workgroup =~ /^[A-Za-z0-9_\.\-]+$/) {
|
|
401 |
print_error("Workgroup \"$global_workgroup\"contains some illegal characters\n");
|
390 | 402 |
exit 1;
|
391 | 403 |
}
|
392 | 404 |
}
|
393 | |
print "[+] Got domain/workgroup name: $global_workgroup\n";
|
|
405 |
print_plus("Got domain/workgroup name: $global_workgroup\n");
|
394 | 406 |
}
|
395 | 407 |
|
396 | 408 |
# Get long domain name via LDAP
|
|
398 | 410 |
sub get_ldapinfo {
|
399 | 411 |
print_heading("Getting information via LDAP for $global_target");
|
400 | 412 |
my $command = "ldapsearch -x -h '$global_target' -p 389 -s base namingContexts 2>&1";
|
401 | |
print "[V] Attempting to long domain name: $command\n" if $verbose;
|
|
413 |
print_verbose("Attempting to long domain name: $command\n") if $verbose;
|
402 | 414 |
unless ($odp_present{"ldapsearch"}) {
|
403 | |
print "[E] Dependent program \"ldapsearch\" not present. Skipping this check. Install ldapsearch to fix.\n\n";
|
|
415 |
print_error("Dependent program \"ldapsearch\" not present. Skipping this check. Install ldapsearch to fix.\n\n");
|
404 | 416 |
return 0;
|
405 | 417 |
}
|
406 | 418 |
|
407 | 419 |
my $output = `$command`;
|
408 | 420 |
|
409 | 421 |
if ($output =~ /ldap_sasl_bind/) {
|
410 | |
print "[E] Connection error\n";
|
|
422 |
print_error("Connection error\n");
|
411 | 423 |
return 0;
|
412 | 424 |
}
|
413 | 425 |
my $parent = 0;
|
|
418 | 430 |
my $long_domain = $1;
|
419 | 431 |
$long_domain =~ s/DC=//g;
|
420 | 432 |
$long_domain =~ s/,/./g;
|
421 | |
print "[+] Long domain name for $global_target: $long_domain\n";
|
|
433 |
print_plus("Long domain name for $global_target: $long_domain\n");
|
422 | 434 |
}
|
423 | 435 |
}
|
424 | 436 |
|
425 | 437 |
if ($parent == 1) {
|
426 | |
print "[+] $global_target appears to be a root/parent DC\n";
|
427 | |
} else {
|
428 | |
print "[+] $global_target appears to be a child DC\n";
|
|
438 |
print_plus("$global_target appears to be a root/parent DC\n");
|
|
439 |
} else {
|
|
440 |
print_plus("$global_target appears to be a child DC\n");
|
429 | 441 |
}
|
430 | 442 |
|
431 | 443 |
}
|
|
434 | 446 |
sub make_session {
|
435 | 447 |
print_heading("Session Check on $global_target");
|
436 | 448 |
my $command = "smbclient -W '$global_workgroup' //'$global_target'/ipc\$ -U'$global_username'\%'$global_password' -c 'help' 2>&1";
|
437 | |
print "[V] Attempting to make null session using command: $command\n" if $verbose;
|
|
449 |
print_verbose("Attempting to make null session using command: $command\n") if $verbose;
|
438 | 450 |
my $os_info = `$command`;
|
439 | 451 |
chomp $os_info;
|
|
452 |
if ($os_info =~ /protocol negotiation failed: NT_STATUS_CONNECTION_RESET/) {
|
|
453 |
print_error("Protocol mismatch. smbclient doesn\'t support the same protocol versions as the server. You likely need to install a later version of Samba.\n");
|
|
454 |
}
|
440 | 455 |
if ($os_info =~ /case_sensitive/) {
|
441 | |
print "[+] Server $global_target allows sessions using username '$global_username', password '$global_password'\n";
|
442 | |
} else {
|
443 | |
print "[E] Server doesn't allow session using username '$global_username', password '$global_password'. Aborting remainder of tests.\n";
|
|
456 |
print_plus("Server $global_target allows sessions using username '$global_username', password '$global_password'\n");
|
|
457 |
} else {
|
|
458 |
print_error("Server doesn't allow session using username '$global_username', password '$global_password'. Aborting remainder of tests.\n");
|
444 | 459 |
exit 1;
|
445 | 460 |
}
|
446 | 461 |
|
447 | 462 |
# Use this info to set workgroup if possible
|
448 | 463 |
unless ($global_workgroup) {
|
449 | 464 |
($global_workgroup) = $os_info =~ /Domain=\[([^]]*)\]/;
|
450 | |
print "[+] Got domain/workgroup name: $global_workgroup\n";
|
|
465 |
print_plus("Got domain/workgroup name: $global_workgroup\n");
|
451 | 466 |
}
|
452 | 467 |
}
|
453 | 468 |
|
454 | 469 |
# Get OS info
|
455 | 470 |
sub get_os_info {
|
456 | 471 |
print_heading("OS information on $global_target");
|
|
472 |
|
|
473 |
|
457 | 474 |
my $command = "smbclient -W '$global_workgroup' //'$global_target'/ipc\$ -U'$global_username'\%'$global_password' -c 'q' 2>&1";
|
458 | |
print "[V] Attempting to get OS info with command: $command\n" if $verbose;
|
|
475 |
print_verbose("Attempting to get OS info with command: $command\n") if $verbose;
|
459 | 476 |
my $os_info = `$command`;
|
460 | 477 |
chomp $os_info;
|
|
478 |
|
461 | 479 |
if (defined($os_info)) {
|
462 | |
($os_info) = $os_info =~ /(Domain=[^\n]+)/s;
|
463 | |
print "[+] Got OS info for $global_target from smbclient: $os_info\n";
|
|
480 |
if ($os_info =~ /(Domain=[^\n]+)/s) {
|
|
481 |
($os_info) = $os_info =~ /(Domain=[^\n]+)/s;
|
|
482 |
print_plus("Got OS info for $global_target from smbclient: ");
|
|
483 |
print "$os_info\n";
|
|
484 |
} else {
|
|
485 |
print_error("Can't get OS info with smbclient\n");
|
|
486 |
}
|
464 | 487 |
}
|
465 | 488 |
|
466 | 489 |
$command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' -c 'srvinfo' '$global_target' 2>&1";
|
467 | |
print "[V] Attempting to get OS info with command: $command\n" if $verbose;
|
|
490 |
print_verbose("Attempting to get OS info with command: $command\n") if $verbose;
|
468 | 491 |
$os_info = `$command`;
|
469 | 492 |
if (defined($os_info)) {
|
470 | 493 |
if ($os_info =~ /error: NT_STATUS_ACCESS_DENIED/) {
|
471 | |
print "[E] Can't get OS info with srvinfo: NT_STATUS_ACCESS_DENIED\n";
|
472 | |
} else {
|
473 | |
print "[+] Got OS info for $global_target from srvinfo:\n$os_info";
|
|
494 |
print_error("Can't get OS info with srvinfo\n");
|
|
495 |
} else {
|
|
496 |
print_plus("Got OS info for $global_target from srvinfo: ");
|
|
497 |
print "$os_info\n";
|
474 | 498 |
}
|
475 | 499 |
}
|
476 | 500 |
}
|
477 | 501 |
|
478 | 502 |
sub enum_password_policy {
|
479 | 503 |
print_heading("Password Policy Information for $global_target");
|
480 | |
my $command = "polenum.py '$global_username':'$global_password'\@'$global_target' 2>&1";
|
481 | |
unless ($odp_present{"polenum.py"}) {
|
482 | |
print "[E] Dependent program \"polenum.py\" not present. Skipping this check. Download polenum from http://labs.portcullis.co.uk/application/polenum/\n\n";
|
|
504 |
my $command = "polenum '$global_username':'$global_password'\@'$global_target' 2>&1";
|
|
505 |
unless ($odp_present{"polenum"}) {
|
|
506 |
print_error("Dependent program \"polenum\" not present. Skipping this check. Download polenum from http://labs.portcullis.co.uk/application/polenum/\n\n");
|
483 | 507 |
return 0;
|
484 | 508 |
}
|
485 | |
print "[V] Attempting to get Password Policy info with command: $command\n" if $verbose;
|
|
509 |
print_verbose("Attempting to get Password Policy info with command: $command\n") if $verbose;
|
486 | 510 |
my $passpol_info = `$command`;
|
487 | 511 |
chomp $passpol_info;
|
488 | 512 |
if (defined($passpol_info)) {
|
489 | 513 |
if ($passpol_info =~ /Account Lockout Threshold/) {
|
490 | 514 |
print $passpol_info;
|
491 | 515 |
} elsif ($passpol_info =~ /Error Getting Password Policy: Connect error/) {
|
492 | |
print "[E] Can't connect to host with supplied credentials.\n";
|
493 | |
} else {
|
494 | |
print "[E] Unexpected error from polenum.py:\n";
|
|
516 |
print_error("Can't connect to host with supplied credentials.\n");
|
|
517 |
} else {
|
|
518 |
print_error("Unexpected error from polenum:\n");
|
495 | 519 |
print $passpol_info;
|
496 | 520 |
}
|
497 | 521 |
} else {
|
498 | |
print "[E] polenum.py gave no output.\n";
|
|
522 |
print_error("polenum gave no output.\n");
|
499 | 523 |
}
|
500 | 524 |
$command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' '$global_target' -c \"getdompwinfo\" 2>&1";
|
501 | |
print "[V] Attempting to get Password Policy info with command: $command\n" if $verbose;
|
|
525 |
print_verbose("Attempting to get Password Policy info with command: $command\n") if $verbose;
|
502 | 526 |
$passpol_info = `$command`;
|
503 | 527 |
chomp $passpol_info;
|
504 | 528 |
print "\n";
|
505 | 529 |
if (defined($passpol_info) and $passpol_info !~ /ACCESS_DENIED/) {
|
506 | |
print "[+] Retieved partial password policy with rpcclient:\n\n";
|
|
530 |
print_plus("Retieved partial password policy with rpcclient:\n\n");
|
507 | 531 |
if ($passpol_info =~ /password_properties: 0x[0-9a-fA-F]{7}0/) {
|
508 | 532 |
print "Password Complexity: Disabled\n";
|
509 | 533 |
} elsif ($passpol_info =~ /password_properties: 0x[0-9a-fA-F]{7}1/) {
|
|
514 | 538 |
print "Minimum Password Length: $minlen\n";
|
515 | 539 |
}
|
516 | 540 |
} else {
|
517 | |
print "[E] Failed to get password policy with rpcclient\n";
|
|
541 |
print_error("Failed to get password policy with rpcclient\n");
|
518 | 542 |
}
|
519 | 543 |
print "\n";
|
520 | 544 |
}
|
521 | 545 |
|
522 | 546 |
sub enum_lsa_policy {
|
523 | 547 |
print_heading("LSA Policy Information on $global_target");
|
524 | |
print "[E] Internal error. Not implmented in this version of enum4linux.\n";
|
|
548 |
print_error("Not implemented in this version of enum4linux.\n");
|
525 | 549 |
}
|
526 | 550 |
|
527 | 551 |
sub enum_machines {
|
528 | 552 |
print_heading("Machine Enumeration on $global_target");
|
529 | |
print "[E] Internal error. Not implmented in this version of enum4linux.\n";
|
|
553 |
print_error("Not implemented in this version of enum4linux.\n");
|
530 | 554 |
}
|
531 | 555 |
|
532 | 556 |
sub enum_names {
|
533 | 557 |
print_heading("Name Enumeration on $global_target");
|
534 | |
print "[E] Internal error. Not implmented in this version of enum4linux.\n";
|
|
558 |
print_error("Not implemented in this version of enum4linux.\n");
|
535 | 559 |
}
|
536 | 560 |
|
537 | 561 |
sub enum_groups {
|
|
540 | 564 |
# Get list of groups
|
541 | 565 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' '$global_target' -c 'enumalsgroups $grouptype' 2>&1";
|
542 | 566 |
if ($grouptype eq "domain") {
|
543 | |
print "[V] Getting local groups with command: $command\n" if $verbose;
|
544 | |
print "\n[+] Getting local groups:\n";
|
545 | |
} else {
|
546 | |
print "[V] Getting $grouptype groups with command: $command\n" if $verbose;
|
547 | |
print "\n[+] Getting $grouptype groups:\n";
|
|
567 |
print_verbose("Getting local groups with command: $command\n") if $verbose;
|
|
568 |
print_plus(" Getting local groups:\n");
|
|
569 |
} else {
|
|
570 |
print_verbose("Getting $grouptype groups with command: $command\n") if $verbose;
|
|
571 |
print_plus("Getting $grouptype groups:\n");
|
548 | 572 |
}
|
549 | 573 |
my $groups_string = `$command`;
|
550 | 574 |
if ($groups_string =~ /error: NT_STATUS_ACCESS_DENIED/) {
|
551 | 575 |
if ($grouptype eq "domain") {
|
552 | |
print "[E] Can't get local groups: NT_STATUS_ACCESS_DENIED\n";
|
|
576 |
print_error("Can't get local groups: NT_STATUS_ACCESS_DENIED\n");
|
553 | 577 |
} else {
|
554 | |
print "[E] Can't get $grouptype groups: NT_STATUS_ACCESS_DENIED\n";
|
|
578 |
print_error("Can't get $grouptype groups: NT_STATUS_ACCESS_DENIED\n");
|
555 | 579 |
}
|
556 | 580 |
} else {
|
557 | 581 |
($groups_string) = $groups_string =~ /(group:.*)/s;
|
|
562 | 586 |
# Get group members
|
563 | 587 |
my %rid_of_group = $groups_string =~ /\[([^\]]+)\]/sg;
|
564 | 588 |
if ($grouptype eq "domain") {
|
565 | |
print "\n[+] Getting local group memberships:\n";
|
566 | |
} else {
|
567 | |
print "\n[+] Getting $grouptype group memberships:\n";
|
|
589 |
print_plus(" Getting local group memberships:\n");
|
|
590 |
} else {
|
|
591 |
print_plus(" Getting $grouptype group memberships:\n");
|
568 | 592 |
}
|
569 | 593 |
foreach my $groupname (keys %rid_of_group) {
|
570 | 594 |
$groupname =~ s/'/'\\''/g;
|
571 | 595 |
$rid_of_group{$groupname} =~ s/^0x//;
|
572 | 596 |
$rid_of_group{$groupname} = hex($rid_of_group{$groupname});
|
573 | 597 |
$command = "net rpc group members '$groupname' -W '$global_workgroup' -I '$global_target' -U'$global_username'\%'$global_password' 2>&1\n";
|
574 | |
print "[V] Running command: $command\n" if $verbose;
|
|
598 |
print_verbose("Running command: $command\n") if $verbose;
|
575 | 599 |
my $members = `$command`;
|
576 | 600 |
my @members = split "\n", $members;
|
577 | 601 |
foreach my $m (@members) {
|
578 | |
print "Group '$groupname' (RID: " . $rid_of_group{$groupname} . ") has member: $m\n";
|
|
602 |
print colored("Group: ", 'magenta');
|
|
603 |
print "$groupname' (RID: " . $rid_of_group{$groupname} . ") has member: $m\n";
|
579 | 604 |
}
|
580 | 605 |
}
|
581 | 606 |
if ($global_detailed) {
|
582 | 607 |
foreach my $groupname (keys %rid_of_group) {
|
583 | |
print "[+] Getting detailed info for group $groupname (RID: " . $rid_of_group{$groupname} . ")\n";
|
|
608 |
print_plus("Getting detailed info for group $groupname (RID: " . $rid_of_group{$groupname} . ")\n");
|
584 | 609 |
get_group_details_from_rid($rid_of_group{$groupname});
|
585 | 610 |
}
|
586 | 611 |
}
|
|
590 | 615 |
sub enum_dom_groups {
|
591 | 616 |
# Get list of groups
|
592 | 617 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' '$global_target' -c \"enumdomgroups\" 2>&1";
|
593 | |
print "[V] Getting domain groups with command: $command\n" if $verbose;
|
594 | |
print "\n[+] Getting domain groups:\n";
|
|
618 |
print_verbose("Getting domain groups with command: $command\n") if $verbose;
|
|
619 |
print_plus(" Getting domain groups:\n");
|
595 | 620 |
|
596 | 621 |
my $groups_string = `$command`;
|
597 | 622 |
if ($groups_string =~ /error: NT_STATUS_ACCESS_DENIED/) {
|
598 | |
print "[E] Can't get domain groups: NT_STATUS_ACCESS_DENIED\n";
|
|
623 |
print_error("Can't get domain groups: NT_STATUS_ACCESS_DENIED\n");
|
599 | 624 |
} else {
|
600 | 625 |
($groups_string) = $groups_string =~ /(group:.*)/s;
|
601 | 626 |
$groups_string = "" unless defined($groups_string);
|
|
604 | 629 |
|
605 | 630 |
# Get group members
|
606 | 631 |
my %rid_of_group = $groups_string =~ /\[([^\]]+)\]/sg;
|
607 | |
print "\n[+] Getting domain group memberships:\n";
|
|
632 |
print_plus(" Getting domain group memberships:\n");
|
608 | 633 |
|
609 | 634 |
foreach my $groupname (keys %rid_of_group) {
|
610 | 635 |
$groupname =~ s/'/'\\''/g;
|
611 | 636 |
$rid_of_group{$groupname} =~ s/^0x//;
|
612 | 637 |
$rid_of_group{$groupname} = hex($rid_of_group{$groupname});
|
613 | 638 |
$command = "net rpc group members '$groupname' -W '$global_workgroup' -I '$global_target' -U'$global_username'\%'$global_password' 2>&1\n";
|
614 | |
print "[V] Running command: $command\n" if $verbose;
|
|
639 |
print_verbose("Running command: $command\n") if $verbose;
|
615 | 640 |
my $members = `$command`;
|
616 | 641 |
my @members = split "\n", $members;
|
617 | 642 |
foreach my $m (@members) {
|
618 | |
print "Group '$groupname' (RID: " . $rid_of_group{$groupname} . ") has member: $m\n";
|
|
643 |
print colored("Group: ", 'magenta');
|
|
644 |
print "'$groupname' (RID: " . $rid_of_group{$groupname} . ") has member: $m\n";
|
619 | 645 |
}
|
620 | 646 |
}
|
621 | 647 |
if ($global_detailed) {
|
622 | 648 |
foreach my $groupname (keys %rid_of_group) {
|
623 | |
print "[+] Getting detailed info for group $groupname (RID: " . $rid_of_group{$groupname} . ")\n";
|
|
649 |
print_plus("Getting detailed info for group $groupname (RID: " . $rid_of_group{$groupname} . ")\n");
|
624 | 650 |
get_group_details_from_rid($rid_of_group{$groupname});
|
625 | 651 |
}
|
626 | 652 |
}
|
|
628 | 654 |
|
629 | 655 |
sub enum_groups_unauth {
|
630 | 656 |
print_heading("Groups on $global_target via RID cycling");
|
631 | |
print "[E] INTERNAL ERROR. Not implmented yet. Maybe in the next version.\n";
|
|
657 |
print_error("Not implemented in this version of enum4linux.\n");
|
632 | 658 |
}
|
633 | 659 |
|
634 | 660 |
sub enum_shares {
|
635 | 661 |
# Share enumeration
|
636 | 662 |
print_heading("Share Enumeration on $global_target");
|
637 | |
print "[V] Attempting to get share list using authentication\n" if $verbose;
|
|
663 |
print_verbose("Attempting to get share list using authentication\n") if $verbose;
|
638 | 664 |
# my $shares = `net rpc share -W '$global_workgroup' -I '$global_target' -U'$global_username'\%'$global_password' 2>&1`;
|
639 | 665 |
my $command = "smbclient -W '$global_workgroup' -L //'$global_target' -U'$global_username'\%'$global_password' 2>&1";
|
640 | 666 |
my $shares = `$command`;
|
641 | 667 |
if (defined($shares)) {
|
642 | 668 |
if ($shares =~ /NT_STATUS_ACCESS_DENIED/) {
|
643 | |
print "[E] Can't list shares: NT_STATUS_ACCESS_DENIED\n";
|
|
669 |
print_error("Can't list shares: NT_STATUS_ACCESS_DENIED\n");
|
644 | 670 |
} else {
|
645 | 671 |
print "$shares";
|
646 | 672 |
}
|
647 | 673 |
}
|
648 | 674 |
|
649 | |
print "\n[+] Attempting to map shares on $global_target\n";
|
650 | |
my @shares = $shares =~ /\n\s+(\S+)\s+(?:Disk|IPC|Printer)/igs;
|
|
675 |
print_plus("Attempting to map shares on $global_target\n");
|
|
676 |
my @shares = $shares =~ /^[\t ]*?([ \S]+?)[\t ]*?(?:Disk|IPC|Printer)[^\n]*/gms;
|
651 | 677 |
foreach my $share (@shares) {
|
|
678 |
my ($mapping_result, $listing_result, $writing_result) = ("N/A","N/A","N/A");
|
|
679 |
|
652 | 680 |
$share =~ s/'/'\\''/g;
|
653 | 681 |
my $command = "smbclient -W '$global_workgroup' //'$global_target'/'$share' -U'$global_username'\%'$global_password' -c dir 2>&1";
|
654 | |
print "[V] Attempting map to share //$global_target/$share with command: $command\n" if $verbose;
|
|
682 |
print_verbose("Attempting map to share //$global_target/$share with command: $command\n") if $verbose;
|
655 | 683 |
my $output = `$command`;
|
|
684 |
|
|
685 |
if ($output =~ /NT_STATUS_ACCESS_DENIED listing/ ||
|
|
686 |
$output =~ /do_list:.*NT_STATUS_ACCESS_DENIED/ ) {
|
|
687 |
$mapping_result="OK"; $listing_result="DENIED";
|
|
688 |
} elsif ($output =~ /tree connect failed: NT_STATUS_ACCESS_DENIED/) {
|
|
689 |
$mapping_result="DENIED"; $listing_result="N/A";
|
|
690 |
} elsif ($output =~ /\n\s+\.\.\s+D.*\d{4}\n/) {
|
|
691 |
$mapping_result="OK" ; $listing_result="OK";
|
|
692 |
} else {
|
|
693 |
print_error("Can't understand response:\n");
|
|
694 |
print $output;
|
|
695 |
}
|
|
696 |
if ($mapping_result eq "OK") {
|
|
697 |
if ($aggressive) {
|
|
698 |
print "testing write access " . $share . "\n";
|
|
699 |
# check for write access
|
|
700 |
my @chars = ("A".."Z", "a".."z", "0".."9");
|
|
701 |
my $random_string;
|
|
702 |
$random_string .= $chars[rand @chars] for 1..8;
|
|
703 |
|
|
704 |
$command = "smbclient -W '$global_workgroup' //'$global_target'/'$share' -U'$global_username'\%'$global_password' -c 'mkdir $random_string' 2>&1";
|
|
705 |
print_verbose("Checking write access to share //$global_target/$share with command: $command\n") if $verbose;
|
|
706 |
$output = `$command` ;
|
|
707 |
if ($output =~ /NT_STATUS_ACCESS_DENIED making/) {
|
|
708 |
$writing_result="DENIED" ;
|
|
709 |
} elsif (length $output) {
|
|
710 |
# the command should not give any output, if something was output maybe it's a failure
|
|
711 |
my $command2 = "smbclient -W '$global_workgroup' //'$global_target'/'$share' -U'$global_username'\%'$global_password' -c dir 2>&1";
|
|
712 |
print_verbose("Attempting check for directory $random_string on //$global_target/$share with command: $command2\n") if $verbose;
|
|
713 |
my $output2 = `$command2`;
|
|
714 |
if ($output2 =~ /.*$random_string.*/) {
|
|
715 |
$writing_result="OK";
|
|
716 |
} else {
|
|
717 |
print_error("Can't understand initial response:\n");
|
|
718 |
print $output;
|
|
719 |
print_error("Can't understand second response:\n");
|
|
720 |
print $output2;
|
|
721 |
}
|
|
722 |
} else {
|
|
723 |
$writing_result="OK";
|
|
724 |
}
|
|
725 |
if ($writing_result ne "DENIED") {
|
|
726 |
# remove the directory we created
|
|
727 |
$command = "smbclient -W '$global_workgroup' //'$global_target'/'$share' -U'$global_username'\%'$global_password' -c 'rmdir $random_string' 2>&1";
|
|
728 |
print_verbose("Removing created directory on share //$global_target/$share with command: $command\n") if $verbose;
|
|
729 |
$output=`$command` ;
|
|
730 |
if (length $output) {
|
|
731 |
print_error("rmdir command returned the following:\n");
|
|
732 |
print $output ;
|
|
733 |
}
|
|
734 |
}
|
|
735 |
}
|
|
736 |
}
|
|
737 |
# print results
|
656 | 738 |
print "//$global_target/$share\t";
|
657 | |
if ($output =~ /NT_STATUS_ACCESS_DENIED listing/) {
|
658 | |
print "Mapping: OK\tListing: DENIED\n";
|
659 | |
} elsif ($output =~ /tree connect failed: NT_STATUS_ACCESS_DENIED/) {
|
660 | |
print "Mapping: DENIED, Listing: N/A\n";
|
661 | |
} elsif ($output =~ /\n\s+\.\.\s+D.*\d{4}\n/) {
|
662 | |
print "Mapping: OK, Listing: OK\n";
|
663 | |
} else {
|
664 | |
print "[E] Can't understand response:\n";
|
665 | |
print $output;
|
666 | |
}
|
|
739 |
print colored("Mapping: ", 'magenta');
|
|
740 |
print $mapping_result ;
|
|
741 |
print colored(" Listing: ", 'magenta');
|
|
742 |
print $listing_result ;
|
|
743 |
print colored(" Writing: ", 'magenta');
|
|
744 |
print $writing_result ;
|
|
745 |
print "\n" ;
|
667 | 746 |
}
|
668 | 747 |
}
|
669 | 748 |
|
670 | 749 |
sub enum_shares_unauth {
|
671 | 750 |
print_heading("Brute Force Share Enumeration on $global_target");
|
672 | |
print "[V] Attempting to get share list using bruteforcing\n" if $verbose;
|
|
751 |
print_verbose("Attempting to get share list using bruteforcing\n") if $verbose;
|
673 | 752 |
my $shares_file = $global_share_file;
|
674 | 753 |
open SHARES, "<$shares_file" or die "[E] Can't open share list file $shares_file: $!\n";
|
675 | 754 |
my @shares = <SHARES>;
|
|
677 | 756 |
|
678 | 757 |
foreach my $share (@shares) {
|
679 | 758 |
# Untaint $share
|
680 | |
if ($share =~ /^([a-zA-Z0-9\._\$-]+)$/) {
|
|
759 |
if ($share =~ /^([a-zA-Z0-9\._\$\-]+)$/) {
|
681 | 760 |
$share = $1;
|
682 | 761 |
} else {
|
683 | |
print "ERROR: Share name $share contains some illegal characters\n";
|
|
762 |
print_error("Share name $share contains some illegal characters\n");
|
684 | 763 |
exit 1;
|
685 | 764 |
}
|
686 | 765 |
|
|
707 | 786 |
# Get SID - try other known usernames if necessary
|
708 | 787 |
foreach my $known_username (@global_known_usernames) {
|
709 | 788 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' '$global_target' -c 'lookupnames $known_username' 2>&1";
|
710 | |
print "[V] Attempting to get SID from $global_target with command: $command\n" if $verbose;
|
711 | |
print "[V] Assuming that user \"$known_username\" exists\n" if $verbose;
|
|
789 |
print_verbose("Attempting to get SID from $global_target with command: $command\n") if $verbose;
|
|
790 |
print_verbose("Assuming that user \"$known_username\" exists\n") if $verbose;
|
712 | 791 |
$logon = "username '$global_username', password '$global_password'";
|
713 | 792 |
$sid = `$command`;
|
714 | 793 |
if ($sid =~ /NT_STATUS_ACCESS_DENIED/) {
|
715 | |
print "[E] Couldn't get SID: NT_STATUS_ACCESS_DENIED. RID cycling not possible.\n";
|
|
794 |
print_error("Couldn't get SID: NT_STATUS_ACCESS_DENIED. RID cycling not possible.\n");
|
716 | 795 |
last;
|
717 | 796 |
} elsif ($sid =~ /NT_STATUS_NONE_MAPPED/) {
|
718 | |
print "[V] User \"$known_username\" doesn't exist. User enumeration should be possible, but SID needed...\n" if $verbose;
|
|
797 |
print_verbose("User \"$known_username\" doesn't exist. User enumeration should be possible, but SID needed...\n") if $verbose;
|
719 | 798 |
next;
|
720 | 799 |
} elsif ($sid =~ /S-1-5-21-[\d-]+-\d+\s+/) {
|
721 | 800 |
($cleansid) = $sid =~ /(S-1-5-21-[\d-]+)-\d+\s+/;
|
722 | |
print "[I] Found new SID: $cleansid\n" unless defined($sids{$cleansid});
|
|
801 |
if (defined($sids{$cleansid})) {
|
|
802 |
print_info("Found new SID: ");
|
|
803 |
print "$cleansid\n";
|
|
804 |
}
|
723 | 805 |
$sids{$cleansid} = 1;
|
724 | 806 |
next;
|
725 | 807 |
} elsif ($sid =~ /S-1-5-[\d-]+-\d+\s+/) {
|
726 | 808 |
($cleansid) = $sid =~ /(S-1-5-[\d-]+)-\d+\s+/;
|
727 | |
print "[I] Found new SID: $cleansid\n" unless defined($sids{$cleansid});
|
|
809 |
if (defined($sids{$cleansid})) {
|
|
810 |
print_info("Found new SID: ");
|
|
811 |
print "$cleansid\n";
|
|
812 |
}
|
728 | 813 |
$sids{$cleansid} = 1;
|
729 | 814 |
next;
|
730 | 815 |
} elsif ($sid =~ /S-1-22-[\d-]+-\d+\s+/) {
|
731 | 816 |
($cleansid) = $sid =~ /(S-1-22-[\d-]+)-\d+\s+/;
|
732 | |
print "[I] Found new SID: $cleansid\n" unless defined($sids{$cleansid});
|
|
817 |
if (defined($sids{$cleansid})) {
|
|
818 |
print_info("Found new SID: ");
|
|
819 |
print "$cleansid\n";
|
|
820 |
}
|
733 | 821 |
$sids{$cleansid} = 1;
|
734 | 822 |
next;
|
735 | 823 |
} else {
|
|
739 | 827 |
|
740 | 828 |
# Get some more SIDs (hopefully)
|
741 | 829 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' '$global_target' -c lsaenumsid 2>&1";
|
742 | |
print "[V] Attempting to get SIDs from $global_target with command: $command\n" if $verbose;
|
|
830 |
print_verbose("Attempting to get SIDs from $global_target with command: $command\n") if $verbose;
|
743 | 831 |
my $sids = `$command`;
|
744 | 832 |
foreach my $sid ($sids =~ /(S-[0-9-]+)/g) {
|
745 | |
print "[V] Processing SID $sid\n" if $verbose;
|
|
833 |
print_verbose("Processing SID $sid\n") if $verbose;
|
746 | 834 |
if ($sid =~ /NT_STATUS_ACCESS_DENIED/) {
|
747 | |
print "[E] Couldn't get SID: NT_STATUS_ACCESS_DENIED. RID cycling not possible.\n";
|
|
835 |
print_error("Couldn't get SID: NT_STATUS_ACCESS_DENIED. RID cycling not possible.\n");
|
748 | 836 |
next;
|
749 | 837 |
} elsif ($sid =~ /S-1-5-21-[\d-]+-\d+/) {
|
750 | 838 |
($cleansid) = $sid =~ /(S-1-5-21-[\d-]+)-\d+/;
|
751 | |
print "[I] Found new SID: $cleansid\n" unless defined($sids{$cleansid});
|
|
839 |
if (defined($sids{$cleansid})) {
|
|
840 |
print_info("Found new SID: ");
|
|
841 |
print "$cleansid\n";
|
|
842 |
}
|
752 | 843 |
$sids{$cleansid} = 1;
|
753 | 844 |
next;
|
754 | 845 |
} elsif ($sid =~ /S-1-5-[\d-]+-\d+/) {
|
755 | 846 |
($cleansid) = $sid =~ /(S-1-5-[\d-]+)-\d+/;
|
756 | |
print "[I] Found new SID: $cleansid\n" unless defined($sids{$cleansid});
|
|
847 |
if (defined($sids{$cleansid})) {
|
|
848 |
print_info("Found new SID: ");
|
|
849 |
print "$cleansid\n";
|
|
850 |
}
|
757 | 851 |
$sids{$cleansid} = 1;
|
758 | 852 |
next;
|
759 | 853 |
} elsif ($sid =~ /S-1-22-[\d-]+-\d+/) {
|
760 | 854 |
($cleansid) = $sid =~ /(S-1-22-[\d-]+)-\d+/;
|
761 | |
print "[I] Found new SID: $cleansid\n" unless defined($sids{$cleansid});
|
|
855 |
if (defined($sids{$cleansid})) {
|
|
856 |
print_info("Found new SID: ");
|
|
857 |
print "$cleansid\n";
|
|
858 |
}
|
762 | 859 |
$sids{$cleansid} = 1;
|
763 | 860 |
next;
|
764 | 861 |
} else {
|
|
768 | 865 |
|
769 | 866 |
foreach my $sid (keys %sids) {
|
770 | 867 |
if (! defined($sid) and $global_username) {
|
771 | |
print "[V] WARNING: Can\'t get SID. Maybe none of the 'known' users really exist. Try others with -k. Trying null session.\n" if $verbose;
|
|
868 |
print_verbose("WARNING: Can\'t get SID. Maybe none of the 'known' users really exist. Try others with -k. Trying null session.\n") if $verbose;
|
772 | 869 |
foreach my $known_username (@global_known_usernames) {
|
773 | 870 |
my $command = "rpcclient -W '$global_workgroup' -U% '$global_target' -c 'lookupnames $known_username' 2>&1";
|
774 | |
print "[I] Assuming that user $known_username exists\n";
|
775 | |
print "[V] Trying null username and password: $command\n" if $verbose;
|
|
871 |
print_info("Assuming that user $known_username exists\n");
|
|
872 |
print_verbose("Trying null username and password: $command\n") if $verbose;
|
776 | 873 |
$sid=`$command`;
|
777 | 874 |
if ($sid =~ /error: NT_STATUS_ACCESS_DENIED/) {
|
778 | |
print "[E] Couldn't get SID: NT_STATUS_ACCESS_DENIED\n";
|
|
875 |
print_error("Couldn't get SID: NT_STATUS_ACCESS_DENIED\n");
|
779 | 876 |
next;
|
780 | 877 |
} else {
|
781 | 878 |
last;
|
|
783 | 880 |
}
|
784 | 881 |
($sid) = $sid =~ /(S-1-5-21-[\d-]+)-\d+\s+/;
|
785 | 882 |
unless (defined($sid)) {
|
786 | |
print "[E] Can't get SID using either a null username or the username \"$global_username\"\n";
|
|
883 |
print_error("Can't get SID using either a null username or the username \"$global_username\"\n");
|
787 | 884 |
exit 1;
|
788 | 885 |
}
|
789 | 886 |
$logon = "username '', password ''"
|
790 | 887 |
}
|
791 | 888 |
unless (defined($sid)) {
|
792 | |
print "[E] Couldn't find SID. Aborting RID cycling attempt.\n\n";
|
|
889 |
print_error("Couldn't find SID. Aborting RID cycling attempt.\n\n");
|
793 | 890 |
return 1;
|
794 | 891 |
}
|
795 | |
print "[+] Enumerating users using SID $sid and logon $logon\n";
|
|
892 |
print_plus("Enumerating users using SID $sid and logon $logon\n");
|
796 | 893 |
|
797 | 894 |
# RID Cycle;
|
798 | 895 |
my $last_range = 0;
|
|
843 | 940 |
if ($sid_and_user =~ /-(\d+) .*\\\1 \(/) {
|
844 | 941 |
$fail_count++;
|
845 | 942 |
} else {
|
846 | |
print "$sid_and_user\n";
|
|
943 |
print "$sid_and_user\n" if $sid_and_user =~ /\((Local|Domain) User\)/;
|
|
944 |
print "$sid_and_user\n" if $sid_and_user =~ /\((Local|Domain) Group\)/;
|
847 | 945 |
$fail_count = 0;
|
848 | 946 |
get_user_details_from_rid($rid) if $sid_and_user =~ /\((Local|Domain) User\)/;
|
849 | 947 |
get_group_details_from_rid($rid) if $sid_and_user =~ /\((Local|Domain) Group\)/;
|
|
863 | 961 |
sub enum_users {
|
864 | 962 |
print_heading("Users on $global_target");
|
865 | 963 |
my $command = "rpcclient -W '$global_workgroup' -c querydispinfo -U'$global_username'\%'$global_password' '$global_target' 2>&1";
|
866 | |
print "[V] Attempting to get userlist with command: $command\n" if $verbose;
|
|
964 |
print_verbose("Attempting to get userlist with command: $command\n") if $verbose;
|
867 | 965 |
my $users = `$command`;
|
868 | 966 |
my $continue = 1;
|
869 | 967 |
if ($users =~ /NT_STATUS_ACCESS_DENIED/) {
|
870 | |
print "[E] Couldn't find users using querydispinfo: NT_STATUS_ACCESS_DENIED\n";
|
|
968 |
print_error("Couldn't find users using querydispinfo: NT_STATUS_ACCESS_DENIED\n");
|
871 | 969 |
} else {
|
872 | 970 |
($users) = $users =~ /(index:.*)/s;
|
873 | 971 |
print $users;
|
|
878 | 976 |
|
879 | 977 |
print "\n";
|
880 | 978 |
$command = "rpcclient -W '$global_workgroup' -c enumdomusers -U'$global_username'\%'$global_password' '$global_target' 2>&1";
|
881 | |
print "[V] Attempting to get userlist with command: $command\n" if $verbose;
|
|
979 |
print_verbose("Attempting to get userlist with command: $command\n") if $verbose;
|
882 | 980 |
$users = `$command`;
|
883 | 981 |
if ($users =~ /NT_STATUS_ACCESS_DENIED/) {
|
884 | |
print "[E] Couldn't find users using enumdomusers: NT_STATUS_ACCESS_DENIED\n";
|
|
982 |
print_error("Couldn't find users using enumdomusers: NT_STATUS_ACCESS_DENIED\n");
|
885 | 983 |
} else {
|
886 | 984 |
($users) = $users =~ /(user:.*)/s;
|
887 | 985 |
print $users;
|
|
901 | 999 |
sub get_group_details_from_rid {
|
902 | 1000 |
my $rid = shift;
|
903 | 1001 |
if (invalid_rid($rid)) {
|
904 | |
print "[E] Invalid rid passed: $rid\n";
|
|
1002 |
print_error("Invalid RID passed: $rid\n");
|
905 | 1003 |
return 0;
|
906 | 1004 |
}
|
907 | 1005 |
return unless $global_detailed;
|
908 | 1006 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' -c 'querygroup $rid' '$global_target' 2>&1";
|
909 | |
print "[V] Attempting to get detailed group info with command: $command\n" if $verbose;
|
|
1007 |
print_verbose("Attempting to get detailed group info with command: $command\n") if $verbose;
|
910 | 1008 |
my $group_info = `$command`;
|
911 | 1009 |
($group_info) = $group_info =~ /([^\n]*Group Name.*Num Members[^\n]*)/s;
|
912 | 1010 |
if (defined($group_info)) {
|
913 | 1011 |
print "$group_info\n\n";
|
914 | 1012 |
} else {
|
915 | |
print "[E] No info found\n\n";
|
|
1013 |
print_error("No info found\n\n");
|
916 | 1014 |
}
|
917 | 1015 |
}
|
918 | 1016 |
|
919 | 1017 |
sub get_user_details_from_rid {
|
920 | 1018 |
my $rid = shift;
|
921 | 1019 |
if (invalid_rid($rid)) {
|
922 | |
print "[E] Invalid rid passed: $rid\n";
|
|
1020 |
print_error("Invalid RID passed: $rid\n");
|
923 | 1021 |
return 0;
|
924 | 1022 |
}
|
925 | 1023 |
return unless $global_detailed;
|
926 | 1024 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' -c 'queryuser $rid' '$global_target' 2>&1";
|
927 | |
print "[V] Attempting to get detailed user info with command: $command\n" if $verbose;
|
|
1025 |
print_verbose("Attempting to get detailed user info with command: $command\n") if $verbose;
|
928 | 1026 |
my $user_info = `$command`;
|
929 | 1027 |
($user_info) = $user_info =~ /([^\n]*User Name.*logon_hrs[^\n]*)/s;
|
930 | 1028 |
print "$user_info\n" if defined($user_info);
|
|
988 | 1086 |
sub get_printer_info {
|
989 | 1087 |
print_heading("Getting printer info for $global_target");
|
990 | 1088 |
my $command = "rpcclient -W '$global_workgroup' -U'$global_username'\%'$global_password' -c 'enumprinters' '$global_target' 2>&1";
|
991 | |
print "[V] Attempting to get printer info with command: $command\n" if $verbose;
|
|
1089 |
print_verbose("Attempting to get printer info with command: $command\n") if $verbose;
|
992 | 1090 |
my $printer_info = `$command`;
|
993 | 1091 |
# ($group_info) = $group_info =~ /([^\n]*Group Name.*Num Members[^\n]*)/s;
|
994 | 1092 |
if (defined($printer_info)) {
|
995 | 1093 |
print "$printer_info\n\n";
|
996 | 1094 |
} else {
|
997 | |
print "[E] No info found\n\n";
|
|
1095 |
print_error("No info found\n\n");
|
998 | 1096 |
}
|
999 | 1097 |
|
1000 | 1098 |
}
|
|
1033 | 1131 |
|
1034 | 1132 |
sub print_heading {
|
1035 | 1133 |
my $string = shift;
|
1036 | |
my $output = "| $string |";
|
1037 | |
my $len = length($output);
|
|
1134 |
my $output = "$string";
|
|
1135 |
my $maxlen = 100;
|
|
1136 |
my $len = $maxlen - length($output);
|
1038 | 1137 |
print "\n";
|
1039 | |
print " " . "=" x ($len - 2) . " \n";
|
1040 | |
print "$output\n";
|
1041 | |
print " " . "=" x ($len - 2) . " \n";
|
1042 | |
}
|
|
1138 |
print colored(" " . "=" x ($len / 2) . "( ", 'blue');
|
|
1139 |
print colored("$output", 'green');
|
|
1140 |
print colored(" )" . "=" x ($len / 2) . "\n\n", 'blue');
|
|
1141 |
}
|
|
1142 |
|
|
1143 |
sub print_verbose {
|
|
1144 |
my $string = shift;
|
|
1145 |
my $output = "$string";
|
|
1146 |
print colored("\n[V] ", 'yellow');
|
|
1147 |
print colored("$output\n", 'magenta');
|
|
1148 |
}
|
|
1149 |
|
|
1150 |
sub print_plus {
|
|
1151 |
my $string = shift;
|
|
1152 |
my $output = "$string";
|
|
1153 |
print colored("\n[+] ", 'yellow');
|
|
1154 |
print colored("$output\n", 'green');
|
|
1155 |
}
|
|
1156 |
|
|
1157 |
sub print_info {
|
|
1158 |
my $string = shift;
|
|
1159 |
my $output = "$string";
|
|
1160 |
print colored("\n[I] ", 'yellow');
|
|
1161 |
print colored("$output\n", 'cyan');
|
|
1162 |
}
|
|
1163 |
|
|
1164 |
sub print_error {
|
|
1165 |
my $string = shift;
|
|
1166 |
my $output = "$string";
|
|
1167 |
print colored("\n[E] ", 'yellow');
|
|
1168 |
print colored("$output\n", 'red');
|
|
1169 |
}
|