Tag Archives: windows registry

Tip: Change the background image in a Windows VM

Thanks to Tom Horsley who worked out how to do this for Windows XP guests (the technique is probably different for other versions of Windows).

Here is Tom’s script and here are more of his KVM tips.

2 Comments

Filed under Uncategorized

hivex 1.2.5 released

The latest version of hivex — the library for extracting and modifying Windows Registry hive files has been released. You can get the source from here.

I spent a lot of time examining real hive files from Windows machines and running the library under the awesome valgrind tool, and found one or two places where a corrupt hive file could cause hivex to read uninitialized memory. It’s not clear to me if these are security issues — I think they are not — but everyone is advised to upgrade to this version anyway.

hivex would be a great candidate for fuzz testing if anyone wants to try that.

Leave a comment

Filed under Uncategorized

Tip: Code for getting DHCP address from a virtual machine disk image

Previously (1) and previously (2) I showed there are many different ways to get the IP address from a virtual machine.

The example below shows one way to use libguestfs and hivex from a C program (virt-dhcp-address) to get the DHCP address that a virtual machine has picked up.

Continue reading

7 Comments

Filed under Uncategorized

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

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.

WHY!!!

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

[\]

[\wcm://Microsoft-Windows-DNS-Client?version=6.1.7600.16385&language=neutral&processorArchitecture=amd64&publicKeyToken=31bf3856ad364e35&versionScope=nonSxS&scope=allUsers]

[\wcm://Microsoft-Windows-DNS-Client?version=6.1.7600.16385&language=neutral&processorArchitecture=amd64&publicKeyToken=31bf3856ad364e35&versionScope=nonSxS&scope=allUsers\metadata]
"@_legacyHandler"=hex(10000005):04,00,00,00
"@_targetNamespace"=hex(1000000c):4d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,2d,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,2d,00,44,00,4e,00,53,00,2d,00,43,00,6c,00,69,00,65,00,6e,00,74,00,00,00
"@language"=hex(1000000c):6e,00,65,00,75,00,74,00,72,00,61,00,6c,00,00,00
"@processorArchitecture"=hex(1000000c):61,00,6d,00,64,00,36,00,34,00,00,00
"@publicKeyToken"=hex(1000000c):33,00,31,00,62,00,66,00,33,00,38,00,35,00,36,00,61,00,64,00,33,00,36,00,34,00,65,00,33,00,35,00,00,00
"@version"=hex(1000000c):36,00,2e,00,31,00,2e,00,37,00,36,00,30,00,30,00,2e,00,31,00,36,00,33,00,38,00,35,00,00,00
"@versionScope"=hex(1000000c):6e,00,6f,00,6e,00,53,00,78,00,53,00,00,00
"@xmlns:asmv3"=hex(1000000c):75,00,72,00,6e,00,3a,00,73,00,63,00,68,00,65,00,6d,00,61,00,73,00,2d,00,6d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,2d,00,63,00,6f,00,6d,00,3a,00,61,00,73,00,6d,00,2e,00,76,00,33,00,00,00
"@xmlns:wcm"=hex(1000000c):68,00,74,00,74,00,70,00,3a,00,2f,00,2f,00,73,00,63,00,68,00,65,00,6d,00,61,00,73,00,2e,00,6d,00,69,00,63,00,72,00,6f,00,73,00,6f,00,66,00,74,00,2e,00,63,00,6f,00,6d,00,2f,00,57,00,4d,00,49,00,43,00,6f,00,6e,00,66,00,69,00,67,00,2f,00,32,00,30,00,30,00,32,00,2f,00,53,00,74,00,61,00,74,00,65,00,00,00
"@xmlns:xmlns"=hex(1000000c):68,00,74,00,74,00,70,00,3a,00,2f,00,2f,00,77,00,77,00,77,00,2e,00,77,00,33,00,2e,00,6f,00,72,00,67,00,2f,00,32,00,30,00,30,00,30,00,2f,00,78,00,6d,00,6c,00,6e,00,73,00,2f,00,00,00
"@xmlns:xsd"=hex(1000000c):68,00,74,00,74,00,70,00,3a,00,2f,00,2f,00,77,00,77,00,77,00,2e,00,77,00,33,00,2e,00,6f,00,72,00,67,00,2f,00,32,00,30,00,30,00,31,00,2f,00,58,00,4d,00,4c,00,53,00,63,00,68,00,65,00,6d,00,61,00,00,00

[\wcm://Microsoft-Windows-DNS-Client?version=6.1.7600.16385&language=neutral&processorArchitecture=amd64&publicKeyToken=31bf3856ad364e35&versionScope=nonSxS&scope=allUsers\metadata\complexTypes]

[\wcm://Microsoft-Windows-DNS-Client?version=6.1.7600.16385&language=neutral&processorArchitecture=amd64&publicKeyToken=31bf3856ad364e35&versionScope=nonSxS&scope=allUsers\metadata\complexTypes\DomainNameCollectionType]
"@_MemberList"=hex(1000800c):44,00,6f,00,6d,00,61,00,69,00,6e,00,4e,00,61,00,6d,00,65,00,00,00,00,00
"@_valid"=hex(10000001):00

[\wcm://Microsoft-Windows-DNS-Client?version=6.1.7600.16385&language=neutral&processorArchitecture=amd64&publicKeyToken=31bf3856ad364e35&versionScope=nonSxS&scope=allUsers\metadata\complexTypes\DomainNameCollectionType\DomainName]
"@_hint"=hex(10000006):01,00,00,00
"@_type"=hex(10000005):0c,60,00,00
"@xsd:maxOccurs"=hex(10000006):ff,ff,ff,ff
"@xsd:minOccurs"=hex(10000006):00,00,00,00
"@xsd:type"=hex(1000000c):44,00,6f,00,6d,00,61,00,69,00,6e,00,4e,00,61,00,6d,00,65,00,54,00,79,00,70,00,65,00,00,00

[\wcm://Microsoft-Windows-DNS-Client?version=6.1.7600.16385&language=neutral&processorArchitecture=amd64&publicKeyToken=31bf3856ad364e35&versionScope=nonSxS&scope=allUsers\metadata\complexTypes\InterfaceCollectionType]
"@_MemberList"=hex(1000800c):49,00,6e,00,74,00,65,00,72,00,66,00,61,00,63,00,65,00,00,00,00,00
"@_valid"=hex(10000001):00

[\wcm://Microsoft-Windows-DNS-Client?version=6.1.7600.16385&language=neutral&processorArchitecture=amd64&publicKeyToken=31bf3856ad364e35&versionScope=nonSxS&scope=allUsers\metadata\complexTypes\InterfaceCollectionType\Interface]
"@_type"=hex(10000005):10,40,00,00
"@key"=hex(1000000c):49,00,64,00,65,00,6e,00,74,00,69,00,66,00,69,00,65,00,72,00,00,00
"@xsd:maxOccurs"=hex(10000006):ff,ff,ff,ff
"@xsd:minOccurs"=hex(10000006):00,00,00,00
"@xsd:type"=hex(1000000c):49,00,6e,00,74,00,65,00,72,00,66,00,61,00,63,00,65,00,54,00,79,00,70,00,65,00,00,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 …

#!/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

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
[...]
SysMain:
  Path: %systemroot%\system32\svchost.exe -k LocalSystemNetworkRestricted
  Start flag: autoload
  Service type: Win32 service using svchost
  Error control: ignore
TabletInputService:
  Path: %SystemRoot%\System32\svchost.exe -k LocalSystemNetworkRestricted
  Group: PlugPlay
  Start flag: load on demand
  Service type: Win32 service using svchost
  Error control: normal
TapiSrv:
  Path: %SystemRoot%\System32\svchost.exe -k NetworkService
  Start flag: load on demand
  Service type: Win32 service using svchost
  Error control: normal
TBS:
  Path: %SystemRoot%\System32\svchost.exe -k LocalServiceAndNoImpersonation
  Start flag: load on demand
  Service type: Win32 service using svchost
  Error control: normal
Tcpip:
  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

2 Comments

Filed under Uncategorized