Nmap Development mailing list archives

Re: Getting system time from SMB (445 or 139)


From: Ron <ron () skullsecurity net>
Date: Sat, 23 Aug 2008 08:56:15 -0500

Brandon Enright wrote:
On Sat, 23 Aug 2008 00:54:05 -0500 or thereabouts Ron
<ron.bowes () javaop com> wrote:

Actually Judy Novak of Sourcefire wrote that script.  If the packet it
sends is already what you need to get the results then that script is
probably the right place to put it.
Ok, cool. It makes sense to go there, too.

We might try renaming the script to something more generic like
netbios-smb-information.nse  I doubt this will be the last useful
addition to the script.
Agreed, that's probably a good idea.

With portrule scripts, returning a multiline string (embedded "\n")
will produce reasonable output.  I haven't tried hostrule scripts but I
suspect they also gracefully handle multiline output.
Works, apparently. :)

You might try looking at SSLv2-support.nse for an idea of how to format
output and how to check the verbosity setting of Nmap to determine how
much info to return in different cases.  Hopefully hostrule scripts
handle the output well.
Cool, I updated my script modifications to:
a) only display in -v or higher
b) display the timezone offset as well as the time
c) display on a separate line from the OS version

Here's how it currently looks
--
Interesting ports on 192.168.1.42:
PORT    STATE SERVICE
445/tcp open  microsoft-ds
MAC Address: 00:0C:29:87:FC:76 (VMware)

Host script results:
|  Discover OS Version over NetBIOS and SMB: Windows 2000
|_ Discover system time over SMB: 2008-08-23 08:48:13 UTC-5
--

Something else I noticed about this script is that it uses the NetBIOS
Session Service on port 139, but it runs if port 445 is open (getting no
results). In my opinion, it should try port 445 first, since it
generates less traffic and doesn't need to know the NetBIOS name first.
I'm going to take a stab at making that change next.

Heck, if you can read and modify netbios-smb-os-discovery.nse you know
as much Lua as me :)
Well, it's a simple enough language for an experienced programmer. But
1-based arrays are going to be the death of me! :)

I'm working on grepping logs to find hosts that already return useful
info for netbios-smb-os-discovery.nse so that I can test your addition.

Brandon
Cool, thanks! I've only tested against Win2k, but I have 2k3 and xp
handy so I'll make sure they work against those. I suspect it will,
since it's standard protocol (of course, it's Microsoft so who knows? :) ).

I've attached my latest nse/patch against svn. Should I keep attaching
both, or is one better than the other?

Ron
Index: scripts/netbios-smb-os-discovery.nse
===================================================================
--- scripts/netbios-smb-os-discovery.nse        (revision 9689)
+++ scripts/netbios-smb-os-discovery.nse        (working copy)
@@ -21,6 +21,8 @@
 copyright = "Sourcefire Inc, (C) 2006-2007"
 license = "Same as Nmap--See http://nmap.org/book/man-legal.html";
 categories = {"version"}
+
+require 'bit'
  
 hostrule = function(host)
 
@@ -47,7 +49,7 @@
 end
 
 action = function(host)
-   local sharename, message, osversion, gen_msg, x
+   local sharename, message, osversion, currenttime, gen_msg, x
 
    osversion = ""
    gen_msg = "OS version cannot be determined.\n"
@@ -55,9 +57,13 @@
    sharename, message = udp_query(host)
 
    if (sharename ~= 0)  then
-       osversion, message = tcp_session(sharename, host)
+       osversion, currenttime, message = tcp_session(sharename, host)
        if (osversion ~= 0) then
-           return(osversion)
+           if (nmap.verbosity() > 0) then
+               return(osversion .. "\n" .. "Discover system time over SMB: " .. currenttime)
+           else
+               return(osversion)
+           end
        else
            return(gen_msg .. message)
        end
@@ -238,7 +244,7 @@
                 socket:close()
     end
 
-    local rec1_payload, rec2_payload, rec3_payload, status, line1, line2, line3, osversion, winshare, pos, message
+    local rec1_payload, rec2_payload, rec3_payload, status, line1, line2, line3, currenttime, osversion, winshare, 
pos, message
  
     message = 0
     local win5 =  "Windows 5.0"
@@ -281,7 +287,7 @@
    if (not status) then
        socket:close()
        message = "Never received a response to SMB Session Request"
-       return 0, message
+       return 0, 0, message
    end
 
    socket:set_timeout(100)
@@ -291,9 +297,11 @@
    if (not status) then
        socket:close()
        message = "Never received a response to SMB Negotiate Protocol Request"
-       return 0, message
+       return 0, 0, message
    end
 
+   currenttime = extract_time(line2);
+
    socket:set_timeout(100)
    try(socket:send(rec3_payload))
    status, line3 = socket:receive_lines(1)
@@ -301,7 +309,7 @@
    if (not status) then
        socket:close()
        message = "Never received a response to SMB Setup AndX Request"
-       return 0, message
+       return 0, currenttime, message
    end
 
    socket:close()
@@ -318,7 +326,7 @@
        end
    end 
 
-   return  osversion, message
+   return  osversion, currenttime, message
 
 end
 
@@ -344,16 +352,13 @@
     temp = string_concatenate(line, 47, ltemp)
     x=1
 
+    osversion = ""
     while (x < ltemp) do
         mychar = string.byte(temp,x)
         if (mychar == 0) then
             return osversion, message
-          else
-            if (x == 1) then
-                 osversion = string.char(mychar)
-               else
-                 osversion = osversion .. string.char(mychar)
-            end
+        else
+            osversion = osversion .. string.char(mychar)
         end
         x = x + 2
     end
@@ -365,3 +370,48 @@
     
 end
 
+-----------------------------------------------------------------------
+-- Response from Negotiate Protocol Response (TCP payload 2)
+-- Must be SMB response.  Extract the time from it from a fixed
+-- offset in the payload.
+
+function extract_time(line)
+
+    local smb, tmp, message, i, timebuf, timezonebuf, time, timezone
+
+    smb = "SMB" .. string.char(0x72) -- 0x72 = Negotiate Protocol
+    temp = string_concatenate(line, 6, 9) -- Remove the NetBIOS Session Service header
+    message = 0
+
+    if(temp ~= smb) then
+        message = "Didn't find correct SMB record as a response to the Negotiate Protocol Response"
+        return 0, message
+    end
+
+    -- Extract the timestamp from the response
+    i = 1
+    time = 0
+    timebuf = string.sub(line, 0x3d, 0x3d + 7)
+    while (i <= 8) do
+        time = time + 1.0 + (bit.lshift(string.byte(timebuf, i), 8 * (i - 1)))
+        i = i + 1
+    end
+    -- Convert time from 1/10 microseconds to seconds
+    time = (time / 10000000) - 11644473600;
+
+    -- Extract the timezone offset from the response
+    timezonebuf = string.sub(line, 0x45, 0x45 + 2)
+    timezone = (string.byte(timezonebuf, 1) + (bit.lshift(string.byte(timezonebuf, 2), 8)))
+
+    if(timezone == 0x00) then
+        timezone = "UTC+0"
+    elseif(bit.band(timezone, 0x8000) == 0x8000) then
+        timezone = "UTC+" .. ((bit.band(bit.bnot(timezone), 0x0FFFF) + 1) / 60)
+    else
+        timezone = "UTC-" .. (timezone / 60)
+    end
+
+    return (os.date("%Y-%m-%d %H:%M:%S", time) .. " " .. timezone), message;
+ 
+end
+
--- This script probes a target for its operating system version.
-- It sends traffic via UDP port 137 and TCP port 139/445.\n\n
-- == Implementation Information ==\n
-- First, we need to
-- elicit the NetBIOS share name associated with a workstation share.
-- Once we have that, we need to encode the name into the "mangled"
-- equivalent and send TCP 139/445 traffic to connect to the host and
-- in an attempt to elicit the OS version name from an SMB Setup AndX
-- response.\n\n
--
-- Thanks to Michail Prokopyev and xSharez Scanner for required 
-- traffic to generate for OS version detection.
--
--@usage
-- sudo nmap -sU -sS --script netbios-smb-os-discovery.nse -p U:137,T:139 127.0.0.1
-----------------------------------------------------------------------

id = "Discover OS Version over NetBIOS and SMB"
description = "Attempt to elicit OS version from host running NetBIOS/SMB"
author = "Judy Novak"
copyright = "Sourcefire Inc, (C) 2006-2007"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html";
categories = {"version"}

require 'bit'
 
hostrule = function(host)

        local port_u137 = nmap.get_port_state(host,
                {number=137, protocol="udp"})
        local port_t139 = nmap.get_port_state(host,
                {number=139, protocol="tcp"})
        local port_t445 = nmap.get_port_state(host,
                {number=445, protocol="tcp"})

        if (
                (port_u137 ~= nil and
                (port_u137.state == "open" or
                 port_u137.state == "open|filtered")) and
                (port_t139 ~= nil and port_t139.state == "open") or
                (port_t445 ~= nil and port_t445.state == "open") 
           )
        then
                return true
        else
                return false
        end

end

action = function(host)
   local sharename, message, osversion, currenttime, gen_msg, x

   osversion = ""
   gen_msg = "OS version cannot be determined.\n"

   sharename, message = udp_query(host)

   if (sharename ~= 0)  then
       osversion, currenttime, message = tcp_session(sharename, host)
       if (osversion ~= 0) then
           if (nmap.verbosity() > 0) then
               return(osversion .. "\n" .. "Discover system time over SMB: " .. currenttime)
           else
               return(osversion)
           end
       else
           return(gen_msg .. message)
       end
   else
       return(gen_msg .. message)
   end

end

-----------------------------------------------------------------------
-- A NetBIOS wildcard query is sent to a host in an attempt to discover
-- any NetBIOS shares on the host.

function udp_query(host)

       local l, sharename, message
       local WildCard = 
       string.char(0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 
                   0x00, 0x00, 0x20, 0x43, 0x4b, 0x41, 0x41, 0x41, 0x41, 0x41, 
                   0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
                   0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 
                   0x41, 0x41, 0x41, 0x41, 0x41, 0x00, 0x00, 0x21, 0x00, 0x00)

       local socket = nmap.new_socket()

       socket:connect(host.ip, 137, "udp")
       socket:send(WildCard)
       socket:set_timeout(100)

       local status, result = socket:receive_bytes(1);

       socket:close()

       if (result ~= nil) then
           l = string.len(result)
           sharename = extract_sharename(result)
           if (sharename ~= 0)  then
              return sharename, 1
           else
              message = "Failed to find NetBIOS share name in response to UDP NetBIOS wildcard query"
              return 0, message
           end
       end
end

-----------------------------------------------------------------------
-- This function extracts the name of a "workstation" share from the
-- response to the UDP NetBIOS wildcard query.  Typically, there are
-- several share types returned, but only one with a "workstation"
-- type/code can be queried later for the OS version.  The workstation
-- type/code is 0x44 0x00 for OS versions prior to Vista.  The type/code
-- for Vista is 0x04 0x00.  

function extract_sharename(resp)
 
    local lenpay, beg, eend, typebeg, typeend, temp, name, nametype, ntgeneric, ntvista, ename, myname, eename, ntunix

    beg = 58
    eend = beg + 15
    typebeg = eend + 1
    lenpay = string.len(resp)

    while (eend <= lenpay) do

        myname = string_concatenate(resp, beg, eend - 1)
        nametype = string.byte(resp, typebeg) .. string.byte(resp, typebeg + 1)
        ntgeneric = string.find(nametype, 0x44,0x00) 
        ntvista = string.find(nametype, 0x04, 0x00)
        ntunix = string.find(nametype, 0x64, 0x00)

        if  (ntgeneric == 1) or (ntvista == 1) or (ntunix == 1) then
           ename = encode(myname)
        end

        if (ename ~= nil) then 
            do
              ename = string.char(0x20) .. ename .. string.char(0x43, 0x41, 0x00) 
              return(ename)
            end
        end

        beg = beg + 18
        eend = beg + 15
        typebeg = eend + 1
    end
    return(0)
end

-----------------------------------------------------------------------
-- Extract multiple bytes from a string and return concatenated result

function string_concatenate(mystring, start, stop)
    local x, temp, newname

    for x = start, stop, 1 do
        temp = string.byte(mystring,x)
        if (x > start) then
            newname = newname .. string.char(temp)
          else
            newname = string.char(temp)
        end
    end
    return(newname)
end

-----------------------------------------------------------------------
-- This function encodes the workstation share name returned from the
-- UDP wildcard NetBIOS query. Each character from the NetBIOS share
-- name is encoded/mangled using a special algorithm.  Rather than 
-- implementing the algorithm, Microsoft offers a conversion table for
-- any valid character found in a share name. I could not figure out
-- how to use a Lua dictionary where the key value included a 
-- non-alphanumeric character.  The static variable chars represents
-- most of the characters that can be found in a share and the position
-- in the string "chars" is the corresponding position in the trtable
-- table. The character " had to be handled separately as it is used
-- to delimit the value of chars.  

encode = function(name)

    local ln, y, nchar, newname, pos, temp, trtable
    local chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 !#$%&'()*+,-.=:;@^_{}~"

    local trtable = 
    {
     string.char(0x45,0x42), string.char(0x45,0x43), string.char(0x45,0x44), string.char(0x45,0x45), 
string.char(0x45,0x46),
     string.char(0x45,0x47), string.char(0x45,0x48), string.char(0x45,0x49), string.char(0x45,0x4A), 
string.char(0x45,0x4B),
     string.char(0x45,0x4C), string.char(0x45,0x4D), string.char(0x45,0x4E), string.char(0x45,0x4F), 
string.char(0x45,0x50),
     string.char(0x46,0x41), string.char(0x46,0x42), string.char(0x46,0x43), string.char(0x46,0x44), 
string.char(0x46,0x45),
     string.char(0x46,0x46), string.char(0x46,0x47), string.char(0x46,0x48), string.char(0x46,0x49), 
string.char(0x46,0x4A),
     string.char(0x46,0x4B), string.char(0x44,0x41), string.char(0x44,0x42), string.char(0x44,0x43), 
string.char(0x44,0x44),
     string.char(0x44,0x45), string.char(0x44,0x46), string.char(0x44,0x47), string.char(0x44,0x48), 
string.char(0x44,0x49),
     string.char(0x44,0x4A), string.char(0x43,0x41), string.char(0x43,0x42), string.char(0x43,0x44), 
string.char(0x43,0x45),
     string.char(0x43,0x46), string.char(0x43,0x47), string.char(0x43,0x48), string.char(0x43,0x49), 
string.char(0x43,0x4A),
     string.char(0x43,0x4B), string.char(0x43,0x4C), string.char(0x43,0x4D), string.char(0x43,0x4E), 
string.char(0x43,0x4F),
     string.char(0x44,0x4E), string.char(0x44,0x4B), string.char(0x44,0x4C), string.char(0x45,0x41), 
string.char(0x46,0x4F),
     string.char(0x46,0x50), string.char(0x48,0x4C), string.char(0x48,0x4E), string.char(0x48,0x4F)
     }

     ln = string.len(name)
     y = 1

     while (y <= ln) do 
         temp = string.byte(name, y)

         if (temp == 0x00) then  --Sharename must be followed by spaces not null's to be acceptable
               return(nil)
             elseif (temp == '"') then
               nchar = string.char(0x43,0x43)
             else do
               temp = string.char(temp)
               pos = string.find(chars, temp)
               nchar = trtable[pos] 
               if (y > 1) then
                  newname = newname .. nchar 
               else
                  newname = nchar
               end 
               y = y + 1     
             end
         end
     end
     return(newname)
end

-----------------------------------------------------------------------
-- This function invokes the TCP traffic that is generated to get
-- a response that yields the OS version information.  The first
-- payload is an SMB session initiation request followed by a 
-- negotiate payload, and followed by a Session Setup AndX request.
-- The workstation share name extracted from the UDP wildcard NetBIOS
-- response must be used in the SMB session initiation request(payload 1).
-- Payload for the requests that follow is static.

function tcp_session(ename, host)

    local catch = function()
                socket:close()
    end

    local rec1_payload, rec2_payload, rec3_payload, status, line1, line2, line3, currenttime, osversion, winshare, pos, 
message
 
    message = 0
    local win5 =  "Windows 5.0"
    local win51 = "Windows 5.1"

    winshare = string.char(0x20, 0x46, 0x48, 0x45, 0x4A, 0x45, 0x4F, 0x45, 0x45, 0x45, 0x50, 0x46, 0x48, 0x46, 0x44, 
0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x43, 0x41, 0x00)

   rec1_payload = string.char(0x81, 0x00, 0x00, 0x44) .. ename  ..  winshare

   rec2_payload = string.char( 0x00, 0x00, 0x00, 0x85, 0xff, 0x53, 0x4d, 0x42, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x01, 0xc0 ) ..
                  string.char( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x1e, 0xfa ) ..
                  string.char( 0x00, 0x00, 0x17, 0x62, 0x00, 0x61, 0x00, 0x02, 0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 
0x57, 0x4f ) ..
                  string.char( 0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 
0x00, 0x02 ) ..
                  string.char( 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e, 0x30, 0x00, 0x02, 0x57, 0x69, 0x6e, 
0x64, 0x6f ) ..
                  string.char( 0x77, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x67, 0x72, 0x6f, 
0x75, 0x70 ) ..
                  string.char( 0x73, 0x20, 0x33, 0x2e, 0x31, 0x61, 0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e, 0x32, 0x58, 
0x30, 0x30 ) ..
                  string.char( 0x32, 0x00, 0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x32, 0x2e, 0x31, 0x00, 0x02, 
0x4e, 0x54 ) ..
                  string.char( 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x00)

   rec3_payload =  string.char( 0x00, 0x00, 0x00, 0xab, 0xff, 0x53, 0x4d, 0x42, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x01, 0xc0 ) ..
                   string.char( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x1e, 0xfa ) ..
                   string.char( 0x00, 0x00, 0x17, 0x62, 0x0d, 0xff, 0x00, 0x00, 0x00, 0x04, 0x11, 0x0a, 0x00, 0x00, 
0x00, 0x00 ) ..
                   string.char( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 
0x00, 0x6d ) ..
                   string.char( 0x00, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 
0x73, 0x00 ) ..
                   string.char( 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x00, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 
0x64, 0x00 ) ..
                   string.char( 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x39, 0x00, 0x35, 0x00, 0x2f, 0x00, 
0x39, 0x00 ) ..
                   string.char( 0x38, 0x00, 0x2f, 0x00, 0x4d, 0x00, 0x65, 0x00, 0x2f, 0x00, 0x4e, 0x00, 0x54, 0x00, 
0x2f, 0x00 ) ..
                   string.char( 0x32, 0x00, 0x6b, 0x00, 0x2f, 0x00, 0x58, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x78, 0x00 ) ..
                   string.char( 0x53, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x7a, 0x00, 0x20, 0x00, 
0x53, 0x00 ) ..
                   string.char( 0x63, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 
0x00)
 
   local socket = nmap.new_socket()
   local try = nmap.new_try(catch)  
   try(socket:connect(host.ip,139,"tcp"))

   socket:set_timeout(100)
   try(socket:send(rec1_payload))
   status, line1 = socket:receive_lines(1)

   if (not status) then
       socket:close()
       message = "Never received a response to SMB Session Request"
       return 0, 0, message
   end

   socket:set_timeout(100)
   try(socket:send(rec2_payload))
   status, line2 = socket:receive_lines(1)

   if (not status) then
       socket:close()
       message = "Never received a response to SMB Negotiate Protocol Request"
       return 0, 0, message
   end

   currenttime = extract_time(line2);

   socket:set_timeout(100)
   try(socket:send(rec3_payload))
   status, line3 = socket:receive_lines(1)

   if (not status) then
       socket:close()
       message = "Never received a response to SMB Setup AndX Request"
       return 0, currenttime, message
   end

   socket:close()
   osversion, message = extract_version(line3)
   if (osversion ~= 0) then
       pos = string.find(osversion, win5) 
       if (pos ~= nil) then
           osversion = "Windows 2000"
       else
           pos = string.find(osversion, win51) 
           if (pos ~= nil) then
               osversion = "Windows XP"
           end
       end
   end 

   return  osversion, currenttime, message

end

-----------------------------------------------------------------------
-- Response from Session Setup AndX Request (TCP payload 3)
-- Must be SMB response.  Extract the OS version from it from a fixed
-- offset in the payload.

function extract_version(line)

    local temp, smb, ltemp, go, x, osversion, mychar, message

    smb = "SMB" .. string.char(0x73)
    temp = string_concatenate(line, 6, 9)
    message = 0
    
    if (temp ~= smb) then
        message = "Didn't find correct SMB record as a response to the Session Setup AndX request"
        return 0, message
    end

    ltemp = string.len(line)
    temp = string_concatenate(line, 47, ltemp)
    x=1

    osversion = ""
    while (x < ltemp) do
        mychar = string.byte(temp,x)
        if (mychar == 0) then
            return osversion, message
        else
            osversion = osversion .. string.char(mychar)
        end
        x = x + 2
    end

    if (x >= ltemp) then 
        message = "OS version not found in expected record Session Setup AndX response"
        return 0, message
    end
    
end

-----------------------------------------------------------------------
-- Response from Negotiate Protocol Response (TCP payload 2)
-- Must be SMB response.  Extract the time from it from a fixed
-- offset in the payload.

function extract_time(line)

    local smb, tmp, message, i, timebuf, timezonebuf, time, timezone

    smb = "SMB" .. string.char(0x72) -- 0x72 = Negotiate Protocol
    temp = string_concatenate(line, 6, 9) -- Remove the NetBIOS Session Service header
    message = 0

    if(temp ~= smb) then
        message = "Didn't find correct SMB record as a response to the Negotiate Protocol Response"
        return 0, message
    end

    -- Extract the timestamp from the response
    i = 1
    time = 0
    timebuf = string.sub(line, 0x3d, 0x3d + 7)
    while (i <= 8) do
        time = time + 1.0 + (bit.lshift(string.byte(timebuf, i), 8 * (i - 1)))
        i = i + 1
    end
    -- Convert time from 1/10 microseconds to seconds
    time = (time / 10000000) - 11644473600;

    -- Extract the timezone offset from the response
    timezonebuf = string.sub(line, 0x45, 0x45 + 2)
    timezone = (string.byte(timezonebuf, 1) + (bit.lshift(string.byte(timezonebuf, 2), 8)))

    if(timezone == 0x00) then
        timezone = "UTC+0"
    elseif(bit.band(timezone, 0x8000) == 0x8000) then
        timezone = "UTC+" .. ((bit.band(bit.bnot(timezone), 0x0FFFF) + 1) / 60)
    else
        timezone = "UTC-" .. (timezone / 60)
    end

    return (os.date("%Y-%m-%d %H:%M:%S", time) .. " " .. timezone), message;
 
end


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

Current thread: