Thread: Hooking Crash?

  1. #1
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654

    Hooking Crash?

    Just a question here...
    I'm trying to hook a DLL into a process (for a private project, only). The first time I do, it works fine. But the second time I do it, it seems to crash. It only happens when I forcibly unload the DLL from the process through:

    Code:
    HMODULE hHookedDll = GetModuleHandle(_T("ThreadSpy.dll"));
    ASSERT( FreeLibrary(hHookedDll) );
    I'm wondering if this is a bad thing? The library was dynamically loaded into the process space via LoadLibrary & CreateRemoteThread by the hooking process, so it is dynamically loaded. So shouldn't it be safe to unload it, then?

    After I unload it and try to inject the DLL again, I get a crash in the process I inject it into. The crash occurs in the function:
    Code:
    _CRTIMP void * __cdecl _decode_pointer(void *codedptr)
    So I don't know if I'm doing something wrong... Does anyone know?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Elysia View Post
    Just a question here...
    I'm trying to hook a DLL into a process (for a private project, only). The first time I do, it works fine. But the second time I do it, it seems to crash. It only happens when I forcibly unload the DLL from the process through:
    And the crash doesn't go away until a reboot? Or what?

  3. #3
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    How do you inject the DLL? Calling LoadLibrary as a function to CreateRemoteThread?
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Do you have the full 2005 install (with CRT source) or just Express? If you do you have the source you should be able to debug the crash - even if you have to create your own test harness to inject into.

    gg

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Inject 1 - OK.
    Inject 2 - Crash.
    If I restart the test app, it works fine again.
    For it to work, I need to unload the DLL from the test app I hooked it into.
    The crash is difficult to find.

    Essentially, I do this:

    First, inject the DLL with the hooking app:
    Code:
    	const char strDll[] = "G:\\w00t\\Visual Studio 2005\\Projects\\Hooking\\Application\\Debug\\ThreadSpy.dll";
    	Stuff::ProcessVector pProcesses = Stuff::EnumerateProcesses();
    	for (std::vector<int>::size_type i = 0; i < pProcesses->size(); i++)
    	{
    		if (_tcscmp(pProcesses->at(i).szExeFile, _T("Hooked App.exe")) == 0)
    		{
    			HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pProcesses->at(i).th32ProcessID);
    			CHandle hhProcess(hProcess);
    			void* pDllMem = VirtualAllocEx(hProcess, NULL, sizeof(strDll), MEM_COMMIT, PAGE_READWRITE);
    			ASSERT( WriteProcessMemory(hProcess, pDllMem, strDll, sizeof(strDll), NULL) );
    
    			typedef DWORD (WINAPI ThreadProc)(void*);
    			HMODULE hKernel32 = ::GetModuleHandle(_T("Kernel32"));
    			ThreadProc* pLoadLibrary = (ThreadProc*)GetProcAddress(hKernel32, "LoadLibraryA");
    			//FreeLibrary(hKernel32);
    
    			HANDLE hLoadLibraryThread = CreateRemoteThread(hProcess, NULL, 0, pLoadLibrary, pDllMem, NULL, NULL);
    			CHandle hhLoadLibraryThrad(hLoadLibraryThread);
    			WaitForSingleObject(hLoadLibraryThread, INFINITE);
    
    			HMODULE hDll;
    			ASSERT( GetExitCodeThread(hLoadLibraryThread, (DWORD*)&hDll) );
    			ASSERT( VirtualFreeEx(hProcess, pDllMem, 0, MEM_DECOMMIT) );
    			MessageBox(_T("App hooked successfully!"), _T("Success!"), MB_ICONINFORMATION);
    		}
    	}
    Then unload the DLL from within the hooked app:
    Code:
    	HMODULE hHookedDll = GetModuleHandle(_T("ThreadSpy.dll"));
    	ASSERT( FreeLibrary(hHookedDll) );
    Then inject again, and boom - crash.
    The crash happens inside CRT's DllInit from what I see. It's a call to GetProcAddress that kills it. I'll keep working on it.

    On second notice, I think there's a bug in the hooking code. It seems that it jumps to an invalid address when calling GetProcAddress (which is hooked!). Do I smell the bug here?
    The problem is, indeed, as I feared. The stupid thing is not unhooking functions correctly, thus causing crashes when the hooked functions are called and the DLL is unloaded.
    And this isn't even my code... Nightmare... >_<

    Ah, but application paths can cause so much trouble. It works fine now that I reconfigured the projects and made sure all paths are correct.
    The fix didn't work because it was using the wrong build >_<
    Last edited by Elysia; 03-15-2008 at 05:47 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    The piece of code you posted where you get the handle to the DLL, is that code from inside the DllMain function?

    If so, why use GetModuleHandle? A handle to the DLL itself it automatically passed to DllMain as first argument.

    Code:
    BOOL APIENTRY DllMain (HINSTANCE hInst     /* ** HANDLE IS HERE ** Library instance handle. */ ,
                           DWORD reason        /* Reason this function is being called. */ ,
                           LPVOID reserved     /* Not used. */ )
    {
                           
        
                           
        switch (reason)
        {
          case DLL_PROCESS_ATTACH:
               MessageBox(0, "Hey!", "Hey!", MB_OK);
               FreeLibrary(hInst);  /* Unload the DLL using the handle passed to DllMain */
            break;
    
          case DLL_PROCESS_DETACH:
            break;
    
          case DLL_THREAD_ATTACH:
            break;
    
          case DLL_THREAD_DETACH:
            break;
        }
    
        /* Returns TRUE on success, FALSE on failure */
        return TRUE;
    }
    If I inject this dll into a process, it unloads properly and injects properly again and again.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The application that I inject the DLL into is the one that unloads it, not the DLL itself.
    The actual test wouldn't work otherwise:

    Code:
    	if ( ExitWindowsEx(0xFF/*EWX_LOGOFF*/, 0) )
    	{
    		AbortSystemShutdown(NULL);
    		MessageBox(_T("System log out successfully initiated and aborted!"), _T("Success"), MB_ICONINFORMATION);
    	}
    	else
    		MessageBox(_T("Failed to log out!"), _T("Error"), MB_ICONERROR);
    And if the SpyThread.dll is injected properly:

    Code:
    BOOL WINAPI MyExitWindowsEx(UINT uFlags, DWORD dwReason)
    {
    	MessageBox(NULL, "System shutdown... DENIED!", "", 0);
    	return FALSE;
    }
    I get feedback.
    I put it as buttons on a dialog to test if it worked.
    Now it unloads fine, but I seem to have run into another problem. It never injects the code at all - CreateRemoteThread fails for some reason. Currently investigating why.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    Quote Originally Posted by Elysia View Post
    The application that I inject the DLL into is the one that unloads it, not the DLL itself.
    The actual test wouldn't work otherwise:

    Code:
    	if ( ExitWindowsEx(0xFF/*EWX_LOGOFF*/, 0) )
    	{
    		AbortSystemShutdown(NULL);
    		MessageBox(_T("System log out successfully initiated and aborted!"), _T("Success"), MB_ICONINFORMATION);
    	}
    	else
    		MessageBox(_T("Failed to log out!"), _T("Error"), MB_ICONERROR);
    And if the SpyThread.dll is injected properly:

    Code:
    BOOL WINAPI MyExitWindowsEx(UINT uFlags, DWORD dwReason)
    {
    	MessageBox(NULL, "System shutdown... DENIED!", "", 0);
    	return FALSE;
    }
    I get feedback.
    I put it as buttons on a dialog to test if it worked.
    Now it unloads fine, but I seem to have run into another problem. It never injects the code at all - CreateRemoteThread fails for some reason. Currently investigating why.
    Are you getting debug privileges before trying to opening the process / creating the thread?

    I have some code handy that you can use to get debug privilege token for your process, if you want it.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    From what I know currently, it's something in the initialization code that fails. Because even a call to LoadLibrary loads & unloads the dll directly.
    Debug token is not necessary I think. The code worked fine before...

    I wonder if I have to inject depedant DLLs first...

    Nope. It won't load the DLL at all, even if injected into the hooking process itself. And Visual Studio won't let me set a breakpoint earlier than DllMain, so I can't see WTF is going on.

    Hmmm. Is it the DLL to load, the parameter to LoadLibrary that's missing!?!

    We have success on this day! It's no fun when you can't use the debugger. Turns out the argument to LoadLibrary was missing.
    Last edited by Elysia; 03-15-2008 at 07:39 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yup, I know that. But I managed to solve it anyway
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Lame null append cause buffer to crash
    By cmoo in forum C Programming
    Replies: 8
    Last Post: 12-29-2008, 03:27 AM
  2. Can not debug a crash
    By hannibar in forum Windows Programming
    Replies: 2
    Last Post: 06-30-2007, 10:02 AM
  3. Strange error while attempting API hooking
    By cefarix in forum Windows Programming
    Replies: 2
    Last Post: 11-10-2006, 01:29 PM
  4. Dynamic array sizing causes crash
    By Mithoric in forum C++ Programming
    Replies: 3
    Last Post: 12-30-2003, 07:46 AM
  5. FYI: asctime(gmtime(&mytime)) = crash!
    By anonytmouse in forum C Programming
    Replies: 2
    Last Post: 09-29-2003, 02:24 AM