Hello.
I think this is my second contribution to this section, hopefully it turns out to be useful.
I wrote up sort of a snippet on how to hook functions that are part of the IDirect3DDevice9 class. I won't be giving much explanation outside of the code tags since I commented mostly everything.
First I should let you know I'm using a detour function I found somewhere. I'll post it for you guys so you don't get confused, since I'm not using Microsoft's detour library.
Explanations are in the code, it's all commented.
Detour.h:
[highlight=cpp]
void *DetourFunc(BYTE *src, const BYTE *dst, const int len)
{
BYTE *jmp = (BYTE*)malloc(len+5);
DWORD dwBack;
VirtualProtect(src, len, PAGE_READWRITE, &dwBack);
memcpy(jmp, src, len);
jmp += len;
jmp[0] = 0xE9;
*(DWORD*)(jmp+1) = (DWORD)(src+len - jmp) - 5;
src[0] = 0x90; //50
src[1] = 0x90; // 58
src[2] = 0xE9;
*(DWORD*)(&src[3]) = (DWORD)(dst - src) - 7;
for (int i=7; i<len; i++) src[i] = 0x90;
VirtualProtect(src, len, dwBack, &dwBack);
return (jmp-len);
}
[/highlight]
And here's Main:
[highlight=cpp]
#include <windows.h>
#include "Detour.h"
#include <d3d9.h>
/* Type definition for our function to store the original EndScene, this way we don't
have to do a long annoying cast when detouring. */
typedef HRESULT(__stdcall* Real_EndScene)(LPDIRECT3DDEVICE9);
/* This is the function we are going to store the original EndScene in. We're going to
need the real function so that we can return properly at the end of our hooked function
otherwise we're most likely to get errors */
Real_EndScene oEndScene = NULL;
/* This is the function we are detouring the original function to. Before we call and
return normally, we can basically do whatever we want in between. This function is part
of the IDirect3DDevice9 class. Every function's first parameter in a class is always 'This'
So the first parameter is IDirect3DDevice9* or LPDIRECT3DDEVICE9. Now we can call other
functions of this class easily. */
HRESULT __stdcall hook_EndScene(LPDIRECT3DDEVICE9 pDevice)
{
MessageBox(NULL,"Hooked","Hooked",MB_OK);
/* Return using original function. */
return oEndScene(pDevice);
}
DWORD GetPointerDereference(int index)
{
/* Using the device pointer, we can easily find addresses for the functions that are
part of the class. There are 2 ways of doing this, the dereference operator or
inline assembly. Example 1: */
DWORD *DevicePointer = **(DWORD***)0x40CE08;
return DevicePointer[index];
}
DWORD GetPointerInlineAssembly(int index)
{
DWORD DevicePointer = 0x40CE08;
/* This method is a little more confusing, obviously. But with a bit of knowledge in
assembly this shouldn't be a problem. I actually find that dereferencing in assembly
is cleaner than C++, and less of an eye sore when trying to figure out what it does.
It basically does the same thing. First, dereferencing DevicePointer and putting the value
in EAX. Dereference EAX and store it in EBX, etc..
Addresses store 1 byte, since addresses are 4 bytes and we're looking for the address to
a function, we have to multiply the index number by 4, then add the result to ecx, then
dereference to get the address.
Example: If we were to do GetPointerInlineAssembly(42), we aren't adding 42 to ecx,
we're adding 168.
Note: The multiplication in assembly as shown below makes everything a little harder to
understand, you don't have to multiply inside the braces. You can multiply the
index before even starting the inline assembly.
index *= 4;
__asm
{
}
*/
__asm
{
mov eax,[DevicePointer]
mov ebx,[eax]
mov ecx,[ebx]
mov eax,index
mov ebx,4
mul ebx
mov edx,[ecx+eax]
mov DevicePointer,edx
}
return DevicePointer;
}
void Hook()
{
/* We can't hook Direct3D function if the module isn't loaded yet can we? (: */
while(!GetModuleHandle("d3d9.dll"))
{
Sleep(100);
}
/* Make sure the value isn't 0 when dereferencing ( in the GetPointer function )
otherwise you're function is going to be trying to read the value at address
0x00000000, most likely to get an access violation error.
*/
while( *(DWORD*)0x40CE08 == 0)
{
Sleep(100);
}
//Detouring
oEndScene = (Real_EndScene)DetourFunc((PBYTE)GetPointerInlineA ssembly(42),(PBYTE)hook_EndScene,5);
}
/* The usual DllMain function */
bool __stdcall DllMain(HINSTANCE hInstance,DWORD reason, void* useless)
{
if(reason == DLL_PROCESS_ATTACH)
{
CreateThread(0,0,(LPTHREAD_START_ROUTINE)Hook,0,0, 0);
}
if(reason == DLL_PROCESS_DETACH)
{
//clean up
}
return true;
}
[/highlight]
I didn't explain how to get the device pointer, maybe I'll make a small tutorial on how to get it, too bad a tutorial using olly would kind of have to be visual otherwise it's hard to understand.
Anyway, I did that from scratch and made it as simple as possible so that it would be the least confusing possible. I gave 2 methods on how to get the virtual addresses from the device pointer.
Note: Using this method, you need the device pointer, not the device address itself since it's dynamic. I used the d3d9 test environment, although it doesn't give you the device pointer, I was able to get it myself.
So yeah.. that's about it. Giving credits to Why06 for explaining the 'mul' instruction I used in the inline assembly.
If you find an mistakes, please notify me. Thanks.
Good luck.
Last edited by NextGen1; 02-07-2011 at 06:07 PM.
Comments!
Nice job ;D
Yes, I felt like commenting while writing the code. It seemed much easier on my side, rather than having to rethink everything over while typing up the post.
powerfear (03-17-2010)
Very nice David, well as expected. I will read later to busy takin over MPGH.
"Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."- Dwight D. Eisenhower
To sleepy to keep up I'll read later ~
"If the world hates you, keep in mind that it hated me first." John 15:18
powerfear (03-17-2010)
Yeh I'll add it to the list once I finish reading it o_O... didn't have time last night. lawl or this morning tbh.
"Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."- Dwight D. Eisenhower
Meh I should have read this by now, but been so occupied lately. I'll add it to tut list tomorrow, rather or not I read it. D:
@zeco: hi ... you and AJ decide to come back on same day or something?
"Every gun that is made, every warship launched, every rocket fired signifies, in the final sense, a theft from those who hunger and are not fed, those who are cold and are not clothed. This world in arms is not spending money alone. It is spending the sweat of its laborers, the genius of its scientists, the hopes of its children. The cost of one modern heavy bomber is this: a modern brick school in more than 30 cities. It is two electric power plants, each serving a town of 60,000 population. It is two fine, fully equipped hospitals. It is some fifty miles of concrete pavement. We pay for a single fighter plane with a half million bushels of wheat. We pay for a single destroyer with new homes that could have housed more than 8,000 people. This is, I repeat, the best way of life to be found on the road the world has been taking. This is not a way of life at all, in any true sense. Under the cloud of threatening war, it is humanity hanging from a cross of iron."- Dwight D. Eisenhower
The comments look discouraging to read, I should've typed it up in the post instead.
Omg. that was cool as hell. Nice tutorial. Finally read it, now I will add.
btw so the LPDIRECT3DDEVICE9 is always a DWORD**?
let me think about: well I know pDevice is atleast a DWORD*, but it only points to the DIRECT3DDEVICE object, and the device object is a pointer to the array or members so it would always be atleast a DWORD** unless you found the wrong address. :P
Very nice David, will add once I get powahs back. ;l
Hell_Demon (04-23-2010)