Snifing specific Win32 API calls (system wide)

I need to catch specific Win32 API calls to winmm.dll (system wide). I'd appritiate any ideas,

Vladip (
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

One easy way is to get SoftICE from Numega, it is a powerful debug tool, allow you to trace any API (and much more...)
I think vladip wanted to do it programmatically.
Programmatically?  Easy, you write soft ice.
C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

I remember seing a description of how to do it.  Unfortunately, lost the reference (sysinternals?)
vladipAuthor Commented:
I need to do sniffing by myself in my aplication, so it doesn't help too much that SoftICE is doing it.
The only solution I'm thinking about is to inject all processes with my dll which will snif each process independently. But for that I need to be notified each time process is going to be created. I don't know how to do it.
For hooking the process and thread creation or deletion see PMon
vladipAuthor Commented:
Pmon is not  good enough.
First, in order to inject dll I need to be called by Loader BEFORE application is started. And second, I need soution for both 95 and NT.

Thanks for your help guys. Don't give up!!!!
>> The only solution I'm thinking about is to inject all processes with my dll
I'm not sure how that is going to help you.  I'm curious though.

If you use a system hook, set by SetWindowsHook(), you can get your DLL mapped into every process.  The event you hook doesn't matter and what you do to handle (ignore) the event doesn't matter.

Now this maps the DLL into the process after it loads, not before.  But I can't see how that matters.
A solution, sort of like the one employed by numga, is to replace the system DLLs with your own DLLs.  These new DLLs do your work and forward the call on to the original system DLLs.  To do this, you have to install your DLLs before windows propper loads.   In 95 this can be done using a DOS program called from the autoexec (if you want to do this each time you boot), or by a DOS install program that is run from DOS compatibility mode.
Note to other experts:  This is in response to an e-mail sent to be me by vladip.  

>> I think thatyour idea (with WindowsHook) will work
Test it first, before you close this question.  

>>The only question I still have is how can I give you points for your answer
If you grade the question with an A - D, then the expert who has the question locked gets the points.  Currently that is faster.  If you want the points to go to a different expert, reject the current answer and ask that expert you want to get the points to submit a "dummy" answer.

>> (BTW how much points should I give for such answer)
You've already committed 200 points.  You can raise that if you wish, but you can't lower it.  If an expert answers a question that is at a particular  point value, then they feel that it is worth that point value, so you are not obligated to raise the value.  

Most importantly, always try to get a working solution before you accept an answer.
I've put sample if intercepting API call at
and here is listing:

/** intercept.cpp                                                          **/
/** ---------------------------------------------------------------------- **/
/** Example of interception of an API or any DLL function call             **/
/** ---------------------------------------------------------------------- **/
/** The method shown here may be very impressive in conjunction with       **/
/** CreateRemoteThread API                                                 **/
/** ---------------------------------------------------------------------- **/
/** July 23, 1998 by Oleg Kagan                                            **/


#include <windows.h>

// Switch all optimizations off
// (Visual C specific... For any other compiler do the same thing)
#pragma optimize("", off)

#define MakePtr(Type, Base, Offset) ((Type)(DWORD(Base) + (DWORD)(Offset)))

BOOL InterceptDllCall(

      HMODULE hLocalModule,
      const char* c_szDllName,
      const char* c_szApiName,
      PVOID pApiNew,
      PVOID* p_pApiOrg,
      PVOID pApiToChange
    DWORD dwProtect;
      BOOL bSuccess = FALSE;
    DWORD dwAddressToIntercept;

      if (pApiToChange) {
            dwAddressToIntercept = (DWORD)pApiToChange;
      else {
            dwAddressToIntercept = (DWORD)GetProcAddress(
                  GetModuleHandle((char*)c_szDllName), (char*)c_szApiName
            ) /*GetProcAddress*/;
      } /*iff*/;

    if (IsBadReadPtr(hLocalModule, sizeof(PIMAGE_NT_HEADERS)))
        return FALSE;
    if (pDOSHeader->e_magic != IMAGE_DOS_SIGNATURE)
        return FALSE;
    pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
    if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
        return FALSE;
    pImportDesc = MakePtr(
            PIMAGE_IMPORT_DESCRIPTOR, hLocalModule,
            ] /*pNTHeader->OptionalHeader.DataDirectory*/.VirtualAddress
      ) /*MakePtr*/;
    if (pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader) return FALSE;
      while (pImportDesc->Name) {
            PIMAGE_THUNK_DATA pThunk;
            pThunk = MakePtr(
                  PIMAGE_THUNK_DATA, hLocalModule, pImportDesc->FirstThunk
            ) /*MakePtr*/;
            while (pThunk->u1.Function) {
                  if (DWORD(pThunk->u1.Function) == dwAddressToIntercept) {      
                        if (
                                    (LPVOID)pThunk->u1.Function, sizeof(DWORD)
                              ) /*!IsBadWritePtr*/
                              if (p_pApiOrg)
                                    *p_pApiOrg = PVOID(pThunk->u1.Function);
                              (PDWORD)pThunk->u1.Function = (PDWORD)pApiNew;
                              bSuccess = TRUE;
                        else {
                              if (
                                          (LPVOID)(&pThunk->u1.Function), sizeof(DWORD),
                                          PAGE_EXECUTE_READWRITE, &dwProtect
                                    ) /*VirtualProtect*/
                                    DWORD dwNewProtect;

                                    if (p_pApiOrg)
                                          *p_pApiOrg = PVOID(pThunk->u1.Function);
                                    pThunk->u1.Function = (PDWORD)pApiNew;
                                    bSuccess = TRUE;

                                    dwNewProtect = dwProtect;
                                          (LPVOID)(&pThunk->u1.Function), sizeof(DWORD),
                                          dwNewProtect, &dwProtect
                                    ) /*VirtualProtect*/;
                              } /*if*/
                        } /*iff*/
                  } /*if*/
            } /*while*/
      } /*while*/

    return bSuccess;
} /*InterceptDllCall(HMODULE, const char*, const char*, PVOID,PVOID*,PVOID)*/

BOOL Win32IsNT()
      static unsigned uIsNT = 2;
      if (uIsNT > 1) {
            // Check NT or Win95/98
            OSVERSIONINFO VersionInfo; {
                  VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
            } /*VersionInfo*/

            uIsNT = (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
      } /*if*/
      return (uIsNT != 0);
} /*Win32IsNT()*/

void ChangeText(

      char* szText
      size_t nLength = strlen(szText);
      for (size_t i = 0; i < nLength; ++i) {
            szText[i] = char((i % 2) ? tolower(szText[i]) : toupper(szText[i]));
      } /*for (size_t i)*/
} /*ChangeText(char*)*/

typedef int (*TMessageBoxFuncPtr)(HWND, LPCTSTR, LPCTSTR, UINT);
TMessageBoxFuncPtr p_fnMessageBoxOrg = NULL;

int WINAPI MyMessageBox(

      HWND hWnd,          // handle of owner window
      LPCTSTR lpText,     // address of text in message box
      LPCTSTR lpCaption,  // address of title of message box
      UINT uType          // style of message box

      if (!p_fnMessageBoxOrg) return 0;
      ChangeText((char*)lpText); ChangeText((char*)lpCaption);
      int nResult = (*p_fnMessageBoxOrg)(hWnd, lpText, lpCaption, uType);
      return nResult;

extern "C" int WINAPI WinMain(

      HINSTANCE hInstance,  // handle to current instance
      HINSTANCE /*hPrevInstance*/,  // handle to previous instance
      LPSTR szCmdLine,  // pointer to command line
      int /*nCmdShow*/  // show state of window

      char* c_szTitle = "API Call Interception";

      if (!Win32IsNT()) {
                  "Sorry, but this example works under Microsoft Windows NT only",
                  c_szTitle, uStyle
            ) /*MessageBox*/;
            return EXIT_FAILURE;
      } /*if*/

      MessageBox(NULL, "Here it is normal                 ", c_szTitle, uStyle);

      // Lets Change it
            hInstance, "user32.dll", "MessageBoxA",
            (PVOID)&MyMessageBox, (PVOID*)&p_fnMessageBoxOrg,
      ) /*InterceptDllCall*/;

      MessageBox(NULL, "Beware of the mad hackers         ", c_szTitle, uStyle);

            hInstance, "user32.dll", "MessageBoxA",
            (PVOID)p_fnMessageBoxOrg, NULL, (PVOID)MyMessageBox
      ) /*InterceptDllCall*/;

      MessageBox(NULL, "Here it is almoust normal again :)", c_szTitle, uStyle);

      return EXIT_SUCCESS;

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
System wide injection is comming soon as DLL with the function like:

BOOL InjectDllIntoProcess(
    HPROCESS hProcess, // Process to inject into :)
    const wchar_t* c_wszDllToInject, // name of the DLL that contain Your code
    const wchar_t* c_wszStartupFunction // name of the void WINAPI Foo(HPROCESS hProcess) function that is going to receive control

vladip... I did it... i can sent to You dll that can help You to inject Your dll into any process and intercept any API... so afterwards You need just to intercept LoadLibrary and/or CreateProcess, etc. APIs and "infect" resulting modules again :)
I still working on simple tool do to do system wide "infection" :) but You can make Your own using the tools i developed already... its easy :) give me Your email and i'll send it to You

Good Luck
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.