22 June 2009

Security lols

Windows Vista protects certain sensitive information, like your WEP, WPA, and WEP2 passphrases/keys, by encrypting them with a Windows API function called CryptProtectData. Needless to say, since Windows itself needs to access those keys, there's no way they can be truly hidden from the user, any more so than DRM keys can be truly hidden from the user. (A Fritz-chip can make keys harder to access, but the fact remains that a device in the physical possession of a dedicated individual cannot really be expected to act against that individual's will.) Not that Windows is trying to do so. The Microsoft's manuals even explain how to extract the keys:

If your process runs in the context of the LocalSystem account, then
you can unencrypt key material by calling CryptUnprotectData.



The fun part is, if you're not terribly familiar with Windows, this can take you ages. Here's how I did it.

Before you start, note that there are programs which will do this for you. WirelessKeyView is one. If you're like me, though, you might be worried about running a random closed-source app that wants administrator privileges. Even if LifeHacker liked it. So here's how do to it the hard way.





First, you need to get the encrypted key. On Vista (XP apparently
doesn't bother with this encryption), wireless network keys are stored
in the directory
c:\ProgramData\Microsoft\Wlansvc\Profiles\Interfaces\, each subdirectory of which is an interface GUID, each subfile of which is an XML document that looks like this:




<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
<name>This is the name of your network.</name>
<SSIDConfig>
<SSID>
<hex>This is your SSID in hex.</hex>
<name>This is where your SSID is.</name>
</SSID>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>auto</connectionMode>
<MSM>
<security>
<authEncryption>
<authentication>open</authentication>
<encryption>WEP</encryption>
<useOneX>false</useOneX>
</authEncryption>
<sharedKey>
<keyType>networkKey</keyType>
<protected>true</protected>
<keyMaterial>!!!!! This is the key that you want. !!!!!</keyMaterial>
</sharedKey>
</security>
</MSM>
</WLANProfile>




If you have a lot of these files and don't fancy opening them one by one to find the correct interface, do a grep -R for the SSID to find the file you want. If you don't have grep installed, I highly recommend installing Cygwin.




The hex string (replaced by "This is the key that you want" above) in the keyMaterial element contains the encrypted key. In order to decrypt it, you have to call CryptUnprotectData. There is a fair bit of material on the Internets explaining how to call this function. I first tried calling it with
this wrapper library, using Visual C++ Express Edition. I ultimately discovered on this page that said I could use Python instead, so I promptly switched to Python. Here's a little Python program that does the decryption, derived from a program posted by "Dirk" in the comments at the above remkoweijnen.nl blog post.




import win32crypt
mykey='replace this with your keyMaterial'
binout = []
for i in range(len(mykey)):
if i % 2 == 0:
binout.append(chr(int(mykey[i:i+2],16)))
pwdHash=''.join(binout)

output = win32crypt.CryptUnprotectData(pwdHash,None,None,None,0)

print "hex:", "".join(["%02X" % ord(char) for char in output[1]])

print "ascii:", output[1]



Note that to run this, you'll need
the Python for
Windows extensions.
. (And, of
course, Python.)



Now, there's a catch. If you execute the code above, you'll get an
error like this:




C:\Users\Joe\Desktop>"c:\Python25\python.exe" foo.py
Traceback (most recent call last):
File "foo.py", line 23, in
output = win32crypt.CryptUnprotectData(pwdHash,None,None,None,0)
pywintypes.error: (-2146893813, 'CryptUnprotectData', 'Key not valid for use in
specified state.')


You will get that error even if you run cmd.exe as an administrator. Here's where you need to know a bit about Windows that, as a Windows n00b, I didn't know: the LocalSystem account is different from the administrator privilege. In order to run cmd.exe with the LocalSystem account, you need to install a Microsoft package called PsTools. Inside PsTools a program called PsExec, which is a little bit like sudo on Un*x. Just download the zip linked at the bottom of the Microsoft TechNet page above and unzip it somewhere where you can find it.

To use PsExec, open cmd.exe as an administrator (open the start menu in the bottom-left of your screen, type cmd.exe into the search box, and press Ctrl+Shift+Enter to run it as an admin). Hit "continue" on the User Account Control dialog box that opens. In the command shell that opens, navigate to the directory where you unzipped PsTools. Now run "psexec.exe /s /i cmd.exe". After you agree to PsTools's EULA, PsTools should open a new cmd.exe shell window
running as LocalSystem.

Now, in that new command shell, navigate your way to wherever you saved the above python script and run it:




c:\Users\Joe\Desktop>c:\Python25\python.exe foo.py
hex: (the hex of the wep/wpa/whatever key)
ascii: (the ascii of the same, which is hopefully printable)


Enjoy. And switch to Linux as soon as you possibly can.

6 comments:

  1. Excellent !

    I was almost there and left it. Now I saw your post and run it in system context and GOT IT !

    Thank You !

    ReplyDelete
  2. i got a syntax error on line 11 always (using pyhton 33)

    ReplyDelete
  3. Man, I just could NOT get this. Thank - YOU.

    ReplyDelete
  4. You can only do this on the same computer where the wlan network has been stored, and where Windows has encrypted the wifi password. You just can't copy the keymaterial to decrypt it on a different computer, which almost makes this way to recover the wifi password unnecessary. Why? If you can only run this on the computer where the network is created, you should have administrator rights. If you have administrator rights there's a much easier way to recover the password. Just navigate to the Windows Network Center, find your network card (it is most common you have Wifi and LAN). Right click the wifi and select "status". Click "properties for wireless network". A pop-up opens, click the tab "Security" and than check the box "Show Characters". There's your password.

    Correct me if I'm wrong, because I would like to retrieve the wifi password from the .xml keymaterial on a different computer than the key or network was created on. Thanks!

    ReplyDelete
    Replies
    1. Hi Renco, I think you are correct. Do you know why it only works on the machine with wifi password stored? How does win32crypt.CryptUnprotectData work? Is there a reference doc? Thanks!

      Delete

About Me

blog at barillari dot org Older posts at http://barillari.org/blog