Tag Archives: windows

Decoding the Windows Event Log using guestfish

The Windows Event Log system is Windows’ centralized way of capturing log messages from the operating system and a wide variety of applications.

In all versions of Windows the messages are stored in binary files and normally you can only read these using Microsoft’s proprietary Event Viewer program. In Windows Vista, Microsoft overhauled the entire messaging system and changed the binary format. Luckily a German computer forensics researcher named Andreas Schuster reverse engineered the format [PDF] and wrote a small GPL’d program called EvtxParser [download dir] which can decode it.

We can use guestfish (or libguestfs) along with EvtxParser to easily look at the events in any Windows Vista / 2008 / 7 virtual machine.

Firstly download EvtxParser. You don’t need to install it (indeed, it doesn’t come with any build system so you can’t install it without some effort). You do need to install a few supporting Perl modules though:

# yum install perl-Digest-CRC perl-DateTime \
    perl-Carp-Assert perl-CPAN tidy
# cpan install Data::Hexify

Also the Perl scripts in the EvtxParser zip file aren’t all executable, so chmod them:

$ chmod +x *.pl

Now grab some *.evtx files from your Windows Vista (or later) system. They are stored in the /Windows/System32/winevt/Logs/ directory:

# guestfish --ro -i -d WindowsGuest
><fs> ll win:/Windows/System32/winevt/Logs
total 10540
drwxrwxrwx 1 root root   28672 Oct  1  2010 .
drwxrwxrwx 1 root root       0 Jul 14  2009 ..
-rwxrwxrwx 2 root root 1118208 Dec 23 18:22 Application.evtx
-rwxrwxrwx 2 root root   69632 Sep 19  2010 HardwareEvents.evtx
-rwxrwxrwx 2 root root   69632 Sep 19  2010 Internet Explorer.evtx
-rwxrwxrwx 2 root root   69632 Sep 19  2010 Key Management Service.evtx
-rwxrwxrwx 2 root root   69632 Sep 19  2010 Media Center.evtx
[and many more]
><fs> download win:/Windows/System32/winevt/Logs/System.evtx /tmp/System.evtx
><fs> exit

You can directly dump the files you have downloaded as XML to reveal the events inside them.

$ ./evtxdump.pl /tmp/System.evtx | tidy -xml -indent -quiet | less

This gives me a 40,000 line XML document(!) As a representative sample, the last event is the shutdown event from when I shut the VM off last time:

  <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
    <System>
      <Provider Name="Service Control Manager"
      Guid="{555908d1-a6d7-4695-8e1e-26931d2012f4}"
      EventSourceName="Service Control Manager" />
      <EventID Qualifiers="16384">7036</EventID>
      <Version>0</Version>
      <Level>4</Level>
      <Task>0</Task>
      <Opcode>0</Opcode>
      <Keywords>0x8080000000000000</Keywords>
      <TimeCreated SystemTime="2010-12-23T18:22:58.4980Z" />
      <EventRecordID>1452</EventRecordID>
      <Correlation />
      <Execution ProcessID="456" ThreadID="1748" />
      <Channel>System</Channel>
      <Computer>win7x32</Computer>
      <Security />
    </System>
    <EventData>
      <Data Name="param1">Power</Data>
      <Data Name="param2">stopped</Data>
      <Binary>50006F007700650072002F0031000000</Binary>
    </EventData>
  </Event>

A tip for reading these: the key field is the EventID. For example, EventID 1074 is a user-initiated clean shutdown.

3 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

libguestfs 1.10.0 (new stable) released

.. with many exciting new features including access to live guests, new tools and greatly improved support for Windows. The full release notes for this version are here. If you are using Fedora 15, you’ll get libguestfs 1.10 in a few days.

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

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

Guestfs browser update 6

Update: The latest Koji scratch build is here

Symlinks on Windows filesystems are now displayed correctly. I’m not even going to begin explaining how this miracle was achieved, just look at the very complicated code.

Leave a comment

Filed under Uncategorized