Nmap Development mailing list archives

Re: [NSE Script] SNMPv1 system information & uptime


From: "DePriest, Jason R." <jrdepriest () gmail com>
Date: Mon, 11 Jun 2007 15:02:09 -0500

Beautiful!  Works as advertised for me.  I pointed it at a networked
printer and got back its model and uptime.

I like this very much.

-Jason

On 6/11/07, Thomas Buchanan  wrote:
Here's a nifty little script (at least I think so) that looks for SNMPv1
systems that respond to "public" community string.  It trys to get the
SNMPv2-MIB::sysDescr.0 OID and prints it, and then gets the
SNMPv2-MIB::sysUpTime.0 OID and calculates the uptime of the system.

Example output:

Windows 2003 Server:

PORT    STATE SERVICE
161/udp open  snmp
|  SNMPv1: Hardware: x86 Family 15 Model 2 Stepping 9 AT/AT COMPATIBLE -
Software: Windows Version 5.2 (Build 3790 Uniprocessor Free)
|_   System uptime: 23 days, 15:3:15.89 (204139589 timeticks)

Linux box w/net-snmp:

PORT    STATE SERVICE
161/udp open  snmp
|  SNMPv1: Linux pengiun 2.6.19.7 #1 Mon Mar 5 11:00:47 CST 2007 i686
|_   System uptime: 97 days, 19:12:35.6 (844995560 timeticks)


HP Network printer:

PORT    STATE SERVICE
161/udp open  snmp
|  SNMPv1: HP ETHERNET MULTI-ENVIRONMENT,ROM
B.25.01,JETDIRECT,JD116,EEPROM B.25.31,CIDATE 07/23/2003
|_   System uptime: 15 days, 2:58:0.1 (130668010 timeticks)


Hopefully other people find this useful.

Thomas

-- SNMP system detection script
-- rev 0.4 (6-11-2007)

id = "SNMPv1"

description = "Attempts to extract system information from SNMP service"

author = "Thomas Buchanan <tbuchanan () thecompassgrp net>"

license = "See nmaps COPYING for licence"

categories = {"discovery", "safe"}

portrule = function(host, port)
        if
                port.number == 161
                and port.protocol == "udp"
                -- if we only run against open or open|filtered ports anyway, leave next two lines commented
                -- and ( port.state == "open"
                -- or port.state == "open|filtered" )
        then
                return true
        else
                return false
        end
end

action = function(host, port)

        -- create the socket used for our connection
        local socket = nmap.new_socket()

        -- set a reasonable timeout value
        socket:set_timeout(5000)

        -- do some exception handling / cleanup
        local catch = function()
                socket:close()
        end

        local try = nmap.new_try(catch)

        -- connect to the potential SNMP system
        try(socket:connect(host.ip, port.number, "udp"))

        local payload

        -- build a SNMP v1 packet
        -- copied from packet capture of snmpget exchange
        -- get value: 1.3.6.1.2.1.1.1.0 (SNMPv2-MIB::sysDescr.0)
        payload = "\048\039\002\001\000\004\006" .. "public" -- community string = public
        payload = payload .. "\160\026\002\002\111\012\002\001"
        payload = payload .. "\000\002\001\000\048\014\048\012"
        payload = payload .. "\006\008\043\006\001\002\001\001"
        payload = payload .. "\001\000\005\000"

        try(socket:send(payload))

        local status
        local response

        -- read in any response we might get
        status, response = socket:receive_bytes(1)

        if (not status) then
                return
        end

        if (response == "TIMEOUT") then
                return
        end

        -- since we got something back, the port is definitely open
        nmap.set_port_state(host, port, "open")

        local result
        result = string.match(response, "\001\001%z\004.(.*)")

        -- build a SNMP v1 packet
        -- copied from packet capture of snmpget exchange
        -- get value: 1.3.6.1.2.1.1.3.0 (SNMPv2-MIB::sysUpTime.0)
        payload = "\048\039\002\001\000\004\006" .. "public" -- community string = public
        payload = payload .. "\160\026\002\002\101\040\002\001"
        payload = payload .. "\000\002\001\000\048\014\048\012"
        payload = payload .. "\006\008\043\006\001\002\001\001"
        payload = payload .. "\003\000\005\000"

        try(socket:send(payload))

        -- read in any response we might get
        status, response = socket:receive_bytes(1)

        if (not status) then
                return result
        end

        if (response == "TIMEOUT") then
                return result
        end

        try(socket:close())

        if string.find(response, "\006\001\002\001\001\003") == nil then
                return result
        end

        local length,uptime,s1,s2,s3,s4

        length = string.len(response)

        s1,s2,s3,s4 = string.byte(response, length - 3, length)

        uptime = s1*(2^24) + s2*(2^16) + s3*(2^8) + s4

        local days, hours, minutes, seconds, htime, mtime, stime
        days = math.floor(uptime / 8640000)
        htime = math.fmod(uptime, 8640000)
        hours = math.floor(htime / 360000)
        mtime = math.fmod(htime, 360000)
        minutes = math.floor(mtime / 6000)
        stime = math.fmod(mtime, 6000)
        seconds = stime / 100

        local dayLabel

        if days == 1 then
                dayLabel = " day, "
        else
                dayLabel = " days, "
        end

        result = result .. "\n  System uptime: " .. days .. dayLabel .. hours .. ":" .. minutes .. ":" .. seconds
        result = result .. " (" .. tostring(uptime) .. " timeticks)"

        return result
end


_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org



-- 
NOTICE:  This email is being sent in clear-text across the public
Internet.  Therefore, any attempts to include unenforceable legalese
restrictions are ridiculous and pointless.  If you can read this,
consider yourself authorized (whether I like it or not).

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: