Page 1 of 2

directx 9 endscene hook

Posted: Thu Jul 28, 2011 3:04 am
by xorc1zt
this code is a dll who hook endscene() function from direct3d

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
The code work with Far Cry 2 and should work with any dx9 games. To inject the dll i use Winject 1.7

Re: directx 9 endscene hook

Posted: Sat Jul 30, 2011 8:29 pm
by Shield
Hi

Wanted to test your code for the whole week but couldn't until now.
It works great! Thanks for sharing that code, great example on how to do such things,
very interesting! :)

Re: directx 9 endscene hook

Posted: Sat Aug 06, 2011 8:12 pm
by Machiavelli
But how to draw some text?

Re: directx 9 endscene hook

Posted: Sun Aug 07, 2011 5:06 am
by xorc1zt
after endscene is hook you got the device pointer from arguments

Code: Select all

Procedure myEndscene(*adevice)
  ;first argument is the device address
  *device=*adevice ;
u can do everything with the device like create a new font with D3DXCreateFont

Re: directx 9 endscene hook

Posted: Mon Aug 08, 2011 9:24 am
by Zach
Neat subject, I won't really pretend to understand it... But may I ask what a practical application of this code would be?

Re: directx 9 endscene hook

Posted: Mon Aug 08, 2011 11:00 am
by xorc1zt
softwares like teamspeak, xfire, mumble or steam are detouring directx to add a overlay into any games. Fraps doing the same to be able to record videos.

Re: directx 9 endscene hook

Posted: Mon Aug 08, 2011 1:46 pm
by Zach
I think I understand. Thanks

Re: directx 9 endscene hook

Posted: Mon Aug 08, 2011 3:58 pm
by xorc1zt
Detouring is modifying the first bytes of a function, we write a jump to our function who will jump back to the first one.

this schema show how work the detour method is used here
Image

Re: directx 9 endscene hook

Posted: Tue Aug 09, 2011 12:03 pm
by Comtois
xorc1zt wrote:To inject the dll i use Winject 1.7
Or you can use this code, it work fine., i have tested with your dll and your example :)

Code: Select all

; Code de SFSxOI
; Injecter une Dll dans un exécutable

Prototype.i PFNCreateToolhelp32Snapshot(dwFlags.i, th32ProcessID.i) ;
Prototype.b PFNProcess32First(hSnapshot.i, *lppe.PROCESSENTRY32) ;
Prototype.b PFNProcess32Next(hSnapshot.i, *lppe.PROCESSENTRY32) ;

Procedure GetPidByName(p_name$)
    Protected hDLL.i, process_name$
    Protected PEntry.PROCESSENTRY32, hTool32.i
    Protected pCreateToolhelp32Snapshot.PFNCreateToolhelp32Snapshot
    Protected pProcess32First.PFNProcess32First
    Protected pProcess32Next.PFNProcess32Next
    Protected pid.i
   
    hDLL = OpenLibrary(#PB_Any,"kernel32.dll")
   
    If hDLL
        pCreateToolhelp32Snapshot = GetFunction(hDLL,"CreateToolhelp32Snapshot")
        pProcess32First = GetFunction(hDLL,"Process32First")
        pProcess32Next = GetFunction(hDLL,"Process32Next")
    Else
        ProcedureReturn 0
    EndIf
   
    PEntry\dwSize = SizeOf(PROCESSENTRY32)
    hTool32 = pCreateToolhelp32Snapshot(#TH32CS_SNAPPROCESS, 0)
    pProcess32First(hTool32, @PEntry)
    process_name$ = Space(#MAX_PATH)
    CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH)
   
    If  UCase(process_name$) = UCase(p_name$)
        ProcedureReturn PEntry\th32ProcessID
    EndIf
   
    While pProcess32Next(hTool32, @PEntry) > 0
        process_name$ = Space(#MAX_PATH)
        CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH)
       
        If  UCase(process_name$) = UCase(p_name$)
            ProcedureReturn PEntry\th32ProcessID
        EndIf
   
    Wend
   
    CloseLibrary(hDLL)
   
    ProcedureReturn 0
EndProcedure

Procedure InjectLibA(dwProcessId.i, pszLibFile$)
  hProcess.i
  hThread.i
  lzLibFileRemote.i
  lSize.i
  endSize.i
  lsThreadRtn.i

  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId)

  If hProcess = 0 : Goto ErrHandle : EndIf
  lSize = 1 + Len(pszLibFile$)
  endSize = lSize

  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE)

  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf

  If (WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) = 0) : Goto ErrHandle : EndIf

  OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryA") : CloseLibrary(0)

  If lsThreadRtn = 0 : Goto ErrHandle : EndIf

  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null)

  If (hThread = 0) : Goto ErrHandle : EndIf

  WaitForSingleObject_(hThread, #INFINITE)

  If lzLibFileRemote<>0
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE)
    MessageRequester("Inject Status", "Injection Suceeded", 0)
    Else
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE)
    MessageRequester("Inject Status", "Injection Failed !!!", 0)
  EndIf
  End

  ErrHandle:
      CloseHandle_(hThread)
      CloseHandle_(hProcess)
EndProcedure

Input_proc$ = InputRequester("Simple DLL injector", "Please enter target process name (.exe):", "") ;enter process name i.e...notepad.exe
val_pid.i = GetPidByName(Input_proc$)
Delay(10)
File_dll$ = OpenFileRequester("Choose .dll file to inject", "C:\", "DLL File (*.dll)|*.dll;*.dll", 0)
Delay(10)
InjectLibA(val_pid, File_dll$)

Re: directx 9 endscene hook

Posted: Tue Aug 09, 2011 1:44 pm
by graph100
c'est pas dangereux ça ?

How do you know the entrie point of the dll you are injecting ? You just have to put the dll inside the executing exe and it works ?

Re: directx 9 endscene hook

Posted: Wed Aug 10, 2011 1:26 am
by Machiavelli
xorc1zt wrote:after endscene is hook you got the device pointer from arguments

Code: Select all

Procedure myEndscene(*adevice)
  ;first argument is the device address
  *device=*adevice ;
u can do everything with the device like create a new font with D3DXCreateFont
I tried, but the target app is crashes everytime.
Is D3DXCreateFont in d3d9.dll and should i just call it, or D3DXCreateFontA?

Re: directx 9 endscene hook

Posted: Wed Aug 10, 2011 9:42 am
by xorc1zt
D3DXCreateFont is from D3DX9 Api (d3dx9.lib)

From msdn

Code: Select all

HRESULT D3DXCreateFont(
  __in   LPDIRECT3DDEVICE9 pDevice,
  __in   INT Height,
  __in   UINT Width,
  __in   UINT Weight,
  __in   UINT MipLevels,
  __in   BOOL Italic,
  __in   DWORD CharSet,
  __in   DWORD OutputPrecision,
  __in   DWORD Quality,
  __in   DWORD PitchAndFamily,
  __in   LPCTSTR pFacename,
  __out  LPD3DXFONT *ppFont
);
The compiler setting also determines the function version. If Unicode is defined, the function call resolves to D3DXCreateFontW. Otherwise, the function call resolves to D3DXCreateFontA because ANSI strings are being used.
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

you must use D3DXCreateFontW for unicode or D3DXCreateFontA for ascii

Import of D3DXCreateFontA

Code: Select all

Import "lib\d3dx9.lib" ; DirectX SDX
  D3DXCreateFontA(*pDevice, Height.i, Width.l, Weight.l, MipLevels.l, Italic.b, CharSet.l, OutputPrecision.l, Quality.l, PitchAndFamily.l, *pFacename, *ppFont)
EndImport
Creation of the font

Code: Select all

*testfont.ID3DXFont
name.s = "Courrier New"
D3DXCreateFontA(*D3DDevice, 12, 0,0,1,0, #DEFAULT_CHARSET, #OUT_DEFAULT_PRECIS, #DEFAULT_QUALITY, #DEFAULT_PITCH, @name,@*testfont)
to draw text you must call drawtext()

Code: Select all

INT DrawText(
  [in]  LPD3DXSPRITE pSprite,
  [in]  LPCTSTR pString,
  [in]  INT Count,
  [in]  LPRECT pRect,
  [in]  DWORD Format,
  [in]  D3DCOLOR Color
);
This method must be called inside a BeginScene ... EndScene block. The only exception is when an application calls DrawText with DT_CALCRECT to calculate the size of a given block of text.
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

First you must create a new rectangle

Code: Select all

textrect.RECT
textrect\left= 10 ; X
textrect\top= 10 ; Y
Then calculate the size of the rectangle with DrawText and DT_CALCRECT as parameter
DT_CALCRECT

Determines the width and height of the rectangle. If there are multiple lines of text, DrawText uses the width of the rectangle pointed to by the pRect parameter and extends the base of the rectangle to bound the last line of text. If there is only one line of text, DrawText modifies the right side of the rectangle so that it bounds the last character in the line. In either case, DrawText returns the height of the formatted text but does not draw the text.

Code: Select all

*testfont\DrawTextA(NULL, "HelloWorld", -1, textrect, #DT_CALCRECT | #DT_LEFT, NULL)
Debug textrect\right
Debug textrect\bottom
and finally draw the text

Code: Select all

   *D3DDevice\Clear(0, 0, #D3DCLEAR_TARGET, D3DRGBA(0,0,0,255), 0.0, 0) 
   *D3DDevice\BeginScene()
   *testfont\DrawTextA(NULL, "HelloWorld", -1, textrect, #DT_LEFT, D3DRGBA(0,0,255,255))
   *D3DDevice\EndScene()
   *D3DDevice\Present(NULL, NULL, NULL, NULL)
You can't use RGBA() with directx, here is a compatible macro

Code: Select all

Macro D3DRGBA (r, g, b, a)
  (a&$ff)<<24 | (r&$ff)<<16 | (g&$ff)<<8 | (b&$ff)
EndMacro

Re: directx 9 endscene hook

Posted: Fri Jan 06, 2012 1:04 pm
by rincewind
So whats wrong with this code?

Code: Select all

del
UPD:
Anyway, punkbuster kicks me using this method.
Does anyone know how is overlay works in Mumble or can translate it to PB?

Re: directx 9 endscene hook

Posted: Sat Sep 14, 2013 5:10 am
by Liqu
would someone please update the code to PB 5?
since i get syntax error :(

i want to create an overlay menu inside directx game ( like warcraft, cod, bf3 , etc ) like steam did, an example to create it will be very helpful

thank you :)

Re: directx 9 endscene hook

Posted: Wed Sep 18, 2013 5:40 pm
by Liqu
Code Updated to PB 5.20 by Demivec

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 = 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

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 = 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

even the code has been updated, i don't know how to use it :oops:

i've compile the dll to testdll.dll then launch the second code, open war3.exe ( warcraft 3 ), use Injecter une Dll dans un exécutable by SFSxOI then nothing happened, no green screen
i also tried open war3.exe, use injector, open second code, but nothing happened too.

really need enlightment :)