Monday, February 18, 2013

When Windows Hosts Files Stop Working

So, working on what should have been a quick PowerShell script today, I ran into quite the hiccup. Annoying as hell.

My Hosts file on my Windows 7 Machine stopped working!

This was a rage inducing issue for me. But luckily I think I've identified the "problem." And yes, it is technically PEBKAC - but I think Microsoft should carry a little of the blame too.

First let us set the stage with a very basic PowerShell script to setup the hosts file the way we'd like.

$hosts = @()
$hosts = $hosts + [String]::Format("{0} {1}", "192.168.0.1", "some.local.domain")
$hosts = $hosts + [String]::Format("{0} {1}", "127.0.0.1", "www.somesite.com")
$hosts > $env:windir\system32\drivers\etc\hosts

Note: This must be run with appropriate permissions to write to the hosts file!

Pretty straight forward, make an array, add two strings to it with formatted IP/domain pairs. Write the array out to the file. When this is all said and done you should have something which looks like the following:
This is what we would expect. A hosts file with two entries that says some.local.domain -> 192.168.0.1 and another entry that says www.somesite.com -> 127.0.0.1.

Looks correct to me - and if you're reading this yours probably looks correct to you too. But as you can see the ping commands are not resolving based on the IPs in the hosts file! This is certainly not the desired effect. As if the hosts file were being "skipped."

What's the deal?

The error that resides in the above script does not reveal itself when opening the hosts file in your text editor. And in fact in some text editors it'll exist all of the time. Why you ask?

Simple; Your text editor probably detects and allows you to edit Unicode files. Optionally your text editor only supports Unicode files.

Yep, the whole annoying as hell bug - is just a simple encoding problem.

Here's how I noticed it - I opened my hosts file in a hex editor (HxD in my case, cause it's free). Viewing the raw hex we see:
This thought occurred to me as a mere suspicion. I did what I've seen a number of sources say to do: open the hosts file, copy it's contents, remove the hosts file and then re-save the contents using just plain-ol'e notepad. This does work, but it's not a solution for automation in the case of scripts (like I need it to be).

Also remember notepad will save it with the extensions .txt and you'll need to rename it.

So this works, in theory, because when notepad saves the contents it saves them in ASCII and stripping the Unicode encoding. Which is seen when viewing the contents of the new hosts file in HxD:

So, how does one fix the PowerShell script to work too? You're in luck,  it's an easy fix. Annoyingly easy after so many hours bashing your head against a keyboard over nothing.

Setup your array in the same way, when you're ready just pass your array to Out-File like so:
$hosts | Out-File -Encoding ASCII -FilePath $env:windir\system32\drivers\etc\hosts
And now, you should have similar - but better - results! Notice how notepad looks exactly the same! But the pings resolve the correct names, etc. Thus confirming my hypothesis.
That's it, I hope this helps someone. So as usual....
Hack Legal, Hack Safe, buy most of all Hack Fun!
Until next time...