Tuesday, November 3, 2009

Episode #67: Time Lords

Hal is still adjusting:

Mr. Bucket suggested a time-related Episode this week in honor of the shift back to Standard Time here in the U.S. Generally, we try to humor Mr. Bucket as long as his requests aren't too deviant (or if Ed is the only one who has to dress up), so here goes.

First I've got a couple of tricks up my sleeve related to the NTP time synchronization service. My favorite command-line tool for checking up on my NTP servers is "ntpdc -p":

$ ntpdc -pn server.example.com
remote local st poll reach delay offset disp
= 16 1024 0 0.00000 0.000000 0.00000
= 2 1024 377 0.06984 -0.003889 0.13681
* 2 1024 377 0.09087 0.002323 0.12178
= 5 64 377 0.00000 0.000000 0.03093

The "st" column that shows the remote server's stratum level. This is useful for detecting downed time servers, because they show up as stratum 16 like on the first line above. The "poll" (polling interval in seconds) and "reach" (displayed in octal notation and capped at 255, the number of recent successful polls) columns give you and idea of how well your server is synchronizing with other time servers. "delay" tells you how far away the remote server is from you, and "offset" is the difference between your local clock and the clock on the remote server (if things are working right, the offset should be less than a hundredth of a second). Note that in the above example, I checked on the remote server.example.com machine, but you can leave off the host name portion to check the time server running on your local box.

In addition to checking status with ntpdc, you can also set the time on your box from the command line using ntpdate. Normally you would just run ntpdate and specify the server you wanted to synchronize against, but here's a cute little bit of awk fu for pulling the server names out of your current ntp.conf file:

# ntpdate `awk '/^(server|peer) / && !/127.127./ {print $2}' /etc/ntp.conf`
29 Oct 19:42:43 ntpdate[13376]: adjust time server offset -0.004818 sec

Here I'm pulling off the host name or IP address specified on the "server" or "peer" lines in your ntp.conf file. I'm skipping any "addresses" that start with "127.127." since these are merely place holders for clock driver definitions and not real IP addresses.

Note that you can only run ntpdate if your NTP daemon is not currently active. If ntpd is running at the same time you execute ntpdate, you get a message like this:

# ntpdate `awk '/^(server|peer) / && !/127.127/ {print $2}' /etc/ntp.conf`
29 Oct 19:42:18 ntpdate[13362]: the NTP socket is in use, exiting

Typically you only need to call NTP date by hand if the NTP daemon is not running and your clock has gotten out of synch. After you use ntpdate to jump your clock to something approximating the right time, you should start your NTP daemon to keep it synced (usually "/etc/init.d/ntpd start").

Getting away from NTP now, let me show you a little environment variable hack that's particularly useful for Forensic Analysts. Suppose you've captured a disk image from a system that was being used in a time zone other than the one your analysis machine is set to. You'd like to mount a copy of the image and be able to observe the timestamps on the files relative to the time zone the image was taken from. You could change the global time zone setting on your analysis workstation, but that could cause you lots of hassle.

It turns out that bash allows you to set the TZ environment variable in your shell to alter the local time zone setting for only that shell. For example, my local time zone is US/Pacific, but suppose I had an image from a machine from the East Coast:

$ date
Thu Oct 29 17:59:13 PDT 2009
$ ls -ld /mnt/image/tmp
drwxrwxrwt 23 root root 4096 Oct 29 17:28 /mnt/image/tmp
$ export TZ=US/Eastern
$ date
Thu Oct 29 21:00:07 EDT 2009
$ ls -ld /mnt/image/tmp
drwxrwxrwt 23 root root 4096 Oct 29 20:28 /mnt/image/tmp

Cool! Now I can look at the dates on files in my image and not constantly have to be doing mental arithmetic to convert the time stamps.

So there are three of my favorite time-related hacks. If we can get Ed out of those leather chaps that Mr. Bucket had him wear, I'm sure he'll have some cool Windows Fu to show us...

Ed chimes in:

Ahhh... time. A great idea for an article, Mr. Bucket. Much better than your last idea... you know... the one about the chaps. Anyway, I digress.

Let's walk before we run. To check the time on your local computer, you can simply run the following command:
C:\> time /t
06:05 AM
Want more precision? We can get that, as discussed in Episode #49, by displaying the %time% environment variable.
C:\> echo %time%
Alternatively, the "net time" command can be used to pull the time from a remote (or even local) Windows box:
C:\> net time \\[computername]
Current time at \\FRED2 is 10/31/2009 6:04 AM
The command completed successfully.
Note that, depending on whether you are a member of a domain and the privileges of your current account, you may need to first initiate an SMB connection with that machine, by running:
C:\> net use \\[computername] [password] /u:[username]
The command completed successfully.
If you happen to trust that server, you can set your local machine's time by its clock through running:
C:\> net time \\[computername] /set /yes
Well, that's all well and good, but Hal was working with NTP, which offers many more time sources than, well, our local host or domain controller. How can we pull time from an NTP server in Windows? First, please note that officially, with built-in capabilities, Windows relies on the Simple Network Time Protocol (SNTP), a stripped down NTP implementation that is often used in applications where time accuracy isn't as vital. That's why you'll see sntp throughout our commands below.

Let's first look to see which NTP server our Windows machine is configured to use:
C:\> net time /querysntp
The current SNTP value is: time.windows.com,0x1
The command completed successfully.
The time.windows.com server is the default. Do you trust Microsoft to accurately track the time on their server? After missing the release date of Windows Vista by... uh... something like 3 years, maybe we shouldn't (darnit... I couldn't resist pouring salt in those old wounds.) We can change the NTP server we're configured to use as follows:
C:\> net time /setsntp:pool.ntp.org
The command completed successfully.
Note that you can put a whole list of NTP servers there by following the colon with a space-separated list of NTP servers enclosed in double quotes, resulting in something like /setsntp:"pool.ntp.org ntp.colby.edu tick.gatech.edu"

OK... now, once we've set ourselves up to use an NTP server, let's try to check the time:
C:\> net time
Could not locate a time-server.

More help is available by typing NET HELPMSG 3912.
What? Why doesn't "net time" work here? Note that the HELPMSG is not at all helpful, as it explains that we could not locate a time-server, which we already saw in the error message itself. Gee, Microsoft... thanks for nothing.

It turns out that we can't pull time via "net time" using NTP (really SNTP) unless we're a domain controller with the Flexible Single Master Operation (FSMO) role. Lovely. But, what if we're just a lowly client, maybe not even in a domain? Can we sync with an NTP server using only built in tools? As Bob the Builder and Barack Obama might say: Yes, we can!

We can rely on that happy old stand-by for configuring time on Windows boxen, the intuitively named w32tm command. And in homage to Heinz Doofenshmirtz, by "intuitively named", I mean, of course, "completely non-intuitively named."

To sync with an NTP server, we start by configuring our Windows box (whether it's a client or server version of Windows) to allow us to pull time manually from an NTP server we'd like to use (note that you have to specify this with w32tm even if you've already run "net time" with the /setsntp option):
C:\> w32tm /config /syncfromflags:manual /manualpeerlist:pool.ntp.org
The command completed successfully.
Now that we're configured, just about ready to sync times, let's do a quick time check before the sync:
C:\> time /t
06:47 AM
Oh... that looks dreadfully wrong. I think my clock is fast. Let's cause Windows to read our new configuration now:
C:\> w32tm /config /update
The command completed successfully.
And finally, let's resync:
c:\> w32tm /resync
Sending resync command to local computer
The command completed successfully.
Boom! The clock in my tool tray is now synchronized! Let's double check that we have the new and proper time:
C:\> time /t
06:13 AM
We've now synced with a remote NTP server at the command line. Yummy.

Also, there are a lot of other fascinating time-related options available with w32tm. For instance, to display your timezone, you could run:
c:\> w32tm /tz
Time zone: Current:TIME_ZONE_ID_STANDARD Bias: 300min (UTC=LocalTime+Bias)
[Standard Name:"Eastern Standard Time" Bias:0min Date:(M:11 D:1 DoW:0)]
[Daylight Name:"Eastern Daylight Time" Bias:-60min Date:(M:3 D:2 DoW:0)]
We can even convert an NT system time (the number of 100 nanosecond intervals that have elapsed since Jan 1st, 1601, the date DOS was first written by monks) to a human readable date and time:
c:\> w32tm /ntte 128904420852883740
149194 22:21:25.2883740 - 6/25/2009 5:21:25 PM
This is especially useful if you have a Vista box (my condolences) and are researching the installation of patches using "wmic qfe". In XP Pro and Windows 7, "wmic qfe list full" returns a list of patches with an "InstalledOn" field in a human readable form. But, in Vista, this date is now a hexadecimal number of an NT system time. Convert that hex number into decimal using you favorite calculator, and then fire up w32tm /ntte to convert it into a date you can read. Also, the "w32tm /ntpte" command converts NTP times (seconds from Jan 1st, 1900, the date that Nicola Tesla implemented the first Unix kernel) into a human readable format.

But, wait, there's more! Hal showed how to add a timestamp into the output of your commands, useful in forensics. I sometimes will put a date and time into my command prompt itself, so that I can then copy and paste my session to use as evidence:
C:\> prompt $D$T$S$P$G
Sat 10/31/2009 6:15:29.97 C:\>
So, there's a bunch of time-related stuff. Have you got any other fun time kickers, Tim?

Tim clocks in:

Let's take a look at the cmdlets available that use the Time or Date nouns.

PS C:\> Get-Command -Noun date
CommandType Name Definition
----------- ---- ----------
Cmdlet Get-Date Get-Date [[-Date] ...
Cmdlet Set-Date Set-Date [-Date] ...

PS C:\> Get-Command -Noun time

Unfortunately, there aren't any built-in cmdlets for NTP. So to answer Ed's question, "No, no interesting kickers this week." But we can still take a look at the Get-Date cmdlet and its properties.

PS C:\> Get-Date | fl

DisplayHint : DateTime
DateTime : Sunday, November 01, 2009 10:17:23 PM
Date : 11/1/2009 12:00:00 AM
Day : 1
DayOfWeek : Sunday
DayOfYear : 305
Hour : 22
Kind : Local
Millisecond : 206
Minute : 17
Month : 11
Second : 23
Ticks : 633927106432066338
TimeOfDay : 22:17:23.2066338
Year : 2009

The object has a number of methods available, and they can be seen by piping the object into Get-Member. The results aren't shown here since it is a pretty long list. Since the reason for this episode is Daylight Savings Time we'll take a quick peek at the relevant method.

PS C:\> (Get-Date).IsDaylightSavingTime()

Ok, that wasn't spectacular, but let's carry on and recreate Ed's command prompt with the date.

PS C:\> function prompt {"PS $(Get-Date) $(Get-Location)>"}
PS 11/01/2009 22:43:53 C:\>

Since the prompt is defined by overloading the prompt function there are endless possibilities for setting a custom prompt.

That's all folks, hope to see you next time.