Tutorial Direct3D9 Hooking / DirectX Hook - Need For Speed: Most Wanted

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

timb3r

Semi-Retired
Dank Tier VIP
Jul 15, 2018
767
22,668
47
This is a two part tutorial, you will find part 2 below this post.

nfsmw-header-1.jpg


Introduction

So while doing research for DirectX VTable hooking I encountered a stumbling block due the unique way some games implement the DirectX interface. I'll revisit it later however for the moment I'm going to present a generic way for hooking DirectX used in projects like DXWrapper.

So many days pouring over binary code I think I even saw a 2!

Originally this tutorial was going to be a simple resolution hack for Need For Speed: Most Wanted, but when I was scouring the internet looking for information it was quite difficult to get the answers I needed. So rather than just dump a bit of information on the net I'm going to put out a detailed tutorial covering a lot of the basics of game hacking which will cover the following:
  • Hooking DirectX 9
  • Modifying the game resolution
  • Drawing a rectangle to the screen
  • Drawing text to the screen
  • Drawing an image to the screen
  • Hooking keyboard input
  • Adding a money hack
  • Adding some polish
I've created a Visual Studio template (attached to post) which will allow you to avoid most of the grunt work involved. It will set your project up correctly so all you need to do is start adding your code.

You'll need to place the zip in this folder to allow you to create a new project:

C:\Users\Username\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual C++ Project
Then when you create a new project you should be able to select it:
2018-08-17-153213_1366x768_scrot.png


I still recommend reading through the tutorial step by step if you've never done DX hooking before. However if your goal is to get running as quickly as possible just download the template.

Hooking DirectX 9

If you've read my ProxyDLL tutorial you'll probably have the basic understanding of how a ProxyDLL might work but not how to go about implementing it. To quickly cover what happens when you launch a game: the operating system reads the executable's Import Address Table (IAT), locates the DLL and calls LoadLibrary on it.

If the DLL is not stored in this registry key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

The OS will then follow this search order:
  1. The directory from which the application loaded.
  2. The system directory. Use the GetSystemDirectory function to get the path of this directory.
  3. The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
  4. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
  5. The current directory.
  6. The directories that are listed in the PATH environment variable.
If we place our DLL in the directory with the name "d3d9.dll" we can get the application to load our DLL instead of the actual DLL which lives in the system32 directory of the windows folder.

We then need to wrap or proxy the exports of d3d9.dll to allow the game to run correctly. So lets go do that.

The Code

Make sure you have the Direct X 9 SDK installed first. Create a new empty project in Visual Studio and go to the project properties. First make sure the output is set to DLL and the output name should be d3d9.


Build Settings


Then make sure the SDK path is correctly setup. Goto VC++ Directories and add the SDK variable to list $(DXSDK_PATH).

Direct X SDK Path


Add a new source file and and type in a DllMain entry point. Make sure to include the directx headers and libraries:

C++:
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

#include <d3d9.h>
#include <d3dx9.h>
Now we need to define Direct3DCreate9.

C++:
IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) {
    return NULL;
}
Now we need to add a defs file to the project so we can export our hooked function (Inside the solution explorer Right Click -> Add -> New Item):

Place the following inside the newly created defs file:

LIBRARY d3d9
EXPORTS
Direct3DCreate9
So now our DLL will be loaded without error into the target process. If you place a MessageBox inside your DllMain and place the compiled DLL into the game folder you should get a popup before the game crashes out:


timb3r's directx hook



In order to get the game to continue loading we need to return a valid pointer to IDirect3D9 to allow the game to draw to the screen. To do this we will load the original d3d9.dll and call it's Direct3DCreate9 to get a valid pointer.

First we need to define the typedef for the target function:

C++:
typedef IDirect3D9* (WINAPI * FND3DC9)(UINT);
FNC3DC9 Direct3DCreate9_out;
Now we can load the library and resolve the address:

C++:
TCHAR szDllPath[MAX_PATH] = { 0 };

GetSystemDirectory(szDllPath, MAX_PATH);

// We have to specify the full path to avoid the search order
lstrcat(szDllPath, "\\d3d9.dll");
HMODULE hDll = LoadLibrary(szDllPath);

if(hDll == NULL)
{
    return FALSE;
}

// Pointer to the original function
Direct3DCreate9_out = (FND3DC9)GetProcAddress(hDll, "Direct3DCreate9");
if(Direct3DCreate9_out == NULL)
{
   FreeLibrary(hDll);
   return FALSE;
}
Now update our hook function:

C++:
IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) {
    return Direct3DCreate9_out(SDKVersion);
}
If you rebuild the project and copy the DLL to the game's directory it should now load without any issue.

Now that we have a pointer to IDirect3D9 we can manipulate the target application however we like. Unfortunately hooking DX isn't as simple as that as we're going to need to wrap two main classes to get the power we need to make the modifications we want.

The two classes we need to wrap are IDirect3D9 and IDirect3DDevice9. This will allow us to hook CreateDevice and EndScene respectively. I'll provide the source files for the two wrapper classes as typing it out by hand is both time consuming and pretty boring.

You can download them here.

Insert the files into your project and include them in the main source file. All we need to do now is modify our hook to dump the pointer into our wrapper class:

C++:
IDirect3D9* WINAPI Direct3DCreate9(UINT SDKVersion) {
    return new f_IDirect3D( Direct3DCreate9_out(SDKVersion) );
}
In order to keep the code clean so save jumping between files constantly we're create a couple of relay functions so we can do all of coding in the main source file.

Define two new function prototypes in the d3d9.h header:

C++:
void HookEndScene(IDirect3DDevice9 *f_pD3DDevice);
void HookCreateDevice(D3DPRESENT_PARAMETERS *pPresentationParameters);
Locate CreateDevice() and place a call to our relay function near the top:

C++:
HookCreateDevice(pPresentationParameters);
Do the same for EndScene:

C++:
HookEndScene(f_pD3DDevice);
Add the main function bodies inside our main source file and compile. Everything should compile without error and we're ready to make our resolution hack.

Modifying the game resolution

To do this we need to understand a bit of background on how CreateDevice works. CreateDevice takes a number of parameters but the parameter we're interested in is D3DPRESENT_PARAMETERS *pPresentationParameters.

D3DPRESENT_PARAMETERS contains the following information:

C++:
  UINT                BackBufferWidth;
  UINT                BackBufferHeight;
  D3DFORMAT           BackBufferFormat;
  UINT                BackBufferCount;
  D3DMULTISAMPLE_TYPE MultiSampleType;
  DWORD               MultiSampleQuality;
  D3DSWAPEFFECT       SwapEffect;
  HWND                hDeviceWindow;
  BOOL                Windowed;
  BOOL                EnableAutoDepthStencil;
  D3DFORMAT           AutoDepthStencilFormat;
  DWORD               Flags;
  UINT                FullScreen_RefreshRateInHz;
At the moment we care about 4 parameters: BackBufferWidth, BackBufferHeight, hDeviceWindow and Windowed. We're going to modify these values in memory to whatever values we like.

On my laptop it's native resolution is 1366x768 (because it's a piece of shit) so we'll use this, however you can substitute this value to your native resolution.

Inside our HookCreateDevice function we add the following code:

C++:
pPresentationParameters->BackBufferWidth  = 1366;
pPresentationParameters->BackBufferHeight = 768;
pPresentationParameters->BackBufferFormat = D3DFMT_X8R8G8B8;
pPresentationParameters->Windowed         = TRUE;

SetWindowLongPtr(p->hDeviceWindow, GWL_STYLE, WS_POPUP);
SetWindowPos(p->hDeviceWindow, HWND_TOP, 0, 0, 1366, 768, SWP_NOZORDER | SWP_SHOWWINDOW);
So now when the game runs whatever values it specifies will be overwritten with our values, allowing us to modify the resolution at will.

But hold on our game still looks weird:
CreateDevice bug



This is because we need to modify the viewport. Because the viewpoint is still being created with the old resolution the game is rendering the image incorrectly.

To fix this we'll create another relay this time for the SetViewport function.

C++:
void HookSetViewport(D3DVIEWPORT9 *vp)
{
    vp->Width = 1366;
    vp->Height = 768;

    return;
}
Now place the relay function inside SetViewport and give it another test. Our game now looks better.

Drawing a rectangle to the screen

Now that we've fixed the game resolution we can move onto something more fun. We're going to draw a simple rectangle to the screen. This part is pretty simple so let's make it more interesting by doing some alpha shading to make it look nice.

Inside our hooked EndScene function we're going to call Clear(). Clear allows you to draw on the screen using a given rectangle. So we begin by defining two rectangles, one will function like a border and the other will function as the background.

C++:
D3DRECT backgroundRect = { 1, 1, 400 /*width*/, 80 /*height*/};

D3DRECT borderRect = { backgroundRect.x1 - 1,
                       backgroundRect.y1 - 1,
                       backgroundRect.x2 + 1,
                       backgroundRect.y2 + 1 };
Now you can simply call Clear like so:

C++:
pD3DDevice->Clear(1, &borderRect, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 0, 0);
pD3DDevice->Clear(1, &backgroundRect, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 0, 0);
Now you should have a cool looking box with a red border around it.

Drawing text to the screen

It was surprisingly difficult to find a way to just "make this work". While prototyping this I had all sorts of issues with this code flat-out breaking or just failing for some obscure reason.

In order to draw text on the screen we first need to create the font with D3DXCreateFont then we can use the pointer it returns to call DrawFont(). There's a few caveats with this. You need to make sure that d3dx9_42.dll is loaded into the target process. With Need For Speed this shouldn't be an issue as I've tested this code dozens of times without issue, however if you're finding that some game is crashing out when you attempt to draw text try forcibly loading d3dx9_42.dll and calling the API directly (especially if you're using a VTable hook or something similar).

Inside your create device function add this line:

C++:
D3DXCreateFont(pD3DDevice, 24 /*Font size*/, 0 /*Font width*/, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 0, DEFAULT_PITCH | FF_DONTCARE, "Consolas", &pFont);
Substitute the font name for any valid font you have on your system. pFont is a variable declared as ID3DXFont *pFont.

Inside your EndScene function you can now call DrawFont like so:

C++:
RECT rc = { 5, 5, 0, 0 };
pFont->DrawText(NULL, "timb3r", -1, &rc, DT_LEFT|DT_NOCLIP, D3DCOLOR_XRGB(220, 0, 0));
The RECT defines the rectangle for drawing the text. If you don't care about clipping you can simply use the first two parameters as x,y coords and pass the DT_NOCLIP parameter to the DrawText Function, otherwise the other two parameters define the bottom and right location of the rectangle.

D3DCOLOR_XRGB defines a color using RGB values, in the example I'm using a red color value of 220.

And that's it. If you run the example you should see the text appearing in the top left with the text size, font face and value you specified.

Drawing an image to the screen

Looks good so far we have our box and text drawn to the screen but let's give it a bit of a flourish to make it look even better! Start by tracking down a transparent PNG we can use as a logo. You can use a website like IconArchive for this purpose.

Once you've chosen your respective picture add it as a resource into your project. Make a note of what name it's given or what you've called it, in my case it was called IDB_PNG1.

Inside your initialization function you need to locate the resource and load it into memory. We need to call a few different functions to achieve this. First we start by locating the resource:

C++:
HRSRC hResourceHandle = FindResource(hInstance, MAKEINTRESOURCE(IDB_PNG1), L"PNG");
Then we need to get the size of the resource like so:

C++:
DWORD nImageSize = SizeofResource(hInstance, hResourceHandle);
Then we need load the resource:

C++:
HGLOBAL hResourceInstance = LoadResource(hInstance, hResourceHandle);
Then we load it into memory like so:

C++:
LPVOID pResourceData = LockResource(hResourceInstance);
Once we have our resource loaded into memory we can draw it using DirectX.

C++:
LPDIRECT3DTEXTURE9 imageTexture;
LPD3DXSPRITE spriteImage;
D3DXVECTOR3 imagePos = {50, 50, 0};
// .... ///
// This code goes inside your CreateDevice function
D3DXCreateTextureFromFileInMemory(pD3DDevice, pResourceData, nImageSize, &imagetex);
D3DXCreateSprite(pD3DDevice, &spriteImage);
Inside your EndScene function we need to draw the image:

C++:
spriteImage->Begin(D3DXSPRITE_ALPHABLEND); // Support alpha blending
    spriteImage->Draw(imageTexture, NULL, NULL, &imagePos, D3DCOLOR_ARGB(255,255,255,255));
spriteImage->End();
With a bit of luck you should now see your png drawn on the screen in all it's glory! But what if it's too big? We luckily we can easily scale images using the DX library.

First we define some variables:

C++:
D3DXMATRIX   mTransform;
D3DXVECTOR2  mScale;
Now we'll set our scale factor:

C++:
mScale.x = 0.5f; // Half size
mScale.y = 0.5f; //

// Perform the transform
D3DXMatrixTransformation2D(&mTransform, NULL, 0.0, &mScale, NULL, NULL, &D3DXVERTOR2(0,0));
Now we can apply the transform to our sprite:

C++:
spriteImage->Begin(D3DXSPRITE_ALPHABLEND); // Support alpha blending
    sprite->SetTransform(&mTransform);
    sprite->Draw(imageTexture, NULL, NULL, &imagePos, D3DCOLOR_ARGB(255,255,255,255));
spriteImage->End();
Aaand done!

Hooking keyboard input

Originally I thought this was going to require hooking DirectInput however there's a really simple way to do this with window subclassing. If you'll recall on of the parameters stored in D3DPRESENT_PARAMETERS was hDeviceWindow.

Taking a look at the SetWindowSubclass function we can see all we need is two parameters to make it work. A handle to the desired window and an function address of our subclass proc.

Update your CreateDevice function to include this line:

C++:
SetWindowSubclass(pPresentationParameters->hDeviceWindow, SubclassWindowProc, (UINT_PTR)0, (DWORD_PTR)0);
Now define the subclass function:

C++:
LRESULT CALLBACK SubclassWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    switch (uMsg) {

        case WM_KEYDOWN:
        {

        }
        break;
    }

    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Now we're hooking the window's message proc so we can grab any standard WM message from the queue and process it (without interfering with main window procedure).

If you check msdn you'll see that WM_KEYDOWN stores the pressed key in the WPARAM parameter. Update your code to check for your desired key (preferably pick something that wont trigger an event in game).


C++:
case WM_KEYDOWN:
{
    if(wParam == '1') {
        // Do something here
    }

}
break;
And that's it! You can add whatever additional functionality you like! Here's a list of Virtual Key Codes for your reference.

To be continued

This tutorial got out of hand very quickly! I'm going to break it here and continue on with the remainder in part 2. I should have it up in a few days! Stay tuned!
 

Attachments

Last edited by a moderator:

timb3r

Semi-Retired
Dank Tier VIP
Jul 15, 2018
767
22,668
47
Part 2

nfsmw-header-1.jpg


Introduction

Let's continue on from the previous tutorial. We have all the basic components we need to make a professional looking hack. Using the code we've built so far lets create a simple hack that when activated will add $30,000 to the player's money.

We'll also add a bit of animation and some sound effects to make it really pop!

Program flow
  1. Call the startup function and load our assets
  2. Perform our DirectX initalisation
  3. Locate a pointer to the money value in memory
  4. Hook keyboard input to fire our function
  5. Modify the player's money and visually alert the user
If you're using my template from the previous tutorial we're going to have to perform some minor modifications. We're going to delete the HookCreateDevice function and replace it with two separate ones.

Open d3d9.h and define two new functions:

C++:
void HookPreCreateDevice(D3DPRESENT_PARAMETERS *pPresentationParameters);
void HookPostCreateDevice(IDirect3DDevice9 *pDevice);
As you can probably guess each function will be called just before and just after the CreateDevice call.

Open up d3d9.cpp and locate CreateDevice:

C++:
// ...
HookPreCreateDevice(pPresentationParameters);

HRESULT hResult = f_pD3D->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
HookPostCreateDevice(*ppReturnedDeviceInterface);

return hResult;
// ...
Add the new code here. Now we have two new hooks that will allow us to modify data before and after the CreateDevice call.

HookPreCreateDevice should be used to modify anything you need prior and HookPostCreateDevice should be used to create your Direct X objects.

We're going to need the following variables defined:

C++:
HINSTANCE g_hInstance; // Handle to our library: set this in Startup

ID3DXFont *g_pHeaderFont; // The header font
ID3DXFont *g_pBodyFont;   // The body font

LPDIRECT3DTEXTURE9 g_imgTexture; // Our image texture
LPD3DXSPRITE g_imgSprite; // Our image sprite

UINT g_imgSize; // Size of our resource
LPVOID g_pImgBuffer; // Pointer to our image in memory
Inside your post-create method begin defining your required objects:

C++:
// Create our fonts
D3DXCreateFont(pDevice, 24, 12, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 0, DEFAULT_PITCH | FF_DONTCARE, "Consolas", &g_pHeaderFont);
D3DXCreateFont(pDevice, 12, 6, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, 0, VARIABLE_PITCH | FF_DONTCARE, "Consolas", &g_pBodyFont);

// Create textures and sprites for the image
D3DXCreateTextureFromFileInMemory(pDevice, g_pImgBuffer, g_imgSize, &g_imgTexture);
D3DXCreateSprite(pDevice, &g_imgSprite);

D3DXMATRIX   mTransform; // Store the transform
D3DXVECTOR2  mScale = { 0.3f, 0.3f }; // Scale by 1/3

D3DXMatrixTransformation2D(&mTransform, NULL, 0.0, &mScale, NULL, NULL, &D3DXVECTOR2(0,0));
g_imgSprite->SetTransform(&mTransform);
Now we'll update our HookEndScene function to draw our box, text and image:

C++:
// ...
D3DRECT rcBox = { 1, 1, 400, 80 };
D3DRECT rcBorder = { rcBox.x1 - 1, rcBox.y1 - 1, rcBox.x2 + 1, rcBox.y2 + 1 };
D3DXVECTOR3 vImgPos = { 45, 70, 0 };

RECT rcHeader = { 60, 15, 0, 0};
RECT rcText   = { rcHeader.left , rcHeader.top + 35, 0, 0};

pD3DDevice->Clear(1, &rcBorder, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 0, 0);
pD3DDevice->Clear(1, &rcBox, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 0, 0);

g_imgSprite->Begin(D3DXSPRITE_ALPHABLEND);

g_pHeaderFont->DrawText(NULL, "> timb3r", -1, &rcHeader, DT_LEFT | DT_NOCLIP, D3DCOLOR_ARGB(255, 220, 0, 0));
g_pBodyFont->DrawText(NULL, "What? I aient giving my name to machine!?", -1, &rcText, DT_LEFT | DT_NOCLIP, D3DCOLOR_ARGB(255, 200, 200, 200));

g_imgSprite->Draw(g_imgTexture, NULL, NULL, &vImgPos, D3DCOLOR_ARGB(255, 255, 255, 255));
g_imgSprite->End();
// ...
If you compile and test your code you should get something like the following:

example-dx-disp.png

Looking good!

So now we've got our message displaying as we want we can now add a bit of extra code to animate it. We're going to restructure the code a bit and add some helper functions to make it a bit cleaner.

First we'll define a flag indicating if we should draw to the screen or not:

C++:
BOOL g_bShouldDraw;
Now we'll define a new structure and a new global:

C++:
struct POPUPDATA{
    TCHAR szHeader[30];
    TCHAR szText[255];
    D3DRECT rcBox;
    D3DRECT rcTemp;
    BOOL bComplete;
    BOOL bPlayedSound;
    int nDuration;
    DWORD dwTicks;   
};

POPUPDATA *g_Popup;
Make sure you initialise this variable in your startup method:

C++:
g_Popup = new POPUPDATA;
Now we can define a new a function which will wrap configuring the structure for use:

C++:
void DisplayPopup(const TCHAR *szHeader, const TCHAR *szText, int nDuration = 3000, int x = 1, int y = 1, int wx = 400, int hx = 80)
{
    ZeroMemory(g_Popup, sizeof(POPUPDATA));
  
    // No bounds checking (be careful!)
    sprintf(g_Popup->szHeader, "%s", szHeader);
    sprintf(g_Popup->szText, "%s", szText);
  
    // Set the size
    g_Popup->rcBox = { x, y, wx, hx};
    g_Popup->nDuration = nDuration;
    g_Popup->dwTicks = GetTickCount();
}
Now we just need to modify our HookEndScene function to incorporate the changes and we'll add our animation code as well:

C++:
// ...
// Check to see if the popup has expired
if (g_Popup->bComplete)
    return;

// Check the elapsed time have we expired yet?
if ((GetTickCount() - g_Popup->dwTicks) >= (DWORD)g_Popup->nDuration)
{
    g_Popup->bComplete = TRUE;
    return;
}

// Can we draw to the screen?
if (!g_bShouldDraw)
    return;

// Should we play our alert sound?
if (!g_Popup->bPlayedSound) {
    PlaySound(MAKEINTRESOURCE(IDR_WAVE1), g_hInstance, SND_RESOURCE | SND_ASYNC);
    g_Popup->bPlayedSound = TRUE;
}

D3DRECT rcBorder = { g_Popup->rcBox.x1 - 1, g_Popup->rcBox.y1 - 1, g_Popup->rcBox.x2 + 1, g_Popup->rcBox.y2 + 1 };
D3DXVECTOR3 vImgPos = { 45, 70, 0 };

RECT rcHeader = { 60, 15, 0, 0 };
RECT rcText = { rcHeader.left , rcHeader.top + 35, 0, 0 };

// If the animation is finished draw everything normally
if (g_Popup->rcTemp.x2 >= g_Popup->rcBox.x2 && g_Popup->rcTemp.y2 >= g_Popup->rcBox.y2)
{
    pD3DDevice->Clear(1, &rcBorder, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 0, 0);
    pD3DDevice->Clear(1, &g_Popup->rcBox, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 0, 0);

    g_imgSprite->Begin(D3DXSPRITE_ALPHABLEND);
    g_pHeaderFont->DrawText(NULL, g_Popup->szHeader, -1, &rcHeader, DT_LEFT | DT_NOCLIP, D3DCOLOR_ARGB(255, 220, 0, 0));
    g_pBodyFont->DrawText(NULL, g_Popup->szText, -1, &rcText, DT_LEFT | DT_NOCLIP, D3DCOLOR_ARGB(255, 200, 200, 200));
    g_imgSprite->Draw(g_imgTexture, NULL, NULL, &vImgPos, D3DCOLOR_ARGB(255, 255, 255, 255));
    g_imgSprite->End();
} else {
    // Our animation
    if (g_Popup->rcTemp.x2 rcBox.x2) {
        g_Popup->rcTemp.x2 += 5;
    } else {
        g_Popup->rcTemp.x2 = g_Popup->rcBox.x2;
    }

    // Draw the border
    g_Popup->rcTemp.x1 = g_Popup->rcBox.x1 - 1;  g_Popup->rcTemp.y1 = g_Popup->rcBox.y1 - 1;
    g_Popup->rcTemp.y2 = g_Popup->rcBox.y2;
    pD3DDevice->Clear(1, &g_Popup->rcTemp, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255, 0, 0), 0, 0);

    // Draw the box
    g_Popup->rcTemp.x1 = g_Popup->rcBox.x1;  g_Popup->rcTemp.y1 = g_Popup->rcBox.y1;
    g_Popup->rcTemp.x2--; g_Popup->rcTemp.y2--;

    pD3DDevice->Clear(1, &g_Popup->rcTemp, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 0, 0);

    // Reset the values for the next loop
    g_Popup->rcTemp.x2++; g_Popup->rcTemp.y2++;
}
// ...
Now we need add some code inside our hooked subclass to call our new function:

C++:
case WM_KEYDOWN:
{
    switch (wParam)
    {
        case '1':
            g_bShouldDraw = TRUE;
            DisplayPopup("Test", "Test");
        break;

        case '2':
            g_bShouldDraw = FALSE;
        break;
    }
}
break;
Finally you'll need to add either winmm.lib to your linker options or simply add it to your source file with a #pragma comment.

C++:
#pragma comment(lib, "winmm.lib")
If you test your updated code you should now have an animated popup (with sound) that slides on from the left when you press '1' and hides when you press '2' not bad gary!

I think that'll do for now. This will be continued in Part 3 where we get down to the business of hacking the game.

Source is attached.
 

Attachments

Last edited by a moderator:
Dec 25, 2019
1
2
0
HookViewPort is either wrong, or you missed something in the tutorial, it doesn't do anything when used like in the tutorial above. (or when adding it into the source of the part2 of this tutorial) :( (or I'm doing it wrong, what is the proper way adding it? can you explain it as if adding it to the part2 source?)
 

Pseudopourri42

Newbie
Full Member
May 29, 2016
22
658
3
Dude you can't imagine how much trouble you've saved me from ! Earlier this year I tried to display text in nfs underground 2, I figured out the hooking pretty easily once I understood it, but as for the text I couldn't get to call D3DXCreateFont without either having the game crash or not do anything (with just all NULLs as parameters), I spent hours and hours in ollydbg and CE trying to figure out what was wrong but it still didn't make any sense, so I gave up until a few weeks ago when I wanted to try again, actually, I didn't try again because I am lazy, but it's been on my mind ever since and this tutorial is a godsend, so thanks you for that.
 
Last edited:

herooyyy

Full Member
Feb 18, 2020
1
102
0
Hi, I've managed to make the game load my d3d9.dll, it popups the MessageBox, but then steam get's stuck on "Preparing to launch X". It just loops infinitely over many popups. Not sure if I should ask the question here or not. Sorry if I'm being annoying somehow.
 
Attention! Before you post:

Read the How to Ask Questions Guide
99% of questions are answered in the Beginner's Guide, do it before asking a question.

No Hack Requests. Post in the correct section.  Search the forum first. Read the rules.

How to make a good post:

  • Fill out the form correctly
  • Tell us the game name & coding language
  • Post everything we need to know to help you
  • Ask specific questions, be descriptive
  • Post errors, line numbers & screenshots
  • Post code snippets using code tags
  • If it's a large project, zip it up and attach it

If you do not comply, your post may be deleted.  We want to help, please make a good post and we will do our best to help you.

Community Mods League of Legends Accounts