You can get it's address easily since it's exported by Engine.DLL
typedef void ( __thiscall *PostRender_t )( void*, class UCanvas* ); PostRender_t pPostRender = nullptr; hash_string hstrPostRenderName = "?MasterProcessPostRender@UInteractionMaster@@QAEXPAVUCanvas@@@Z"; DWORD_PTR dwPostRender = g_moduleManager->getExport( hstrEngineModuleName, hstrPostRenderName ); if( dwPostRender ) { pPostRender = reinterpret_cast<PostRender_t>( postRenderDetour.setHook( (BYTE*)dwPostRender, (BYTE*)Hooked_PostRender )); } .............. static void __fastcall Hooked_PostRender( void *pThis, void *edx, UCanvas *pCanvas ) { pPostRender.unHook(); pPostRender( pThis, pCanvas ); pPostRender.reHook(); }
I will add more later but for starters Getting FCanvasUtils -pointer from UCanvas and also getting DrawString -functionpointer:
typedef int ( __thiscall * DrawString_t )( void*, int, int, const unsigned short*, UFont*, FColor ); DrawString_t pDrawString = nullptr; DWORD_PTR dwDrawString = g_moduleManager->getModule( hstrEngineModuleName )->m_moduleBase + 0x1BD420; // this can be updated by searching for calls to ENGINE.#something and then name of DrawString export or just GetProcAddress/EAT-walk this, I will add the full name to this post later since I dont remember it at the moment if( dwDrawString ) { pDrawString = reinterpret_cast<DrawString_t>( dwDrawString ); }
/* ESI 0BC70FA4 = pCanvasUtil EDI 0BC70EE0 = UCanvas */ // God I'm bad with these ptr-to-ptr-to-ref-to-ptr-ptr-reference-ptr-ptrs shit gafsjgnfagfsdmfsa DWORD_PTR dwPtrAddress = (DWORD_PTR)pCanvas + 0xC4; PDWORD_PTR pThisPtr = reinterpret_cast<PDWORD_PTR>( *(&(DWORD_PTR)dwPtrAddress) ); PDWORD_PTR pdwThisPtr = reinterpret_cast<PDWORD_PTR>( *pThisPtr ); ............................... if( pCanvas ) { if( pDrawString ) { wchar_t szBuf[512]; swprintf( szBuf, L"0x%X", pdwThisPtr ); pDrawString( pdwThisPtr, 50, 50, szBuf, pCanvas->MedFont, FColor( 255, 255, 255, 255 ) ); } }