It allows the same binary to run just fine on Bochs, real machines
with regular VGA drivers at any resolution, and some machines with
accelerated drivers.
Here's how it works:
- First, find the name of the video miniport driver kernel object. We
do this by following a set of registry keys:
-- \HKLM\Hardware\DeviceMap\Video contains a value named
\Device\Video0 that points to another key, such as
\HKLM\System\CurrentControlSet\Services\ialm\Device0
-- This value has the last part chopped off, and the code looks for
the 'Video' key at a lower level, such as
\HKLM\System\CurrentControlSet\Services\ialm\Video
-- This key contains a value named Service that has the name of the
driver. The value is appended to the string '\Driver\' to get a full
path to the driver object in the kernel
- Then we call the undocumented function ObReferenceObjectByName to
get a DRIVER_OBJECT pointer for the miniport driver. We can't just
open a handle because it's opened at boot time by (GDI?) with
exclusive access.
- Then we make a couple IOCTL calls to the driver:
-- IOCTL_VIDEO_MAP_VIDEO_MEMORY: this lets us map the framebuffer
memory to virtual memory. We just take the result and get the physical
address for it, then unmap it. This is because sometimes the miniport
driver will screw with you and only return a very small chunk of
memory. It works better if we just get the physical address then use
MmMapIoSpace() on it ourselves
-- IOCTL_VIDEO_QUERY_CURRENT_MODE: this returns a
VIDEO_MODE_INFORMATION structure that contains everything we need to
know about the current resolution
- This physical address and size of the frame buffer and 3 resolution
components (height, width, stride) are passed back to video.c and
everything else works like it always did.
The 'stride' value is kind of tricky. It's the number of bytes between
the start of one scanline and the next. In non-VGA and non-32bpp
modes, it's possible for the stride to be different than the screen
width. This is done for performance, to make sure each scanline starts
on a boundary with a certain alignment. If you just use the width of
the display to calculate where to place a pixel, the screen gets
weird. It's nice that the miniport driver interface has a way to
retrieve the right stride value. Unforunately, the accelerated
miniport drivers I've seen refuse to return the right value - they
just return the width, even when it's the wrong value. This sucks.
What I did to make this work on my machine was hard-code the stride
value for my resolution in GetRealStride() in xpvideo.c. That's only
called for non-VGA drivers for now. Finding the real stride for a
certain video mode on your own machine takes a bit of guesswork and
trial and error.
By changing the stride value for my laptop (1440x900 with Intel HD
graphics) to 2048, HyperDbg works great with the accelerated driver
from Intel.
But like we've already discussed, there are other modern video cards
that don't map the frame buffer directly to the display in a linear
fashion (such as the nVidia 8800 GTS in my desktop). This little hack
still won't let you run HyperDbg in accelerated modes with those
cards.
This also won't work in Vista or Windows 7 - they use completely
different video driver models.
I'm still doing some research to figure out other ways to get decent
graphics support in HyperDbg, but hopefully this patch makes testing
and developing HyperDbg a bit easier for people. Like I already said,
it's experimental, and I'd like to see how it works for everyone, but
I can't guarantee it'll work for anyone other than me. No warranty for
damages, blah blah blah...
-jon
On Wed, Jun 9, 2010 at 5:52 AM, Jon Larimer <jlar...@gmail.com> wrote:
> Here's a patch that includes some experimental new code that does a
> better job of video mode detection in Windows XP. Apply the patch and
> check out hyperdbg/xpvideo.[ch] and changes made to hyperdbg/video.c.
> To use this new code, you have to define XPVIDEO, but the patch
> includes that change for build_code.cmd.
Great! :-)
We will test the patch ASAP and we will let you know how it behaves on
our physical machines.
Roberto
I just uploaded Jon's patch into the repository. I successfully tried
it into the Bochs environment with different resolution but I still
hadn't the possibility to try it on a real machine. I applied a small
refactoring to the proposed patch in order to make it compliant with
the comments/function naming style adopted in other files but I didn't
make any functional change whatsoever.
Cheers,
Aristide
--
GnuPG Key on keyserver.pgp.com ID 291D712D
http://security.dico.unimi.it/~joystick/