Tag Archives: virt-win-reg

Tip: Another way to get the IP address of a virtual machine

In this earlier post several ways were discussed of getting the IP address of a virtual machine (specifically if the VM is acquiring a different address each time from DHCP).

Another way is to use virt-cat or virt-win-reg to grab the information out of the virtual machine itself.

When a VM acquires an IP address from DHCP then it writes the address to a log file, or in the Windows case updates the Windows Registry. The idea is simply that we’ll read the information from the VM’s log files or the Registry.

The details vary depending on the precise guest type, and probably we should wrap this up in a nice virt tool. But here’s how you would do it for Fedora/RHEL and Windows guests:

# virt-cat RHEL60x64 /var/log/messages | grep 'dhclient.*bound to'
Mar 30 19:56:22 rhel60x64 dhclient: bound to 192.168.122.220 -- renewal in 1527 seconds.
Mar 30 20:21:49 rhel60x64 dhclient: bound to 192.168.122.220 -- renewal in 1375 seconds.
Mar 30 20:44:44 rhel60x64 dhclient: bound to 192.168.122.220 -- renewal in 1287 seconds.
Mar 30 21:06:11 rhel60x64 dhclient: bound to 192.168.122.220 -- renewal in 1461 seconds.
# virt-win-reg Win7x32 \
  'HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Tcpip\Parameters' | \
  grep DhcpIPAddress
"DhcpIPAddress"=hex(1):31,00,39,00,32,00,2e,00,31,00,36,00,38,00,2e,00,31,00,32,00,32,00,2e,00,31,00,37,00,38,00,00,00

In the Windows case you need to note that ControlSet001 isn’t always the right control set — consult this note in the virt-win-reg man page to find the correct way to do this. Furthermore virt-win-reg prints out the hex-encoded UTF16-LE string, which requires a little bit of conversion to produce a printable string (192.168.122.178 in this instance).

Update: To add to all the other methods from the previous post, and the method described above, Eric Blake also points out that nwfilter can sniff IP addresses used by VMs.

2 Comments

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 …

#!/usr/bin/python

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

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).

#!/usr/bin/python

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)

7 Comments

Filed under Uncategorized

Guest post: Converting VMware guests to libvirt/KVM guests

This is a guest post by Marko Myllynen.

VMware guests can be converted as Libvirt/QEMU/KVM guests without any need for proprietary VMware tools. There are two ways to do the conversion, use the one appropriate for your environment.

Converting On-Disk VMware Guests to Libvirt Guests

This method is suitable if you have locally the VMDK image file (e.g., the Virtual XP image from local Service Desk).

First, install needed packages:

# yum install qemu-img libguestfs-tools libguestfs-winsupport virsh

[RWMJ notes: libguestfs-winsupport package is only needed on RHEL 6 hosts]

Then, you’ll need to acquire the Windows registry entries described in Microsoft KB article 314082 and adjust them for use with virt-win-reg (that is, replace all CurrentControlSet instances with ControlSet001 and make sure the file is properly encoded – see the virt-win-reg(1) manual page for details). The resulting file is also available here. The steps below expect that the entries are available in the file named ./mergeide.reg.

Also, you’ll need to create a domain XML definition file for your new libvirt guest. Please download this file as ./virtual-xp.xml and adjust the following fields as needed:

  • name
  • uuid
  • memory / currentMemory
  • arch
  • mac address

Note: you *must* set the full path of the virtual image inside the XML (look for the source file definition).

Finally, the actual conversation can be done in three steps:

# qemu-img convert virtual-xp.vmdk virtual-xp.img
# virt-win-reg --merge virtual-xp.img mergeide.reg
# virsh --connect qemu:///system define virtual-xp.xml

After this you should see your new XP VM in your virt-manager display.

Converting VMware Guests from ESX Server to Libvirt Guests

This method is suitable if your VMware guests are on an ESX server. Please install virt-v2v and see the manual page virt-v2v(1) for details.


Thanks Marko for this excellent tip!

8 Comments

Filed under Uncategorized

Tip: Get the hostname of a guest

Because different operating systems store the hostname in different places, you have to know in advance what sort of OS your guest is (perhaps using virt-inspector). Perhaps we should add the hostname to virt-inspector.

This works for Fedora guests:

# virt-cat F13x64 /etc/sysconfig/network | \
  grep HOSTNAME= | \
  awk -F= '{print $2}'
f13x64.home.annexia.org

This is for Debian/Ubuntu guests:

# virt-cat Debian5x64 /etc/hostname
debian5x64.home.annexia.org

For Windows guests:

# virt-win-reg Win7x32 \
  'HKEY_LOCAL_MACHINE\System\ControlSet001\Services\Tcpip\Parameters' \
  Hostname
win7x32

I’m not completely clear how to get the DNS domain name from Windows. According to this article you should just replace “Hostname” with “Domain” in the above command, but for me that yields just an empty string.

4 Comments

Filed under Uncategorized

Windows SAM and hivex

On Windows, the file C:\windows\system32\config\SAM contains the users and passwords known to the local machine. hivex can process this file to reveal the usernames and password (hashes):

$ virt-win-reg WinGuest HKLM\\SAM > sam.reg

For each local user you’ll see a key like this:

[HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\Names\rjones]
@=hex(3e9):

With typical technical brilliance Microsoft developers have written a zero-length key with the type field (0x3e9) overloaded as a key to use in another part of the registry:

[HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\000003E9]
"F"=hex(3):omitted...
"UserPasswordHint"=str(3):"usual"
"V"=hex(3):omitted...

(Apparently the number 0x3e9 is called the “RID” in Microsoft parlance).

My password hint is the “usual”. The “F” key is a dumped C structure containing the last login date amongst other things. The “V” key is another C structure containing my full name, home directory, the password hash and a bunch of other stuff.

With a bit of effort it looks like you could read and even modify these entries.

1 Comment

Filed under Uncategorized

Tip: Install a service in a Windows VM

Previously I discussed how to get a script to run the first time a user logs in. This tip goes further and demonstrates how to install a service into a Windows VM using guestfish, virt-win-reg and a new open source program written by my colleague Yuval Kashtan called RHSrvAny1.

First, compile RHSrvAny from source. You can do this using our completely free Fedora Windows cross-compiler stack. Just:

# yum install mingw32-gcc

Clone the RHSrvAny git repo and compile it:

$ mingw32-configure
$ make

Second we’ll copy the files we need into the Windows guest. Note: The Windows VM must be shut off.

# guestfish -i Windows7x64
Welcome to guestfish, the libguestfs filesystem interactive shell for
editing virtual machine filesystems.

Type: 'help' for a list of commands
      'man' to read the manual
      'quit' to quit the shell

><fs> upload RHSrvAny/rhsrvany.exe /rhsrvany.exe
><fs> upload test.exe /test.exe
><fs> exit

“test.exe” is a little program I wrote which writes the date into C:\TEST.LOG but you can also use the batch file from the last tip or any JScript or VBScript you happen to have (via cscript.exe).

Third we need to add some Windows Registry keys to tell Windows about the new service:

# cat service.reg
[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\RHSrvAny]
"Type"=dword:00000010
"Start"=dword:00000002
"ErrorControl"=dword:00000001
"ImagePath"="c:\\rhsrvany.exe"
"DisplayName"="RHSrvAny"
"ObjectName"="LocalSystem"

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\RHSrvAny\Parameters]
"CommandLine"="c:\\test.exe"
"PWD"="c:\\Temp"
# virt-win-reg --merge Windows7x64 service.reg

The magic numbers in the registry entries let you do things like boot with the service disabled. See this MSDN article.

Edit: See Yuval’s comment about alternatives to using "ObjectName"="LocalSystem".

Now boot your Windows guest, and observe the log file to prove that test.exe was run, and/or look at the list of services in the control panel.

><fs> cat /TEST.LOG
Hello
Thu Apr 29 18:39:13 2010

1 Actually you could install any service, but I’m using RHSrvAny because it can turn ordinary Windows programs and scripts into services. It takes care of the Windows “Service Control Protocol” for us.

8 Comments

Filed under Uncategorized