Solved Hooking DrawIndexedPrimitive. One of those errors.

Hexui Undetected CSGO Cheats Sinkicheat PUBG Cheat


Full Member
Dec 24, 2016
Hi everyone.
So as the title states, I'm doing a DrawIndexedPrimitive hook.
Hooking the VMT doesn't work cuz :bicepleft:directx:bicepright: so I went for the beginning of the function.

I've even started another project just for it, of which I'm gonna dump the code, in case it turns out to be something obvious and you figure it out just by looking at the code, then I'll go to deeper into the issue.

The hack thread (I can dump the rest if you ask but I felt it was irrelevant given it's just basically skeleton dll code):
        //--------------------------------------------------------------------FINDING DIRECTX9
	uintptr_t d3d9_dll = NULL;
	SIZE_T d3d9_dll_size = NULL;
	DWORD ScannedTable = NULL;
	d3d9_dll = GetModuleBase_i(L"d3d9.dll", &d3d9_dll_size);
	if (!d3d9_dll) { std::cout << "Failed To Get d3d9.dll\n"; return Exit(); }
	std::cout << "d3d9.dll starts @: " << std::hex << d3d9_dll << " and has a length of " << d3d9_dll_size << std::endl;
	ScannedTable = Sigscan_i(d3d9_dll, d3d9_dll + d3d9_dll_size, "\xC7\x06\x00\x00\x00\x00\x89\x86\x00\x00\x00\x00\x89\x86", "xx????xx????xx", 14);
	if (!ScannedTable) { std::cout << "Sig Not Found\n"; }
	else std::cout << "SigScanned Boii: " << std::hex << ScannedTable << std::endl;
	D3DVMTable = *(DWORD**)(ScannedTable + 2);
	//--------------------------------------------------------------------SET UP ADDRESSES
	uintptr_t DIPaddr = NULL;
	DIPaddr = D3DVMTable[iDrawIndexedPrimitive];
	FixedDrawIndexedPrimitiveAddress = DIPaddr + 5; //in DetouredFuncs.h
	//-----------------------------------------------------------HOOK DRAWINDEXEDPRIMITIVE
				DWORD Protection = NULL;
				VirtualProtect((LPVOID)DIPaddr, 5, PAGE_EXECUTE_READWRITE, &Protection);
	*(unsigned char*)DIPaddr = 0xE9; //first byte
	*(uintptr_t*)(DIPaddr+1) = (uintptr_t)DrawIndexedPrimitiveDetour - DIPaddr - 5; //Address(4 bytes)
				VirtualProtect((LPVOID)DIPaddr, 5, Protection, &Protection);
uintptr_t FixedDrawIndexedPrimitiveAddress = NULL;

_declspec(naked) HRESULT oDrawIndexedPrimitive(LPDIRECT3DDEVICE9 pDevice, D3DPRIMITIVETYPE PrimType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT PrimitiveCount) {
	_asm {
		push ebp
		mov ebp, esp
		jmp FixedDrawIndexedPrimitiveAddress

HRESULT DrawIndexedPrimitiveDetour(LPDIRECT3DDEVICE9 pDevice, D3DPRIMITIVETYPE PrimType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT PrimitiveCount) {
	HRESULT returnal;
	returnal = oDrawIndexedPrimitive(pDevice, PrimType, BaseVertexIndex, MinVertexIndex, NumVertices, startIndex, PrimitiveCount);
	return returnal;

The error is get is the following:
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

The original beginning of DrawIndexedPrimitive looks like this:

And ends up looking like this:

Which is correct.

Now FixedDrawIndexedPrimitiveAddress also ends up pointing to the instruction after, but you'll have to take my word for it for now cuz I crashed the game and have 2% battery.

Also, the stack seems correct in the beginning of both DrawIndexedPremitiveDetour and oDrawIndexedPrimitive (it's the same, which would be correct because it's the same function), as you can see in:

Stack at the beginning of DrawIndexedPremitiveDetour:

Stack at the beginning of oDrawIndexedPrimitive:

So yeah. I'm nearly convinced it's something to do with the calling convention and registers, but I can't seem to be able to solve it so huelp.

Thanks in advance and have a nice day :D


Escobar Tier VIP
Dank Tier Donator
Aug 3, 2015
ECX is 0 in oDIP before jumping into the real DIP.
This will cause any subsequent function calls that originate from the devices virtual table to crash your program because you're dereferencing a null pointer.

Looking at the stack and the registers you seem to be really close, just missed the fact that ECX was empty before calling the original DIP function.

BTW it's not DirectX's fault that the VMT hook isn't working. It's probably just getting overwritten and has to be reapplied ;)
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