Skarma
September 20th, 2009, 02:30 PM
Old, but decided to post it since it's very informational!
Just did this tonight, found global static pointer to IDirect3dDevice9. It was pretty rough. Here's how I got it:
Opened halo 2 vista in ollydbg, searched for all Names, found references to Direct3DCreate9, call is here:
00CC3417 PUSH 20
00CC3419 CALL <JMP.&d3d9.Direct3DCreate9>
00CC341E MOV DWORD PTR DS:[149C640],EAX
20 hex is 32 decimal:
#define D3D_SDK_VERSION 32
call would look like this:
IDirect3D9* pDirect3D9 = Direct3DCreate9(D3D_SDK_VERSION);
pDirect3D9 address would be 0x0149C640
So, from this, we know this address holds the pointer to the IDirect3d9 interface, which has a call to CreateDevice, which creates our device that has all the functions we need. In olly I searched for that constant address, because it has to store the pointer in a register before it can call CreateDevice. Looking at d3d9.h from the sdk, we can calculate what the offset would be.
QueryInterface 0
AddRef 1
Release 2
RegisterSoftwareDevice 3
GetAdapterCount 4
GetAdapterIdentifier 5
GetAdapterModeCount 6
EnumAdapterModes 7
GetAdapterDisplayMode 8
CheckDeviceType 9
CheckDeviceFormat 10
CheckDeviceMultiSampleType 11
CheckDepthStencilMatch 12
CheckDeviceFormatConversion 13
GetDeviceCaps 14
GetAdapterMonitor 15
CreateDevice 16
So, index is 16, multiply that by 4 bytes, gives us 64 in decimal and 40 in heximal
We now know we need to look for *pDirect3D9 + 0x40. After digging, I found the CreateDevice call...
00CBE978 MOV EAX,DWORD PTR DS:[149C640]
00CBE97D MOV EDX,DWORD PTR DS:[EAX]
00CBE97F MOV EDX,DWORD PTR DS:[EDX+40]
00CBE982 PUSH halo2.0149C6B4
00CBE987 LEA ECX,DWORD PTR SS:[ESP+34]
00CBE98B PUSH ECX
00CBE98C MOV ECX,DWORD PTR DS:[143A8B0]
00CBE992 NEG ECX
00CBE994 SBB ECX,ECX
00CBE996 AND ECX,20
00CBE999 ADD ECX,20
00CBE99C OR ECX,106
00CBE9A2 PUSH ECX
00CBE9A3 MOV ECX,DWORD PTR DS:[ECD9C4]
00CBE9A9 PUSH ECX
00CBE9AA PUSH EDI
00CBE9AB PUSH ESI
00CBE9AC PUSH EAX
00CBE9AD CALL EDX
Parameters are pushed last to first, and the first push here is a static memory address...hmm what is the last parameter in the CreateDevice call?: IDirect3DDevice9 ** ppReturnedDeviceInterface
AWESOME. We now have a global static address that stores the device pointer...and will never change unless they update the game, which will probably never happen.
0x0149C6B4 is the device pointer address.
Example usage:
IDirect3DDevice9*** g_pH2VDevice = (IDirect3DDevice9***)0x0149C6B4;
IDirect3DDevice9* g_pDevice = (IDirect3DDevice9*)**g_pH2VDevice;
g_pDevice->DrawIndexedPrimitive();
have fun
EDIT: It's only static from the module base, cuz when I tried hooking last night it wouldn't work, it changed. So above you have to get halo2 base then add the result to
0x00A3C6B4, ex:
DWORD Base = (DWORD)GetModuleHandle("halo2.exe");
DWORD DeviceOffset = 0x00A3C6B4;
IDirect3DDevice9*** pH2VDevice = (IDirect3DDevice9***)(Base + DeviceOffset);
Just did this tonight, found global static pointer to IDirect3dDevice9. It was pretty rough. Here's how I got it:
Opened halo 2 vista in ollydbg, searched for all Names, found references to Direct3DCreate9, call is here:
00CC3417 PUSH 20
00CC3419 CALL <JMP.&d3d9.Direct3DCreate9>
00CC341E MOV DWORD PTR DS:[149C640],EAX
20 hex is 32 decimal:
#define D3D_SDK_VERSION 32
call would look like this:
IDirect3D9* pDirect3D9 = Direct3DCreate9(D3D_SDK_VERSION);
pDirect3D9 address would be 0x0149C640
So, from this, we know this address holds the pointer to the IDirect3d9 interface, which has a call to CreateDevice, which creates our device that has all the functions we need. In olly I searched for that constant address, because it has to store the pointer in a register before it can call CreateDevice. Looking at d3d9.h from the sdk, we can calculate what the offset would be.
QueryInterface 0
AddRef 1
Release 2
RegisterSoftwareDevice 3
GetAdapterCount 4
GetAdapterIdentifier 5
GetAdapterModeCount 6
EnumAdapterModes 7
GetAdapterDisplayMode 8
CheckDeviceType 9
CheckDeviceFormat 10
CheckDeviceMultiSampleType 11
CheckDepthStencilMatch 12
CheckDeviceFormatConversion 13
GetDeviceCaps 14
GetAdapterMonitor 15
CreateDevice 16
So, index is 16, multiply that by 4 bytes, gives us 64 in decimal and 40 in heximal
We now know we need to look for *pDirect3D9 + 0x40. After digging, I found the CreateDevice call...
00CBE978 MOV EAX,DWORD PTR DS:[149C640]
00CBE97D MOV EDX,DWORD PTR DS:[EAX]
00CBE97F MOV EDX,DWORD PTR DS:[EDX+40]
00CBE982 PUSH halo2.0149C6B4
00CBE987 LEA ECX,DWORD PTR SS:[ESP+34]
00CBE98B PUSH ECX
00CBE98C MOV ECX,DWORD PTR DS:[143A8B0]
00CBE992 NEG ECX
00CBE994 SBB ECX,ECX
00CBE996 AND ECX,20
00CBE999 ADD ECX,20
00CBE99C OR ECX,106
00CBE9A2 PUSH ECX
00CBE9A3 MOV ECX,DWORD PTR DS:[ECD9C4]
00CBE9A9 PUSH ECX
00CBE9AA PUSH EDI
00CBE9AB PUSH ESI
00CBE9AC PUSH EAX
00CBE9AD CALL EDX
Parameters are pushed last to first, and the first push here is a static memory address...hmm what is the last parameter in the CreateDevice call?: IDirect3DDevice9 ** ppReturnedDeviceInterface
AWESOME. We now have a global static address that stores the device pointer...and will never change unless they update the game, which will probably never happen.
0x0149C6B4 is the device pointer address.
Example usage:
IDirect3DDevice9*** g_pH2VDevice = (IDirect3DDevice9***)0x0149C6B4;
IDirect3DDevice9* g_pDevice = (IDirect3DDevice9*)**g_pH2VDevice;
g_pDevice->DrawIndexedPrimitive();
have fun
EDIT: It's only static from the module base, cuz when I tried hooking last night it wouldn't work, it changed. So above you have to get halo2 base then add the result to
0x00A3C6B4, ex:
DWORD Base = (DWORD)GetModuleHandle("halo2.exe");
DWORD DeviceOffset = 0x00A3C6B4;
IDirect3DDevice9*** pH2VDevice = (IDirect3DDevice9***)(Base + DeviceOffset);