IAT patching, problem when calling back to original target function?

chrispauljarram
chrispauljarram used Ask the Experts™
on
Hi,

I was wondering if an expert could help me with IAT patching on NT based O/Ss as I've come a little unstuck.  I'm trying to install an API hook using DLL injection (LoadLibrary/CreateRemoteThread technique), and then patch a couple of OpenGL functions to be able to intercept their parameters and perform operations before calling the originals.  All of this is working apart from, it seems, when I call back to the original versions of functions that have a parameter list - calling back to functions with no parameters is fine.

I suspect it is how I've specified by function pointers, I'm new to this technique and can't seem to figure out which is the correct way of doing things.  When I call back to the original functions with the parameter list it just crashes the target process.

The code I'm using is as follows:-

// Pointer to original function:

void (WINAPI *glRotatefOrig)(GLfloat  angle, GLfloat x, GLfloat y, GLfloat z);

// Code to get original function pointer:

glRotatefOrig = (void (WINAPI *)(GLfloat, GLfloat, GLfloat, GLfloat)) GetProcAddress(hMod, "glRotatef"); // hMod = handle to openGL module.

// My own function implentation (this is called successfully by the target process following IAT patch):

void myglRotatef( GLfloat angle,  GLfloat x,  GLfloat y,  GLfloat z)
{
      console->Write("glRotatef Called\n"); // prints ok
      glRotatefOrig(angle, x, y, z); // This call crashes the application (no meaningful error given).
}

Can anyone possibly point me to where I'm going wrong?  I've tried numerous different ways of specifying the original function pointer but all end in tears :/

Cheers in advance if you can help,
Chris
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®

Author

Commented:
Any help at alll?  Apologies, it is fairly urgent.  I forgot to mention (if it's any help at all) that the IAT patching function I'm using here is the ReplaceIATEntryInOneMod(PCSTR pszCalleeModName, PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) found in other threads in the knowledgebase.  I did have a look and see there are experts in IAT patching here but couldn't quite find the answer I was looking for.

Thanks,
Chris J
Hi chrispauljarram,

I'm not sure if this is the reason, but I guess you need to declare the pointer as an 'extern "C"' since the functions come from a C compiled library.

To do so please try this:

extern "C"
{
 typedef void (WINAPI *GlRotateProc)(GLfloat, GLfloat, GLfloat, GLfloat );
}

...
GlRotateProc glRotatefOrig = (GlRotateProc)GetProcAddress( ... );
...

Hope that helps,

ZOPPO

Author

Commented:
Hi Zoppo,

Thanks for jumping on this one.. I tried what you said however and I still get the same problem :(   I know this is definately possible as others have IAT patched this function successfully previously.

Again, with your way of doing things above, the functions with no argument lists work fine but when I try and call one with parameters all I get is '<appname> has stopped working' (I'm running win 7 x86).

This works fine:

extern "C"
{
typedef void (WINAPI *GlFlushProc)();
}
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

Author

Commented:
(Sorry, annoyingly that posted itself somehow before I finished writing it!  Here it is again:)

Hi Zoppo,

Thanks for jumping on this one.. I tried what you said however and I still get the same problem :(   I know this is definately possible as others have IAT patched this function successfully previously.

Again, with your way of doing things above, the functions with no argument lists work fine but when I try and call one with parameters all I get is '<appname> has stopped working' (I'm running win 7 x86).

This works fine:

extern "C"
{
  typedef void (WINAPI *GlFlushProc)();
}

GlFlushProc glFlushOrig;

...

glFlushOrig = (GlFlushProc) GetProcAddress(hMod, "glFlush");


// My own function...

/**
 */
void myglFlush()
{
  console->Write("glFlush Called\n");
  glFlushOrig(); // callback to original - this works fine when there is no param list.
}


I'm a little stumped but surely it must be something simple..  I'm using all the correct datatypes from what I can see so its a bit of a weird one.  Is there anything else you know of that I can try? :-/

Thanks again,
Chris
Commented:
Hi Chris,

IAT patching is something I fiddled with quite a lot not so long ago: J.Richter's books really are required reading on this :)

I wrote a wrapper class, inspired by the above gentleman, which enabled me to successfully hook functions such as ::MessageBox etc.  I have attached my helper class below, along with example usage.  Please try it out using your OpenGL functions - it should work without problem.

You will see that when I hook the call to ::MessageBox, I change the text that was originally specified to "I have hooked this call!"
// Set up the hook
VERIFY ( CFuncInAPIHook::Instance().HookFunction ( _T("user32.dll"), _T("MessageBoxW"), AfxGetInstanceHandle(), ( PROC )&MyMessageBox ) );

// Replacement procedure
int WINAPI MyMessageBox( HWND hWnd,
    LPCTSTR lpText,
    LPCTSTR lpCaption,
    UINT uType
)
{
	// Function pointer must have same calling convention as PROC (WINAPI)!  Therefore, prepend WINAPI (__stdcall)!
	typedef int  (WINAPI *MESSAGEBOX_FUNC)(HWND, LPCTSTR, LPCTSTR, UINT);

	// Only retrieve the original function's address once!
	static MESSAGEBOX_FUNC pFunc = ( MESSAGEBOX_FUNC ) CFuncInAPIHook::Instance().RetrieveOriginalAPIFunctionAddress ( _T("user32.dll"), _T("MessageBoxW") );
	ASSERT ( pFunc );
	return pFunc ? ( *pFunc )( hWnd, _T("I have hooked this call!"), lpCaption, uType ) : 0;
}

// This call will be hooked
::MessageBox ( NULL, _T(""), _T("Title"), MB_OK );

Open in new window

APIFunctionHooker.h
APIFunctionHooker.cpp

Author

Commented:
Hi mrwad99,

I shall give that a try this pm, thanks for that!  I would say though the only line that matters is:

// Only retrieve the original function's address once!
      static MESSAGEBOX_FUNC pFunc = ( MESSAGEBOX_FUNC ) CFuncInAPIHook::Instance().RetrieveOriginalAPIFunctionAddress ( _T("user32.dll"), _T("MessageBoxW") );
      ASSERT ( pFunc );
      return pFunc ? ( *pFunc )( hWnd, _T("I have hooked this call!"),

I know I am getting the original function address ok, and I am calling back to it using essentially the same mechanism as you:

 ( *pFunc )( hWnd, _T("I have hooked this call!")

This is where it is failing, if I debug into the assembly of the target app. I get a 'privaledged instruction' error.

Will let you know if this works shortly anyway, hopefully I've missed something simple.

Cheers,
Chris

Commented:
Not really.  It depends on how you have "patched" the memory that contains the address of the API you wish to override with your custom function.  If you look deep into my code, you will see bits like

[code]
                  // The addresses match; change the import section address.
                  // NOTE: the memory assigned for the code is read-only by default.  We need to change the protection mode prior to the write
                  // otherwise we will fail in release mode with 998: "Invalid access to memory location".
                  DWORD dwOrgProtect ( 0 );
                  VirtualProtect ( ppfn, sizeof ( pFuncReplacement ), PAGE_READWRITE, &dwOrgProtect );
                  BOOL bOK = WriteProcessMemory ( GetCurrentProcess(), ppfn, &pFuncReplacement, sizeof ( pFuncReplacement ), NULL );
                  VirtualProtect ( ppfn, sizeof ( pFuncReplacement ), dwOrgProtect , &dwOrgProtect );      // Restore original protection mode.
                  if ( bOK ) return TRUE;
[/code]

Just as one example.  This really is delicate stuff.  But either way, if you don't get it working with this code, post your usage code and I will try it at my end.

Author

Commented:
Gonna give it a try now...

I am using VirtualProtect before WriteProcessMemory, but I'm not restoring the original protection mode so that might have something to do with it?

Will let you know how I get on.. thanks again :)

Author

Commented:
Hi mrwad99,

Hmm, well restoring the original privs didn't make any difference - just trying your library but says I'm missing ExensionDLL.h.. Could you possibly post this and any other dependencies I may need here?

Cheers,
Chris

Commented:
Yeah sorry about that; this is part of a DLL that contains mixed functionality; this class was just one part.  

Remove references to ExtensionDLL.h, and remove DLL_SPEC.

That should do the trick.

Author

Commented:
Hi again,

Working thanks! :)  Very helpful indeed.

I'm not sure what was going wrong as poking around in your code revealed I am largely doing the same thing, however I created a completely new project and now seems to work with your libraries :-/

Thanks so much for the help, has saved me a real headache...

Chris

Commented:
Excellent, glad to be of help.  If you have any problems using it anytime, post back here :)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial