A common request by IT security offices everywhere is that when logging on, have the server tell the user when they last logged on, in the hope that if a user actually remembers when they last logged on, they can figure out when their account is compromised.

Although I question the effectiveness of this practice, as a former CISSP, it’s hard to find a strong reason to argue against implementing it.

So as Active Directory admins, how exactly do we do that without a lot of work? Well I’m going to assume your AD domain controllers are running at least Windows Server 2008 (preferrably R2). If not, upgrade. Then come back here and read the rest of this post.

For a while now, the AD schema has had two “last logon” related attributes. lastLogon and lastLogontimeStamp. You can find more information about those two attributes, and what the intended use is here:


(hint: it has nothing to do with showing the last logon of the user — they are used to help identify unused computer/user objects)

So yeah, you can pretty much ignore those attributes. The lastLogon attribute doesn’t replicate across DC’s, and the lastLogontimeStamp attribute replicates very slowly (on purpose — see above link).

Luckily it’s now 2008..er..I mean 2012, and we now have even more logon-time related attributes to play with, but these are slightly more useful:


As long as your AD forest is at 2008 functional level, you can edit the group policy being applied to your DC’s to enable these new attributes.

Note: If you enable this feature on your member servers/workstations before your DC’s, you’ll lock everyone out of those systems, so don’t do that.

As this Microsoft KB article (951020) suggests, you need to look for the “Domain Controllers provide information about previous logons when display is not enabled” setting. Except it doesn’t tell you where that is, and if you google for it (in quotes), you’ll get exactly 3 results. The first is the KB article referenced above. Besides, thats not what the setting is called. heh. Anyway, the setting is located here:

Computer Configuration -> Administrative Templates -> System -> KDC -> “Provide information about previous logons to client computers”

Yeah, enable that one. This just tells the DC’s that they now support these new attributes, but doesn’t affect servers/workstations. *NOW* you can edit group policy wherever you want to, and enable the other setting, which actually tells windows to show the last time you logged on:

Computer Configuration -> Administrative Templates -> Windows Components -> Windows Logon Options -> “Display information about previous logons during user logon”

I would provide screenshots, but it really isn’t all that exciting. Ok it kinda is, but I still don’t wanna take screenshots. :-) If you *really* want to see one, go here:


Happy logons!


There are a lot of examples out there on the interwebs showing how to run the various Powershell cmdlets to gather information about your Exchange 2010 databases. One thing that isn’t out there (or at least, isn’t easy to find), is how to throw the disk usage information into nice pretty CSS graphs that magically show up in your email inbox every morning.

For the impatient, just grab the script from poshcode.org here: get-exstats.ps1

Basically what this script does, is gather various data and stores it in two tables.  The first table is formatted “pretty” with the bytes converted into something easy to read (MB, GB, etc) and is used in the top part of the email.  The second table keeps the raw unformatted bytes for use only in generating the CSS graphs.  The only part of this script you will need to modify is at the very bottom, where it sends the email.  Just update the SMTP server and the to/from addresses, and (hopefully), you’re set.

This was written for an environment that uses mountpoints, but if you specify the -nomountpoint switch, it should work around one of the issues I encountered in my test environment that doesn’t use mountpoints.

The results that are emailed to you should look something like this:

And the CSS charts below the table should look like this:

And of course, the graph key so you know what the colors mean:

(The DB names have been cropped). Anyway, that’s the idea. Hopefully this works for you, but if not, try to figure out where the problem is or feel free to post in the comments and I’ll help if I can.



You just brought up a Powershell prompt to navigate to the Exchange install folder, or perhaps the Exchange scripts folder.  Lets see… cd \program[tab complete].  cd Micro[tab].  “dir”  cd Exch[tab].  “dir” cd v[tab]….

And you think to yourself, “I’ll have that path memorized one of these years…”  But wait! Those smart Exchange developers knew you would probably need to go here often, so they went ahead and put those paths in the $exbin and $exscripts variables.

[PS] C:\> cd $exbin
[PS] C:\Program Files\Microsoft\Exchange Server\V14\bin>


[PS] C:\> cd $exscripts
[PS] C:\Program Files\Microsoft\Exchange Server\V14\scripts>

You’re welcome. :-)


This is a topic I’ve thought about posting for a long time.  It seems almost like common sense, and I didn’t want to insult anyone, but the more I’ve thought about this, the more I’ve realized that this is an art.  Or perhaps a skill.  Maybe even an intuition.

What the hell am I talking about?  Googling.  You know, your server just blew up.  10,000 users can’t get their email.  All you see is a stream of errors in the event log, and at the same time, end users are yelling at you because they *have* to send this super important file using a non-guaranteed delivery mechanism (email).  Managers are calling you on the phone, sending you an IM, your pager is going off, and you’re getting urgent tickets in your ticketing system.  What to do?!?!?!!11??omgwtfbbq!!

Well first of all, take a chill pill and be thankful you don’t have a flesh eating bacteria.  Yeah, it could be worse.  Seriously.  You always want to poke around the system for obvious stuff (is the disk full?  what was the first error event in the event log? was another admin logged in and now you aren’t hearing a peep out of them?), but you know what, the most simple brain dead way to help track down a problem is to just google it.

Now here is what separates experience from omgwtfbbq?!!11!!.  What do you google for?  This is almost basic troubleshooting 101.  Don’t just search for “email broken, halp”.  You need to at least try and find the source of the issue, or if your logs don’t go back that far, just search for the event ID and source of whatever you do see.  Or if a system-generated error message shows up, search for that, because you KNOW that a system-generated message will be the SAME on every other system in the world running that same version.  And thats what you want to find, other people running the same software, who have seen the same problem.  If the search results are too broad, add some additional keywords that are relevant to the problem.  If you suspect it could be a bug, limit your search to the vendor’s website only.  For example, add site:microsoft.com to your search query.  Over time you will start to see the same blogs or message boards pop up, so you will know which ones are likely to have useful information.  Even if you don’t find the exact answer, it will at least get you thinking about things you may not have realized were relevant at first.

Remember that search engines are just a tool, and although rare, it *is* possible that you are the first person to have a particular problem, although probably not.  I can’t tell you how many times someone has come to me with a problem that they’ve been working on forever, and I typed in google, word-for-word, what that person just told me, and the answer was the first result.  Don’t be that guy.  GIYF!



Late last year, Apple released an updated document detailing how to manage Macs in an Active Directory environment.  You can either add an Open Directory server to the mix, which is another LDAP directory (sorta like AD, except for Macs), or you can just take the Apple specific “schema” modifications in Open Directory, and just apply them to AD (this is called extending the schema).  By the way, an LDAP schema defines what types of attributes are allowed to be stored, such as usernames, computernames, phone numbers, etc, but that’s really way out of scope of this post.

Anyway, even though Apple was nice enough to provide that document (grab it here: http://training.apple.com/pdf/wp_integrating_active_directory.pdf), they didn’t go so far as to *give* us the schema (ldif) file.  They make us create it on our own.  Ugh, really, Apple?  Their argument is that if we are forced to create our own LDIF file, then we’re sure to capture the exact differences between our AD and Open Directory (OD).  That is sort of a valid argument, but having gone through the process of creating that LDIF file, the instructions are so specific, that it appears everyone will end up with exactly the same file, so why didn’t they just give it to us in the first place?  But I digress…

Anyway, the document is well written and easy to follow, They want an OD server, and AD server, and an XP box in the middle with the ADAM (AD Application Mode) tools installed so that we can connect to both directories and spit out the schema differences.  This was slightly annoying because I haven’t had an XP box around for….quite some time.  What I did was to use a Windows 2008 test server I had laying around, and added the AD LDS role.  LDS (Lightweight Directory Services) is the 2008 version of ADAM.  After installing that, the same diff tool was still available, so I didn’t need an XP box, and the instructions still worked flawlessly.

To save you some trouble, just grab the file here:  apple-mods.ldf

Obviously, be sure to test this in a TEST ENVIRONMENT first, because these changes aren’t as common as Microsoft provided schema updates, so who knows how they will affect your existing environment, especially if someone before you has already extended your schema with earlier Apple stuff.

Hat tip to Michael Kuron who has a blog post on an earlier schema update.  If you’re considering extending your schema, you’ll definitely want to read the comments at the bottom of that post.  Very informative.


iPhone 4S Review

It’s been a while since I posted anything on this blog, and I’ve been thinking about getting things started again, so why not start with the iPhone 4S?  It’s not like there aren’t any reviews out there, but at least I can give you my take on it.

My last phone was the iPhone 3GS.  And before that, the original iPhone.  So yeah, i’ve been an iPhone guy for a while. Kinda surprising for a guy who used to not like Apple *at all*, but that was in the OS9 days.

I’ll admit to some disappointment regarding the 4S release.  I, like basically everyone else, expected a mind-blowing iPhone 5 with features that nobody would have been able to predict, but thats what happens when the rumor mill goes nuts.  Either way, the 3GS was old enough, and I was ready enough to upgrade (and switch from AT&T to Verizon), that I took the plunge, and got in line at the Apple store at ~4am on Friday morning.

So lets get to it.  The iPhone 4S has an amazing screen (the retina display), which is identical to the 4, but coming from a 3GS, it’s totally worth the upgrade just for that alone.  It’s definitely faster than prior models with the faster Apple A5 processor, but they clocked the processor at only 800MHz, which is slower than the identical processor in the iPad 2.  This was likely done to conserve battery life.  I’ve heard of some complaints about battery life in iOS 5 in general, but I have not experienced those problems.  In fact, the battery life has been great for me, except for the first few days when I was playing with it non-stop.

Siri:  Everybody is talking about Siri, and yes, it totally rocks.  Siri does say some crazy stuff but that has already been big news.  See “Shit that Siri Says“.  But how useful is it, really?  It’s way faster to get siri to do a few things than going through the usual apps and typing on the keyboard.  Just saying “Wake me up at 7am” sets the alarm.  Oh, you meant 6am?  Just say “make that 6am.”  Yeah, it’s that easy.  Also, typing text messages or email is way faster using Siri too, as long as you make a slight effort to speak clearly.  Even when you don’t talk that clear, it can usually still figure out what you meant.  That’s probably what I’ve been most impressed about after using other voice recognition products over the years.

Camera/Video:  The 8mp camera rocks.  The thing shoots full 1080p video at 30 frames per second.  60 fps would be ideal for motion (sports, etc), but I’ll settle for 30. :-)  It does very well in lower light conditions too.  There isn’t much need to haul around a point-and-shoot camera anymore, but I’ll probably still take my 12mp Sony DSX-WX5 on vacations.  Check out a test video I took on the 4S this past Friday at the NC State Fair below.  You’ll have to go to vimeo to see the full HD version:

2011 NC State Fair from Robbie Foust on Vimeo
So was it worth it?  For me, yeah, definitely.  But I love new techy geeky stuff, so for me it was a no-brainer.  If you already have an iPhone 4, they no, it’s probably not worth it, especially if you’re still in a contract.  Oh and by the way, yes, I get way better reception with Verizon at my house.

Feel free to ask questions and I’ll try to answer if I can.



If you have a VMware ESX cluster running some Windows VMs, you’ve probably noticed very poor mouse response when on the console of your VMs. The fix is actually very simple. You need to bump up the hardware acceleration in the display preferences. You can either do it from the GUI (right click desktop -> properties -> settings -> advanced -> troubleshoot), or you can do it from Powershell:

set-itemproperty -path (((get-itemproperty "hklm:\hardware\devicemap\video")."\Device\Video0") -replace "\\Registry\\Machine","HKLM:") -name "Acceleration.Level" -value 0

What this command does is query the HKLM:\Hardware\Devicemap\Video registry branch to find the true location of your primary video device, and then sets the Acceleration.Level key to a value of 0.

The only problem with editing the registry setting directly is that Windows doesn’t automatically reload the display configuration, so the change doesn’t immediately take effect. Although it is technically possible to do that from Powershell, it isn’t easy (requires p/invoke) and you’re probably better off just rebooting the VM. :)

Using Group Policy in Active Directory, you can force the Windows Firewall to be enabled across your servers or clients, but sometimes you might not want to do that.  After all, when troubleshooting a software communications problem, it’s really easy to rule out the firewall configuration as a possible problem if you can disable it for a few minutes while you troubleshoot.

The only problem with allowing that kind of flexibility is how do you know that you remembered to re-enable the firewall on those 30 servers you worked on last week?  Well, some quick googling will show that you can use WMI to query the HNet_ConnectionProperties class and look at the IsFirewalled property.  Except….it’s always True!  Even if the firewall is disabled.  Apparently, this is because the ICS service is running so the property is a bit misleading.

So I did things the hard way.  I used Regmon to find out what registry key was flipped on/off when I enabled/disabled the Windows Firewall, and wrote a quick Powershell function to query that setting and return True or False (as type [bool]).

# returns true if windows firewall is enabled, false if it is disabled
filter global:get-firewallstatus ([string]$computer = $env:computername)
	if ($_) { $computer = $_ }

	$HKLM = 2147483650

	$reg = get-wmiobject -list -namespace root\default -computer $computer | where-object { $_.name -eq "StdRegProv" }
	$firewallEnabled = $reg.GetDwordValue($HKLM, "System\ControlSet001\Services\SharedAccess\Parameters\FirewallPolicy\DomainProfile","EnableFirewall")


Update (Feb 1, 2009):

In the comments, Shay Levy reminded me of an alternate method of querying the registry that doesn’t use WMI. Here is the exact same script using the [Microsoft.Win32.RegistryKey] class. Thanks Shay!

filter global:get-firewallstatus2 ([string]$computer = $env:computername)
	if ($_) { $computer = $_ }

	$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$computer)

	$firewallEnabled = $reg.OpenSubKey("System\ControlSet001\Services\SharedAccess\Parameters\FirewallPolicy\DomainProfile").GetValue("EnableFirewall")


View/Download Get-Packet.ps1 Script

I’ve posted an updated version of my Get-Packet Powershell packet sniffer script.  It is still completely standalone (it doesn’t require any additional software to run).  New features include:

  • Added IP Version field
  • TCP flags are now stored in an array
  • New switch added to resolve IPs to hostnames
  • ESC key will cleanly exit the script
  • New switch added to generate statistics

.NET includes a method to resolve IPs to Hostnames in [System.Net.Dns]::GetHostByName(), but if the lookup fails, then there is a 5 second delay that forces the script to pause execution. I instead chose to scrape the output of nslookup since it returns much quicker.  To further decrease processing time, I cache the results in a hashtable so multiple calls to nslookup for the same host are not needed.

Using the -Statistics switch will cause the script to generate statistics after the ESC key is pressed to stop the trace.  Most of the statistics code was borrowed from Jeffery Hicks’s Analyze-Packet script.  A few basic stats will be printed to the screen with write-host, but the bulk of the data will be stored in a global $stats variable that you can access after the script has exited.  This isn’t how features would normally be implemented in cmdlets (they would be separate cmdlets), but I figured it would be ok in a script, and I have found the integration to be pretty convenient.

I had looked at adding IPv6 support, but design limitations in Windows prevented me from being able to access the raw IPv6 header.  See my earlier blog post for more details.  I also looked at adding the ability to save the capture in libpcap format, but I’m not getting the raw IP frame, so the data wouldn’t be as complete as a capture done in something like Wireshark.

Anyway, I hope you enjoy the new features!  Let me know in the comments if you would like to see any other features added.

  • EDIT: If you’re on Vista, you might need to disable the firewall to see TCP packets.  Not sure why yet. :)
  • EDIT #2: Found out why.  Add powershell.exe as an allowed application. (duh) :)

– Robbie

View/Download get-regex.ps1 Script

When I write scripts, every now and then I need to use Regular Expressions.  RegEx’s are very powerful, but I don’t use them enough to have it all memorized.  So instead of searching for my quick reference book all the time, I just made a Powershell function to display all of the info at the prompt.

Poweshell’s built in “get-help” includes some basic RegEx documentation, but it is lacking some detail, and I don’t want to have to read through all the “fluff” to get to what I want.

The output of the script looks like this:

PS C:\scripts> get-regex | ft -auto
Sequence                    Meaning                                                                      Table
--------                    -------                                                                      -----
\a                          Alert (bell), x07.                                                           Character r...
\b                          Backspace, x08, supported only in character class.                           Character r...
\e                          ESC character, x1B.                                                          Character r...
\n                          Newline, x0A.                                                                Character r...
\r                          Carriage return, x0D.                                                        Character r...
\f                          Form feed, x0C.                                                              Character r...
\t                          Horizontal tab, x09.                                                         Character r...
\v                          Vertical tab, x0B.                                                           Character r...
\0octal                     Character specified by a two-digit octal code.                               Character r...
\xhex                       Character specified by a two-digit hexadecimal code.                         Character r...
\uhex                       Character specified by a four-digit hexadecimal code.                        Character r...
\cchar                      Named control character.                                                     Character r...
[...]                       A single character listed or contained within a listed range.                Character c...
[^...]                      A single character not listed and not contained within a listed range.       Character c...
.                           Any character, except a line terminator (unless single-line mode, s).        Character c...
\w                          Word character.                                                              Character c...
\W                          Non-word character.                                                          Character c...
\d                          Digit.                                                                       Character c...
\D                          Non-digit.                                                                   Character c...
\s                          Whitespace character.                                                        Character c...
\S                          Non-whitespace character.                                                    Character c...



– Robbie