the dll is doing
1. create a direct3d device, scan the virtual table to get the functions address then delete the device (being useless)
2. hook d3d endcene() address, we write a JMP to our function
3. we grab the device address from endscene arguments and use it to draw anythings
Code: Select all
; DirectX 9 Hook
; xorc1zt
#D3DFMT_A8R8G8B8=21
#D3DPOOL_SCRATCH=3
#D3DADAPTER_DEFAULT=0
#D3DDEVTYPE_HAL=1
#D3DDEVTYPE_NULLREF=4
#D3DDEVTYPE_REF=2
#D3DDEVTYPE_SW=3
#D3DDEVTYPE_FORCE_DWORD=$ffffffff
#D3DCREATE_SOFTWARE_VERTEXPROCESSING=$00000020
#D3DCREATE_HARDWARE_VERTEXPROCESSING=$00000040
#D3D_SDK_VERSION=32
#D3DSWAPEFFECT_DISCARD=1
#D3DFMT_UNKNOWN=0
#D3DXIFF_BMP=0
#D3DCLEAR_TARGET=1
#ENDSCENE = 42
Structure D3DPRESENT_PARAMETERS
BackBufferWidth.i
BackBufferHeight.i
BackBufferFormat.i
BackBufferCount.i
MultiSampleType.i
MultiSampleQuality.l
SwapEffect.i
hDeviceWindow.i
Windowed.i
EnableAutoDepthStencil.i
AutoDepthStencilFormat.i
Flags.l
FullScreen_RefreshRateInHz.i
PresentationInterval.i
EndStructure
Global *g_pD3D.IDirect3D9
Global *g_pd3dDevice.IDirect3DDevice9
Global Dim dxfuncsaddress.l(0)
Global *endscene
Global *backtoendscene
Global *device.IDirect3DDevice9
Procedure grabvtable()
OpenWindow(0,0,0,300,300, "hello")
d3dpp.D3DPRESENT_PARAMETERS
d3dpp\Windowed=#True
d3dpp\SwapEffect=#D3DSWAPEFFECT_DISCARD
d3dpp\BackBufferFormat=#D3DFMT_UNKNOWN
d3dpp\BackBufferWidth=320
d3dpp\BackBufferHeight=240
d3dpp\hDeviceWindow=WindowID(0)
OpenLibrary(0,"d3d9.dll")
*g_pD3D=CallFunction(0,"Direct3DCreate9",#D3D_SDK_VERSION)
*g_pD3D\CreateDevice(#D3DADAPTER_DEFAULT,#D3DDEVTYPE_HAL,0,#D3DCREATE_HARDWARE_VERTEXPROCESSING,@d3dpp,@*g_pd3dDevice)
*vtable.l = PeekL(*g_pd3dDevice) ; store the address of the vtable
ConsoleColor(7, 0)
Print("D3D Address = ")
ConsoleColor(4, 0)
PrintN("0x" + Hex(*g_pD3D))
ConsoleColor(7, 0)
Print("D3D Device Address = ")
ConsoleColor(4, 0)
PrintN("0x" + Hex(*g_pd3dDevice))
ConsoleColor(7, 0)
Print("D3D VTable Address = ")
ConsoleColor(4, 0)
PrintN("0x" + Hex(*vtable))
PrintN("")
PrintN("")
ConsoleColor(7, 0)
PrintN("VTABLE Functions Address:")
boucle.i=0
vtablefuncaddress.l = PeekL(*vtable) ; read the first address of the vtable
While(vtablefuncaddress) ; read each address till end of the vtable
;Debug Str(boucle) + " " + Hex(vtablefuncaddress) + " +" + Str(boucle*4)
ConsoleColor(7, 0)
Print(Str(boucle))
ConsoleColor(4, 0)
Print(" 0x" + Hex(vtablefuncaddress))
ConsoleColor(2, 0)
PrintN(" +" + Hex(boucle*4))
dxfuncsaddress(boucle)=vtablefuncaddress
boucle+1
ReDim dxfuncsaddress(boucle)
vtablefuncaddress = PeekL(*vtable+(boucle*4))
Wend
ConsoleColor(7, 0)
PrintN("VTable End")
*g_pd3dDevice\Release()
*g_pD3D\Release()
CloseWindow(0)
EndProcedure
Procedure myEndscene(*adevice)
;first argument is the device address
*device=*adevice ;
;we save the registers and flags
PUSHAD
PUSHFD
;we do our stuff
ConsoleColor(7, 0)
PrintN("myEndscene called!")
*device\Clear(0, 0, #D3DCLEAR_TARGET, RGBA(0,255,0,0), 0.0, 0)
;we restore the registers and flags
POPFD
POPAD
;POP ebx
;here is the original endscene first bytes
MOV edi,edi
PUSH EBP
MOV EBP, ESP
;we jump back to endscene
JMP *backtoendscene
EndProcedure
;First bytes of endscene should be this
; 6B0A279F 8BFF MOV EDI,EDI
; 6B0A27A1 55 PUSH EBP
; 6B0A27A2 8BEC MOV EBP,ESP
; 6B0A27A4 6A FF PUSH -1
Procedure.i EndsceneHOOK()
protection.w
*endscene = dxfuncsaddress(#ENDSCENE)
JMPaddr.l = (@myEndscene() - *endscene)-5
ConsoleColor(7, 0)
Print("Endscene (")
ConsoleColor(4, 0)
Print("0x"+Hex(dxfuncsaddress(#ENDSCENE)))
ConsoleColor(7, 0)
Print(") : ")
ConsoleColor(14, 0)
Print(Hex(PeekA(*endscene))+" ")
Print(Hex(PeekA(*endscene+1))+" ")
Print(Hex(PeekA(*endscene+2))+" ")
Print(Hex(PeekA(*endscene+3))+" ")
Print(Hex(PeekA(*endscene+4))+" ")
Print(Hex(PeekA(*endscene+5))+" ")
PrintN(Hex(PeekA(*endscene+6))+" ")
ConsoleColor(7, 0)
Print("Writting a jump to myEndscene (")
ConsoleColor(4, 0)
Print("0x"+Hex(@myEndscene()))
ConsoleColor(7, 0)
PrintN(")")
; make the target writable, write our jump and restore the protection.
VirtualProtect_(*endscene, 5, #PAGE_EXECUTE_READWRITE, @protection)
PokeA(*endscene,$E9)
PokeL(*endscene+1, JMPaddr)
VirtualProtect_(*endscene, 5, protection, @protection )
ConsoleColor(7, 0)
Print("Endscene (")
ConsoleColor(4, 0)
Print("0x"+Hex(dxfuncsaddress(#ENDSCENE)))
ConsoleColor(7, 0)
Print(") : ")
ConsoleColor(14, 0)
Print(Hex(PeekA(*endscene))+" ")
Print(Hex(PeekA(*endscene+1))+" ")
Print(Hex(PeekA(*endscene+2))+" ")
Print(Hex(PeekA(*endscene+3))+" ")
Print(Hex(PeekA(*endscene+4))+" ")
Print(Hex(PeekA(*endscene+5))+" ")
PrintN(Hex(PeekA(*endscene+6))+" ")
*backtoendscene = *endscene+5
ConsoleColor(7, 0)
Print("myEndscene will Jump back to ")
ConsoleColor(4, 0)
PrintN("0x"+Hex(*backtoendscene))
PrintN("")
PrintN("")
EndProcedure
Procedure MyThread()
grabvtable()
EndsceneHOOK()
EndProcedure
ProcedureDLL AttachProcess(Instance)
OpenConsole()
ConsoleTitle("D3D Hook")
CreateThread(@MyThread(),1)
EndProcedure
ProcedureDLL DetachProcess(Instance)
CloseConsole()
EndProcedure
ProcedureDLL AttachThread(Instance)
EndProcedure
ProcedureDLL DetachThread(Instance)
EndProcedure
A little executable code to test the dll, after the dll got injected the screen should turn green.
Code: Select all
#D3DFMT_A8R8G8B8=21
#D3DPOOL_SCRATCH=3
#D3DADAPTER_DEFAULT=0
#D3DDEVTYPE_HAL=1
#D3DDEVTYPE_NULLREF=4
#D3DDEVTYPE_REF=2
#D3DDEVTYPE_SW=3
#D3DDEVTYPE_FORCE_DWORD=$ffffffff
#D3DCREATE_SOFTWARE_VERTEXPROCESSING=$00000020
#D3DCREATE_HARDWARE_VERTEXPROCESSING=$00000040
#D3D_SDK_VERSION=32
#D3DSWAPEFFECT_DISCARD=1
#D3DFMT_UNKNOWN=0
#D3DXIFF_BMP=0
#D3DCLEAR_TARGET=1
Global Dim dxfuncsaddress.l(0)
Procedure test()
Debug test
EndProcedure
Structure D3DPRESENT_PARAMETERS
BackBufferWidth.i
BackBufferHeight.i
BackBufferFormat.i
BackBufferCount.i
MultiSampleType.i
MultiSampleQuality.l
SwapEffect.i
hDeviceWindow.i
Windowed.i
EnableAutoDepthStencil.i
AutoDepthStencilFormat.i
Flags.l
FullScreen_RefreshRateInHz.i
PresentationInterval.i
EndStructure
*g_pD3D.IDirect3D9
*g_pd3dDevice.IDirect3DDevice9
OpenWindow(0,0,0,300,300,"Direct3D Tutorial 01: CreateDevice",#WS_OVERLAPPEDWINDOW | 1)
d3dpp.D3DPRESENT_PARAMETERS
d3dpp\Windowed=#True
d3dpp\SwapEffect=#D3DSWAPEFFECT_DISCARD
d3dpp\BackBufferFormat=#D3DFMT_UNKNOWN
d3dpp\BackBufferWidth=320
d3dpp\BackBufferHeight=240
d3dpp\hDeviceWindow=WindowID(0)
r = OpenLibrary(0,"d3d9.dll")
*g_pD3D=CallFunction(0,"Direct3DCreate9",#D3D_SDK_VERSION)
*g_pD3D\CreateDevice(#D3DADAPTER_DEFAULT,#D3DDEVTYPE_HAL,0,#D3DCREATE_HARDWARE_VERTEXPROCESSING,@d3dpp,@*g_pd3dDevice)
*vtable.l = PeekL(*g_pd3dDevice) ; store the address for the vtable
Debug "D3DCreate at 0x"+Hex(*g_pD3D)
Debug "Device at 0x"+Hex(*g_pd3dDevice)
Debug "Vtable at 0x" + Hex(PeekL(*g_pd3dDevice))
boucle.i=0
vtablefuncaddress.l = PeekL(*vtable) ; read the first address of the vtable
While(vtablefuncaddress) ; read each address till end of the vtable
Debug Str(boucle) + " " + Hex(vtablefuncaddress) + " +" + Str(boucle*4)
boucle+1
vtablefuncaddress = PeekL(*vtable+(boucle*4))
Wend
Repeat
*g_pd3dDevice\Clear(0, 0, #D3DCLEAR_TARGET, RGBA(255,0,0,0), 0.0, 0)
*g_pd3dDevice\BeginScene()
*g_pd3dDevice\EndScene()
*g_pd3dDevice\Present(NULL, NULL, NULL, NULL)
Until WaitWindowEvent()=#PB_Event_CloseWindow
End