#!/usr/pkg/bin/perl -w

## DO NOT DISTRIBUTE THIS TOOL !!!
## IF YOU HAVE COME ACROSS THIS TOOL AND YOU AREN'T ONE OF MY TESTERS,
## PLEASE LET ME KNOW AT THE E-MAIL ADDRESS BELOW, THANKS

#######################################################################
# gosh-nt.pl - A Windows NT/200 SNMP Auditing Tool
# (C) 2001 jshaw[at]sps[dot]lane[dot]edu
# version: 2001APR21 (For UNIX & WIN32 using ActivePerl
# url: http://www.sps.lane.edu/~jshaw
#
# I more than welcome ideas, contributions, and constructive criticism
#
# Part of my G.O.S.H. Toolkit
# GOSH is an acronym for "Groper Of SNMP Hosts", or at your leisure:
# "GOSH! I didn't know the Windows NT SNMP Service gave out that 
# much information!", although if it's your machine, I'm sure you'd
# rather use another four-letter word in place of "GOSH".
#
# I plan to work on more tools as part of the GOSH Kit, specifically
# a cisco device and HP printer device tool, that essentially does the 
# same thing as this one. Also, a UNIX one would be handy (maybe for the
# UCD-SNMP kit?
#
# Submissions and ideas welcome. I will give you proper credits. :-)
#
#
# Synopsis:
# This program takes a flurry of arguments and returns the data you 
# request. As you can see, it gives you a lot of information, and
# I see it as being valuable to both network administrators and security
# engineers.
#
#
# Background/Rant/More Information/Etc:
# Most network administrators these days block the handful of NetBIOS
# ports at their firewall. An alarming number of net admins don't bother
# blocking port 161/udp from the outside world. To make it worse, the
# SNMP Service is (perhaps unnecessarily) required for a host of add-on
# programs that come with Windows NT and 2000. Administrators don't bother
# to properly configure the SNMP services with remote host access controls
# or even changing the community strings. Some day, I expect Microsoft
# to get a clue about security, but first their customers do, and they
# have to let Microsoft know they won't settle for anything less than
# proactively secure. They won't change until they see a financial
# incentive to do so.
#
# Now, more than ever, security is an essential part of any network. You
# read in the news daily about company's servers being cracked and 
# credit card databases being stolen due to lax security practices and
# procedures. This is unacceptable.
#
#
# What You Can Do To Fix Your Network:
# Learn the basics of SNMP, there are several good sources on the web.
# Use my gosh-scan.pl (formerly snoopy.pl), and this tool to scan your
# network for "open" devices. Set their community strings to something
# other than "public" and "private" AND set access controls so that only
# certain IP addresses can query the equipment in question.
#
#
# A Final Word: (Trying not to make it political ;-) )
#
# script kiddy <noun>: a person who uses this script to crack into other
# people's equipment.
#
# Many network and system administrators out there are overworked, under-
# budgetted, and underskilled. But they all generally try to do the best
# they can to support themselves and their families. And the last thing 
# they need is someone most likely a lot less skilled than them, trying
# to break into their network with this script.
#
# You haven't proved anything, except that you can make someone's hard
# job, harder. And if you can't at least follow the above, don't change
# their webpage to point out how lame the system administrator is. 
#
# In short, be good & have some respect and compassion! Thanks :-) 
#
# Installation:
# 1. Install the Net::SNMP perl module. Don't worry about Getopt::Std, it 
#    comes with PERL.
# 2. chmod u+x this script and type /path/to/this/script and hit [Enter]. 
#    The program will give you a list of options along with a couple of
#    simple options.
#
#
# Thanks: (Yes, most have funny names.)
# LnkStern - for *lots* of patience, WIN32 testing, and input
# Rob Beck from @Stake - patience, testing, input, help with some PERLisms
#                        providing a box for testing, thanks :-) 
# SirDystic - for input and ideas to help make this more full-featured 
# SPS Techs - for having test machines ready to go
#
#
# Hello's To Important People:
# t12, sangfroid, nee, athena, captain skynyrd, ells & the rest of the cDc
# shep@juniper, syke & the rest of NHC, valsmith, diluted, optyx, bronc
# the networking folks @ the University of Oregon, the Casas family
#

use strict;
use Net::SNMP;                                                          
        # Get this
use Getopt::Std;                                                        
        # Comes with PERL

# Program variables
my $version     = ".9beta 2001 APR 23";
my $port        = 161;
my $session;
my $error;
my $response;
my %option;
my $remote;
my $community;

# MIBs Involved - do not touch
my $mibDescr            = "1.3.6.1.2.1.1.1.0";                  # System Descri
ption
my $mibNTDomain         = "1.3.6.1.4.1.77.1.4.1.0";             # NT Primary Do
main
my $mibUptime           = "1.3.6.1.2.1.1.3.0";                  # System Uptime
my $mibContact          = "1.3.6.1.2.1.1.4.0";                  # System Contac
t
my $mibName                     = "1.3.6.1.2.1.1.5.0";                  # Syste
m Name
my $mibLocation         = "1.3.6.1.2.1.1.6.0";                  # System Locati
on
my $mibRunning          = "1.3.6.1.2.1.25.4.2.1.2";             # Running Progr
ams
my $mibRunPid           = "1.3.6.1.2.1.25.4.2.1.1";             # Running PIDs
my $mibInstalled        = "1.3.6.1.2.1.25.6.3.1.2";             # Installed Pro
grams
my $mibInstDate         = "1.3.6.1.2.1.25.6.3.1.5";             # Installed Dat
e
my $mibServices         = "1.3.6.1.4.1.77.1.2.3.1.1";   # Services (add to it)
my $mibAccounts         = "1.3.6.1.4.1.77.1.2.25";              # User Accounts
my $mibDateTime         = "1.3.6.1.2.1.25.1.2.0";               # System Date &
 Time
my $mibMemSize          = "1.3.6.1.2.1.25.2.2.0";               # Total System 
Memory

# Storage
my $mibStorDescr        = "1.3.6.1.2.1.25.2.3.1.3";             # Storage Descr
iption
my $mibStorSize         = "1.3.6.1.2.1.25.2.3.1.5";             # Storage Total
 Size
my $mibStorUsed         = "1.3.6.1.2.1.25.2.3.1.6";             # Storage Used
my $mibPtype            = "1.3.6.1.2.1.25.3.8.1.4";             # Partition Typ
e
my $mibSDType           = "1.3.6.1.2.1.25.2.3.1.2";             # Storage Devic
e Type

# Network
my $mibInt          = "1.3.6.1.2.1.2.2.1.2";        # Network Interfaces
my $mibIntMTU           = "1.3.6.1.2.1.2.2.1.4";                # Net Int MTU S
ize
my $mibIntSpeed         = "1.3.6.1.2.1.2.2.1.5";        # Net Int Speed
my $mibIntBytesIn       = "1.3.6.1.2.1.2.2.1.10";               # Net Int Octet
s In
my $mibIntBytesOut      = "1.3.6.1.2.1.2.2.1.16";               # Net Int Octec
ts Out
my $mibIntPhys          = "1.3.6.1.2.1.2.2.1.6";                # Int MAC addr
my $mibAdminStat        = "1.3.6.1.2.1.2.2.1.7";                # Int up/down?
my $mibIPForward        = "1.3.6.1.2.1.4.1.0";                  # IP Forwarding
?
my $mibIPAddr           = "1.3.6.1.2.1.4.20.1.1";               # Int IP Addres
s
my $mibNetmask          = "1.3.6.1.2.1.4.20.1.3";               # Int IP Netmas
k


###################### M A I N #######################################

# Duh...
getopts("aghrisunt:c:", \%option);

# Start queries...
if(!$option{t}) { &Usage; }                                             
# rtfm
        else { $remote = $option{t}; }
if(!$option{c}) { $community = "public"; }                      # community str
ing
        else { $community = $option{c}; }

&Init;
if($option{g} || $option{a}) { &General; }                      # -g
if($option{h} || $option{a}) { &Hardware; }                     # -h
if($option{r} || $option{a}) { &Running; }                      # -r
if($option{i} || $option{a}) { &Installed; }            # -i
if($option{s} || $option{a}) { &Services; }                     # -s
if($option{u} || $option{a}) { &UserAccounts; }         # -u
if($option{n} || $option{a}) { &Network; }                      # -n

# Finished
$session->close;



###################### SUBROUTINES ##################################

sub Init {
        # Establish SNMP session...
        ($session, $error) = Net::SNMP->session(
                Hostname    => $remote,
                Community   => $community,
                Port        => $port
        );

        # Die if SNMP session fails to work...
        if(!defined($session))
                { die "ERROR: $error\nIs the host running SNMP?\n\n"; }

        # Set session timeout value to 1 second (Default is 5 secs)
        $session->timeout(1);
}


sub General {
        my $Name                = &GetRequest($mibName);
        my $NTDomain    = &GetRequest($mibNTDomain);
        my $Descr               = &GetRequest($mibDescr);
        my $Contact             = &GetRequest($mibContact);
        my $Location    = &GetRequest($mibLocation);
        my $DateTime    = &GetDate(&GetRequest($mibDateTime));
                #$DateTime      = &GetDate($response->{$mibDateTime});
                
        print <<"EOF";
Information for $Name [$remote] Primary Domain: $NTDomain
-----------------------------------------------------------

Description:
--------------
$Descr

Contact: $Contact
Location: $Location
System Date \& Time: $DateTime

EOF

}


sub Hardware {
        my $MemSize             = &GetRequest($mibMemSize);             # Total
 Memory
        my @StorDescr   = &GetTable($mibStorDescr);             # Device Descri
ption
        my @SDType              = &GetTable($mibSDType);                # Devic
e Type
        #my @StorSize   = &GetTable($mibStorSize);              # Device Size
        #my @StorUsed   = &GetTable($mibStorUsed);              # Device Used
        my @Ptype               = &GetTable($mibPtype);                 # Parti
tion Type


        print <<"EOF";
Hardware Configuration:
-----------------------------------------------------------

Total Memory: $MemSize KB

Storage:
--------------
EOF

        # Process garbagely looking variables & then print!!!
        for ($a = 0; $a < scalar(@StorDescr); $a++) {

                ## Convert device type to human-readable
                if($SDType[$a] eq "1.3.6.1.2.1.25.2.1.3")
                        { $SDType[$a] = "Virtual Memory"; }
                if($SDType[$a] eq "1.3.6.1.2.1.25.2.1.4")
                        { $SDType[$a] = "Fixed Disk"; }
                if($SDType[$a] eq "1.3.6.1.2.1.25.2.1.5")
                        { $SDType[$a] = "Removable Disk"; }
                if($SDType[$a] eq "1.3.6.1.2.1.25.2.1.7")
                        { $SDType[$a] = "Compact Disc"; }

                ## fudge for the chocolate cluebies
                #if($StorSize[$a] eq "0") { $StorSize[$a] = "N/A"; }

                ## Convert partition type to human-readable
                #my $spork = scalar(@Ptype);
                #my $spoon = scalar(@StorDescr);
                #print "DEBUG: StorDescr: $spoon  a: $a  Ptype: $spork    $Ptyp
e[$a]\n\n\n\n";
        if($Ptype[$a] eq "1.3.6.1.2.1.25.3.9.2") { $Ptype[$a] = "UNKNOWN"; }
        if($Ptype[$a] eq "1.3.6.1.2.1.25.3.9.9") { $Ptype[$a] = "NTFS"; }

                ## a kludge, yes i know
                if($StorDescr[$a] ne "Virtual Memory") {

                        print <<"EOF";
$StorDescr[$a]
        Device Type:    $SDType[$a]
        Partition Type: $Ptype[$a]

EOF
                        ############## BROKEN ############################
                        ####  print "\tPartition Type: $Ptype[$a]\t\t\n";
                }
        }
}


sub Running {
        my $temp;
        my @Running                     = GetTable($mibRunning);
        my @RunPid                      = GetTable($mibRunPid);

        #my @Running = reverse @RevRunning;
        print "\n\nRunning Applications:\n";
        print "-----------------------------------------------------------\n";
        #foreach $temp (@Running) { print "$temp\n"; }
        for ($a = 0; $a < scalar(@RunPid); $a++) {
                if($Running[$a] ne "System Idle Process") {
                        print "$RunPid[$a]\t\t$Running[$a] \n";
                }
        }
}


sub Installed {
        my $temp;
        my @Installed           = &GetTable($mibInstalled);
        my @InstDate            = &GetTable($mibInstDate);

    print "\n\nInstalled Applications:\n";
    print "-----------------------------------------------------------\n";

        # header for below info
        print "Date Installed\tTime\n";
        for($a = 0; $a < scalar(@Installed); $a++) {
                my $Date = &GetDate($InstDate[$a]);
                print "$Date\t$Installed[$a]\n";
        }
}


sub Services {
        my $temp;
        my @Services            = GetTable($mibServices);

    print "\n\nServices:\n";
    print "-----------------------------------------------------------\n";
        foreach $temp (@Services) { print "$temp\n"; }
}


sub UserAccounts {
        my $temp;
        my @Accounts            = GetTable($mibAccounts);

    print "\n\nUser Accounts:\n";
    print "-----------------------------------------------------------\n";
        foreach $temp (@Accounts) { print "$temp\n"; }
}


sub Network {
        my @Int = &GetTable($mibInt);                                   # inter
face names
        my @MTU = &GetTable($mibIntMTU);                                # inter
face MTU size
        my @IntSpeed = &GetTable($mibIntSpeed);                 # interface spe
eds
        my @IntBytesIn = &GetTable($mibIntBytesIn);             # interface byt
es in
        my @IntBytesOut = &GetTable($mibIntBytesOut);   # interface bytes out
        my @IntPhys = &GetTable($mibIntPhys);                   # MAC address
        my @IPAddr = &GetTable($mibIPAddr);                             # inter
face IP addresses
        my @Netmask = &GetTable($mibNetmask);                   # interface IP 
netmask
        my @AdminStat = &GetTable($mibAdminStat);               # admin status
        my $IPForward = &GetRequest($mibIPForward);             # IP Fwding?
                if ($IPForward eq "0" || $IPForward eq "2") 
                        { $IPForward = "no"; }

        # Hell if I know why we need this, chalk it up as a bug
        # For whatever reason, the netmask values return opposite of 
        # what everything else does. *beats head against dead goat*
        @Netmask = reverse @Netmask;

        print "\n\nNetwork:\n";
    print "-----------------------------------------------------------\n";
        print "IP Forwarding Enabled: $IPForward\n";

        # Output data
        print "\n\nInterfaces:\n--------------\n";

        for ($a = 0; $a < scalar(@Int); $a++) {

                chop $Int[$a];

                if($AdminStat[$a] eq "0") 
                        {$AdminStat[$a] = "down"} else { $AdminStat[$a] = "up";
 }

                $IntSpeed[$a] = $IntSpeed[$a] / 1000000;
                print "Interface: [ $AdminStat[$a] ] $Int[$a]\n";
                print "\tHardware Address: $IntPhys[$a]\n";
                print "\tInterface Speed: $IntSpeed[$a] Mbps\n";
                print "\tIP Address: $IPAddr[$a]\n";
                print "\tNetmask: $Netmask[$a]\n";
                print "\tBytes In: $IntBytesIn[$a]\n";
                print "\tBytes Out: $IntBytesOut[$a]\n";
                print "\n";
        }
}


sub GetRequest {
        # Takes only one MIB as an argument!

        my $response;

    if(!defined($response = $session->get_request($_[0]))) {
        $session->close;
        die "GetRequest() for $_[0] failed!\n";
    }

        my $Return = $response->{$_[0]};
    return $Return;
}


sub GetTable {
        # Takes only one MIB as argument!

        my @Return;
        my $response;

    # Grab all the MIBs under the specified OID
    if(!defined($response = $session->get_table($_[0]))) {
        $session->close;
        die "GetTable() for $_[0] failed!\n";
    }
        my $x = 0;
        my $key;

        foreach $key (sort keys %$response) {
                if($$response{$key} ne "Virtual Memory") {
                        $Return[$x] = $$response{$key};
                        $x++;
                }
        }

    # Jam information into array
    #while(my ($currOID, $Back) = each %$response) { 
        #               $Return[$x] = $Back;
        #               $x++;
                        #push(@Return, $Back);
                        #print "DEBUG: $currOID\t$Back\n"; 
        #}
        #for($a = 0; $a < scalar(@Return); $a++) {
        #       print "$a\t$Return[$a]\n";
        #}
        return @Return;
}


sub GetDate {
        # Converts yay byte string to human-readable
        my $year = hex(substr($_[0], 2, 4));
        my $day = hex(substr($_[0], 6, 2));
        my $month = hex(substr($_[0], 8, 2));
        my $hour = hex(substr($_[0], 10, 2));
        my $minute = hex(substr($_[0], 12, 2));
        my $Return = "$day/$month/$year\t$hour:$minute";
        return $Return;
}


sub Usage {
print <<"EOF";

gosh-nt.pl v$version - A Windows NT/2000 SNMP auditing tool
(C) 2001 jshaw [at] sps [dot] lane [dot] edu
http://www.sps.lane.edu/~jshaw

Usage:
./gosh-nt.pl <options> <target> <community>

        Options:
        --------
        -t      - specify target hostname/ip *REQUIRED*
        ----------------------------------------------------------
        *Plus one or more of the below*
        -a      - ALL; lists all information about the remote host
        -g      - provides general information about the remote host
        -h      - provides hardware information about the remote host
        -r      - lists running processes on remote host
        -i      - lists installed applications & install date on remote host
        -c      - lists services on remote host
        -u      - lists user accounts on remote host
        -n      - lists network information from remote host

   Examples:
   --------
   ./gosh-nt.pl -a -t 10.0.0.1 -c public
   (Would report ALL information for host 10.0.0.1 using community "public")

   ./gosh-nt.pl -gn -t 10.0.0.1 -c public
   (Would only report general & network information for host 10.0.0.1)

EOF

exit;

}

