Archive for the ‘Linux’ Category

GCJ, the GNU compiler with java extensions, does a great job at compiling Java into bytecode, but still has some bugs in its libraries when dealing with Swing components. Installing Sun’s Java packages on Debian thus is occasionally necessary, and has historically been a chore. I won’t list the process here to even show my distaste for it - it just wasn’t very fun.

Things are much easier now, though. Just make sure a non-free package repository is listed in your sources.list, and things become magic:

sudo echo "deb http://ftp.us.debian.org/debian/ lenny non-free" >> /etc/apt/sources.list

(Note that if you aren’t using lenny, you should change that. Also, feel free to choose a different mirror.)

Now update your package repository:

sudo apt-get update

And finally install whichever Sun Java packages you want!

sudo apt-get install sun-java6-jdk sun-java6-jre sun-java6-plugin

Cheers to Matthias Klose (Ubuntu), Juergen Kreileder (Blackdown), Barry Hawkins, Jeroen van Wolffelaar, and the other folks behind debian-java for adding these packages to Debian’s repositories. It is another push that greatly enhances the usability of the project for both developers and users alike.

My coolest project from work as of late has been to write a program to control the Sharp LCD projectors in RIT’s Software Engineering department through a serial interface. I really like writing code that interfaces with hardware, so this was one I enjoyed doing.

One thing I learned quickly is that debugging serial applications is hard. When my code wasn’t working, I didn’t know if it was because of the hardware, the software, or the command messages I was sending. If serial consoles or line printers were still widely available, it wouldn’t be hard to see what was going on. Since they aren’t, an alternate solution was devised utilizing GNU screen.

With two Linux boxes running Debian, I set one up with my code to send data from, and the other with screen attached to the serial device at /dev/ttyS0. Screen functions normally, but with the added bonus of displaying messages recieved from the serial device, and when entered, sending messages to the device. Screen makes it possible to visualize serial communications and send test messages without having to write or modify any code, making it an infinitely useful tool in debugging serial applications.

My bug turned out to be twofold: one hardware, and one software. The first was that the serial connection to the projector was not complete; there is a break somewhere in the wall. The second was that the manual states only that the command message be followed by a newline character. I was sending Unix newlines, like ‘\n’. The projector was written expecting Windows style newlines, which is a newline prepended by a carriage return, or ‘\r\n’. This simple fix, which I would have never stumbled over without the help of screen, was the source of my software based problems.

As is plastered all over the Internet, Ubuntu 8.04 Hardy Heron was recently released for the public to feast upon. I really don’t care about the release itself, but I *do* care about Mark Shuttleworth’s blog post regarding the release. Specifically:

We all owe a great deal to the team who make Debian’s “unstable” repository possible, and of course to the upstream projects from GNOME and KDE through to the Linux kernel.

Read the rest of it here.

I think Mark’s statement shows maturity in the Ubuntu project, and I respect him for showing the open source community some love.

I’m not affiliated with the Debian project in any official capacity (yet!), but I’m happy they are getting the credit they deserve. Kudos to the Debian team and every package maintainer - you don’t hear it enough, but there is a large percentage of the technically aware population that appreciates the work you do beyond measure.

I’ve been seeing a lot of sites throwing around a “how to reset BIOS passwords” tip that revolve around using the DOS/Windows DEBUG tool. In case you haven’t seen it, it goes a little like this:

  1. Create a boot floppy/disc with the debug tool on it
  2. Type -o 70 2e
  3. Type -o 71 FF
  4. Type quit
  5. Reboot

Curious as to why this works? So was I, but none of the sites I saw included an explanation. So after some googling, I uncovered the nitty-gritty details.

The CMOS memory is actually accessible to the user for reading and writing. I’m not aware of a recent operating system that doesn’t restrict write access to the administrator/super user, but it is there nontheless. It contains a lot of information, such as the system time (direct access to the real-time clock), BIOS information, and CMOS data. With this knowledge, I would suggest taking a look at this link, which is a reference to how the CMOS memory is laid out. It is what I used to determine what the hex values being output were doing.

The -o option of debug just outputs a value to an io port. The CMOS memory is accessed through ports 70 and 71, which explains the first parameter of the steps above. The second part can be seen from the CMOS reference I linked to above - by latching the address 0×2e for writing, and then setting its value to 0xff, we are manually telling the CMOS that it has an invalid checksum. The behavior when this occurs is to revert to the default BIOS, a feature which is supported independent of operating system or processor architecture - ie, any AT/ATX motherboard will do this.

None of the sites list instructions for if you are a Linux user, and assume you’ll have access to the debug program. So, now understanding how this specific utilization of debug worked, I wrote my own version in C. It can be compiled using gcc, and is compatible with all *nix distributions - so add it to your rescue LiveCD toolkit, you never know when you’ll need it :)

Here is the source:

resetBIOS.c

#include <stdio.h >
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>

/* Written by Robert Peaslee - www.robertpeaslee.com */
/* compile: gcc -o resetBIOS resetBIOS.c */
/* Run as superuser. */

int main() {

  /* Allow writing to ports 70 and 71  */
  if( ioperm(0x70, 1, 1) || ioperm(0x71, 1, 1) ) {
    perror("Error setting write permissions");
    printf("\n");
    exit(1);
  }

  /* output 0x2e to port 70, which is the address where the
   * CMOS checksum is stored */
  outb(0x2e, 0x70);
  /* Small sleep to allow the changes to take effect. */
  usleep(100000);
  /* Tell the CMOS that the checksum is bad, forcing it to
   * load the default BIOS on reboot. */
  outb(0xff, 0x71);

  /* Reset the port permissions to not be writeable */
  if( ioperm(0x70, 3, 0)) {
    perror("Error restoring permissions");
    printf("\n");
    exit(2);
  }

  exit(0);

}

And if you only want the assembly specific portions without relying on external libraries:

out 70, 0x2e
out 71, 0xff

…but note you’ll have to add your own data/text sections and a main: entry point if you want to actually assemble it. Additionally, you’ll have to convert this to at&t syntax if you want to inline it in C code using the gcc compiler.

So there you have it - a full explanation of why it works, an example in C, and a complete reference of the layout of CMOS memory. If you still have questions, leave them in the comments!

I enjoy computer security. There aren’t a lot of opportunities to study it formally within computer science, so my education in this field is entirely from what I read and practice in my own time.

Most recently, I’ve been feeling the itch to write a worm. The idea is attractive because a worm can be developed modularly with reusable components. Each individual component will increase my knowledge substantially in a different area of security, making the development a measurable goal with incremental positive feedback.

However, before development could begin, I wanted to ensure that I wouldn’t end up in court for an accidental release of one of the components gone awry. I love virtual machines as a tool to aid in the development process, so the solution was immediately obvious - create a multi-host virtual network that is isolated from the world. Further, I wanted each machine on this isolated network to occasionally be able to access the Internet to retrieve updates or tools, so the isolation needed to be complete but /controllable./ The final requirements of the virtual network ended up looking like this:

  • Isolated network except when explicitly given access to the Internet
  • Multiple hosts with different operating systems
  • Must be able to easily add and remove hosts
  • All hosts on the network must both default and fail to isolation

The way to implement this using VMWare Workstation (and I’m sure other products in their virtualization line) is to utilize teams. Teams are a ‘wrapper’ of a sort that encompass multiple VMs with additional configuration. When you start a team, each virtual machine included in the team’s configuration is also started. The team can be configured to also provide a virtual network segment for the virtual machines to use, which when paired with each VM in the team being configured with ‘host only’ network access, results in a virtual isolated network.

The team doesn’t provide DHCP though, which means the network has to be maintained with static address and modifications to each machine’s host file. This hardly met my requirement for easily adding and removing hosts from the network. Creating a host that would act as the network server fulfills this requirement, and will also facilitate network control access. As we continue on, please note that I’m using Debian Linux with a 2.6.x kernel, and all of the commands I give below and edits to configuration files *must be done as a superuser.*

Enough setup: time for implementation. To speed the process, I created two base images, one Windows XP SP2 install, and one Debian Lenny netinstall with a 2.6.x kernel. Each image was updated to include the latest patches, user accounts were created, and standard tools were installed. Once these base images were created, they were set aside to never be modified. Clones of the base images are created for each of the expendable hosts, and one clone of the Debian base image was used as the only ‘permanent’ member of the team. All members of the team share one virtual network segment, and have one interface. The only exception to this is the network server VM, which is dual-homed to be connected to both the virtual network and the Internet via NAT.

All hosts default to DHCP, so cloned images have no need for additional configuration when added. The network server is the only machine that had be set up specially. The bind9 and dhcp3-server packages were obtained (for DNS and DHCP, respectively) using Debian’s awesome package manager:

apt-get install bind9 dhcp3-server

Configuring bind is trivial, it defaults to forwarding DNS requests, so nothing is required as far as configuration unless you want to. dhcpd, provided by dhcp3-server, is a little more complicated. First, the interface connected to the isolated network must be set up to have a static address in the subnet in which you will be offering IP addresses, like 10.10.10.1 for the 10.10.10.x subnet or 192.168.30.1 for the 192.168.x.x subnet. It would be wise to modify your interface configuration to make this change survive rebooting.

/etc/network/interfaces:

auto lo eth0 ethiface lo inet loopback
iface eth0 inet static
 	address 10.10.10.1
 	netmask 255.255.255.0iface eth1 inet dhcp

The external interface is eth1, and is configured with DHCP since it is NAT routed. The internal interface is eth0, and is given an ip of 10.10.10.1 with a subnet mask of 255.255.255.0. (This means that the last quartet of the IP address is variable and available for use.) Next comes the configuration for dhcpd:

/etc/dhcp3/dhcpd.conf:

default-lease-time 600;max-lease-time 7200;
authoritative;option domain-name-servers 10.10.1.1 192.168.30.1

subnet 10.10.10.0 netmask 255.255.255.0 {
 range 10.10.10.2 10.10.10.254;
 option routers 10.10.10.1;
 option ip-forwarding off;
 option broadcast address 10.10.10.255;
 option subnet-mask 255.255.255.0;
}

Here we are saying that the subnet is 10.10.10.*, and that we will assign addresses from 10.10.10.2 - 10.10.10.254. The other options should be self-explanatory - read up on networking if you have questions. As it stands, when the interfaces are brought down and back up and dhcpd is started, addresses will be assigned to all virtual machines sharing that network segment. If this is all you want, just issue:

ifdown eth1 eth0
ifup eth1 eth0
/etc/init.d/dhcpd3-server start

And you are done! The machine now will serve DHCP to the isolated subnet, while maintaining separate access for itself to the Internet.

However, if you want to continue on to enable Internet access for other hosts on the isolated network, we still have some work to do.

My solution for this involves iptables and masquerading. Before we do anything, we’ll need to enable IP forwarding. This can be done in multiple ways, but the most reliable for me has been the following simple command:

echo 1 > /proc/sys/net/ipv4/ip_forward

With IP forwarding enabled, we can now utilize the masquerading features of iptables, the Linux firewall. By creating rules that will take packets coming in from our internal network’s interface and sending them out on our external interface, in addition to creating a complementing rule that will accept return packets coming in from the external interface headed for the isolated host, we can accomplish this. The individual rules for my setup are:

iptables -t nat -A POSTROUTING -s  -o eth1 -j MASQUERADE
iptables -A FORWARD -d  -i eth0 -j ACCEPT

Since these are annoying to have to type in each time I want to enable access for a host, I wrote a set of scripts. The first two enable and disable access for a host or multiple hosts respectively. The third script is my emergency “oh crap” failsafe, with which a simple command I can disable all isolated hosts’s access immediately followed by bringing down the network server’s interfaces for complete assurance that whatever is going on won’t get out of the virtual network. Here they are:

enableInternet.sh

#!/bin/bash
if [ $UID -ne 0 ]; then
        echo
        echo “Must be root to run this program.”
        echo
        exit 1
fi

if [[ -z $* ]]; then
        echo
        echo ”  Usage: ./enableInternet.sh <ipaddress [ipaddress2...ipaddressN]>”
        echo
        exit 1
fi

for ip in $@; do
        # Will match an address of type 10.10.1.2, which matches our subnet
        # definition
        check=`echo $ip | grep -E “^([[:digit:]]{2}[.]){2}[[:digit:]][.][[:digit:]]+$”`
        # If it doesn’t match, print a warning and skip it
        if [ -z $check ]; then
                echo “Improperly formatted address $ip, skipping…”
                continue
        fi

        # Enable Internet access for the address
        iptables -t nat -A POSTROUTING -s $ip -o eth1 -j MASQUERADE
        iptables -A FORWARD -d $ip -i eth0 -j ACCEPT
        echo “$ip’s internet access enabled…”

done

echo “Done.”

blockInternet.sh

#!/bin/bash
if [ $UID -ne 0 ]; then
        echo
        echo “Must be root to run this program.”
        echo
        exit 1
fi

if [[ -z $* ]]; then
        echo
        echo ”  Usage: ./blockInternet.sh <ipaddress [ipaddress2...ipaddressN]>”
        echo
        exit 1
fi

for ip in $@; do
        # Will match an address of type 10.10.1.2, which matches our subnet definition
        check=`echo $ip | grep -E “^([[:digit:]]{2}[.]){2}[[:digit:]][.][[:digit:]]+$”`
        # If it doesn’t match, print a warning and skip it
        if [ -z $check ]; then
                echo “Improperly formatted address $ip, skipping…”
                continue
        fi

        # Disable Internet access for the address
        iptables -t nat -D POSTROUTING -s $ip -o eth1 -j MASQUERADE
        iptables -D FORWARD -d $ip -i eth0 -j ACCEPT
        echo “$ip’s internet access disabled…”
done

echo “Done.”

blockAll.sh

#!/bin/bash
if [ $UID -ne 0 ]; then
        echo
        echo “Must be root to run this program.”
        echo
        exit 1
fi

echo “Disabling Internet access for all hosts on 10.10.1.0/255.255.255.0…”

iptables –flush
iptables –delete-chain
iptables -t nat –flush
iptables -t nat –delete-chain
ifdown eth0 eth1

echo “Done.”

I alias’d all the commands in my shell’s configuration scripts and prefixed them with sudo so they may be executed quickly and from anywhere on the system. If you’ve read this far, you should too - at least for the blockAll script. You don’t want to be fumbling around trying to remember where you put the script when you need complete isolation 30 seconds ago :)

I know this post was long, but there was a lot to cover. With this setup, hosts can now be easily added thanks to DHCP, Internet access is manually granted and defaults to none, and the environment is completely homogeneous. Perfect for worm development, malware analysis, or what have you. If you replicate this environment, let me know how it works out for you and what improvements you make. I’m always interested in making better systems!

One of the relatively recent additions to KDE/Gnome has been the ‘network-manager’ tool. It attempts to make the life of its users easier by automagically managing your interfaces. I can’t comment on its effectiveness during a normal user’s session, but my experiences were frustrating.

I guess it isn’t fair to say network-manager’s operation was frustrating, but rather that it was running without my knowledge, causing weird behavior. I’m setting up dhcpd in a virtual machine to provide addresses for an isolated network. Normally this requires that you only set up the interface, grab the package, set up the subnets you want to assign addresses to in /etc/dhcp/dhcpd.conf, and start up the daemon. However, this time around, I ran into some problems.

First, I attempted to set up my primary interface to use a static IP. I edited /etc/network/interfaces to set eth0 to use a static IP, set it and its netmask, and then brought the interface back up. The output from ifconfig showed no IP assignment. What!? Thinking it was something I was doing wrong, I brought the interface back down and ignored it while I configured dhcpd.

The dhcpd.conf file isn’t difficult to set up. The subnets to service were declared, as were the address ranges to use when assigning addresses dynamically. When the configuration was done, I attempted to bring up the daemon. /etc/init.d/dhcp3-server start… and… errors. “Not configured to listen on any interfaces?” Ugh. Further digging revealed that dhcpd was looking to serve addresses on a 10.10.1.0 network that I had configured, but the only active interface was listening on a 169.0.0.0 network.

Wait - an interface is up? I took it down! I again checked the syslogs, and sure enough, something is initiating dhclient to find an IP address, and upon failing, is assigning a private IP from the 169.0.0.0 range to my interface. The root cause of it ended up being network manager trying to maintain a connection on the interface utilizing its own configuration. Stopping the network-manager service immediately fixed the problem - bringing up the eth0 interface resulted in it being assigned the static IP I wanted, dhcpd ran without a problem, and I was happy.

I have some gripes with network-manager from this experience.

First, I edited /etc/network/interfaces to make the changes to eth0’s configuration. That is the way changes have been made to interfaces since before I started using Linux. I understand what network manager was trying to do, but two things perplex me. Why did it block my static IP assignment when I tried to bring the interface up? It wasn’t even immediately overridden, there was literally no address assigned to the interface. And also, why, WHY is it ignoring standard configuration files? /etc/network/interfaces should remain the be-all is-all configuration for network interfaces. Using another configuration file just makes things confusing.

Second, I believe the behavior of network-manager needs to be changed. I don’t know how this would be possible, so it may be an unreasonable thought - but if I bring down an interface manually, I don’t want it back up until I manually bring it up. Network-manager bringing up that interface after I had manually taken it down was confusing as all hell, and I certainly don’t use Linux to have my machine work against me.

I have disabled network manager permanently on my system. For a standard user (are there any ’standard’ Linux users?) it may function well, but for anyone that wants control of their machine, I suggest they do the same.

Ubuntu seems to be the latest, greatest thing in the world of operating systems. The creators of Ubuntu have done some good things in terms of making Linux easier to use and in providing guidance for Linux newbs. But with newbs you bring ignorance, and there are a couple things I’ve been seeing that are kind of ridiculous.

First, I saw a post stating that “I’m of the opinion that Ubuntu could not exist without Debian.” The poster of that comment is Mark Shuttleworth, the founder of the Ubuntu project. Just as you would expect Bill Gates to downplay the significance of taking ideas from other operating systems, Mark is downplaying his project’s dependence on Debian. The quote above should be “Ubuntu absolutely could not exist without Debian.” That is it - no opinions, just solid fact. Ubuntu is being developed by a relatively small team, and what they achieve seems impossible for their size. Their secret is simple: work on the Debian project is being done by coders working to advance the project, not for money, and Ubuntu is a thin interface on top of that work. I’m not bashing any of the paid Ubuntu developers, but the development of Ubuntu is extremely dependent on the advancement of Debian. In fact, this point has been the source of some unfavorable feelings toward Ubuntu by Debian developers, with the criticism that Ubuntu is taking a *lot* from Debian, and returning very little. So if you take one thing away from this paragraph, let it be that Debian can exist without Ubuntu. Ubuntu cannot exist without Debian.

And second, the number of Ubuntu users who believe “Ubuntu = Linux” or the same users who have never heard of Debian is surprisingly high. If one of you happens to be reading this post, here is a simple analogy to explain the truth. The Linux kernel is the component common to all distributions of Linux - you could say that it is Mr. Potato Head’s body. Distributions of Linux are different sets of packages on top of the kernel that enable the user to do different things easily. You could call these the accessories you put on Mr. Potato Head. Debian and Ubuntu are such distributions. However, Ubuntu is built on /top/ of Debian, so you could call Ubuntu the paint on the accessories on Mr. Potato Head. All in all, there was extra work to make those accessories more appealing, but that work is trivial when compared to what it took to make the accessories themselves. You can make a Debian installation behave exactly like an Ubuntu installation with very little work (just by grabbing the packages, possibly from a different package level), but doing the opposite is near impossible. To summarize: Ubuntu is Debian. Debian is not Ubuntu. Both are Linux distributions.

I really hope that this sheds some light on the dependency that Ubuntu has on Debian. And really, I would *love* to see some activism on the Ubuntu community’s side to give more back to the Debian project. The farther Debian goes, the better Ubuntu gets - they only stand to benefit.

Anyone worth their weight in salt knows how Linux came to be. What is interesting though is how Linus chose what features to include, and how things got started on a larger scale. I came across this posting on exactly that topic:

Hello everybody out there using minix -
I’m doing a (free) operating system (just a hobby, won’t be big and
professional like gnu) for 386(486) AT clones.  This has been brewing
since april, and is starting to get ready.  I’d like any feedback on
things people like/dislike in minix, as my OS resembles it somewhat
(same physical layout of the file-system (due to practical reasons)
among other things).
I’ve currently ported bash(1.08) and gcc(1.40), and things seem to work.
This implies that I’ll get something practical within a few months, and
I’d like to know what features most people would want.  Any suggestions
are welcome, but I won’t promise I’ll implement them :-)
Linus (torvalds@kruuna.helsinki.fi)
PS.  Yes - it’s free of any minix code, and it has a multi-threaded fs.
It is NOT protable (uses 386 task switching etc), and it probably never
will support anything other than AT-harddisks, as that’s all I have :-(.

The responses to this initial posting are really cool, and provide direct lineage to many of the features Linux is known for. Pseudo TTYs, BSD sockets, user-mode filesystems, and POSIX compatibility were all suggested by Jyrki Kuoppala (who is a supporter of the EFF!). Other ideas which are completely standard now include paging to disk and processes that aren’t assigned a fixed amount of memory on process creation, which were both suggested by early kernel hacker Peter Holzer.

There is a lot more in those responses, and they aren’t long. Take a quick look at them, and enjoy gems like Linus stating “it is NOT portable.” If only he knew where his little project would be even five years later…

In my last post I chronicled the time consuming process of converting an image produced using the Unix dd utility to a vmware VMDK virtual disk. The process does work, but VMWare will only load it if the image contains a master boot record that still contains the appropriate information when removed from the rest of the system. Additionally, I think it is appropriate to mention again how terribly slow it is. We can circumvent these problems with Live View for Windows, a program developed for forensic work by Carnegie Mellon University.

The process for creating the image with dd is the same as last time, IE, by doing something along the lines of:


dd if=/dev/hdc3 of=/mnt/external/diskImage/XPSP2.img bs=1024

Once that image is generated and you are back in Windows, simply launch the Live View utility and… the rest is pretty self explanatory. Once the dd image is generated, the Live View program takes only a couple minutes to create the new vmdk, configure the virtual machine, and launch it. Sweet, sweet efficiency!

[Update: there is an alternative method here. It has better success and is more reliable for partitions that reside in the second or later primary partition positions. It is also a more user friendly.]

I have a Windows XP SP2 installation that I use for work, while my current personal OS of choice is Windows Vista. I only work weekends, so rebooting wasn’t too bothersome initially. Over time it has become more and more of a chore, as I can’t easily switch from one development environment to another without rebooting. I decided it was time to make my work installation a virtual machine.

I had some additional complications that made the process a little non-standard. I originally tried using VMWare’s converter tool, but it would fail at 97% of the creation of the disk. I then tried using a Windows port of the Unix utility ‘dd’ to create a raw image of the disk, but because the Windows volume manager was accessing the disk, dd would give me access errors. Additionally, the VMWare converter doesn’t support converting from a raw image (…grr…), so Qemu’s qemu-img tool would have to be used to convert the raw image to a disk in VMWare’s vmdk format.

The steps to reach our goal aren’t too complicated, and can be replicated by others easily. To do it, I used:

  • VMWare Workstation
  • A Linux installation or LiveCD (I used my existing Debian installation, but something like Knoppix would work fine)
  • Qemu
  • NTFS-3G (if you plan on writing out to an NTFS partition from Linux, as I did)

I started by booting into my Linux install. Linux only mounts the disks it uses (hint hint, Microsoft) so we can access all sectors of the partition to make a dump of the disk with dd. I first had to mount the partition where I wanted the output file to reside, which uses NTFS:

ntfs-3g /dev/sdb1 /mnt/external

Next, create the image. I did this with the following (substitute your device/partition and output file):

dd if=/dev/hdc3 of=/mnt/external/diskImage/XPSP2.img bs=1024

When that finishes, the file specified with the ‘of’ option in dd will contain a block-by-block exact copy of your partition. However, it is in a raw format - we need it in a format VMWare can read. This is where Qemu comes in. Qemu is distributed with qemu-img, a tool used for creating, manipulating, and converting images. Specifically, our goal is to use qemu-img’s convert functionality to convert from a raw image format to the vmdk format. This is accomplished with:

qemu-img convert -f raw /mnt/external/diskImage/XPSP2.img -O vmdk /mnt/external/diskImage/XPSP2.vmdk

Be prepared to wait. For a 40gb image, this process took roughly 12 hours. Since qemu-img provides no status as to how far it has come, I kept tabs on it just by monitoring the filesize of the output image. This is entirely unnecessary, but if you want to do the same, just open a new terminal and type the following:

while [1 -gt 0 ]; do du -hs /mnt/external/diskImage/XPSP2.vmdk; sleep 10; clear; done

This will just print out the size of the file on your screen so you can watch it grow. Alternatively, Roberte provided a tip in the comments that suggested using the “watch” command. Either will work:

watch ‘ls -lh /mnt/external/diskImage/XPSP.vmdk’

When the process is completed, boot back into Windows (or if you are using Linux as the host, stay put) and create a virtual machine around your new disk image. Don’t forget to remove the original img created with dd, it is a huge waste of disk space :)

[Notes]

  1. This process is really only feasible if you have a lot of disk space. At worst, the disk requirements are greater than 2*P, where P is the partition size of the virtual machine you wish to create. However, qemu-img only writes out actual data, not empty sectors, so your output image will be the size of the used space in the input image. For my conversion, I used over 40gb (input)+15gb (output) of disk space, which was reclaimed with the deletion of the output of dd, and resizing another partition to use the old physical installation’s space.
  2. qemu-img doesn’t support stream input, which is why we can’t pipe dd’s output directly into qemu-img convert. This would have reduced the disk requirements to only the size of the vmdk image, and sped up the process substantially. Bug the Qemu developers to implement this feature :)