Solved GetD3D9Device fails after recent CS:GO update

  • CSGO recently moved logic from 'client_panorama.dll' to 'client.dll', you must update all code that uses 'client_panorama.dll' and replace it with 'client.dll' or the code will not work.
Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat

Kekz

Maybe Pasting
Dank Tier Donator
Nobleman
Jan 10, 2020
143
3,668
12
Tutorial Link
https://guidedhacking.com/threads/csgo-direct3d9-endscene-hook-d3d9-esp-tutorial-series.14570/
How long you been coding/hacking?
~3 years / 5 months
Coding Language
C++
This is a follow up question to my post here: Question - Has CSGO updated their "anti-cheat" system yet again?

I managed to track down why it would crash. The call stack is still the same.
Unbenannt.PNG
I'm getting the d3d9 device VMT as shown in the linked tutorial by creating a dummy device.
This method no longer works for me and results in the mentioned exception.

This is all of my code for getting the device (pretty much the same as in the tutorial, worked fine until now):
GetD3D9Device:
bool GetD3D9Device(void ** pTable, size_t size)
{
    if (!pTable)
        return false;

    IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    if (!pD3D)
        return false;

    IDirect3DDevice9* pDummyDevice = nullptr;

    D3DPRESENT_PARAMETERS d3dpp = {};
    d3dpp.Windowed = false;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = GetProcessWindow();

    PRINT_DEBUG("Creating dummy device: First attempt");

    // create a device so we can access the vTable pointer and get the EndScene function address
    HRESULT dummyDevCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

    // if device wasn't created succesfully, try again with windowed mode
    if (dummyDevCreated != S_OK)
    {
        d3dpp.Windowed = !d3dpp.Windowed;
        PRINT_DEBUG("Creating dummy device: Second attempt");
        dummyDevCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

        if (dummyDevCreated != S_OK)
        {
            PRINT_DEBUG("Failed to create dummy device");
            pD3D->Release();
            return false;
        }
    }

    PRINT_DEBUG("Copying D3D9Device's vTable");
    memcpy(pTable, *(void***)(pDummyDevice), size);
    PRINT_DEBUG("Releasing d3d9 objects");
    pDummyDevice->Release();
    pD3D->Release();
    return true;
}
Helper methods:
BOOL CALLBACK enumWind(HWND handle, LPARAM lp)
{
    DWORD procID;
    GetWindowThreadProcessId(handle, &procID);
    // returns true if we haven't found our window, keep searching
    if (GetCurrentProcessId() != procID)
        return TRUE;

    // We found a window that belongs to the CS:GO process

    char buffer[256]{ 0 };
    GetWindowText(handle, buffer, sizeof(buffer));

    // Also check the window name, so that we don't accidentally grab our console window if we allocated one
    if (!strstr(buffer, AY_OBFUSCATE("Counter-Strike: Global Offensive")))
        return TRUE;

    window = handle;
    return FALSE;
}

HWND GetProcessWindow()
{
    PRINT_DEBUG("Gettings process window");

    window = NULL;

    EnumWindows(enumWind, NULL);

    RECT size;
    GetWindowRect(window, &size);
    windowWidth = size.right - size.left;
    windowHeight = size.bottom - size.top;

    return window;
}
However, the weird thing is that this only happens on the newest CS:GO build where Valve blocks LoadLibrary injection. (I use GH Injector with Manual Mapping etc...)
On the 1.37.5.9 beta build it works no problem.

I have pin pointed the exact location of the crash to
HRESULT dummyDevCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice); calls, which would explain why the callstack originates in d3d9.dll
Unbenannt.PNG
The call that always crashes is the one that takes the d3dpp with d3dpp.Windowed = true. The other call always doesn't generate a device but also never crashes.
If I start with d3dpp.Windowed = true; it crashes on the first attempt.
It also doesn't matter if I start CS:GO in windowed or fullscreen mode.

What I don't understand is that this only happens if VAC is enabled, meaning I start CS:GO without the -insecure parameter.
If I start it in insecure mode I can inject no problem and draw all my stuff to the screen (which is how I know that stuff like GetProcessWindow() works).
Could it be that VAC is blocking access to some imports that the CreateDevice call needs?
I have no clue what to do in this situation. A possible solution would be to abandon this approach and get the device through a signature, but I would still like to know why this is happening
I would greatly appreciate anyone knowing what could be wrong or who has experienced a similar issue.
 

Attachments

Last edited:

Rake

Cesspool Admin
Administrator
Jan 21, 2014
12,178
78,998
2,399
code works fine for me, no changes necessary, using original code from the tutorial, just tested it, I manual mapped it btw

C++:
bool GetD3D9Device(void** pTable, size_t Size)
{
    if (!pTable)
        return false;

    IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    if (!pD3D)
        return false;

    IDirect3DDevice9* pDummyDevice = NULL;

    // options to create dummy device
    D3DPRESENT_PARAMETERS d3dpp = {};
    d3dpp.Windowed = false;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = GetProcessWindow();

    HRESULT dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

    if (dummyDeviceCreated != S_OK)
    {
        // may fail in windowed fullscreen mode, trying again with windowed mode
        d3dpp.Windowed = !d3dpp.Windowed;

        dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

        if (dummyDeviceCreated != S_OK)
        {
            pD3D->Release();
            return false;
        }
    }

    memcpy(pTable, *reinterpret_cast<void***>(pDummyDevice), Size);

    pDummyDevice->Release();
    pD3D->Release();
    return true;
}
 

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,298
37,938
269
open up csgo in a debugger, navigate to VTable for the functions youre trying to call. Are they nuked? Theres the issue

No? Then navigate to the function themselves, are they hooked? Follow them and see whats up
 
  • Like
Reactions: Kekz

Kekz

Maybe Pasting
Dank Tier Donator
Nobleman
Jan 10, 2020
143
3,668
12
open up csgo in a debugger, navigate to VTable for the functions youre trying to call. Are they nuked? Theres the issue

No? Then navigate to the function themselves, are they hooked? Follow them and see whats up
Thanks for the hints. I had a look at pD3D's VMT in Reclass and CheatEngine and at what I think was the CreateDevice but I didn't find anything that stood out to me. But this may just be because I'm not that experienced yet.
Anyway I did manage to solve the crash by getting the device through a signature.
I just used hazedumper's signature
Code:
"A1 ? ? ? ? 50 8B 08 FF 51 0C" in shaderapidx9.dll
offset by one and double dereference.
I don't know if this is related but after this I also encountered problems getting the window size via GetWindowRect() when in fullscreen mode, so I use GetSystemMetrics instead
C++:
windowWidth = GetSystemMetrics(SM_CXSCREEN);
windowHeight = GetSystemMetrics(SM_CYSCREEN);
I may look into it again when I have more time.
 
  • Like
Reactions: XdarionX

mambda

headass
Escobar Tier VIP
Trump Tier Donator
Jun 25, 2014
2,298
37,938
269
Thanks for the hints. I had a look at pD3D's VMT in Reclass and CheatEngine and at what I think was the CreateDevice but I didn't find anything that stood out to me. But this may just be because I'm not that experienced yet.
Anyway I did manage to solve the crash by getting the device through a signature.
I just used hazedumper's signature
Code:
"A1 ? ? ? ? 50 8B 08 FF 51 0C" in shaderapidx9.dll
offset by one and double dereference.
I don't know if this is related but after this I also encountered problems getting the window size via GetWindowRect() when in fullscreen mode, so I use GetSystemMetrics instead
C++:
windowWidth = GetSystemMetrics(SM_CXSCREEN);
windowHeight = GetSystemMetrics(SM_CYSCREEN);
I may look into it again when I have more time.
if youre using the directx api, the best way to get window size is via the viewport.

IDirect3DDevice9::GetViewport (d3d9helper.h) - Win32 apps
 
  • Like
Reactions: Rake and Kekz

Kekz

Maybe Pasting
Dank Tier Donator
Nobleman
Jan 10, 2020
143
3,668
12
code works fine for me, no changes necessary, using original code from the tutorial, just tested it, I manual mapped it btw

C++:
bool GetD3D9Device(void** pTable, size_t Size)
{
    if (!pTable)
        return false;

    IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION);

    if (!pD3D)
        return false;

    IDirect3DDevice9* pDummyDevice = NULL;

    // options to create dummy device
    D3DPRESENT_PARAMETERS d3dpp = {};
    d3dpp.Windowed = false;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.hDeviceWindow = GetProcessWindow();

    HRESULT dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

    if (dummyDeviceCreated != S_OK)
    {
        // may fail in windowed fullscreen mode, trying again with windowed mode
        d3dpp.Windowed = !d3dpp.Windowed;

        dummyDeviceCreated = pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);

        if (dummyDeviceCreated != S_OK)
        {
            pD3D->Release();
            return false;
        }
    }

    memcpy(pTable, *reinterpret_cast<void***>(pDummyDevice), Size);

    pDummyDevice->Release();
    pD3D->Release();
    return true;
}
Since you marked it as a solution I'm gonna post this here aswell:
Did you start CSGO with -insecure?
I tested it today: downloaded the source from the D3D9 Tutorial 1, compiled in Release mode, start CSGO without -insecure (VAC enabled) and inject. (GH Injector with Manual Mapping, Thread Hijacking and Handle Hijack, everything else default). I obviously recommend using a free account since idk what VAC thinks about debuggers.
I get the same exact exception as in my thread.
Edit: Just tested with ONLY Manual Map, still crashes.
 
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