CEGUI - EndScene Hook - DLL Function Call menu

User Tag List

Results 1 to 6 of 6
  1. #1
    Orix's Avatar Member
    Reputation
    1
    Join Date
    Jun 2007
    Posts
    10
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    CEGUI - EndScene Hook - DLL Function Call

    After googling and trying different solutions and then googling again and trying some more solutions I've decided I'm a bit out of my league here. Hopefully you guys can lend a hand. First this program isn't used for World of Warcraft, I don't think that will matter all that much, as it is pretty generalized. What I'm doing is have a dll called Mod.dll and inside Mod.dll I hook endScene and initialize the CEGUI with the pointer in endScene.

    Code:
    HRESULT WINAPI hkEndScene (LPDIRECT3DDEVICE9 pDevice) {
    
        static bool init = true;
        if (init) {
    
            log_dll._stream << "Attempting to setup CEGUI for the first time" << std::endl;
    
            CEGUI::Direct3D9Renderer::bootstrapSystem (pDevice);
    
            setupGuiFluff();
    
            CEGUI::Window* myRoot = CEGUI::WindowManager::getSingletonPtr()->loadWindowLayout ("dps.layout");
            CEGUI::System::getSingletonPtr()->setGUISheet (myRoot);
    
            init = false;
        }
    
        CEGUI::System::getSingletonPtr()->renderGUI();
    
        /*
        IDirect3DStateBlock9 *pStateBlock;
        pDevice->CreateStateBlock (D3DSBT_ALL, &pStateBlock);
    
        pStateBlock->Apply();
        pStateBlock->Release();*/
    
        __asm nop;
        return oEndScene (pDevice);
    }
    Code:
    DWORD WINAPI hookThread (LPVOID) {
    
        DWORD vTable[1] = {0};
    
        while (GetModuleHandle ("d3d9.dll") == NULL ) {
    
            Sleep (250);
        }
    
        initDX (vTable);
        HOOK (EndScene, vTable[0]);
    
        return 0;
    }
    Code:
    BOOL APIENTRY DllMain( HMODULE hInstance, DWORD dwReason, LPVOID lpReserved ) {
    
        switch (dwReason) {
    
            case DLL_PROCESS_ATTACH:
    
                log_dll._stream.open ("C:\\ModDll.txt");
    
                log_dll._stream << "CallSomething address:" << CallSomething << std::endl;
    
                CreateThread (0, 0, hookThread, 0, 0, 0);
            break;
    
            case DLL_PROCESS_DETACH:
    
                log_dll._stream << "Detaching from process" << std::endl;
    
            break;
        }
    
    	return TRUE;
    }
    I then Inject the DLL using this piece of code, I'm not sure how "safe" it is or if it's exactly the best way to do the job. I wrapped it in a class for pure convenience.

    Code:
    #ifndef DLLMANAGER_HPP
    #define DLLMANAGER_HPP
    
    #include <Windows.h>
    #include <tlhelp32.h>
    #include <Psapi.h>
    #include "shlwapi.h"
    #include "Logger.hpp"
    
    class DLLManager {
    
        public:
    
            Logger log;
    
            DWORD processId;
            DWORD dwBaseAddress;
            HANDLE hProcess;
            std::string dll;
    
            DLLManager () { log._stream.open ("C:\\DLLManager.txt"); }
            ~DLLManager () { log._stream.close(); }
    
            DWORD findProcessId (const std::string &processName) {
    
                PROCESSENTRY32 processInfo;
                processInfo.dwSize = sizeof (processInfo);
    
                HANDLE processesSnapshot = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, NULL);
                if (processesSnapshot == INVALID_HANDLE_VALUE) {
    
                    log._stream << "findProcessId() -> processSnapshot failed" << std::endl;
                    return 0;
                }
    
                Process32First (processesSnapshot, &processInfo);
                if (!processName.compare (processInfo.szExeFile)) {
    
                    CloseHandle (processesSnapshot);
                    log._stream << "findProcessId() -> Process '" << processInfo.szExeFile << "' found and id is '" << processInfo.th32ProcessID << "'" << std::endl;
                    processId = processInfo.th32ProcessID;
                    return processInfo.th32ProcessID;
                }
    
                while (Process32Next (processesSnapshot, &processInfo)) {
    
                    if (!processName.compare (processInfo.szExeFile)) {
    
                        CloseHandle (processesSnapshot);
                        log._stream << "findProcessId() -> Process '" << processInfo.szExeFile << "' found and id is '" << processInfo.th32ProcessID << "'" << std::endl;
                        processId = processInfo.th32ProcessID;
                        return processInfo.th32ProcessID;
                    }
                }
    
                log._stream << "findProcessId() -> Failed to find process id, are you sure it's running?" << std::endl;
                CloseHandle (processesSnapshot);
                return 0;
            }
    
    
    
            bool injectDLL (DWORD pId, std::string dll) {
    
                this->dll = dll;
    
                HMODULE hLocKernel32 = GetModuleHandle ("Kernel32");
                FARPROC hLocLoadLibrary = GetProcAddress (hLocKernel32, "LoadLibraryA");
    
                HANDLE hToken;
                TOKEN_PRIVILEGES tkp;
                if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
    
                    LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
                    tkp.PrivilegeCount = 1;
                    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
                    AdjustTokenPrivileges (hToken, 0, &tkp, sizeof (tkp), NULL, NULL);
                }
    
                HANDLE hProc = OpenProcess (PROCESS_ALL_ACCESS, false, pId);
    
                dll += '\0';
                LPVOID hRemoteMem = VirtualAllocEx (hProc, NULL, dll.size(), MEM_COMMIT, PAGE_READWRITE);
               
                DWORD numBytesWritten;
                WriteProcessMemory (hProc, hRemoteMem, dll.c_str(), dll.size(), &numBytesWritten);
    
                HANDLE hRemoteThread = CreateRemoteThread (hProc, NULL, 0, (LPTHREAD_START_ROUTINE) hLocLoadLibrary, hRemoteMem, 0, NULL);
                log._stream << "hRemoteThread:" << hRemoteThread << std::endl;
    
                bool result = false;
                if (hRemoteThread)
                    result = (bool) WaitForSingleObject (hRemoteThread, 10000) != WAIT_TIMEOUT;
    
                if (!GetExitCodeThread (hRemoteThread, &dwBaseAddress)) result = false;
                log._stream << "DLL Successfully injected at location:" << dwBaseAddress << std::endl;
    
                VirtualFreeEx (hProc, hRemoteMem, dll.size(), MEM_RELEASE);
    
                hProcess = hProc;
                CloseHandle (hProc);
    
                return result;
            }
    
            bool callFunction (const std::string &function) {
    
                HINSTANCE hLibrary = LoadLibrary (dll.c_str());
                if (!hLibrary)
                    log._stream << "Attempted to load a dll but failed" << std::endl;
    
                FARPROC pPrototype = GetProcAddress (hLibrary, function.c_str());
                if (!pPrototype)
                    log._stream << "Could not find function '" << function << "' in specified library" << std::endl;
    
                FARPROC pRelative = (FARPROC)((DWORD)pPrototype - (DWORD)hLibrary);
    
                LPVOID pFunction = (LPVOID)((DWORD)pRelative + dwBaseAddress);
    
                log._stream << "Attempting to call '" << function << "' at location:" << pFunction << std::endl;
    
                DWORD dwExitCode;
                //HANDLE hThread = CreateRemoteThread (hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunction, NULL, 0, NULL);
                HANDLE hThread = CreateRemoteThread (GetCurrentProcess(), NULL, 0, (LPTHREAD_START_ROUTINE)pFunction, NULL, 0, NULL);
    
                if (WaitForSingleObject (hThread, 10000) != WAIT_OBJECT_0) {
                
                    log._stream << "Failed to create thread to run function in" << std::endl;
                    return false;
                }
    
                if (!GetExitCodeThread (hThread, &dwExitCode)) {
    
                    log._stream << "Remote function call failed to execute" << std::endl;
                    return false;
                }
    
                log._stream << "Function ran with exit code:" << dwExitCode << std::endl;
                return (dwExitCode != 0);
            }
    
            bool unloadDll () {
    
                DWORD dwNeeded;
                HMODULE hMods[0x400];
    
                HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, processId);
    
                EnumProcessModules (hProcess, hMods, 0x400, &dwNeeded);
    
                for (int i = 0; i < (dwNeeded / sizeof (DWORD)); i++) {
    
                    char szPath[MAX_PATH] = "";
                    GetModuleFileNameExA (hProcess, hMods[i], szPath, MAX_PATH);
                    PathStripPathA (szPath);
    
                    // uncomment below line to see all modules loaded into the given process id
                    // log._stream << szPath << std::endl;
    
                    if (!_stricmp (szPath, "ModDll.dll")) {
    
                        log._stream << "Located dll inside of process" << std::endl;
                        FreeLibrary (hMods[i]);
                        return true;
                    }
                }
                return false;
            }
    };
    
    #endif
    Then in my applications main thread I do.

    Code:
    #pragma comment (lib, "ModDll.lib")
    
    extern "C" __declspec (dllimport) int CallSomething();
    
    int main (int argc, char *argv[]) {
    
        DLLManager Manager;
    
        Manager.injectDLL (Manager.findProcessId ("app.exe"), "C:\\Programming\\Projects\\Mod\\Debug\\ModDll.dll");
        Manager.callFunction ("CallSomething");
    
        int ret = CallSomething();
    
        return 0;
    }
    The DLL seems to inject fine and I get my GUI window displayed that I want, the big issue comes when I try to call a function (defined below) from inside the application. It seems to be crashing out on the WindowManager::getSingleton() call (bad pointer?) if I use WindowManager::getSingletonPtr() it will crash out on GetWindow call I assume this is pointing to bad memory as well.

    Code:
    extern "C" __declspec (dllexport) int CallSomething(const char *data) {
    
        log_dll._stream << "CallSomething()" << std::endl;
    
        // setup variables;
        CEGUI::String str ("player");
        CEGUI::ListboxTextItem *add = new CEGUI::ListboxTextItem (str);
    
        log_dll._stream << "CallSomething(): " << str << std::endl;
    
         // crash
        // CEGUI::Window *listBox = CEGUI::WindowManager::getSingleton().getWindow ("Root/testWindow/players");
        // get the listbox and add the name - crash
        CEGUI::Window *listBox = CEGUI::WindowManager::getSingletonPtr()->getWindow ("Root/testWindow/players");
        static_cast <CEGUI::Listbox *> (listBox)->addItem (add);
    
        log_dll._stream << "CallSomething(): complete" << std::endl;
    
        return 1;
    }
    Just as an FYI CEGUI has been statically linked. I thought maybe the issue was with my DLL so I downloaded memory hacker and injected my dll through that and called the functions from there, it has no issue populating my listbox. I've included two call stacks, the first when using CEGUI::WindowManager::getSingletonPtr() and the second when using CEGUI::Window::Manager::getSingleton().

    Code:
    >	ModDll.dll!std::_Tree<std::_Tmap_traits<CEGUI::String,CEGUI::Window *,CEGUI::String::FastLessCompare,std::allocator<std::pair<CEGUI::String const ,CEGUI::Window *> >,0> >::_Root()  Line 1789 + 0x3 bytes	C++
     	ModDll.dll!std::_Tree<std::_Tmap_traits<CEGUI::String,CEGUI::Window *,CEGUI::String::FastLessCompare,std::allocator<std::pair<CEGUI::String const ,CEGUI::Window *> >,0> >::_Lbound(const CEGUI::String & _Keyval)  Line 1725 + 0x8 bytes	C++
     	ModDll.dll!std::_Tree<std::_Tmap_traits<CEGUI::String,CEGUI::Window *,CEGUI::String::FastLessCompare,std::allocator<std::pair<CEGUI::String const ,CEGUI::Window *> >,0> >::lower_bound(const CEGUI::String & _Keyval)  Line 1455 + 0x10 bytes	C++
     	ModDll.dll!std::_Tree<std::_Tmap_traits<CEGUI::String,CEGUI::Window *,CEGUI::String::FastLessCompare,std::allocator<std::pair<CEGUI::String const ,CEGUI::Window *> >,0> >::find(const CEGUI::String & _Keyval)  Line 1433 + 0x10 bytes	C++
     	ModDll.dll!CEGUI::WindowManager::getWindow(const CEGUI::String & name)  Line 252 + 0x13 bytes	C++
     	ModDll.dll!CallSomething(const char * data)  Line 124 + 0x23 bytes	C++
     	kernel32.dll!76da3677() 	
     	[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]	
     	ntdll.dll!77309d42() 	
     	ntdll.dll!77309d15()
    Code:
    ModDll.dll!_wassert(const wchar_t * expr, const wchar_t * filename, unsigned int lineno)  Line 325	C
    >      ModDll.dll!CEGUI::Singleton<CEGUI::WindowManager>::getSingleton()  Line 79 + 0x38 bytes	C++
            ModDll.dll!CallSomething(const char * data)  Line 124 + 0x1c bytes	C++
     	kernel32.dll!76da3677() 	
     	[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]	
     	ntdll.dll!77309d42() 	
     	ntdll.dll!77309d15()
    Please rip it apart, critique it, flame it, anything that will help me through this issue. I've also been thinking about moving over to HadesMem but I haven't been having much luck with Boost.Build.

    Thanks, Orix
    /mmowned cherry popped

    CEGUI - EndScene Hook - DLL Function Call
  2. #2
    caytchen's Avatar Contributor
    Reputation
    138
    Join Date
    Apr 2007
    Posts
    162
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just a general FYI, please don't start threads from DllMain. Also, you're linking to ModDll from your injector and call CallSomething() twice, through the Manager and normally - do you expect this to magically break through virtual memory?!

  3. #3
    Orix's Avatar Member
    Reputation
    1
    Join Date
    Jun 2007
    Posts
    10
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the response. The Dllimport and the DoSomething() shouldve been commented out, I left them in for "completeness". As for virtual memory, I wouldn't expect it would magically break through virtual memory does this mean I have too allocate some memory for my calls in the process itself? I figured since I had the actual memory address of the function I could just call it. As for the creating threads in the dllmain, I realize this could cause deadlock, is there a best practice for creating threads?

    Thanks, Orix

  4. #4
    caytchen's Avatar Contributor
    Reputation
    138
    Join Date
    Apr 2007
    Posts
    162
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by Orix View Post
    Thanks for the response. The Dllimport and the DoSomething() shouldve been commented out, I left them in for "completeness". As for virtual memory, I wouldn't expect it would magically break through virtual memory does this mean I have too allocate some memory for my calls in the process itself? I figured since I had the actual memory address of the function I could just call it. As for the creating threads in the dllmain, I realize this could cause deadlock, is there a best practice for creating threads?
    Just add another function that you can call through Manager.callFunction to start the thread, or just hook already.
    On the "virtual memory" part - that was only for the normal call and DllImport stuff - I thought you had the idea that importing it would magically reroute the normal call to the injected instance.
    You should force your CallSomething function to use __stdcall (aka WINAPI) calling convention, CreateRemoteThread (which DLLManager uses to remotely call functions) has no way of verifying this.

  5. #5
    Orix's Avatar Member
    Reputation
    1
    Join Date
    Jun 2007
    Posts
    10
    Thanks G/R
    0/0
    Trade Feedback
    1 (100%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks caytchen, it was a pretty easy fix but I'm very appreciative non the less. rep!

    Orix

  6. #6
    bad6oy30's Avatar Member Authenticator enabled
    Reputation
    1
    Join Date
    Dec 2010
    Posts
    41
    Thanks G/R
    0/0
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You got a leak:

    VirtualFreeEx (hProc, hRemoteMem, dll.size(), MEM_RELEASE);

    MEM_RELEASE: If you specify this value, dwSize must be 0 (zero). The function fails otherwise.

Similar Threads

  1. [C# DLL] aHook, use ASM through EndScene hook
    By JuJuBoSc in forum WoW Memory Editing
    Replies: 81
    Last Post: 6 Days Ago, 02:55 PM
  2. x64 ws2_32.dll function hooks c++
    By BitHacker in forum Programming
    Replies: 0
    Last Post: 06-06-2012, 04:13 PM
  3. [Test Theory] EndScene hook without Native Code (Kinda)
    By Apoc in forum WoW Memory Editing
    Replies: 7
    Last Post: 09-04-2009, 12:46 PM
  4. EndScene Hook not changing anything
    By lanman92 in forum WoW Memory Editing
    Replies: 32
    Last Post: 06-01-2009, 11:46 PM
  5. ASM function call?
    By akh in forum WoW Memory Editing
    Replies: 15
    Last Post: 09-02-2008, 12:31 AM
All times are GMT -5. The time now is 07:15 AM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search