Detours3.0下的Traceapi.dll实例可以Attach到任意Win32应用程序中并监控API调用的情况。

原版的Traceapi.dll使用Makefile编译并调用首先用syelogd实例监听然后调用withdll实例将traceapi.dll挂载到目标应用程序中。文件多,调用频繁,在以后的使用当中十分不方便。

重写思路:

直接重写监听实例syelogd的主函数,在获取命令行中添加一个选项可以直接指定要挂载的程序然后在执行监听之后调用DetourCreateProcessWithDll函数将traceapi.dll挂载到指定的exe文件中并启动exe。

MyTraceapi.cpp:

 
  
  1. //////////////////////////////////////////////////////////////////////////////  
  2. //  
  3. //  Detours Test Program (syelogd.cpp of syelogd.exe)  
  4. //  
  5. //  Microsoft Research Detours Package, Version 3.0.  
  6. //  
  7. //  Copyright (c) Microsoft Corporation.  All rights reserved.  
  8. //  
  9. #include <windows.h>  
  10. #include <stdio.h>  
  11. #include <stdlib.h>  
  12. #include <stddef.h>  
  13. #include <string.h>  
  14. #include "syelog.h"  
  15. #include <detours.h>  
  16. #include <detver.h>  
  17.  
  18. #pragma comment(lib,"detours.lib")  
  19. #pragma comment(lib,"ws2_32.lib")  
  20. #pragma comment(lib,"mswsock.lib")  
  21. #pragma comment(lib,"advapi32.lib")  
  22.  
  23. #if (_MSC_VER < 1299)  
  24. typedef ULONG * PULONG_PTR;  
  25. typedef ULONG ULONG_PTR;  
  26. typedef LONG * PLONG_PTR;  
  27. typedef LONG LONG_PTR;  
  28. #endif  
  29.  
  30. enum {  
  31.     CLIENT_AWAITING_PIPE_ACCEPT = 0x21,  
  32.     CLIENT_AWAITING_PIPE_DATA   = 0x22,  
  33. };  
  34.  
  35. typedef struct _CLIENT : OVERLAPPED  
  36. {  
  37.     HANDLE          hPipe;  
  38.     BOOL            fAwaitingAccept;  
  39.     PVOID           Zero;  
  40.     SYELOG_MESSAGE  Message;  
  41. } CLIENT, *PCLIENT;  
  42.  
  43. //////////////////////////////////////////////////////////////////////////////  
  44. //  
  45. BOOL        s_fLogToScreen  = TRUE;     // Log output to screen.  
  46. BOOL        s_fExitAfterOne = FALSE;  
  47. BOOL        s_fDeltaTime    = FALSE;  
  48. HANDLE      s_hOutFile      = INVALID_HANDLE_VALUE;  
  49.  
  50. LONG        s_nActiveClients = 0;  
  51. LONGLONG    s_llStartTime = 0;  
  52. LONGLONG    s_llLastTime = 0;  
  53.  
  54. BOOL LogMessageV(BYTE nSeverity, PCHAR pszMsg, ...);  
  55.  
  56. //////////////////////////////////////////////////////////////////////////////  
  57. //  
  58. VOID MyErrExit(PCSTR pszMsg)  
  59. {  
  60.     DWORD error = GetLastError();  
  61.  
  62.     LogMessageV(SYELOG_SEVERITY_FATAL, "Error %d in %s.", error, pszMsg);  
  63.     fprintf(stderr, "SYELOGD: Error %d in %s.\n", error, pszMsg);  
  64.     fflush(stderr);  
  65.     exit(1);  
  66. }  
  67.  
  68. //////////////////////////////////////////////////////////////////////////////  
  69. //  
  70. static PCSTR FileTimeToString(PCHAR pszBuffer, DWORD cbBuffer, FILETIME ftTime)  
  71. {  
  72.     (void)cbBuffer;  
  73.  
  74.     static BOOL bGotTzi = FALSE;  
  75.     static DWORD dwTzi = TIME_ZONE_ID_UNKNOWN;  
  76.     static TIME_ZONE_INFORMATION tzi;  
  77.     if (!bGotTzi) {  
  78.         dwTzi = GetTimeZoneInformation(&tzi);  
  79.         if (dwTzi == TIME_ZONE_ID_UNKNOWN) {  
  80.             ZeroMemory(&tzi, sizeof(tzi));  
  81.         }  
  82.         bGotTzi = TRUE;  
  83.     }  
  84.     SYSTEMTIME stUtc;  
  85.     SYSTEMTIME stLocal;  
  86.  
  87.     pszBuffer[0] = '\0';  
  88.  
  89.     if (s_fDeltaTime) {  
  90.         if (s_llLastTime == 0) {  
  91.             s_llLastTime = s_llStartTime;  
  92.         }  
  93.  
  94.         ULARGE_INTEGER ul;  
  95.         ul.LowPart = ftTime.dwLowDateTime;  
  96.         ul.HighPart = ftTime.dwHighDateTime;  
  97.  
  98.         ULONG64 delta = ul.QuadPart - s_llLastTime;  
  99.         s_llLastTime = ul.QuadPart;  
  100.         delta /= 10000;  
  101.  
  102. #ifdef _CRT_INSECURE_DEPRECATE  
  103.         sprintf_s(pszBuffer, cbBuffer, "%7I64d", delta);  
  104. #else  
  105.         sprintf(pszBuffer, "%7I64d", delta);  
  106. #endif  
  107.     }  
  108.     else {  
  109.         if (!FileTimeToSystemTime(&ftTime, &stUtc)) {  
  110. #ifdef _CRT_INSECURE_DEPRECATE  
  111.             sprintf_s(pszBuffer, cbBuffer, "ft:%16I64d", *(LONGLONG *)&ftTime);  
  112. #else  
  113.             sprintf(pszBuffer, "ft:%16I64d", *(LONGLONG *)&ftTime);  
  114. #endif  
  115.             return pszBuffer;  
  116.         }  
  117.         else if (!SystemTimeToTzSpecificLocalTime(&tzi, &stUtc, &stLocal)) {  
  118.             CopyMemory(&stLocal, &stUtc, sizeof(stLocal));  
  119.         }  
  120.  
  121. #ifdef _CRT_INSECURE_DEPRECATE  
  122.         sprintf_s(pszBuffer, cbBuffer, "%4d%02d%02d%02d%02d%02d%03d",  
  123.             stLocal.wYear,  
  124.             stLocal.wMonth,  
  125.             stLocal.wDay,  
  126.             stLocal.wHour,  
  127.             stLocal.wMinute,  
  128.             stLocal.wSecond,  
  129.             stLocal.wMilliseconds);  
  130. #else  
  131.         sprintf(pszBuffer, "%4d%02d%02d%02d%02d%02d%03d",  
  132.             stLocal.wYear,  
  133.             stLocal.wMonth,  
  134.             stLocal.wDay,  
  135.             stLocal.wHour,  
  136.             stLocal.wMinute,  
  137.             stLocal.wSecond,  
  138.             stLocal.wMilliseconds);  
  139. #endif  
  140.     }  
  141.     return pszBuffer;  
  142. }  
  143.  
  144. BOOL CloseConnection(PCLIENT pClient)  
  145. {  
  146.     LogMessageV(SYELOG_SEVERITY_INFORMATION, "Client closed pipe.");  
  147.  
  148.     InterlockedDecrement(&s_nActiveClients);  
  149.     if (pClient != NULL) {  
  150.         if (pClient->hPipe != INVALID_HANDLE_VALUE) {  
  151.             FlushFileBuffers(pClient->hPipe);  
  152.             if (!DisconnectNamedPipe(pClient->hPipe)) {  
  153.                 MyErrExit("DisconnectNamedPipe");  
  154.             }  
  155.             CloseHandle(pClient->hPipe);  
  156.             pClient->hPipe = INVALID_HANDLE_VALUE;  
  157.         }  
  158.         GlobalFree(pClient);  
  159.         pClient = NULL;  
  160.     }  
  161.  
  162.     if (s_fExitAfterOne) {  
  163.         ExitProcess(0);  
  164.     }  
  165.     return TRUE;  
  166. }  
  167.  
  168. // Creates a pipe instance and initiate an accept request.  
  169. //  
  170. PCLIENT CreatePipeConnection(HANDLE hCompletionPort)  
  171. {  
  172.     HANDLE hPipe = CreateNamedPipe(SYELOG_PIPE_NAME,           // pipe name  
  173.         PIPE_ACCESS_INBOUND |       // read-only access  
  174.         FILE_FLAG_OVERLAPPED,       // overlapped mode  
  175.         PIPE_TYPE_MESSAGE |         // message-type pipe  
  176.         PIPE_READMODE_MESSAGE |     // message read mode  
  177.         PIPE_WAIT,                   // blocking mode  
  178.         PIPE_UNLIMITED_INSTANCES,   // unlimited instances  
  179.         0,                          // output buffer size  
  180.         0,                          // input buffer size  
  181.         20000,                      // client time-out  
  182.         NULL);                      // no security attributes  
  183.     if (hPipe == INVALID_HANDLE_VALUE) {  
  184.         MyErrExit("CreatePipe");  
  185.     }  
  186.  
  187.     // Allocate the client data structure.  
  188.     //  
  189.     PCLIENT pClient = (PCLIENT) GlobalAlloc(GPTR, sizeof(CLIENT));  
  190.     if (pClient == NULL) {  
  191.         MyErrExit("GlobalAlloc pClient");  
  192.     }  
  193.  
  194.     ZeroMemory(pClient, sizeof(*pClient));  
  195.     pClient->hPipe = hPipe;  
  196.     pClient->fAwaitingAccept = TRUE;  
  197.  
  198.     // Associate file with our complietion port.  
  199.     //  
  200.     if (!CreateIoCompletionPort(pClient->hPipe, hCompletionPort, (ULONG_PTR)pClient, 0)) {  
  201.         MyErrExit("CreateIoComplietionPort pClient");  
  202.     }  
  203.  
  204.     if (!ConnectNamedPipe(hPipe, pClient)) {  
  205.         if (GetLastError() != ERROR_IO_PENDING &&  
  206.             GetLastError() != ERROR_PIPE_LISTENING) {  
  207.                 MyErrExit("ConnectNamedPipe");  
  208.         }  
  209.     }  
  210.     else {  
  211.         LogMessageV(SYELOG_SEVERITY_INFORMATION,  
  212.             "ConnectNamedPipe accepted immediately.");  
  213.     }  
  214.     return pClient;  
  215. }  
  216.  
  217. BOOL LogMessageV(BYTE nSeverity, PCHAR pszMsg, ...)  
  218. {  
  219.     FILETIME ftOccurance;  
  220.     CHAR szTime[64];  
  221.     GetSystemTimeAsFileTime(&ftOccurance);  
  222.     FileTimeToString(szTime, sizeof(szTime), ftOccurance);  
  223.  
  224.     if (s_fLogToScreen) {  
  225.         printf(s_fDeltaTime  
  226.             ? "%-7.7s ---- --.%02x: " 
  227.             : "%-17.17s ---- --.%02x: " 
  228.             , szTime, nSeverity);  
  229.         va_list args;  
  230.         va_start(args, pszMsg);  
  231.         vprintf(pszMsg, args);  
  232.         va_end(args);  
  233.         printf("\n");  
  234.     }  
  235.     if (s_hOutFile != INVALID_HANDLE_VALUE) {  
  236.         DWORD cbWritten = 0;  
  237.         CHAR szBuf[4096];  
  238.         INT cbToWrite;  
  239.  
  240. #ifdef _CRT_INSECURE_DEPRECATE  
  241.         cbToWrite = _snprintf_s(szBuf, sizeof(szBuf), sizeof(szBuf)-1,  
  242.             s_fDeltaTime  
  243.             ? "%-7.7s ---- --.%02x: " 
  244.             : "%-17.17s ---- --.%02x: " 
  245.             , szTime, nSeverity);  
  246. #else  
  247.         cbToWrite = _snprintf(szBuf, sizeof(szBuf),  
  248.             s_fDeltaTime  
  249.             ? "%-7.7s ---- --.%02x: " 
  250.             : "%-17.17s ---- --.%02x: " 
  251.             , szTime, nSeverity);  
  252. #endif  
  253.  
  254.         va_list args;  
  255.         va_start(args, pszMsg);  
  256. #ifdef _CRT_INSECURE_DEPRECATE  
  257.         cbToWrite += _vsnprintf_s(szBuf + cbToWrite,  
  258.             sizeof(szBuf) - cbToWrite,  
  259.             sizeof(szBuf) - cbToWrite - 1,  
  260.             pszMsg, args);  
  261. #else  
  262.         cbToWrite += _vsnprintf(szBuf + cbToWrite, sizeof(szBuf) - cbToWrite, pszMsg, args);  
  263. #endif  
  264.         va_end(args);  
  265.  
  266. #ifdef _CRT_INSECURE_DEPRECATE  
  267.         cbToWrite += _snprintf_s(szBuf + cbToWrite,  
  268.             sizeof(szBuf) - cbToWrite,  
  269.             sizeof(szBuf) - cbToWrite - 1,  
  270.             "\n");  
  271. #else  
  272.         cbToWrite += _snprintf(szBuf + cbToWrite, sizeof(szBuf) - cbToWrite, "\n");  
  273. #endif  
  274.  
  275.         if (cbToWrite < 0) {  
  276.             szBuf[sizeof(szBuf)-2] = '\n';  
  277.             szBuf[sizeof(szBuf)-1] = '\0';  
  278.             cbToWrite = sizeof(szBuf);  
  279.         }  
  280.         WriteFile(s_hOutFile, szBuf, cbToWrite, &cbWritten, NULL);  
  281.     }  
  282.     return TRUE;  
  283. }  
  284.  
  285. BOOL LogMessage(PSYELOG_MESSAGE pMessage, DWORD nBytes)  
  286. {  
  287.     // Sanity check the size of the message.  
  288.     //  
  289.     if (nBytes > pMessage->nBytes) {  
  290.         nBytes = pMessage->nBytes;  
  291.     }  
  292.     if (nBytes >= sizeof(*pMessage)) {  
  293.         nBytes = sizeof(*pMessage) - 1;  
  294.     }  
  295.  
  296.     // Don't log message if there isn't and message text.  
  297.     //  
  298.     if (nBytes <= offsetof(SYELOG_MESSAGE, szMessage)) {  
  299.         return FALSE;  
  300.     }  
  301.  
  302.     CHAR szTime[64];  
  303.     FileTimeToString(szTime, sizeof(szTime), pMessage->ftOccurance);  
  304.  
  305.     PCHAR pszMsg = pMessage->szMessage;  
  306.     while (*pszMsg) {  
  307.         pszMsg++;  
  308.     }  
  309.     while (pszMsg > pMessage->szMessage && isspace(pszMsg[-1])) {  
  310.         *--pszMsg = '\0';  
  311.     }  
  312.  
  313.     if (s_fLogToScreen) {  
  314.         printf(s_fDeltaTime  
  315.             ? "%-7.7s %4d %02x.%02x: %s\n" 
  316.             : "%-17.17s %4d %02x.%02x: %s\n",  
  317.             szTime,  
  318.             pMessage->nProcessId,  
  319.             pMessage->nFacility,  
  320.             pMessage->nSeverity,  
  321.             pMessage->szMessage);  
  322.     }  
  323.     if (s_hOutFile != INVALID_HANDLE_VALUE) {  
  324.         DWORD cbWritten = 0;  
  325.         CHAR szBuf[4096];  
  326.         INT cbToWrite;  
  327.  
  328. #ifdef _CRT_INSECURE_DEPRECATE  
  329.         cbToWrite = _snprintf_s(szBuf, sizeof(szBuf), sizeof(szBuf) - 1,  
  330.             s_fDeltaTime  
  331.             ? "%-7.7s %4d %02x.%02x: %s\n" 
  332.             : "%-17.17s %4d %02x.%02x: %s\n",  
  333.             szTime,  
  334.             pMessage->nProcessId,  
  335.             pMessage->nFacility,  
  336.             pMessage->nSeverity,  
  337.             pMessage->szMessage);  
  338. #else  
  339.         cbToWrite = _snprintf(szBuf, sizeof(szBuf),  
  340.             s_fDeltaTime  
  341.             ? "%-7.7s %4d %02x.%02x: %s\n" 
  342.             : "%-17.17s %4d %02x.%02x: %s\n",  
  343.             szTime,  
  344.             pMessage->nProcessId,  
  345.             pMessage->nFacility,  
  346.             pMessage->nSeverity,  
  347.             pMessage->szMessage);  
  348. #endif  
  349.  
  350.         if (cbToWrite < 0) {  
  351.             szBuf[sizeof(szBuf)-2] = '\n';  
  352.             szBuf[sizeof(szBuf)-1] = '\0';  
  353.             cbToWrite = sizeof(szBuf);  
  354.         }  
  355.         WriteFile(s_hOutFile, szBuf, cbToWrite, &cbWritten, NULL);  
  356.     }  
  357.     return TRUE;  
  358. }  
  359.  
  360. DWORD WINAPI WorkerThread(LPVOID pvVoid)  
  361. {  
  362.     PCLIENT pClient;  
  363.     BOOL b;  
  364.     LPOVERLAPPED lpo;  
  365.     DWORD nBytes;  
  366.     HANDLE hCompletionPort = (HANDLE)pvVoid;  
  367.  
  368.     for (BOOL fKeepLooping = TRUE; fKeepLooping;) {  
  369.         pClient = NULL;  
  370.         lpo = NULL;  
  371.         nBytes = 0;  
  372.         b = GetQueuedCompletionStatus(hCompletionPort,  
  373.             &nBytes, (PULONG_PTR)&pClient, &lpo, INFINITE);  
  374.  
  375.         if (!b || lpo == NULL) {  
  376.             fKeepLooping = FALSE;  
  377.             MyErrExit("GetQueuedCompletionState");  
  378.             break;  
  379.         }  
  380.         else if (!b) {  
  381.             if (pClient) {  
  382.                 if (GetLastError() == ERROR_BROKEN_PIPE) {  
  383.                     LogMessageV(SYELOG_SEVERITY_INFORMATION, "Client closed pipe.");  
  384.                 }  
  385.                 else {  
  386.                     LogMessageV(SYELOG_SEVERITY_ERROR,  
  387.                         "GetQueuedCompletionStatus failed %d [%p]",  
  388.                         GetLastError(), pClient);  
  389.                 }  
  390.                 CloseConnection(pClient);  
  391.             }  
  392.             continue;  
  393.         }  
  394.  
  395.         if (pClient->fAwaitingAccept) {  
  396.             InterlockedIncrement(&s_nActiveClients);  
  397.             pClient->fAwaitingAccept = FALSE;  
  398.             b = ReadFile(pClient->hPipe,  
  399.                 &pClient->Message,  
  400.                 sizeof(pClient->Message),  
  401.                 &nBytes,  
  402.                 pClient);  
  403.             if (!b) {  
  404.                 if (GetLastError() != ERROR_IO_PENDING) {  
  405.                     LogMessageV(SYELOG_SEVERITY_ERROR,  
  406.                         "ReadFile failed %d.", GetLastError());  
  407.                     continue;  
  408.                 }  
  409.             }  
  410.  
  411.             CreatePipeConnection(hCompletionPort);  
  412.         }  
  413.         else {  
  414.             if (nBytes < offsetof(SYELOG_MESSAGE, szMessage)) {  
  415.                 CloseConnection(pClient);  
  416.             }  
  417.  
  418.             if (pClient->Message.fTerminate) {  
  419.                 LogMessageV(SYELOG_SEVERITY_NOTICE,  
  420.                     "Client requested terminate on next connection close.");  
  421.                 s_fExitAfterOne = TRUE;  
  422.             }  
  423.  
  424.             LogMessage(&pClient->Message, nBytes);  
  425.  
  426.             b = ReadFile(pClient->hPipe,  
  427.                 &pClient->Message,  
  428.                 sizeof(pClient->Message),  
  429.                 &nBytes,  
  430.                 pClient);  
  431.             if (!b && GetLastError() == ERROR_BROKEN_PIPE) {  
  432.                 CloseConnection(pClient);  
  433.             }  
  434.         }  
  435.     }  
  436.     return 0;  
  437. }  
  438.  
  439. BOOL CreateWorkers(HANDLE hCompletionPort)  
  440. {  
  441.     DWORD dwThread;  
  442.     HANDLE hThread;  
  443.     DWORD i;  
  444.     SYSTEM_INFO SystemInfo;  
  445.  
  446.     GetSystemInfo(&SystemInfo);  
  447.  
  448.     for (i = 0; i < 2 * SystemInfo.dwNumberOfProcessors; i++) {  
  449.         hThread = CreateThread(NULL, 0, WorkerThread, hCompletionPort, 0, &dwThread);  
  450.         if (!hThread) {  
  451.             MyErrExit("CreateThread WorkerThread");  
  452.             // Unreachable: return FALSE;  
  453.         }  
  454.         CloseHandle(hThread);  
  455.     }  
  456.     return TRUE;  
  457. }  
  458.  
  459. //////////////////////////////////////////////////////////////////////////////  
  460. //  
  461. BOOL WINAPI ControlHandler(DWORD dwCtrlType)  
  462. {  
  463.     switch (dwCtrlType) {  
  464.     case CTRL_C_EVENT:  
  465.     case CTRL_BREAK_EVENT:  
  466.     case CTRL_CLOSE_EVENT:  
  467.     case CTRL_LOGOFF_EVENT:  
  468.     case CTRL_SHUTDOWN_EVENT:  
  469.         LogMessageV(SYELOG_SEVERITY_INFORMATION, "User requested stop.");  
  470.         printf("\nSYELOGD: Closing connections.\n");  
  471.         if (s_hOutFile != INVALID_HANDLE_VALUE) {  
  472.             printf("Closing file.\n");  
  473.             FlushFileBuffers(s_hOutFile);  
  474.             CloseHandle(s_hOutFile);  
  475.             s_hOutFile = INVALID_HANDLE_VALUE;  
  476.         }  
  477.         ExitProcess(0);  
  478.     }  
  479.     return FALSE;  
  480. }  
  481.  
  482. DWORD main(int argc, char **argv)  
  483. {  
  484.     HANDLE hCompletionPort;  
  485.     BOOL fNeedHelp = FALSE;  
  486.     STARTUPINFO si;  
  487.     PROCESS_INFORMATION pi;  
  488.     LPVOID lpAppName;  
  489.     LPSTR lpDllName = "traceapi.dll";  
  490.     GetSystemTimeAsFileTime((FILETIME *)&s_llStartTime);  
  491.     SetConsoleCtrlHandler(ControlHandler, TRUE);  
  492.     BOOL fResult = TRUE;  
  493.     int arg = 1;  
  494.     for (; arg < argc; arg++) {  
  495.         int iCmdLength = strlen(argv[arg]);  
  496.         LPSTR lpCheck = (argv[arg]+(iCmdLength-3));  
  497.         if (argv[arg][0] == '-' || argv[arg][0] == '/') {  
  498.             CHAR *argn = argv[arg] + 1;  
  499.             CHAR *argp = argn;  
  500.             while (*argp && *argp != ':') {  
  501.                 argp++;  
  502.             }  
  503.             if (*argp == ':') {  
  504.                 *argp++ = '\0';  
  505.             }  
  506.  
  507.             switch (argn[0]) {  
  508.  
  509.             case 'd':                                 // Delta time.  
  510.             case 'D':  
  511.                 s_fDeltaTime = TRUE;  
  512.                 break;  
  513.  
  514.             case 'o':                                 // Only one.  
  515.             case 'O':  
  516.                 s_fExitAfterOne = TRUE;  
  517.                 break;  
  518.  
  519.             case 'q':                                 // Quiet.  
  520.             case 'Q':  
  521.                 s_fLogToScreen = FALSE;  
  522.                 break;  
  523.  
  524.             case '?':                                 // Help.  
  525.                 fNeedHelp = TRUE;  
  526.                 break;  
  527.  
  528.             default:  
  529.                 fNeedHelp = TRUE;  
  530.                 printf("SYELOGD: Bad argument: %s:%s\n", argn, argp);  
  531.                 break;  
  532.             }  
  533.         }  
  534.         else if(lstrcmp(lpCheck,"exe") == 0){  
  535.             lpAppName = HeapAlloc(GetProcessHeap(),0,MAX_PATH);  
  536.             ZeroMemory(lpAppName,MAX_PATH);  
  537.             lpAppName = argv[arg];  
  538.         }else if(lstrcmp(lpCheck,"txt") == 0){  
  539.             if (s_hOutFile != INVALID_HANDLE_VALUE) {  
  540.                 printf("SYELOGD: Error, more than one output file specified.\n\n");  
  541.                 fNeedHelp = TRUE;  
  542.                 break;  
  543.             }  
  544.  
  545.             s_hOutFile = CreateFile(argv[arg],  
  546.                 GENERIC_WRITE,  
  547.                 FILE_SHARE_READ,  
  548.                 NULL,  
  549.                 CREATE_ALWAYS,  
  550.                 FILE_ATTRIBUTE_NORMAL |  
  551.                 FILE_FLAG_SEQUENTIAL_SCAN,  
  552.                 NULL);  
  553.             if (s_hOutFile == INVALID_HANDLE_VALUE) {  
  554.                 printf("SYELOGD: Error opening output file: %s: %d\n\n",  
  555.                     argv[arg], GetLastError());  
  556.                 fNeedHelp = TRUE;  
  557.                 break;  
  558.             }  
  559.             else {  
  560.                 printf("SYELOGD: Logging to %s.\n", argv[arg]);  
  561.             }  
  562.         }else{  
  563.             lpAppName = HeapAlloc(GetProcessHeap(),0,MAX_PATH);  
  564.             ZeroMemory(lpAppName,MAX_PATH);  
  565.             lpAppName = "";  
  566.         }  
  567.     }  
  568.     if (fNeedHelp) {  
  569.         printf("Usage:\n" 
  570.             "    %s [options] {output_file} {injfile_path}\n" 
  571.             "Options:\n" 
  572.             "    /d         List delta time in ms from previous event (not absolute time).\n" 
  573.             "    /o         Exit after one client disconnects.\n" 
  574.             "    /q         Disable event logging to screen (quiet mode).\n" 
  575.             "    /?         Display this help message.\n" 
  576.             "Summary:\n" 
  577.             "    If given, all events will be logged to the output file.\n" 
  578.             "\n",argv[0]);  
  579.         exit(1);  
  580.     }  
  581.  
  582.  
  583.     // Create the completion port.  
  584.     hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);  
  585.     if (hCompletionPort == NULL) {  
  586.         MyErrExit("CreateIoCompletionPort");  
  587.     }  
  588.  
  589.     // Create completion port worker threads.  
  590.     //  
  591.     CreateWorkers(hCompletionPort);  
  592.     CreatePipeConnection(hCompletionPort);  
  593.     printf("SYELOGD: Target process:%s\n",lpAppName);  
  594.     printf("SYELOGD: Ready for clients.  Press Ctrl-C to stop.\n");  
  595.     ZeroMemory(&si,sizeof(STARTUPINFO));  
  596.     ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));  
  597.     si.cb = sizeof(STARTUPINFO);  
  598.     fResult = DetourCreateProcessWithDll((LPSTR)lpAppName,NULL,NULL,NULL,FALSE,CREATE_DEFAULT_ERROR_MODE,NULL,NULL,&si,&pi,lpDllName,NULL);  
  599.     if(!fResult){  
  600.         printf("Detour %s to %s failed.(%d)\n",lpDllName,lpAppName,GetLastError());  
  601.         return 0;  
  602.     }  
  603.     while (argc) {  
  604.         Sleep(10000);  
  605.     }  
  606.  
  607.     SetConsoleCtrlHandler(ControlHandler, FALSE);  
  608.  
  609.     if (s_hOutFile != INVALID_HANDLE_VALUE) {  
  610.         FlushFileBuffers(s_hOutFile);  
  611.         CloseHandle(s_hOutFile);  
  612.         s_hOutFile = INVALID_HANDLE_VALUE;  
  613.     }  
  614.  
  615.     return 0;  
  616. }  
  617. //  
  618. //////////////////////////////////////////////////////////////////////////////  

调用Nmake出来的现成的traceapi.dll

重写后的程序只有一个exe一个dll,可以指定要挂载的exe文件:


 

随便操作一下计算器,关掉,会在当前目录下生成log.txt记录了calc.exe api的调用情况。