Tag Archives: windows registry

Stay classy, Microsoft

I thought when I was looking at the Windows Registry I’d seen it all … until today when I found that the Windows 7 installation CD contains what seems like a registry that directly encodes an XML schema document.


If you have a Win7 install CD, it is /sources/schema.dat. After passing it through hivexregedit –export you get:

Windows Registry Editor Version 5.00









(and on for 1,355 lines)

Leave a comment

Filed under Uncategorized

Tip: Updating the Windows registry using libguestfs and hivex

virt-win-reg is a high level tool for merging Registry changes into a Windows virtual machine, and it’s relatively simple to use. You can also do the same thing using the libguestfs and hivex APIs directly, but it’s a little bit more complicated. This posting explains how to do it the low-level way.

First understand how the Windows Registry is stored in a VM: Although in Windows it appears as a single tree with top level nodes called things like HKEY_LOCAL_MACHINE and HKEY_USERS, this is not how Windows actually stores it. The Registry is split across several files called hives. Hivex is a C library for editing this proprietary file format.

A hive file contains a part of the Registry tree. The main hives of interest are called SOFTWARE, SYSTEM, SECURITY and SAM (without any file extension) and they live in the %systemroot%\System32\Config directory. These hives correspond to HKEY_LOCAL_MACHINE\SOFTWARE, HKEY_LOCAL_MACHINE\SYSTEM etc. There are also per-user hives stored in a location that depends on the version of Windows.

Another thing to understand about the Registry is that when Windows is running it synthesizes “symbolic keys” which don’t really exist in the hive file itself. The most important example is CurrentControlSet which is really a link to ControlSetXXX as explained in more detail here.

The plan for modifying a Windows Registry in an offline guest is therefore:

  1. Locate the hive file containing the key we want to modify.
  2. Download it to a local temporary directory.
  3. Modify it with hivex.
  4. Upload it back to the Windows VM.

(This is essentially what virt-win-reg does).

Below is a Python program which demonstrates how to change the hostname of a Windows VM using the APIs directly. The hostname is stored in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters in the key Hostname. Notice from the name that this is located in the SYSTEM hive file, and in this case I’m going to assume that CurrentControlSet is a link to ControlSet001 but in reality you’d probably want to read this and do it right.

A final note: Although this changes the Hostname registry key correctly, Windows doesn’t use this key for very much (in particular, this is not the name of the machine), and also it appears that Windows will overwrite this key with whatever name it gets from a DHCP server. It’s only an example though …


import guestfs
import hivex

windows_domain = "Win7x32"

# Windows strings stored in the registry have a trailing NUL
new_hostname = "win7x32\0"

# Use libguestfs to download the HKEY_LOCAL_MACHINE\SYSTEM hive.
g = guestfs.GuestFS ()
g.add_domain (windows_domain)
g.launch ()

roots = g.inspect_os ()
root = roots[0]
g.mount_options ("", root, "/")

systemroot = g.inspect_get_windows_systemroot (root)
path = "%s/system32/config/system" % systemroot
path = g.case_sensitive_path (path)
g.download (path, "/tmp/system")

# Open the hive file for writing.
h = hivex.Hivex ("/tmp/system", write=True)

# Navigate down to the TCP/IP parameters.
key = h.root ()
key = h.node_get_child (key, "ControlSet001")
key = h.node_get_child (key, "Services")
key = h.node_get_child (key, "Tcpip")
key = h.node_get_child (key, "Parameters")

# Get the old hostname.
val = h.node_get_value (key, "Hostname")
old_hostname = h.value_value (val)

# Keep the old type (probably 1 = string)
type = old_hostname[0]

# The registry key is encoded as UTF-16LE.
old_hostname = old_hostname[1].decode ('utf-16le').encode ('utf-8')

print "old hostname = %s" % old_hostname

# Change the hostname.
new_hostname = new_hostname.encode ('utf-16le')
new_value = { 'key': "Hostname", 't': type,
              'value': new_hostname }
h.node_set_value (key, new_value)

# Commit the changes to the hive.
h.commit (None)

# Upload the hive back to the guest.
g.upload ("/tmp/system", path)

# This is only needed for libguestfs < 1.5.24, but
# it won't hurt for newer versions.
g.sync ()

Leave a comment

Filed under Uncategorized

Tip: List services in a Windows guest

The lengthy program after the fold uses libguestfs and hivex to list out the services from a Windows guest. You point it to a Windows guest and it will produce a rather long list, like this:

# ./services.pl WindowsGuest
  Path: %systemroot%\system32\svchost.exe -k LocalSystemNetworkRestricted
  Start flag: autoload
  Service type: Win32 service using svchost
  Error control: ignore
  Path: %SystemRoot%\System32\svchost.exe -k LocalSystemNetworkRestricted
  Group: PlugPlay
  Start flag: load on demand
  Service type: Win32 service using svchost
  Error control: normal
  Path: %SystemRoot%\System32\svchost.exe -k NetworkService
  Start flag: load on demand
  Service type: Win32 service using svchost
  Error control: normal
  Path: %SystemRoot%\System32\svchost.exe -k LocalServiceAndNoImpersonation
  Start flag: load on demand
  Service type: Win32 service using svchost
  Error control: normal
  Path: System32\drivers\tcpip.sys
  Group: PNP_TDI
  Start flag: boot loader
  Service type: kernel device driver
  Error control: normal
TCPIP6 (Microsoft IPv6 Protocol Driver):
  Microsoft IPv6 Protocol Driver
  Path: system32\DRIVERS\tcpip.sys
  Start flag: load on demand
  Service type: kernel device driver
  Error control: normal
tcpipreg (TCP/IP Registry Compatibility):
  Provides compatibility for legacy applications which interact with TCP/IP through the registry. If this service is stopped, certain applications may have impaired functionality.
  Path: System32\drivers\tcpipreg.sys
  Start flag: autoload
  Service type: kernel device driver
  Error control: normal

Continue reading


Filed under Uncategorized

Use hivex from Python to read and write Windows Registry “hive” files

I added Python bindings to hivex today.

Here is an example using Python, libguestfs and hivex to download the user preferences registry from a Windows virtual machine and print out the Internet Explorer start page for a particular user. When you run it, it should print out something like:

User rjones's IE home page is http://go.microsoft.com/fwlink/?LinkId=69157

This example shows downloading and printing values, but libguestfs and hivex can also be used to make changes (but not to live guests).


import guestfs
import hivex

# The name of a Windows virtual machine on this host.  This
# example script makes some assumptions about the registry
# location and contents which only apply on Windows Vista
# and later versions.
windows_domain = "Win7x32"

# Username on the Windows VM.
username = "rjones"

# Use libguestfs to download the HKEY_CURRENT_USER hive.
g = guestfs.GuestFS ()
g.add_domain (windows_domain, readonly=1)
g.launch ()

roots = g.inspect_os ()
root = roots[0]
g.mount_ro (root, "/")

path = "/users/%s/ntuser.dat" % username
path = g.case_sensitive_path (path)
g.download (path, "/tmp/ntuser.dat")

# Use hivex to pull out a registry key.
h = hivex.Hivex ("/tmp/ntuser.dat")

key = h.root ()
key = h.node_get_child (key, "Software")
key = h.node_get_child (key, "Microsoft")
key = h.node_get_child (key, "Internet Explorer")
key = h.node_get_child (key, "Main")

val = h.node_get_value (key, "Start Page")
start_page = h.value_value (val)
#print start_page

# The registry key is encoded as UTF-16LE, so reencode it.
start_page = start_page[1].decode ('utf-16le').encode ('utf-8')

print "User %s's IE home page is %s" % (username, start_page)


Filed under Uncategorized

Tip: Install a device driver in a Windows VM

Previously we looked at how to install a service in a Windows VM. You can use that technique or the RunOnce tip to install some device drivers too.

But what if Windows needs the device driver in order to boot? This is the problem we faced with converting old Xen and VMWare guests to use KVM. You can’t install viostor (the virtio disk driver) which KVM needs either on the source Xen/VMWare hypervisors (because those don’t use the virtio standard) or on the destination KVM hypervisor (because Windows needs to be able to see the disk first in order to be able to boot).

Nevertheless we can modify the Windows VM off line using libguestfs to install the virtio device driver and allow it to boot.

(Note: virt-v2v will do this for you. This article is for those interested in how it works).

There are three different aspects to installing a device driver in Windows. Two of these are Windows Registry changes, and one is to install the .SYS file (the device driver itself).

So first we make the two Registry changes. Device drivers are a bit like services under Windows, so the first change looks like installing a service in a Windows guest. The second Registry change adds viostor to the “critical device database”, a map of PCI addresses to device drivers used by Windows at boot time:

# virt-win-reg --merge Windows7x64

; Add the viostor service

"Group"="SCSI miniport"


"ParamDesc"="Maximum Transfer Size"

"0"="64  KB"
"1"="128 KB"
"2"="256 KB"



; Add viostor to the critical device database




Comparatively speaking, the second step of uploading viostor.sys to the right place in the image is simple:

# guestfish -i Windows7x64
><fs> upload viostor.sys /Windows/System32/drivers/viostor.sys

After that, the Windows guest can be booted on KVM using virtio. In virt-v2v we then reinstall the viostor driver (along with other drivers like the virtio network driver) so that we can be sure they are all installed correctly.


Filed under Uncategorized

Use hivex to unpack a Windows Boot Configuration Data (BCD) hive

Thanks to “TJ” for tipping me off about another use of the Registry “hive” format in recent versions of Windows.

There are scant details available, but if you have a version of Windows Vista or later, then the boot loader is no longer configured through a plain text file (“BOOT.INI”) but via a binary blob. Microsoft provides a tool called “BCDEDIT.EXE” that you are supposed to use to edit this, but the blob is a hive so you can use hivex to display or modify it.

We first use guestfish to download the blob:

$ guestfish --ro -a /dev/vg_trick/Windows7x64 -m /dev/sda1

Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.

Type: 'help' for help with commands
      'quit' to quit the shell

><fs> ll /
total 392
drwxrwxrwx  1 root root   4096 Dec 15 04:48 .
dr-xr-xr-x 20 root root      0 Mar 30 13:30 ..
-rwxrwxrwx  1 root root   8192 Dec 15 12:47 BOOTSECT.BAK
drwxrwxrwx  1 root root   4096 Dec 15 12:47 Boot
drwxrwxrwx  1 root root      0 Dec 15 04:48 System Volume Information
-rwxrwxrwx  1 root root 383562 Jul 13  2009 bootmgr
><fs> ll /Boot/
total 596
drwxrwxrwx 1 root root   4096 Dec 15 12:47 .
drwxrwxrwx 1 root root   4096 Dec 15 04:48 ..
-rwxrwxrwx 1 root root  24576 Mar 25 12:25 BCD
-rwxrwxrwx 1 root root  21504 Mar 25 12:25 BCD.LOG
-rwxrwxrwx 2 root root      0 Dec 15 12:47 BCD.LOG1
-rwxrwxrwx 2 root root      0 Dec 15 12:47 BCD.LOG2
-rwxrwxrwx 1 root root  65536 Dec 15 12:47 BOOTSTAT.DAT
><fs> download /Boot/BCD /tmp/BCD
><fs> ^D

Then we can dump the contents out using hivexregedit. (We could also browse the contents with hivexsh).

$ hivexregedit --export /tmp/BCD '\' > /tmp/BCD.reg

In typical Microsoft style, the contents themselves are obscure, consisting of plenty of subkeys that look like this:


(Note that “type 7″ is a list of strings, and the whole thing is encoded in UTF-16LE, so this requires some further work to parse).

There’s scope here to extend virt-inspector to understand this stuff, or even to write a BCDEDIT-style tool to modify the way Window VMs boot. Apparently the current BCDEDIT tool is half-arsed, so here’s another opportunity to beat Microsoft’s own tooling.


Filed under Uncategorized

Edit the Windows Registry in your VMs from the host

Update: Want to test this out? There are packages for RHEL / CentOS 5 here.

For a while we have shipped a tool virt-win-reg which lets you read keys out from the Registry. The top feature people have asked for is the ability to make changes in the Registry, and we have now implemented this (tracking bug 575738).

With the virtual machine shutdown (live merges are not supported), you prepare a text file describing the changes in “.REG” format. For example:

"Key2"="This is key 2"

and simply merge that into the Registry:

virt-win-reg --merge Windows7x32 /tmp/updates.reg

After booting Windows, we can see the new subkey has appeared:

Now I change my updates file slightly:


(which means “delete Key1″). I have to shut down Windows, run the same virt-win-reg command, and start Windows again.

At this point Windows decides to punish me by demanding “activation” (I believe this event is entirely separate from the Registry change). Red Hat pays lots of money each year to Microsoft for genuine MSDN licenses so we can do this sort of interop testing, to improve the utility of Windows, and this Windows installation is fully licensed. Nevertheless, there is a bug in this version of Windows which means it can never be activated because activation runs before the network setup. So I’m punished with a black desktop and a stern warning. This makes me hate Windows just a little bit more than before …

Anyway, the key has been removed:

Finally I put this into an updates file:


And after shutting down Windows, running virt-win-reg and rebooting Windows, we see that the Registry key has been removed entirely:

Leave a comment

Filed under Uncategorized

Tip: virt-win-reg: CurrentControlSet in Windows Registry

I was asked today why this command doesn’t work (this Registry key would be visible if you were inside the Windows guest):

$ virt-win-reg Win2003x32 \
  '\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout\DosKeybCodes'
hivexget: \CurrentControlSet: CurrentControlSet: path element not found

It’s because CurrentControlSet (and several other “Current*” keys) are synthetic. They don’t exist in the underlying Registry “hive” (file), but are created by Windows when it is running to refer to the currently selected setting for the local user (This isn’t quite correct. For the specifics refer to the Microsoft KB article and this stackoverflow posting).

Instead you have to refer to one of the possible selections. Usually ControlSet001 will work, so:

$ virt-win-reg Win2003x32 \
  '\HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Keyboard Layout\DosKeybCodes'

Leave a comment

Filed under Uncategorized

virt-win-reg: get at the Windows Registry in your Windows guests

This is now in libguestfs git and will appear in version 1.0.75 in Fedora shortly.

 $ virt-win-reg MyWinGuest \
   '\HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion' \
 Microsoft Windows Server 2003

 $ virt-win-reg MyWinGuest \
   '\HKEY_LOCAL_MACHINE\System\ControlSet001\Control' \

 $ virt-win-reg MyWinGuest \


Filed under Uncategorized

libhivex: Windows Registry hive extractor library

Several people managing Windows virtual machines have told me that libguestfs/virt-cat isn’t enough for them. They’d like to be able to get at Windows Registry entries in the guest.

A typical example is the imaginary [as of now] virt-win-reg command that lets you interrogate the Registry in a guest:

$ virt-win-reg MyWinGuest '\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
"ProductName"="Microsoft Windows Server 2003"
"RegisteredOwner"="Richard Jones"

Right now you can only do this indirectly, by laboriously downloading the registry hives and decoding them with tools such as reged. I outlined how to do that here but there’s no doubt that it should be made a lot easier.

The first step is a more reliable way to query registry files themselves. The files come from foreign, buggy, possibly malicious guests, and so code that touches them must be written carefully and conservatively to avoid security problems.

Another problem is that the tools in this area tend to convert the binary, proprietary “hive” format into a regedit-compatible text format. The problem is that regedit itself is no easier to parse. What we would like is a more compatible format — XML or a library.

There are several existing tools to do this. The best is certainly Petter Nordahl’s chntpw utility which we’ve been carrying in Fedora for a while. Unfortunately Petter hasn’t been answering our queries about issues in the code and we are concerned that the code isn’t cautious enough to deal with an onslaught of malicious registry files. Another is the BSD-licensed dumphive program written in Pascal.

To address our concerns I have spent the last three days writing a simpler version of Petter’s program called libhivex. This library and associated programs are able to extract the contents of Windows Registry “hive” files, and make this available through a simple C API or as XML. The library is written very defensively and should deal with malicious files. The scope of the library is also being kept intentionally small: we won’t use it to modify these files ever, just to extract data from them.

I hope to publish a patch series for this soon for libguestfs, followed by some useful command line tools to let sysadmins get data from their Windows virtual machines.

Got a suggestion for a useful libguestfs-related tool? Let me know in the comments.


Filed under Uncategorized