Overriding Dll



This part of documentation explains you how to build an overriding dll.

You can find examples in the "Overriding Dll SDK" directory.



To know which kind of hook you want to write, take a look at the Hooking Sequence
An overriding dll alows you to add 3 different hooks:
1) Overrinding hook : to fully replace function code (allow to avoid to call original function)
2) Pre API call hook : allow to call one or more functions before the API is called. These functions allow to change parameter(s) content.
3) Post API call hook : allow to call one or more functions after the API is called. These functions allow to change returned value and output parameter(s) content.

When writing an overrinding function, take care of parameters, because they can be NULL
So, don't hesitate to do parameter checking before using them, like in the following example
If (!IsBadRead(Value,sizeof(TypeOfValue))
// my secured code goes here

1) Overriding Hook
  - Explanation
  - MessageBox example
  - Exe intenal example
  - Asm exe internal example

2) Pre Hook
  - Explanation
  - MessageBox example

3) Post Hook
  - Explanation
  - MessageBox example

4) Initializing data
  - Initializing data at dll loading

5) Debugging
  - Debugging an overriding Dll


1) Overriding Hook
Explanation

1) First an overriding dll must contain a redirection array.
This array defines a redirection table and the size of arguments.

By the way if we want to redirect MessageBoxA calls to your own mMessageBoxA function, you need to had the following line to array

{_T("User32.dll"),_T("MessageBoxA"),(FARPROC)mMessageBoxA,StackSizeOf(HWND)+StackSizeOf(LPCSTR)+StackSizeOf(LPCSTR)+StackSizeOf(UINT),0}

The _T macro is just for an ansi/unicode compatibility.
Library name "User32.dll" and function name "MessageBoxW" allow to get the address of original function to redirect.
mMessageBoxW gives the address of your own function.

At this point there's enough information to redirect.

You next need to specify the size of parameters. This is done thanks to the "StackSizeOf" macro. So only do the sum of all StackSizeOf(ParameterType).

Optionaly you can use the last array element to specify a different hook way (see the following for more information)

2) From now you only have to fill the content of your mMessageBoxA function.

Keep exactly the same parameters and calling convention than the original function

To override a Borland / Embarcadero fastcall function, you need to use the Borland / Embarcadero compiler to build the overriding dll

You can use the original function call inside your function as many time as you want.
You will not reenter the hook.
Notice : it's wrong only if you are monitoring the function in the same time with a |BlockingCall option specified and if Powerless hooks option is used.
In this case and only this one, you can reenter the hook by calling original function

 
All provided examples are located in the "OverridingSDK folder"


Array syntax :

{ LibraryName ,FunctionName, FunctionHandler, StackSize, Additional Options}

LibraryName is library name or one of WinAPIOverride keyword (DLL_ORDINAL@0xAddress@LibraryName, EXE_INTERNAL@0xAddress, EXE_INTERNAL_RVA@0xRelativeAddress,
DLL_INTERNAL@0xAddress@LibraryName, EXE_INTERNAL_POINTER@0xAddress, EXE_INTERNAL_RVA_POINTER@0xRelativeAddress, DLL_INTERNAL_POINTER@0xAddress@LibraryName)

FunctionName : function name
Notice : For DLL_ORDINAL, EXE_INTERNAL, EXE_INTERNAL_RVA, DLL_INTERNAL, EXE_INTERNAL_POINTER, EXE_INTERNAL_RVA_POINTER and DLL_INTERNAL_POINTER you can put whatever you want for "FunctionName" parameter :
as full address is specified by first parameter, FunctionName becomes useless.


FunctionHandler : function called instead of original one : Must have same calling convention and parameters !

StackSize : stack size required by the function ( = sum(StackSizeOf(ParameterType))

Additional Options :
   Before Winapioverride 5.5.1 (overriding framework sdk version < 6)
FirstBytesCanExecuteAnywhereSize :
It allows you to specify if first bytes of function can be executed in another location.
It's the same feature as the monitoring file "|FirstBytesCanExecuteAnywhere=" keyword. (see monitoring file advanced options)
Put 0 if you want your dll to be the more portable. (Winapioverride will try to get the more efficient size by disassembling first opcodes)
Else enter the number of first bytes to be executed at another location (between 5 and 64)
If you want your function don't execute at another place (same as "|FirstBytesCantExecuteAnywhere" monitoring file keyword), put 0xFFFFFFFF.

   Since Winapioverride 5.5.1 (overriding framework sdk version >= 6)
Combinaison (binary or) between the following :
a) FirstBytesCanExecuteAnywhereSize :
It allows you to specify if first bytes of function can be executed in another location.
It's the same feature as the monitoring file "|FirstBytesCanExecuteAnywhere=" keyword. (see monitoring file advanced options)
Put 0 if you want your dll to be the more portable. (Winapioverride will try to get the more efficient size by disassembling first opcodes)
Else enter the number of first bytes to be executed at another location (between 5 and 64)
If you want your function don't execute at another place (same as "|FirstBytesCantExecuteAnywhere" monitoring file keyword),
use the OVERRIDING_DLL_API_OVERRIDE_EXTENDED_OPTION_FIRST_BYTES_CANT_EXECUTE_ANYWHERE flag.

b) OVERRIDING_DLL_API_OVERRIDE_EXTENDED_OPTION_DONT_CHECK_MODULES_FILTERS flag :
allow overriding to bypass overriding module filtering. That means your function will always be called instead of original API whatever the calling module.


Array Items Examples
{_T("User32.dll"),_T("MessageBoxA"),(FARPROC)mMessageBoxA,StackSizeOf(HWND)+StackSizeOf(LPCSTR)+StackSizeOf(LPCSTR)+StackSizeOf(UINT),0}
{_T("EXE_INTERNAL@0x4010A0"),_T("RotateRegisters"),(FARPROC)mRotateRegisters,0,0}
{_T("EXE_INTERNAL@0x401000"),_T("add"),(FARPROC)mInternalAddSample,StackSizeOf(int)+StackSizeOf(int),0}

{_T("DLL_INTERNAL@0x1000@MyDll"),_T("TheNameIWant"),(FARPROC)myFunc,StackSizeOf(BYTE),0}
{_T("DLL_ORDINAL@0x1e4@user32.dll"),_T("MessageBoxW"),(FARPROC)mMessageBoxW,StackSizeOf(HWND)+StackSizeOf(LPCWSTR)+StackSizeOf(LPCWSTR)+StackSizeOf(UINT),0}


MessageBox example

  1. #include "../../GenericFakeAPI.h"
  2.  
  3. int WINAPI mMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);
  4. int WINAPI mMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);
  5.  
  6. ///////////////////////////////////////////////////////////////////////////////
  7. // Overriding API array. Redirection are defined here
  8. ///////////////////////////////////////////////////////////////////////////////
  9. STRUCT_FAKE_API pArrayFakeAPI[]=
  10. {
  11. // library name ,function name, function handler, stack size (required to allocate enough stack space)
  12. // stack size= sum(StackSizeOf(ParameterType))
  13. {_T("User32.dll"),_T("MessageBoxA"),(FARPROC)mMessageBoxA,StackSizeOf(HWND)+StackSizeOf(LPCSTR)+StackSizeOf(LPCSTR)+StackSizeOf(UINT),0},
  14. {_T("User32.dll"),_T("MessageBoxW"),(FARPROC)mMessageBoxW,StackSizeOf(HWND)+StackSizeOf(LPCWSTR)+StackSizeOf(LPCWSTR)+StackSizeOf(UINT),0},
  15. {_T(""),_T(""),NULL,0,0}// last element for ending loops
  16. };
  17.  
  18. int WINAPI mMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)
  19. {
  20. UNREFERENCED_PARAMETER(lpCaption);
  21.  
  22. char szMsg[2*MAX_PATH];
  23. strcpy(szMsg,"Oups !! It's not your text !!!\r\n[Begin of] Original Text :\r\n");
  24. strncat(szMsg,lpText,MAX_PATH-strlen(szMsg)-1);
  25. szMsg[MAX_PATH-1]=0;// assume end of string
  26. return MessageBoxA(NULL,szMsg,"API Override:MessageBoxA",uType);
  27. }
  28.  
  29.  
  30. int WINAPI mMessageBoxW(HWND hWnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
  31. {
  32. UNREFERENCED_PARAMETER(lpCaption);
  33. wchar_t szMsg[2*MAX_PATH];
  34.  
  35. wcscpy(szMsg,L"Oups !! It's not your text !!!\r\n[Begin of] Original Text :\r\n");
  36. wcsncat(szMsg,lpText,MAX_PATH-wcslen(szMsg)-1);
  37. szMsg[MAX_PATH-1]=0;// assume end of string
  38.  
  39. return MessageBoxW(NULL,szMsg,L"API Override:mMessageBoxW",uType);
  40. }


Exe intenal example

  1. #include "../../GenericFakeAPI.h"
  2.  
  3. int _cdecl mInternalAddSample(int a,int b);
  4.  
  5. STRUCT_FAKE_API pArrayFakeAPI[]=
  6. {
  7. {_T("EXE_INTERNAL@0x401000"),_T("add"),(FARPROC)mInternalAddSample,StackSizeOf(int)+StackSizeOf(int),0},
  8. {_T(""),_T(""),NULL,0,0}// last element for ending loops
  9. };
  10.  
  11. int _cdecl mInternalAddSample(int a,int b) // _cdecl only if your internal func is _cdecl
  12. {
  13. // make a mult instead of add
  14. return a*b;
  15. }



Asm exe internal example

  1. #include "../../GenericFakeAPI.h"
  2.  
  3. extern "C" void mRotateRegisters();
  4.  
  5. STRUCT_FAKE_API pArrayFakeAPI[]=
  6. {
  7. // library name ,function name, function handler, stack size (required to allocate enough stack space)
  8. // stack size= sum(StackSizeOf(ParameterType))
  9. {_T("EXE_INTERNAL@0x4010A0"),_T("RotateRegisters"),(FARPROC)mRotateRegisters,0,0},
  10. {_T(""),_T(""),NULL,0,0}// last element for ending loops
  11. };
  12.  
  13. ///////////////////////////////////////////////////////////////////////////////
  14. // your overriding asm sources are located in an .asm file
  15. ///////////////////////////////////////////////////////////////////////////////
Source code of asm file :
  1. .386
  2. .MODEL flat, C
  3.  
  4. .CODE
  5.  
  6. mRotateRegisters PROC
  7.  
  8. ; rotate registers in another order
  9. push edx
  10. mov edx,ecx
  11. mov ecx,ebx
  12. mov ebx,eax
  13. pop eax
  14. ret
  15.  
  16. ret
  17. mRotateRegisters ENDP
  18. END

2) Pre Hook

Explanation

You have to fill the redirection array called "pArrayBeforeAPICall".

Array syntax :

{ LibraryName ,FunctionName, FunctionHandler, StackSize, FirstBytesCanExecuteAnywhereSize,UserParam}

LibraryName is library name or one of WinAPIOverride keyword (DLL_ORDINAL@0xAddress@LibraryName, EXE_INTERNAL@0xAddress,
DLL_INTERNAL@0xAddress@LibraryName, EXE_INTERNAL_POINTER@0xAddress, DLL_INTERNAL_POINTER@0xAddress@LibraryName)

FunctionName : function name
Notice : For DLL_ORDINAL, EXE_INTERNAL, DLL_INTERNAL, EXE_INTERNAL_POINTER and DLL_INTERNAL_POINTER you can put whatever you want for "FunctionName" parameter :
as full address is specified by first parameter, FunctionName becomes useless.


FunctionHandler : function called before the original one. See below for it's declaration

StackSize : stack size rquired by the function ( = sum(StackSizeOf(ParameterType))

FirstBytesCanExecuteAnywhereSize : same keyword as monitoring file one. Put 0 for better compatibility (for more information see monitoring files advanced syntax)
and put 0xFFFFFFFF, if you want your function don't execute at another place (same as "|FirstBytesCantExecuteAnywhere" monitoring file keyword)

UserParam : a value that will be provided to you as UserParam arg when your hook function will be called

FunctionHandler decalration :

Here the call back function must have following declaration
BOOL __stdcall YourFunction(PBYTE pEspArgs,REGISTERS* pBeforeCallRegisters,PRE_POST_API_CALL_HOOK_INFOS* pHookInfos,PVOID UserParam).

where provided parameters are the following :

pEspArgs : pointer to current stack.
So parameter 0 = *((PBYTE*)pEspArgs);
parameter 1= *((PBYTE*)(pEspArgs+StackSizeOf(Param0Type)))
parameter 2 = *((PBYTE*)(pEspArgs+StackSizeOf(Param0Type)+StackSizeOf(Param1Type)))

pBeforeCallRegisters register (eax, ebx, ...)

pHookInfos : gives you some information like:
   - the return address of API having created object,
   - the handle of module having done call
   - if current call match current overriding modules filters

UserParam : UserParam value provided in pArrayBeforeAPICall.

Returned Value : As you can use multiple Pre Hook functions for the same API,
the returned value specify if other Pre Hook functions defined for this API must be called or not.
Returning TRUE, other functions will be called.
Returning FALSE, other functions won't be called.

MessageBox example

Example can be found in directory "Overriding Dll SDK\API\PrePostHooksMsgBox"

First we fill the pArrayBeforeAPICall array.
Here we use the same callback for MessageBoxA and MessageBoxW, using the user param to make difference in callback (0 for MessageBoxA and 1 for MessageBoxW)

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Before API call array. Redirection are defined here
  3. ///////////////////////////////////////////////////////////////////////////////
  4. STRUCT_FAKE_API_WITH_USERPARAM pArrayBeforeAPICall[]=
  5. {
  6. // library name ,function name, function handler, stack size , FirstBytesCanExecuteAnywhereSize ,userParam
  7. // stack size= sum(StackSizeOf(ParameterType))
  8. {_T("User32.dll"),_T("MessageBoxA"),(FARPROC)MessageBoxesPreApiCall,StackSizeOf(HWND)+StackSizeOf(LPCSTR)+StackSizeOf(LPCSTR)+StackSizeOf(UINT),0,0},
  9. {_T("User32.dll"),_T("MessageBoxW"),(FARPROC)MessageBoxesPreApiCall,StackSizeOf(HWND)+StackSizeOf(LPCWSTR)+StackSizeOf(LPCWSTR)+StackSizeOf(UINT),0,(PVOID)1},
  10. {_T(""),_T(""),NULL,0,0,0}// last element for ending loops
  11. };
Next we write our functions handler
  1. BOOL __stdcall MessageBoxesPreApiCall(PBYTE pEspArgs,REGISTERS* pBeforeCallRegisters,PRE_POST_API_CALL_HOOK_INFOS* pHookInfos,PVOID UserParam)
  2. {
  3. // to change parameters you can directly act on the stack or value pointed by the stack
  4.  
  5. // Reminder : MessageBox(HWND hWnd,LPCTSTR lpText,LPCSTR lpCaption,UINT uType);
  6. HWND Hwnd=(HWND)(*((PBYTE*)pEspArgs));
  7. PBYTE TextString=*((PBYTE*)(pEspArgs+1*sizeof(PBYTE)));
  8. PBYTE TextCaption=*((PBYTE*)(pEspArgs+2*sizeof(PBYTE)));
  9. UINT Type=(UINT)(*((PBYTE*)(pEspArgs+3*sizeof(PBYTE))));
  10.  
  11. // Warning you have to do your own memory protection
  12. if (IsBadReadPtr(TextString,sizeof(CHAR)))
  13. return TRUE;
  14. if (IsBadReadPtr(TextCaption,sizeof(CHAR)))
  15. return TRUE;
  16.  
  17. // change messagebox Type by acting on stack
  18. PBYTE* pArgType=(PBYTE*)(pEspArgs+3*sizeof(PBYTE));
  19. Type&=~MB_ICONERROR;
  20. Type&=~MB_ICONWARNING;
  21. Type|=MB_ICONINFORMATION;
  22. *pArgType=(PBYTE)Type;
  23.  
  24. // you can change some registers if you want
  25. pBeforeCallRegisters->eax=12;
  26.  
  27. if (UserParam==0)// messageBoxA
  28. {
  29. OutputDebugString(_T("MessageBoxesPreApiCall for MessageBoxA\r\n"));
  30. OutputDebugStringA((LPCSTR)TextString);
  31. OutputDebugStringA((LPCSTR)TextCaption);
  32.  
  33. // avoid to override statically allocated string
  34. if (!IsBadWritePtr(TextString,3*sizeof(CHAR)))
  35. {
  36. // change messagebox text by acting on value pointed by stack
  37. PCHAR pcTextString=(PCHAR)TextString;
  38. pcTextString[0]='O';
  39. pcTextString[1]='K';
  40. pcTextString[2]=' ';
  41. }
  42. }
  43. else // messageBoxW
  44. {
  45. OutputDebugString(_T("MessageBoxesPreApiCall for MessageBoxW\r\n"));
  46. OutputDebugStringW((LPCWSTR)TextString);
  47. OutputDebugStringW((LPCWSTR)TextCaption);
  48.  
  49. // avoid to override statically allocated string
  50. if (!IsBadWritePtr(TextString,3*sizeof(WCHAR)))
  51. {
  52. // change messagebox text by acting on value pointed by stack
  53. PWCHAR pwTextString=(PWCHAR)TextString;
  54. pwTextString[0]='O';
  55. pwTextString[1]='K';
  56. pwTextString[2]=' ';
  57. }
  58. }
  59.  
  60. // continue chain (if any other func)
  61. return TRUE;
  62. }

3) Post Hook

Explanation

You have to fill the redirection array called "pArrayAfterAPICall".

Array syntax :

{ LibraryName ,FunctionName, FunctionHandler, StackSize, FirstBytesCanExecuteAnywhereSize,UserParam}

LibraryName is library name or one of WinAPIOverride keyword (DLL_ORDINAL@0xAddress@LibraryName, EXE_INTERNAL@0xAddress,
DLL_INTERNAL@0xAddress@LibraryName, EXE_INTERNAL_POINTER@0xAddress, DLL_INTERNAL_POINTER@0xAddress@LibraryName)

FunctionName : function name
Notice : For DLL_ORDINAL, EXE_INTERNAL, DLL_INTERNAL, EXE_INTERNAL_POINTER and DLL_INTERNAL_POINTER you can put whatever you want for "FunctionName" parameter :
as full address is specified by first parameter, FunctionName becomes useless.


FunctionHandler : function called after the original one. See below for it's declaration

StackSize : stack size rquired by the function ( = sum(StackSizeOf(ParameterType))

FirstBytesCanExecuteAnywhereSize : same keyword as monitoring file one. Put 0 for better compatibility (for more information see monitoring files advanced syntax)
and put 0xFFFFFFFF, if you want your function don't execute at another place (same as "|FirstBytesCantExecuteAnywhere" monitoring file keyword)

UserParam : a value that will be provided to you as UserParam arg when your hook function will be called

FunctionHandler decalration :

Here the call back function must have following declaration
BOOL __stdcall YourFunction(PBYTE pEspArgs,REGISTERS* pAfterCallRegisters,PRE_POST_API_CALL_HOOK_INFOS* pHookInfos,PVOID UserParam).

where provided parameters are the following :

pEspArgs : pointer to current stack.
So parameter 0 = *((PBYTE*)pEspArgs);
parameter 1= *((PBYTE*)(pEspArgs+StackSizeOf(Param0Type)))
parameter 2 = *((PBYTE*)(pEspArgs+StackSizeOf(Param0Type)+StackSizeOf(Param1Type)))

pBeforeCallRegisters register (eax, ebx, ...)

pHookInfos : gives you some information like:
   - the return address of API having created object,
   - the handle of module having done call
   - if current call match current overriding modules filters

UserParam : UserParam value provided in pArrayBeforeAPICall.

Returned Value : As you can use multiple Pre Hook functions for the same API,
the returned value specify if other Pre Hook functions defined for this API must be called or not.
Returning TRUE, other functions will be called.
Returning FALSE, other functions won't be called.

MessageBox example

Example can be found in directory "Overriding Dll SDK\API\PrePostHooksMsgBox"

First we fill the pArrayAfterAPICall array.
Here we use the same 1 callback for MessageBoxA and 2 for MessageBoxW
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // After API call array. Redirection are defined here
  3. ///////////////////////////////////////////////////////////////////////////////
  4. STRUCT_FAKE_API_WITH_USERPARAM pArrayAfterAPICall[]=
  5. {
  6. // library name ,function name, function handler, stack size (required to allocate enough stack space), FirstBytesCanExecuteAnywhereSize ,userParam
  7. // stack size= sum(StackSizeOf(ParameterType))
  8. {_T("User32.dll"),_T("MessageBoxA"),(FARPROC)MessageBoxAPostApiCall,StackSizeOf(HWND)+StackSizeOf(LPCSTR)+StackSizeOf(LPCSTR)+StackSizeOf(UINT),0,0},
  9. {_T("User32.dll"),_T("MessageBoxW"),(FARPROC)MessageBoxWPostApiCall,StackSizeOf(HWND)+StackSizeOf(LPCWSTR)+StackSizeOf(LPCWSTR)+StackSizeOf(UINT),0,0},
  10. // the following is added to show you the chain mechanism, this declaration could have been in another overriding dll
  11. {_T("User32.dll"),_T("MessageBoxW"),(FARPROC)MessageBoxWPostApiCall2,StackSizeOf(HWND)+StackSizeOf(LPCWSTR)+StackSizeOf(LPCWSTR)+StackSizeOf(UINT),0,0},
  12. {_T(""),_T(""),NULL,0,0,0}// last element for ending loops
  13. };
Next we write our functions handler
  1. BOOL __stdcall MessageBoxAPostApiCall(PBYTE pEspArgs,REGISTERS* pAfterCallRegisters,PRE_POST_API_CALL_HOOK_INFOS* pHookInfos,PVOID UserParam)
  2. {
  3. // to change parameters you can directly act on the stack or value pointed by the stack
  4. // can be used to change output parameter values
  5.  
  6. // you can change after call register, by the way to modify the returned value
  7. pAfterCallRegisters->eax=0;// always set returned value to 0
  8.  
  9. OutputDebugString(_T("MessageBoxAPostApiCall\r\n"));
  10. // continue chain (if any other func)
  11. return TRUE;
  12. }
  13.  
  14. BOOL __stdcall MessageBoxWPostApiCall(PBYTE pEspArgs,REGISTERS* pAfterCallRegisters,PRE_POST_API_CALL_HOOK_INFOS* pHookInfos,PVOID UserParam)
  15. {
  16. OutputDebugString(_T("MessageBoxWPostApiCall\r\n"));
  17.  
  18. // to continue chain (allow MessageBoxWPostApiCall2 call)
  19. return TRUE;
  20.  
  21. // to stop chain (don't allow MessageBoxWPostApiCall2 call)
  22. // return FALSE;
  23. }
  24.  
  25. BOOL __stdcall MessageBoxWPostApiCall2(PBYTE pEspArgs,REGISTERS* pAfterCallRegisters,PRE_POST_API_CALL_HOOK_INFOS* pHookInfos,PVOID UserParam)
  26. {
  27. OutputDebugString(_T("MessageBoxWPostApiCall2\r\n"));
  28. // continue chain
  29. return TRUE;
  30. }

4) Initializing data

Initializing data at dll loading


By default, overriding dlls do not use DllMain. So fill free to use it to get function addresses, set some array UserParams, or do your own variables initialization.
By the way, if you need the NtDeviceIoControlFile function in your overrinding functions, as it must be dynamically loaded, you can do the following
  1. typedef NTSTATUS (__stdcall *pNtDeviceIoControlFile)(
  2. HANDLE FileHandle,
  3. HANDLE Event,
  4. PIO_APC_ROUTINE ApcRoutine,
  5. PVOID ApcContext,
  6. PIO_STATUS_BLOCK IoStatusBlock,
  7. ULONG IoControlCode,
  8. PVOID InputBuffer,
  9. ULONG InputBufferLength,
  10. PVOID OutputBuffer,
  11. ULONG OutputBufferLength);
  12.  
  13. pNtDeviceIoControlFile pfNtDeviceIoControlFile;
  14. BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, PVOID pvReserved)
  15. {
  16. UNREFERENCED_PARAMETER(pvReserved);
  17. switch (dwReason)
  18. {
  19. case DLL_PROCESS_ATTACH:
  20. // your initialization goes here
  21. pfNtDeviceIoControlFile=(pNtDeviceIoControlFile)GetProcAddress(GetModuleHandle(_T("ntdll.dll")),"NtDeviceIoControlFile");
  22. if (!pfNtDeviceIoControlFile)
  23. return FALSE;
  24. break;
  25.  
  26. case DLL_PROCESS_DETACH:
  27. // your destruction goes here
  28. break;
  29. }
  30.  
  31. return TRUE;
  32. }

5) Debugging

Debugging an overriding Dll

If your overriding dll is crashing, the following steps must be followed
Notice : A classical error is due to lack of parameter checking.

1) Assume that function can be hooked
To do it, just make a monitoring file containing only the function name you want to override.
Load it into your target application.
If monitoring works, that means function can be hooked and overrideed, else don't loose your time: it's not possible

2) Make test of your code in a small exe.
Copy the code of your overriding dll, and make a call of it in the main function
This can solve basics troubles.

3)
a) If code crash quicky :
Open your dll project, set it in debug configuration, put a breakpoint on your overrided functions, specify the targeted application path (or another application that call the overrided function) in the project properties under "Debbugging" / "Command".
Start debugging your dll project by pressing F5. Targetted application will start.
Now you have to load your overriding dll built in debug mode inside process. So use WinAPIOverride and load it inside the application being debugged.
The breakpoint will be reached the next time the API will be called, allowing you to quickly debug

b) If code doesn't crash quicky : you have to found parameters that are crashing your function, use the monitoring file created at step 1) and add the |InNoRet option.
Load your monitoring file, and next your dll.
When the target application crashs, just look at WinAPIOverride last log : it's the one responsable of crash.
So go back to 2) using the same parameters.
Notice: if parameters are unsopported, use the :DataSize and :PointedDataSize options,
or one of the break parameter option coupled with |breakBeforeCall option (see monitoring file advanced syntax)