Probably, to some others use static address is easier..
Here's how to find JuJu's pointers.
Credits: Apoc, JuJu
Code:
enum Direct3D9Ptrs
{
pDevicePtr_1 = 0x00C776B8, // 3.3.2
pDevicePtr_2 = 0x397C, // 3.3.2
oEndScene = 0xA8, // 3.3.2
};
Code:
/*
to find pDevicePtr_1 (which has more than 2500 xrefs)
search:
.rdata:00A166C0 43 6F 6E 73 6F 6C 65 44+aConsoledevic_0 db 'ConsoleDeviceInitialize(): output device does not have dual TMUs!'
go above to:
.text:006FE1E7 E8 E4 80 F1 FF call apoc_wyc_BeforeInitWnd <<<< In this call, LD3device will be created, but inside, this->[0x28h] will be called, no worry, at least is found.
.text:006FE1EC 83 C4 10 add esp, 10h
.text:006FE1EF 85 C0 test eax, eax
.text:006FE1F1 A3 B8 52 CC 00 mov dword_CC52B8, eax
.text:006FE1F6 0F 84 79 FF FF FF jz loc_6FE175
.text:006FE1FC
.text:006FE1FC loc_6FE1FC: ; CODE XREF: apoc_ConsoleDeviceInitialize+38Fj
.text:006FE1FC ; apoc_ConsoleDeviceInitialize+4B2j
.text:006FE1FC B9 16 00 00 00 mov ecx, 16h
.text:006FE201 8D 75 94 lea esi, [ebp+var_6C]
.text:006FE204 BF D8 52 CC 00 mov edi, offset unk_CC52D8
.text:006FE209 F3 A5 rep movsd
.text:006FE20B B9 16 00 00 00 mov ecx, 16h
.text:006FE210 8D 75 94 lea esi, [ebp+var_6C]
.text:006FE213 BF 00 54 CC 00 mov edi, offset unk_CC5400
.text:006FE218 F3 A5 rep movsd
.text:006FE21A 8D 75 94 lea esi, [ebp+var_6C]
.text:006FE21D E8 8E E9 FF FF call sub_6FCBB0
.text:006FE222 8B 0D B8 76 C7 00 mov ecx, dword ptr unk_C776B8 <<<< this is pDevicePtr_1 !
.text:006FE228 E8 D3 9B F1 FF call apoc_CGxDevice__Caps
.text:006FE22D 83 38 02 cmp dword ptr [eax], 2
.text:006FE230 0F 83 3C 01 00 00 jnb loc_6FE372
.text:006FE236 8B 15 B8 52 CC 00 mov edx, dword_CC52B8
.text:006FE23C 52 push edx ; char
.text:006FE23D E8 7E 99 F1 FF call sub_617BC0
.text:006FE242 68 C0 66 A1 00 push offset aConsoledevic_0 ; "ConsoleDeviceInitialize(): output devic"...
to find pDevicePtr_2:
search signature: 1B DB 83 E3 30 83 C3 22 53 52 6A 01 6A 00
CPU Disasm
Address Hex dump Command Comments (3.3.2 zhTW dump)
006243F4 |. 8B86 78390000 MOV EAX,DWORD PTR DS:[ESI+3978]
006243FA |. 8B08 MOV ECX,DWORD PTR DS:[EAX]
006243FC |. F6DB NEG BL
006243FE |. 8DBE 7C390000 LEA EDI,[ESI+397C] ppReturnedDeviceInterface <<<< THE pDevicePtr_2
00624404 |. 57 PUSH EDI
00624405 |. 8D55 C4 LEA EDX,[LOCAL.16]
00624408 |. 52 PUSH EDX pPresentationParameters
00624409 |. 8B96 68390000 MOV EDX,DWORD PTR DS:[ESI+3968]
0062440F |. 1BDB SBB EBX,EBX <<<<<< this is the bytes as signature to search for
00624411 |. 83E3 30 AND EBX,00000030
00624414 |. 83C3 22 ADD EBX,22 = 0x52
00624417 |. 53 PUSH EBX D3DCREATE = D3DCREATE_HARDWARE_VERTEXPROCESSING(0x40)+D3DCREATE_PUREDEVICE(0x10) +D3DCREATE_FPU_PRESERVE(0x02)
00624418 |. 52 PUSH EDX hFocusWindow
00624419 |. 6A 01 PUSH 1 DeviceType typedef enum D3DDEVTYPE { D3DDEVTYPE_HAL = 1, D3DDEVTYPE_NULLREF = 4,D3DDEVTYPE_REF = 2, D3DDEVTYPE_SW = 3,D3DDEVTYPE_FORCE_DWORD = 0xffffffff,} D3DDEVTYPE, *LPD3DDEVTYPE;
0062441B |. 6A 00 PUSH 0 Adapter : 0 for primary monitor
0062441D |. 50 PUSH EAX << IDirect3D9
0062441E |. 8B41 40 MOV EAX,DWORD PTR DS:[ECX+40] <<<< this is IDirect3D9-> STDMETHOD(CreateDevice)(THIS_ UINT Adapter,D3DDEVTYPE DeviceType,HWND hFocusWindow,DWORD BehaviorFlags,D3DPRESENT_PARAMETERS* pPresentationParameters,IDirect3DDevice9** ppReturnedDeviceInterface) PURE;
00624421 |. FFD0 CALL EAX
to find oEndScene:
Check d3d9.h IDirect3DDevice9::EndScene
to find D3D_SDK_VERSION being used in case blizz use a new SDK (almost impossible but anyway):
search aDirect3dcreate ; "Direct3DCreate9", then compare with <d3d9.h>
.text:00635871 68 48 BD A0 00 push offset aD3d9_dll ; "d3d9.dll"
.text:00635876 C7 06 00 00 00 00 mov dword ptr [esi], 0
.text:0063587C FF 15 64 52 9C 00 call ds:LoadLibraryA
.text:00635882 85 C0 test eax, eax
.text:00635884 89 07 mov [edi], eax
.text:00635886 75 07 jnz short loc_63588F
.text:00635888 68 90 CB A0 00 push offset aCgxdeviced3d9e ; "CGxDeviceD3d9Ex::ILoadD3dLib(): unable "...
.text:0063588D EB 26 jmp short loc_6358B5
.text:0063588F ; ---------------------------------------------------------------------------
.text:0063588F
.text:0063588F loc_63588F: ; CODE XREF: sub_635860+26j
.text:0063588F 68 00 BD A0 00 push offset aDirect3dcreate ; "Direct3DCreate9"
.text:00635894 50 push eax
.text:00635895 FF 15 8C A3 AD 00 call off_ADA38C
.text:0063589B 85 C0 test eax, eax
.text:0063589D 75 07 jnz short loc_6358A6
.text:0063589F 68 54 CB A0 00 push offset aCgxdeviced3d_4 ; "CGxDeviceD3d9Ex::ILoadD3dLib(): unable "...
.text:006358A4 EB 0F jmp short loc_6358B5
.text:006358A6 ; ---------------------------------------------------------------------------
.text:006358A6
.text:006358A6 loc_6358A6: ; CODE XREF: sub_635860+3Dj
.text:006358A6 6A 20 push 20h <<<<< this is the D3D_SDK_VERSION
.text:006358A8 FF D0 call eax
*/
enum Direct3D9Ptrs
{
pDevicePtr_1 = 0x00C776B8, // 3.3.2
pDevicePtr_2 = 0x397C, // 3.3.2
oEndScene = 0xA8, // 3.3.2
};
When exe starts, it follows the procedure as below:
0. "apoc_ConsoleDeviceInitialize()" at sub6FDDE0 (by searching "do hardware detection")
1. load 'd3d9.dll' on the fly in ".text:00623CD0 apoc_CGxDeviceD3d__ILoadD3dLib proc near"
2. call Direct3DCreate9(D3D_SDK_VERSION)
3. load 'd3d9.dll' again in ".text:00623CD0 apoc_CGxDeviceD3d__ILoadD3dLib proc near"
4. call Direct3DCreate9(D3D_SDK_VERSION)
5. Window created, start initializing.
5. CreateDevice() called by IDirect3D9-> VTable[0x40]
which is inside sub_624310
which is inside "CGxDeviceD3d:
eviceSetFormat(): unable to set format!"
which is called by CGxDeviceD3d->VTable[0x34]
which is inside sub_617cf0
which is inside sub_6254a0
which is called by someClass->VTable[0x28]
which is called by sub_6162d0
which is called by "apoc_ConsoleDeviceInitialize()"
back to the step 0. "apoc_ConsoleDeviceInitialize()" again.
So once consoleDeviceInitialize() is found and hooked, your dll can create D3Device before the real one starts.
ps: "->" is really the source of all evilness, as the symbol represents, it only allows tracking in one direction.