Statistics

Members: 1927
News: 293
Web Links: 1
Visitors: 3932941

Who's Online

Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home arrow Submit Your Paper!
How to use DirectDraw in ASM
User Rating: / 0
PoorBest 
Written by X-Calibre [Diamond]   


Well, there has been quite a large demand for this essay, so I finally started writing it. This essay will show you how to use C++ objects and COM interface in Win32ASM, using DirectDraw as an example.

Well, in this part of the Win32 API, you will soon find out how important it is to know C and C++ when you want to use an API written in these languages. Judging from the demand for this essay, I think it will be necessary to explain a bit of how objects work in C++. I will not go too deep, but only show the things you need to know in Win32ASM.

 

 

What are objects really?

Actually a structure is an object of which all fields are public. We will look at it the other way around. So the public fields in an object make up a structure. The other fields in an object are private and are not reachable from the outside. So they are not interesting to us.

A special thing about objects is that they can contain pointers to functions. Normally, when using C or ASM, this would be possible, but a bit error-prone. It can be seen as 'dirty' programming. That's why you probably haven't seen it before.

When using C++ with a compiler, there will be no errors, as long as the compiler does its job. So here you can use this technique with no chance of errors, and it gives you some nice new programming options.

C++ goes even further with this 'structure of functions' idea. With inheritance, you can also overwrite functions of the base class in the inherited class. You can also create 'virtual' functions, which are defined in the base class, but the actual code is only in inherited classes.

This is of course interesting for DirectX, where you want to have standard functions, but with different code, depending on the hardware on which it is running. So in DirectX, all functions are defined as virtual, and the base class is inherited by hardware-specific drivers which supply hardware-specific code. And the beauty of this is, that it's all transparent to the programmer. The function pointers can change at runtime because of this system, so the C++ designers had to think of a way to keep the pointers to the functions available to the program at all time.

What this all boils down to is that there is a table with pointers to the functions. It's called the Virtual Function Table. I will call this the vtable from now on.

So we need to get this table, in order to call functions from our object. Lucky for you, Z-Nith has already made a C program to 'capture' the table, and converted the resulting header file to an include file for use with MASM. So I'll just explain how you should use this table, and you can get going soon.

Well, actually it's quite simple. The DirectX objects are defined like this:

IDirectDraw STRUC

lpVtbl DWORD ?
IDirectDraw ENDS

IDirectDrawPalette STRUC

lpVtbl DWORD ?
IDirectDrawPalette ENDS

IDirectDrawClipper STRUC

lpVtbl DWORD ?
IDirectDrawClipper ENDS

IDirectDrawSurface STRUC

lpVtbl DWORD ?
IDirectDrawSurface ENDS

So these structs are actually just a pointer to the vtables, and don't contain any other values. Well, this makes it all very easy for us then. I'll give you a small example:

Say we have an IDirectDraw object called lpDD. And we want to call the RestoreDisplayMode function.
Then we need to do 2 things:

  1. Get the vtable.
  2. Get the address of the function, using the vtable.

The first part is simple. All the struct contains, is the pointer to the vtable. So we can just do this:

mov eax, [lpDD]
mov eax, [eax]

Simple, isn't it? And the next part isn't really much harder. The vtable is put into a structure called IDirectDrawVtbl in DDRAW.INC. We now have the address of the structure in eax. All we have to do now, is get the correct member of that structure, to get the address of the function we want to call. You would have guessed by now, that this will do the trick:

call [IDirectDrawVtbl.RestoreDisplayMode][eax]

That is not a bad guess...
But there's one more thing, which is very important: this function needs to be invoked on the IDirectDraw object. We may only see the vtable in the structure, but there are also private members inside the object. So there's more than meets the eye here. What it comes down to is that the call needs the object as an argument. And this will be done by stack as always. So we just need to push lpDD before we call. The complete call will look like this:

push [lpDD]
call [IDirectDrawVtbl.RestoreDisplayMode][eax]

Simple, was it not? And calls with arguments are not much harder. Let's set the displaymode to 320x200 in 32 bits next. This call requires 3 arguments:

SetDisplayMode( width, height, bpp );

Well, the extra arguments work just like normal API calls: just push them onto the stack in backward order.
So it will look like this:

push 32
push 200
push 320
mov eax, [lpDD]
push eax
mov eax, [eax]
call [IDirectDrawVtbl.SetDisplayMode][eax]

And that's all there is to it.

To make life easier, we have included some MASM macros in DDRAW.INC, for use with the IDirectDraw and IDirectDrawSurface objects:

DDINVOKE MACRO func, this, arglist :VARARG

mov eax, [this]
mov eax, [eax]

IFB <arglist>

INVOKE [IDirectDrawVtbl. func][eax], this ELSE

INVOKE [IDirectDrawVtbl. func][eax], this, arglist ENDIF
ENDM

DDSINVOKE MACRO func, this, arglist :VARARG

mov eax, [this]
mov eax, [eax]

IFB <arglist>

INVOKE [IDirectDrawSurfaceVtbl. func][eax], this ELSE

INVOKE [IDirectDrawSurfaceVtbl. func][eax], this, arglist ENDIF
ENDM

With these macros, our 2 example calls will look as simple as this:

DDINVOKE RestoreDisplayMode, lpDD

DDINVOKE SetDisplayMode, lpDD, 320, 200, 32

Well, that's basically all there is to know about using objects, COM and DirectX in Win32ASM. Have fun with it!

And remember:

C and C++ knowledge is power!