За заготовку возьмем готовый пример Wallhack от RaXoR
Код:
library lib;

{$R *.dres}

uses
  Windows,
  classes,
  SysUtils,
  advApiHook,
  Direct3D9,
  D3DX9;

{$R *.res}

var
  g_Font  : ID3DXFont;
  TextRect: TRect;
  StridesN: integer;
  Wallhack:boolean=false;
  wall : string;

var EndScene9Next : function (self: pointer): HResult stdcall = nil;
var CreateDevice9Next: function (self: pointer; Adapter: LongWord; DeviceType: TD3DDevType; hFocusWindow: HWND; BehaviorFlags: DWord; pPresentationParameters: PD3DPresentParameters; out ppReturnedDeviceInterface: IDirect3DDevice9): HResult; stdcall = nil;
var Direct3DCreate9Next: function (SDKVersion: LongWord): DWORD stdcall = nil;
var ResetNext: function (self: pointer; const pPresentationParameters: TD3DPresentParameters): HResult; stdcall;
var SetStreamSourceNext: function (self: pointer; StreamNumber: LongWord; pStreamData: IDirect3DVertexBuffer9; OffsetInBytes, Stride: LongWord): HResult; stdcall;
var DrawIndexedPrimitiveNext: function (DeviceInterface: IDirect3DDevice9; _Type: TD3DPrimitiveType; BaseVertexIndex: Integer; MinVertexIndex, NumVertices, startIndex, primCount: LongWord): HResult; stdcall;

procedure CheckPressed;
begin
if (GetAsyncKeyState(VK_NUMPAD1) and 1)<> 0 then
   begin
    wallhack:= not wallhack;
   end;
end;

procedure All_OnLostDevice;
begin
g_Font.OnLostDevice;
end;
procedure All_OnResetDevice;
begin
g_Font.OnResetDevice;
end;
function ResetCallback(self: pointer; const pPresentationParameters: TD3DPresentParameters): HResult; stdcall;
begin
All_OnLostDevice;
result:= ResetNext(self,pPresentationParameters);
if( SUCCEEDED(result) ) then
 begin
  All_OnResetDevice;
 end;
end;
function SetStreamSourceCallback(self: pointer; StreamNumber: LongWord; pStreamData: IDirect3DVertexBuffer9; OffsetInBytes, Stride: LongWord): HResult; stdcall;
begin
  StridesN := Stride;
  result  := SetStreamSourceNext(self,StreamNumber,pStreamData,OffsetInBytes, StridesN);
end;
function EndScene9Callback(self: pointer): HResult; stdcall;
begin
  CheckPressed;
  if Wallhack then wall := 'On' else wall := 'Off';
  g_Font.DrawTextW(nil,PWideChar('Walhack: '+ wall),-1,@TextRect,DT_LEFT or DT_NOCLIP,D3DCOLOR_ARGB(255,0,255,0));
  Result:=EndScene9Next(self);
end;


function DrawIndexedPrimitiveCallback(DeviceInterface: IDirect3DDevice9; _Type: TD3DPrimitiveType; BaseVertexIndex: Integer; MinVertexIndex, NumVertices, startIndex, primCount: LongWord): HResult; stdcall;
begin
if (Wallhack = true) then
    begin
     if (StridesN = 20) and (NumVertices>0) then
        begin
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
          DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
        end;
    end;
result :=  DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
end;

function CreateDevice9Callback(self: pointer; Adapter: LongWord; DeviceType: TD3DDevType; hFocusWindow: HWND; BehaviorFlags: DWord; pPresentationParameters: PD3DPresentParameters; out ppReturnedDeviceInterface: IDirect3DDevice9): HResult; stdcall;
begin
Result :=CreateDevice9Next(self,Adapter,DeviceType, hFocusWindow,BehaviorFlags,pPresentationParameters,ppReturnedDeviceInterface);
if (result = 0) then
  begin
  TextRect:=Rect(15,25,0,0);
  D3DXCreateFont(ppReturnedDeviceInterface,20,0,FW_Bold,1,false,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
                      6,DEFAULT_PITCH or FF_DONTCARE,PChar('Sylfaen'),g_Font);
  HookCode(GetInterfaceMethod(ppReturnedDeviceInterface, 42), @EndScene9Callback, @EndScene9Next);
  HookCode(GetInterfaceMethod(ppReturnedDeviceInterface, 16), @ResetCallback, @ResetNext);
  HookCode(GetInterfaceMethod(ppReturnedDeviceInterface, 100),@SetStreamSourceCallback, @SetStreamSourceNext);
  HookCode(GetInterfaceMethod(ppReturnedDeviceInterface, 82), @DrawIndexedPrimitiveCallback, @DrawIndexedPrimitiveNext);
  end
end;

function Direct3DCreate9Callback(SDKVersion: LongWord): DWORD; stdcall;
begin
  Result:=Direct3DCreate9Next(SDKVersion);
  if (Result <> 0) then
  begin
    if (@CreateDevice9Next <> nil) then
      UnhookCode(@CreateDevice9Next);
    HookCode(GetInterfaceMethod(result, 16), @CreateDevice9Callback, @CreateDevice9Next);
  end;
end;

procedure DLLEntryPoint(dwReason:DWord);
begin
  case dwReason of
    DLL_PROCESS_ATTACH:
     begin
      HookProc('d3d9.dll', 'Direct3DCreate9', @Direct3DCreate9Callback, @Direct3DCreate9Next);
     end;
    DLL_PROCESS_DETACH:
     begin
     end;
   end;
end;

begin
  DllProc:= @DLLEntryPoint;
  DLLEntryPoint(DLL_PROCESS_ATTACH);
end.

Для загрузки мы будем использовать функцию D3DXCreateTextureFromFile()
Учтите:
D3DXCreateTextureFromFile() для загрузки изображений из файлов, в качестве файлов можно задавать почти любой популярный формат (bmp, jpeg, tga, tiff и т.д.). Важно только помнить - что лучше всего использовать квадратные текстуры со стороной кратной степени двойки (2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 и т.д.).
Выглядеть это будет примерно так:
Код:
D3DXCreateTextureFromFile(Device,PWideChar(FileName), TextureName);

Поскольку в качестве Device в функции DrawIndexedPrimitiveCallback в качестве девайса у нас выступает DeviceInterface
Код:
DeviceInterface: IDirect3DDevice9;
То собственно и объявим его также в глобальных переменных проекта
Код:
Var
 DeviceInterface: IDirect3DDevice9;
В качестве FileName нужно указать имя файла и его путь:
Код:
PWideChar('yellow.bmp')
Это означает, что мы загрузим файл yellow.bmp из папки, где располагается исполнительный .exe файл игры, в который будет происходить инжект при создании процесса игры, а значит и сам файл yellow.bmp должен находится в этой папке.
По изученным выше сведениям, создаем yellow.bmp размером 4х4 (степень двойки)
и заливаем его желтым цветом. Сохраняем картинку с глубиной 24bit.
2 составные этой цепочки собраны, осталось лишь назначить текстуру, в которую будет происходить загрузка картинки.

По аналогии, назовем ее yellow
Описываем её в глобальных переменных
Код:
Var
  yellow:IDirect3DTexture9;
И в результате получаем функцию такого типа:
Код:
D3DXCreateTextureFromFile(DeviceInterface,PWideChar('yellow.bmp'), yellow);
И прописываем её в DrawIndexedPrimitiveCallback
Код:
function DrawIndexedPrimitiveCallback(DeviceInterface: IDirect3DDevice9; _Type: TD3DPrimitiveType; BaseVertexIndex: Integer; MinVertexIndex, NumVertices, startIndex, primCount: LongWord): HResult; stdcall;
begin
D3DXCreateTextureFromFile(DeviceInterface,PWideChar('yellow.bmp'), yellow);
if (wallhack = true) then
    begin
     if (StridesN = 20) and (NumVertices>0) then
        begin
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
          DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
        end;
    end;
result :=  DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
end;
Осталось присвоить текстуре с заданными StridesN и NumVertices присвоить нашу текстуру
Используем функцию SetTexture:
Код:
Deviceinterface.SetTexture(0,TextureName);
где TextureName - имя текстуры, в нашем случаем - yellow

И таким образом получаем:
Код:
function DrawIndexedPrimitiveCallback(DeviceInterface: IDirect3DDevice9; _Type: TD3DPrimitiveType; BaseVertexIndex: Integer; MinVertexIndex, NumVertices, startIndex, primCount: LongWord): HResult; stdcall;
begin
D3DXCreateTextureFromFile(DeviceInterface,PWideChar('yellow.bmp'), yellow);
if (wallhack = true) then
    begin
     if (StridesN = 20) and (NumVertices>0) then
        begin
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
          Deviceinterface.SetTexture(0,yellow);
          DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
          Deviceinterface.SetTexture(0,yellow);
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
        end;
    end;
result :=  DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
end;
Компилим, инжектим, получаем результат.
Но есть один недостаток - поскольку текстура загружается с частотой обновления экрана без перерыва, то и на выходе получаем перезаполнение памяти или серьезную просадку FPS в игре (до 1 в зависимости от времени)

Поэтому немного схитрим:
1) В глобальных переменных
Код:
Var
 r:byte;
Изменяем функцию:
Код:
function DrawIndexedPrimitiveCallback(DeviceInterface: IDirect3DDevice9; _Type: TD3DPrimitiveType; BaseVertexIndex: Integer; MinVertexIndex, NumVertices, startIndex, primCount: LongWord): HResult; stdcall;
begin
if r<=5 then 
begin
 r:=r+1; //ограничение кол-ва загрузок с запасом(на вся)
 D3DXCreateTextureFromFile(DeviceInterface,PWideChar('yellow.bmp'), yellow);
end;
if (wallhack = true) then
    begin
     if (StridesN = 20) and (NumVertices>0) then
        begin
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
          Deviceinterface.SetTexture(0,yellow);
          DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
          Deviceinterface.SetTexture(0,yellow);
          DeviceInterface.SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
        end;
    end;
result :=  DrawIndexedPrimitiveNext(DeviceInterface, _Type, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, primCount);
end;
Присваиваем счетчику начальное значение:
Код:
begin
  r:=1;
  DllProc:= @DLLEntryPoint;
  DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
Вот и всё!