3 # This file is a part of PRADS.
5 # Copyright (C) 2010, Edward Fjellskål <edwardfjellskaal@gmail.com>
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #use Getopt::Long qw(:config no_ignore_case bundling);
26 use Getopt
::Long qw
/:config auto_version auto_help/;
33 prads2snort.pl - Some one needs to populate the host_attribute.xml file!
41 $ prads2snort.pl [options]
45 -i|--infile : file to feed prads2snort.pl
46 -o|--outfile : file to write host_attribute data to (host_attribute.xml)
47 -d|--default : set Default OS if unknown (linux,bsd,macos,windows)
48 -s|--skip : Skip OSes that has a match less than XX %
49 -v|--verbose : prints out OS, frag, stream and confidence of asset
50 -h|--help : this help message
51 --version : show prads2snort.pl version
61 our $INFILE = qq(/var/log/prads
-asset
.log);
62 our $OUTFILE = qq(hosts_attribute
.xml
);
63 our $DEFAULTOS = qq(linux
);
67 Getopt
::Long
::GetOptions
(
68 'infile|i=s' => \
$INFILE,
69 'outfile|o=s' => \
$OUTFILE,
70 'default|d=s' => \
$DEFAULTOS,
71 'skip|s=s' => \
$SKIPOS,
72 'verbose|v' => \
$VERBOSE,
84 make_attribute_table
();
88 ################################################################################
89 ############# F - U - N - C - T - I - O - N - S - ##############################
90 ################################################################################
94 =head2 parse_asset_file
96 Opens the asset file, parses it, and stor info in a hash
100 sub parse_asset_file
{
101 # Open prads asset file
102 open (ASSETFILE
, "<$INFILE") or die "[!] ERROR: Unable to open file: $INFILE - $!\n";
104 print "\n*** PARSING OF ASSET FILE ***\n\n" if $DEBUG;
105 while (<ASSETFILE
>) {
107 next if (/^asset,vlan,port,proto/ || /^#/);
110 # asset,vlan,port,proto,service,[service-info],distance,discovered
111 /^([\w\.:]+),([\d]{1,4}),([\d]{1,5}),([\d]{1,3}),(\S+?),\[(.*)\],([\d]{1,3}),(\d{10})/ && do {
112 my ($sip, $vlan, $sport, $proto, $service, $s_info, $distance, $discovered) = ($1, $2, $3, $4, $5, $6, $7, $8);
115 my $os = my $details = my $services = "unknown";
116 print "[*] $asset\n" if $DEBUG;
118 if ( $service =~ /SYN/ || $service =~ /^ACK$/ || $service =~ /^RST$/ || $service =~ /^FIN$/ ) {
119 if ($s_info =~ /:[\d]{2,4}:\d:.*:.*:.*:(\w+):(.*):link/) {
122 print "[**] SYN(+ACK):$os - $details\n" if $DEBUG;
123 } elsif ($s_info =~ /:[\d]{2,4}:\d:.*:.*:.*:(\w+):(.*):uptime/) {
126 print "[**] RST/ACK/FIN:$os - $details\n" if $DEBUG;
131 $s_info =~ /:Linux:(.*):?/;
132 $details = $1 if defined $1;
136 $s_info =~ /:Windows:(.*):?/;
137 $details = $1 if defined $1;
140 $s_info =~ /:(\w+BSD):(.*):?/;
141 $os = $1 if defined $1;
142 $details = $2 if defined $2;
146 $s_info =~ /:MacOS:(.*):?/;
147 $details = $1 if defined $1;
150 print "[**] FALLBACK: $s_info\n" if $DEBUG;
151 print "[**] FALLBACK: $os - $details\n" if $DEBUG;
153 } elsif ( $service =~ /SERVER/ || $service =~ /CLIENT/ ) {
154 $s_info =~ s/^(\w+):(.*)$/$2/;
157 # Assign this line to the asset data structure.
160 if ( $service =~ /SERVER/ ) {
161 push (@
{$ASSETDB{$sip}{"TCPSER"}}, [ $sport, $service, $services, $s_info, $discovered ]);
162 } elsif ($service =~ /CLIENT/ ) {
163 push (@
{$ASSETDB{$sip}{"TCPCLI"}}, [ $sport, $service, $services, $s_info, $discovered ]);
164 } elsif ( $service =~ /SYN/ || $service =~ /^ACK$/ || $service =~ /^RST$/ || $service =~ /^FIN$/ ) {
165 push (@
{$ASSETDB{$sip}{"OS"}}, [ $service, $os, $details, $discovered ]);
167 } elsif ($proto == 17) {
169 if ( $service =~ /SERVER/ ) {
170 push (@
{$ASSETDB{$sip}{"UDPSER"}}, [ $sport, $service, $services, $s_info, $discovered ]);
171 } elsif ($service =~ /CLIENT/ ) {
172 push (@
{$ASSETDB{$sip}{"UDPCLI"}}, [ $sport, $service, $services, $s_info, $discovered ]);
182 =head2 make_attribute_table
184 Makes a snort host_attribute xml table of the assets
188 sub make_attribute_table
{
190 my ($xmlout, $putxml, $feed, $confidence);
192 if (-e
$OUTFILE && $FORCE == 0) {
193 print "[*] File Exists! Use -f|--force to force writing...\n";
194 print "[*] Exiting!\n";
198 $xmlout = new IO
::File
($OUTFILE, O_WRONLY
| O_TRUNC
|O_CREAT
) or
199 die "[!] ERROR: Cannot open output file for writing - $!\n";
200 $putxml = new XML
::Writer
(OUTPUT
=> $xmlout, NEWLINES
=> 0, DATA_MODE
=> 1, DATA_INDENT
=> 1, UNSAFE
=> 1);
201 $putxml->startTag('SNORT_ATTRIBUTES');
202 $putxml->startTag('ATTRIBUTE_MAP');
203 $putxml->startTag('ENTRY');
204 $putxml->startTag('ID');
205 $putxml->characters("31337");
206 $putxml->endTag('ID');
207 $putxml->startTag('VALUE');
208 $putxml->characters("Edward Fjellskaal");
209 $putxml->endTag('VALUE');
210 $putxml->endTag('ENTRY');
211 $putxml->endTag('ATTRIBUTE_MAP');
213 $putxml->startTag('ATTRIBUTE_TABLE');
215 print "\n*** PARSING OF ASSET DB ***\n\n" if $DEBUG;
216 foreach $asset (sort (keys (%ASSETDB))) {
217 next if not defined $asset;
219 print "[****] Processing $asset\n" if $DEBUG;
220 my ($os,$desc,$confidence,$timestamp,$flux) = guess_asset_os
($asset);
221 my $details = normalize_description
($os, $desc);
222 my ($frag3, $stream5) = get_policy
($os, $desc);
223 $STATS{'OS'}{"$os"}{'count'} ++;
224 $STATS{'OS'}{"$os"}{'confidence'} += $confidence;
225 if ($confidence < $SKIPOS) {
226 print "$asset OS:Unknown - Skipping, confidence:$confidence\n" if $VERBOSE;
229 if ($os =~ /unknown/) {
232 print "$asset OS:Unknown - Applying frag3=$frag3, stream5=$stream5 and confidence:$confidence\n";
236 $aconfedence += $confidence;
238 print "$asset OS:$os - Applying frag3=$frag3, stream5=$stream5 and confidence:$confidence\n";
241 $putxml->startTag('HOST');
242 $putxml->startTag('IP');
243 $putxml->characters("$asset");
244 $putxml->endTag('IP');
245 $putxml->startTag('OPERATING_SYSTEM');
246 $putxml->startTag('NAME');
247 $putxml->startTag('ATTRIBUTE_VALUE');
248 $putxml->characters("$os");
249 $putxml->endTag('ATTRIBUTE_VALUE');
250 $putxml->startTag('CONFIDENCE');
251 $putxml->characters("$confidence");
252 $putxml->endTag('CONFIDENCE');
253 $putxml->endTag('NAME');
254 $putxml->startTag('VENDOR');
255 $putxml->startTag('ATTRIBUTE_VALUE');
256 $putxml->characters("$os");
257 $putxml->endTag('ATTRIBUTE_VALUE');
258 $putxml->startTag('CONFIDENCE');
259 $putxml->characters("$confidence");
260 $putxml->endTag('CONFIDENCE');
261 $putxml->endTag('VENDOR');
262 $putxml->startTag('VERSION');
263 $putxml->startTag('ATTRIBUTE_VALUE');
264 $putxml->characters("$details");
265 $putxml->endTag('ATTRIBUTE_VALUE');
266 $putxml->startTag('CONFIDENCE');
267 $putxml->characters("$confidence");
268 $putxml->endTag('CONFIDENCE');
269 $putxml->endTag('VERSION');
270 $putxml->startTag('FRAG_POLICY');
271 $putxml->characters("$frag3");
272 $putxml->endTag('FRAG_POLICY');
273 $putxml->startTag('STREAM_POLICY');
274 $putxml->characters("$stream5");
275 $putxml->endTag('STREAM_POLICY');
276 $putxml->endTag('OPERATING_SYSTEM');
278 if ($ASSETDB{$asset}->{"TCPSER"} || $ASSETDB{$asset}->{"UDPSER"}) {
279 # Metadata service tags in rules:
280 # grep "metadata:service" /etc/snort/rules/*.rules|sed "s/.*metadata\:service \(.\+\);.*;)/\1/"|awk '{print $1}'|sort -u
281 $putxml->startTag('SERVICES');
282 if ($ASSETDB{$asset}->{"TCPSER"}) {
283 make_service_attributes
($asset, "tcp", "TCPSER", $putxml, $timestamp);
286 if ($ASSETDB{$asset}->{"UDPSER"}) {
287 make_service_attributes
($asset, "udp", "UDPSER", $putxml, $timestamp);
289 $putxml->endTag('SERVICES');
291 # Commented out for now !
292 #if ($ASSETDB{$asset}->{"TCPCLI"} || $ASSETDB{$asset}->{"UDPCLI"}) {
293 # $putxml->startTag('CLIENTS');
294 # if ($ASSETDB{$asset}->{"TCPCLI"}) {
295 # make_client_attributes($asset, "tcp", "TCPCLI", $putxml);
297 # if ($ASSETDB{$asset}->{"UDPCLI"}) {
298 # make_client_attributes($asset, "udp", "UDPCLI", $putxml);
300 # $putxml->endTag('CLIENTS');
302 $putxml->endTag('HOST');
303 print "[****] Done\n\n" if $DEBUG;
307 $putxml->endTag('ATTRIBUTE_TABLE');
308 $putxml->endTag('SNORT_ATTRIBUTES');
315 Gets the frag3 and stream5 policy
320 my ($OS, $DESC) = @_;
321 my ($frag3, $stream5) = ("BSD", "bsd");
323 case
/Cisco/ {$frag3 = "Last"; $stream5 = "last";}
324 case
/IOS/ {$frag3 = "Last"; $stream5 = "last";}
325 case
/JetDirect/ {$frag3 = "BSD-right"; $stream5 = "bsd";}
328 case
/10/ {$frag3 = "BSD"; $stream5 = "hpux10";}
329 case
/11/ {$frag3 = "First"; $stream5 = "hpux";}
330 else {$frag3 = "First"; $stream5 = "hpux";}
333 case
/IRIX/ {$frag3 = "BSD"; $stream5 = "irix";}
335 # stream5: Linux 2.4 and 2.6 = linux
336 # Linux 2.2 and earlier = old-linux
337 # frag3: linux for all linuxes
340 case
/2\.6/ {$stream5 = "linux";}
341 case
/2\.4/ {$stream5 = "linux";}
342 case
/2\.2/ {$stream5 = "old-linux";}
343 case
/2\.0/ {$stream5 = "old-linux";}
344 else {$stream5 = "linux";}
348 # Assuming Freebsd properties!
349 # frag3: FreeBSD = BSD
351 $frag3 = "BSD"; $stream5 = "bsd";
354 # frag3: FreeBSD = BSD
356 $frag3 = "BSD"; $stream5 = "bsd";
359 # frag3: OpenBSD = linux
360 # stream5: OpenBSD = bsd
361 $frag3 = "linux"; $stream5 = "bsd";
363 case
/MacOS/ {$frag3 = "First"; $stream5 = "macos";}
364 case
/^SunOS/ {$frag3 = "First"; $stream5 = "first";}
365 case
/Solaris/ {$frag3 = "Solaris"; $stream5 = "solaris";}
367 # frag3 :Windows (95/98/NT4/W2K/XP) = Windows
368 # stream5: Windows 2003 Server (Guessing also 2008) = win2003
369 # Windows Vista = vista
370 # All other Windows = windows
373 case
/200[3,8]/ {$stream5 = "win2003";}
374 case
/Vista/ {$stream5 = "vista";}
375 else {$stream5 = "windows";}
379 if ($DEFAULTOS =~ /linux/) {
382 } elsif ($DEFAULTOS =~ /bsd/) {
385 } elsif ($DEFAULTOS =~ /windows/) {
387 $stream5 = "windows";
388 } elsif ($DEFAULTOS =~ /macos/) {
393 #else {$frag3 = "BSD"; $stream5 = "bsd";}
395 push my @policy, ($frag3, $stream5, 90);
399 =head2 normalize_description
401 Normalized the description to something more snort lookalike
405 sub normalize_description
{
406 my ($OS, $DESC) = @_;
410 case
/2\.6/ { return "2.6"; }
411 case
/2\.4/ { return "2.4"; }
412 case
/2\.2/ { return "2.2"; }
413 case
/2\.0/ { return "2.0"; }
414 else { return $DESC; }
419 case
/XP/ { return "XP"; }
420 case
/2003/ { return "Windows 2003"; }
421 case
/2008/ { return "Windows 2008"; }
422 case
/Vista/ { return "Vista"; }
423 else { return $DESC; }
426 else { return $DESC; }
430 sub check_last_os_switch
{
434 foreach my $OS (@
{$ASSETDB{$asset}->{"OS"}}) {
435 if ($OS->[0] =~ /^SYN$/ ) {
437 $ctimestamp = $OS->[3] if ($OS->[3] > $ctimestamp);
442 foreach my $OS (sort { $a <=> $b } (@
{$ASSETDB{$asset}->{"OS"}})) {
443 if ($OS->[0] =~ /^SYNACK$/ ) {
445 $ctimestamp = $OS->[3] if ($OS->[3] > $ctimestamp);
450 push my @return, ($ctimestamp, $syn);
451 #print "[--] Returning from check_last_os_switch\n" if $DEBUG;
455 =head2 guess_asset_os
457 Tries to guess the asset OS in an inteligent way..
458 Snort OSes off importance:
459 bsd, old-linux, linux, first, last, windows, solaris,
460 win2003/win2k3, vista, hpux/hpux11, hpux10, irix, macos
467 my ($OS, $DETAILS, $CONFIDENCE, $TS, $FLUX) = ("unknown", "unknown", 0, 0, 0);
471 # look for latest os switch...
472 ($TS,$FLUX) = check_last_os_switch
($asset);
473 # Lets look back the last 12 hours... Configurable?
476 foreach $OS (@
{$ASSETDB{$asset}->{"OS"}}) {
477 next if ($OS->[3] < $TS);
478 print "[-] " . $OS->[0] . ": " . $OS->[1] . "\n" if $DEBUG;
479 if ($OS->[0] =~ /^SYNACK$/ ) {
480 $countos{ $OS->[1] }{"count"} += 4;
481 } elsif ($OS->[0] =~ /^SYN$/ ) {
482 $countos{$OS->[1]}{"count"} += 6;
483 } elsif ($OS->[0] =~ /^ACK$/ || $OS->[0] =~ /^FIN$/ || $OS->[0] =~ /^RST$/ ) {
484 $countos{$OS->[1]}{"count"} += 1;
490 for my $os (sort { $countos{$a} <=> $countos{$b} } keys %countos) {
491 next if ($os =~ /unknown/ );
492 print "[-] OS Counts: $os (" . $countos{$os}{"count"} . ")\n" if $DEBUG;
493 if ($countos{$os}{"count"} > $HighestCNT) {
494 $HighestCNT = $countos{$os}{"count"};
495 $HighestOS->[1] = $HighestOS->[0] if defined $HighestOS->[0];
496 $HighestOS->[0] = $os;
497 } elsif ($countos{$os}{"count"} == $HighestCNT) {
498 $HighestOS->[2] = $HighestOS->[1] if defined $HighestOS->[1];
499 $HighestOS->[1] = $os;
503 if (not defined $HighestOS->[0]) {
506 $OS = $HighestOS->[0];
509 push my @midfiltered, ("unknown", "unknown", 0, $TS, $FLUX);
510 return @midfiltered unless $OS;
511 return @midfiltered if ($OS =~ /unknown/);
513 print "[-] Final Guess OS: $OS\n" if $DEBUG;
515 foreach my $DESC (@
{$ASSETDB{$asset}->{"OS"}}) {
516 next if ($DESC->[3] < $TS);
517 next if not $DESC->[1] =~ /$OS/;
518 if ($DESC->[0] =~ /^SYN$/) {
519 $DETAILS = $DESC->[2];
521 } elsif ($DESC->[0] =~ /^SYNACK$/) {
522 $DETAILS = $DESC->[2];
524 $DETAILS = $DESC->[2];
528 if (not defined $DETAILS) {
529 print "[*] ERR - No details!\n" if $DEBUG;
530 foreach my $DESC (@
{$ASSETDB{$asset}->{"OS"}}) {
531 next if ($DESC->[3] < $TS);
532 next if not $DESC->[1] =~ /$OS/;
533 if ($DESC->[0] =~ /^RST$/) {
534 $DETAILS = $DESC->[2];
536 } elsif ($DESC->[0] =~ /^ACK$/) {
537 $DETAILS = $DESC->[2];
539 $DETAILS = $DESC->[2];
544 if ( not defined $OS ) {
545 print "[*] ERR - No OS!\n" if $DEBUG;
546 $DETAILS = "unknown";
550 $CONFIDENCE = 20 + (10 * $countos{$OS}{count
});
551 $CONFIDENCE = 100 if $CONFIDENCE > 100;
553 print "[-] Final Guess Details: $DETAILS\n" if $DEBUG;
554 print "[-] Confidence: $CONFIDENCE\n" if $DEBUG;
555 push my @postfiltered, ($OS, $DETAILS, $CONFIDENCE, $TS, $FLUX);
556 return @postfiltered;
559 =head2 make_service_attributes
561 Populates all server attributes
565 sub make_service_attributes
{
566 my ($asset, $proto, $key, $putxml, $TS) = @_;
567 #my @unique = @{$ASSETDB{$asset}->{"$key"}};
568 my @servassets = sort {$$a[0] <=> $$b[0]} @
{$ASSETDB{$asset}->{"$key"}};
569 #$proto =~ tr/A-Z/a-z/;
571 foreach my $SA (@servassets) {
572 next if not defined $SA;
573 if ($SA->[4] < $TS) { # Skipp old assets
574 print "[##] Skipping old ASSET! " . $SA->[3] . "\n" if $DEBUG;
577 my ($port, $service, $services, $details, $discovered) = ($SA->[0], $SA->[1], $SA->[2], $SA->[3], $SA->[4]);
578 if ($service =~ /SERVER/) {
579 print "[#*] SERVER: $services:$port - $details" if $DEBUG;
580 if ($services =~ /unknown/ || $services =~ /^@/) {
581 print " (Skipped)\n" if $DEBUG;
584 if (defined $PORTS->[$port]) {
585 if ($PORTS->[$port]->[4] < $discovered) {
586 $PORTS->[$port] = $SA;
587 print " (Updated!)\n" if $DEBUG;
590 $PORTS->[$port] = $SA;
591 print " (New)\n" if $DEBUG;
595 return if not defined $PORTS;
599 foreach $_ (@
$PORTS) {
600 next if not defined $_;
601 my ($port, $service, $services, $details, $discovered) = ($_->[0], $_->[1], $_->[2], $_->[3], $_->[4]);
602 if ($service =~ /SERVER/) {
603 print "[#+] SERVER: $services:$port - $details (Added)\n" if $DEBUG;
604 if ($tservices eq '') {
605 $tservices = $services;
607 $tservices = "$tservices, $services"
610 my ($serv, $vers) = get_server_and_version
($details);
611 $STATS{'SERVICE'}{"$serv"}{'count'} ++;
612 $putxml->startTag('SERVICE');
613 $putxml->startTag('PORT');
614 $putxml->startTag('ATTRIBUTE_VALUE');
615 $putxml->characters("$port"); # 22/80/443...
616 $putxml->endTag('ATTRIBUTE_VALUE');
617 $putxml->startTag('CONFIDENCE');
618 $putxml->characters("$confidence");
619 $putxml->endTag('CONFIDENCE');
620 $putxml->endTag('PORT');
621 $putxml->startTag('IPPROTO');
622 $putxml->startTag('ATTRIBUTE_VALUE');
623 $putxml->characters("$proto"); # tcp/udp/icmp...
624 $putxml->endTag('ATTRIBUTE_VALUE');
625 $putxml->startTag('CONFIDENCE');
626 $putxml->characters("$confidence");
627 $putxml->endTag('CONFIDENCE');
628 $putxml->endTag('IPPROTO');
629 $putxml->startTag('PROTOCOL');
630 $putxml->startTag('ATTRIBUTE_VALUE');
631 $putxml->characters("$services"); # http/ssh/smtp/ssl...
632 $putxml->endTag('ATTRIBUTE_VALUE');
633 $putxml->startTag('CONFIDENCE');
634 $putxml->characters("$confidence");
635 $putxml->endTag('CONFIDENCE');
636 $putxml->endTag('PROTOCOL');
637 $putxml->startTag('APPLICATION');
638 $putxml->startTag('ATTRIBUTE_VALUE');
639 $putxml->characters("$serv");
640 $putxml->endTag('ATTRIBUTE_VALUE');
641 $putxml->startTag('VERSION');
642 $putxml->startTag('ATTRIBUTE_VALUE');
643 $putxml->characters("$vers");
644 $putxml->endTag('ATTRIBUTE_VALUE');
645 $putxml->startTag('CONFIDENCE');
646 $putxml->characters("$confidence");
647 $putxml->endTag('CONFIDENCE');
648 $putxml->endTag('VERSION');
649 $putxml->endTag('APPLICATION');
650 $putxml->endTag('SERVICE');
653 if ($VERBOSE && not $tservices eq '') {
654 print "$asset SERVICES $proto: $tservices\n";
656 #print "[--] Returned from make_server_attributes\n" if $DEBUG;
659 =head2 make_client_attributes
661 Populates all client attributes for an asset
665 sub make_client_attributes
{
666 my ($asset, $proto, $key, $putxml) = @_;
667 my @sorted = sort {$$a[0] <=> $$b[0]} @
{$ASSETDB{$asset}->{"$key"}};
668 #$proto =~ tr/A-Z/a-z/;
670 foreach $_ (@sorted) {
671 my ($port, $service, $services, $details, $discovered) = ($_->[0], $_->[1], $_->[2], $_->[3], $_->[4]);
672 if ($service =~ /CLIENT/) {
673 next if $services =~ /unknown/;
674 next if $services =~ /^@/;
675 $details =~ s/^(\w+)\d?(.*)/$2/;
677 $putxml->startTag('CLIENT');
678 $putxml->startTag('PROTOCOL');
679 $putxml->startTag('ATTRIBUTE_VALUE');
680 $putxml->characters("$services"); # tcp/udp/
681 $putxml->endTag('ATTRIBUTE_VALUE');
682 $putxml->endTag('PROTOCOL');
683 $putxml->startTag('APPLICATION');
684 $putxml->startTag('ATTRIBUTE_VALUE');
685 $putxml->characters("$client"); # MS IE/Mozilla FX/..
686 $putxml->endTag('ATTRIBUTE_VALUE');
687 $putxml->startTag('VERSION');
688 $putxml->startTag('ATTRIBUTE_VALUE');
689 $putxml->characters("$details"); # 5.0/8.0/3.3
690 $putxml->endTag('ATTRIBUTE_VALUE');
691 $putxml->endTag('VERSION');
692 $putxml->endTag('APPLICATION');
693 $putxml->endTag('CLIENT');
698 =head2 get_server_and_version
700 Tries to extract server and version from "details"
704 sub get_server_and_version
{
706 my ($serv, $vers) = ("UNKNOWN","UNKNOWN");
711 if ($details =~ /([.\d]+)/) {
715 case
/Microsoft-IIS/ {
716 $serv = "Microsoft-IIS";
717 if ($details =~ /([.\d]+)/) {
722 $details =~ /Server: (.*)/;
724 if ($details =~ /([.\d]+)/) {
728 case
/Generic TLS 1\.0 SSL/ {
733 $details =~ /(\w*[Ss]{2}[Hh]{1}\w*)/;
735 if ($details =~ /([.\d]+)/) {
741 if ($details =~ /([.\d]+).*/) {
745 case
/Remote Desktop Protocol/ {
747 if ($details =~ /\((.*)\)/) {
751 #case /SMTP|HTTP|.../ {
755 if ($details =~ /^(\w+)[\ :](.*)/ ) {
757 if ($details =~ /([.\d]+).*/) {
760 } elsif ($details =~ /^(\w+).*/ ) {
762 if ($details =~ /([.\d]+).*/) {
766 if ($details =~ /([.\d]+)/) {
773 push my @matches, ($serv, $vers);
779 Some info to go on top...
784 print "\n[*] Made by Edward Fjellskaal <edwardfjellskaal\@gmail.com> (c) 2010\n";
785 print "[*] Reading PRADS log file: $INFILE\n";
786 print "[*] Writing to snort attribute file: $OUTFILE\n";
788 print "[*] Version: $VERSION\n\n";
795 Some info to go on bottom...
800 if ((not defined $assetcnt) || ($assetcnt == 0)) {
801 print "[*] No assets found!\n";
804 $STATS{"OS"}{"unknown"}{'count'} = 0 if not defined $STATS{"OS"}{"unknown"}{'count'};
805 my $avg = ($aconfedence / ($assetcnt - $STATS{"OS"}{"unknown"}{'count'} )) ;
806 $avg =~ s/(\d{1,3})\.?.*/$1/;
807 print "[*] Processed $assetcnt hosts...\n";
808 print "[*] Hosts with Indication of a known OS: $knowns\n";
809 foreach my $OS (keys %{$STATS{"OS"}}) {
810 next if not defined $STATS{"OS"}{"$OS"}{'count'};
811 next if $STATS{"OS"}{"$OS"}{'count'} == 0;
812 next if not defined $STATS{"OS"}{"$OS"}{'confidence'};
813 next if $STATS{"OS"}{"$OS"}{'confidence'} == 0;
814 my $conf = $STATS{"OS"}{"$OS"}{'confidence'} / $STATS{"OS"}{"$OS"}{'count'};
815 $conf =~ s/(\d{1,3})\.?.*/$1/;
816 print "[--] $OS: " . $STATS{"OS"}{"$OS"}{'count'} .
819 print "[*] Overall average OS confidence: $avg%\n";
820 foreach my $SRV (keys %{$STATS{"SERVICE"}}) {
821 print "[--] $SRV: " . $STATS{"SERVICE"}{"$SRV"}{'count'} . "\n";
823 print "[*] Done...\n\n";