home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 October / PCWorld_1999-10_cd1.bin / Hardware / Drivers / APISpy / APISpy32.cpp < prev    next >
C/C++ Source or Header  |  1999-07-25  |  19KB  |  882 lines

  1. // ----------------------------------- //
  2. //            APISpy32 v2.0            //
  3. //     Copyright 1999 Yariv Kaplan     //
  4. //          WWW.INTERNALS.COM          //
  5. // ----------------------------------- //
  6.  
  7. #include <windows.h>
  8. #include "APISpy32.h"
  9. #include "LinkList.h"
  10. #include "LogAPI.h"
  11.  
  12. #pragma check_stack(off)
  13.  
  14. #ifdef WIN95
  15.  
  16. #pragma comment(linker, "/section:.data,RWS /section:.idata,RWS /section:.bss,RWS")
  17. #pragma comment(linker, "/base:0xBFF70000")
  18.  
  19. #include "Ring0.h"
  20.  
  21. #endif
  22.  
  23. PSTR TrimString(PSTR pszStr);
  24. char *GetParamFormat(tagParamType ParamType);
  25. char *GetParamName(tagParamType ParamType);
  26. tagParamType GetParamType(PSTR pszParameter);
  27. DWORD GetParamMask(tagParamType ParamType);
  28. void FormatString(PSTR pszSrcStr, PSTR pszDstStr, DWORD dwMaxSize);
  29.  
  30.  
  31. tagParamSpec ParamSpec[] = {{"INT",    PARAM_INT,    "%d",  0xFFFFFFFF},
  32.                             {"DWORD",  PARAM_DWORD,  "%u",  0xFFFFFFFF},
  33.                             {"WORD",   PARAM_WORD,   "%u",  0x0000FFFF},
  34.                             {"BYTE",   PARAM_BYTE,   "%u",  0x000000FF},
  35.                             {"PSTR",   PARAM_PSTR,   "%#x", 0xFFFFFFFF},
  36.                             {"PVOID",  PARAM_PVOID,  "%#x", 0xFFFFFFFF},
  37.                             {"PINT",   PARAM_PINT,   "%#x", 0xFFFFFFFF},
  38.                             {"PDWORD", PARAM_PDWORD, "%#x", 0xFFFFFFFF},
  39.                             {"PWORD",  PARAM_PWORD,  "%#x", 0xFFFFFFFF},
  40.                             {"PBYTE",  PARAM_PBYTE,  "%#x", 0xFFFFFFFF},
  41.                             {"HANDLE", PARAM_HANDLE, "%#x", 0xFFFFFFFF},
  42.                             {"HWND",   PARAM_HWND,   "%#x", 0xFFFFFFFF},
  43.                             {"BOOL",   PARAM_BOOL,   "%u",  0xFFFFFFFF},
  44.                             {"PWSTR",  PARAM_PWSTR,  "%#x", 0xFFFFFFFF},
  45.                             {"UNKNOWN",PARAM_UNKNOWN,"%u",  0xFFFFFFFF}};
  46.  
  47. #ifdef WIN95
  48.  
  49. __declspec(naked) void Ring0ModifyPageProtection()
  50. {
  51.   _asm
  52.   {
  53.     Mov EAX, ECX
  54.     Shr EAX, 22
  55.     Test DWORD PTR [0FFBFE000h + EAX * 4], 1
  56.     Jz Fail
  57.  
  58.     Mov EAX, ECX
  59.     Shr EAX, 12
  60.     Mov EBX, EAX
  61.     Mov EAX, DWORD PTR [0FF800000h + EAX * 4]
  62.     Test EAX, 1
  63.     Jz Fail
  64.  
  65.     Mov EAX, 1
  66.  
  67.     Cmp EDX, PAGE_READWRITE
  68.     Je PageReadWrite
  69.  
  70.     And DWORD PTR [0FF800000h + EBX * 4], 0xFFFFFFFD
  71.     Jmp Done
  72.  
  73. PageReadWrite:
  74.  
  75.     Or DWORD PTR [0FF800000h + EBX * 4], 2
  76.     Jmp Done
  77.  
  78. Fail:
  79.  
  80.     Xor EAX, EAX
  81.  
  82. Done:
  83.  
  84.     Retf
  85.   }
  86. }
  87.  
  88.  
  89. bool CallRing0(PVOID pvRing0FuncAddr, PVOID pvAddr, DWORD dwPageProtection)
  90. {
  91.  
  92.   GDT_DESCRIPTOR *pGDTDescriptor;
  93.   GDTR gdtr;
  94.   bool Result;
  95.  
  96.   _asm Sgdt [gdtr]
  97.  
  98.   // Skip the null descriptor
  99.  
  100.   pGDTDescriptor = (GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8);
  101.  
  102.   // Search for a free GDT descriptor
  103.  
  104.   for (WORD wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++)
  105.   {
  106.     if (pGDTDescriptor->Type == 0     &&
  107.         pGDTDescriptor->System == 0   &&
  108.         pGDTDescriptor->DPL == 0      &&
  109.         pGDTDescriptor->Present == 0)
  110.     {
  111.       // Found one !
  112.       // Now we need to transform this descriptor into a callgate.
  113.       // Note that we're using selector 0x28 since it corresponds
  114.       // to a ring 0 segment which spans the entire linear address
  115.       // space of the processor (0-4GB).
  116.  
  117.       CALLGATE_DESCRIPTOR *pCallgate;
  118.  
  119.       pCallgate =    (CALLGATE_DESCRIPTOR *) pGDTDescriptor;
  120.       pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr);
  121.       pCallgate->Selector = 0x28;
  122.       pCallgate->ParamCount =    0;
  123.       pCallgate->Unused = 0;
  124.       pCallgate->Type = 0xc;
  125.       pCallgate->System = 0;
  126.       pCallgate->DPL = 3;
  127.       pCallgate->Present = 1;
  128.       pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr);
  129.  
  130.       // Prepare the far call parameters
  131.  
  132.       WORD CallgateAddr[3];
  133.  
  134.       CallgateAddr[0] = 0x0;
  135.       CallgateAddr[1] = 0x0;
  136.       CallgateAddr[2] = (wGDTIndex << 3) | 3;
  137.  
  138.       // Please fasten your seat belts!
  139.       // We're about to make a hyperspace jump into RING 0.
  140.  
  141.       _asm
  142.       {
  143.         Mov ECX, [pvAddr]
  144.         Mov EDX, [dwPageProtection]
  145.         Cli
  146.         Call FWORD PTR [CallgateAddr]
  147.         Sti
  148.         Mov DWORD PTR [Result], EAX
  149.       }
  150.       
  151.       // Now free the GDT descriptor
  152.  
  153.       memset(pGDTDescriptor, 0, 8);
  154.  
  155.       return Result;
  156.     }
  157.  
  158.     // Advance to the next GDT descriptor
  159.  
  160.     pGDTDescriptor++;
  161.   }
  162.  
  163.   // Whoops, the GDT is full
  164.  
  165.   return false;
  166. }
  167.  
  168.  
  169. bool RemovePageProtection(PVOID pvAddr)
  170. {
  171.   return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READWRITE);
  172. }
  173.  
  174.  
  175. bool SetPageProtection(PVOID pvAddr)
  176. {
  177.   return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READONLY);
  178. }
  179.  
  180. #endif
  181.  
  182.  
  183. void APILogFunction(tagAPIInfo *pAPIInfo, PSTR pszLogString, ...)
  184. {
  185.   va_list Marker;
  186.   DWORD dwParamValue;
  187.   char szParamStr[MAX_TEXT_LEN + 6];
  188.   char szUnicodeStr[MAX_TEXT_LEN + 1];
  189.   char cIndex;
  190.  
  191.   va_start(Marker, pszLogString);
  192.   
  193.   strcpy(pszLogString, pAPIInfo->szAPIName);
  194.   strcat(pszLogString, "(");
  195.  
  196.   for (cIndex = 0; cIndex < pAPIInfo->ParamCount; cIndex++)
  197.   {
  198.     dwParamValue = va_arg(Marker, DWORD);
  199.  
  200.     dwParamValue &= GetParamMask(pAPIInfo->ParamList[cIndex]);
  201.     
  202.     strcat(pszLogString, GetParamName(pAPIInfo->ParamList[cIndex]));
  203.     strcat(pszLogString, ":");
  204.     wsprintf(szParamStr, GetParamFormat(pAPIInfo->ParamList[cIndex]), dwParamValue);
  205.     strcat(pszLogString, szParamStr);
  206.  
  207.     switch (pAPIInfo->ParamList[cIndex])
  208.     {
  209.       case PARAM_PSTR:
  210.  
  211.         strcat(pszLogString, ":");
  212.         FormatString((PSTR)dwParamValue, szParamStr, MAX_TEXT_LEN);
  213.         strcat(pszLogString, szParamStr);
  214.  
  215.       break;
  216.       
  217.       case PARAM_PINT:
  218.  
  219.         strcat(pszLogString, ":");
  220.         
  221.         if (IsBadReadPtr((PVOID)dwParamValue, 4) == 0)
  222.         {
  223.           wsprintf(szParamStr, "%d", *(int *)dwParamValue);
  224.           strcat(pszLogString, szParamStr);
  225.         }
  226.         else strcat(pszLogString, "?");
  227.  
  228.       break;
  229.  
  230.       case PARAM_PDWORD:
  231.  
  232.         strcat(pszLogString, ":");
  233.  
  234.         if (IsBadReadPtr((PVOID)dwParamValue, 4) == 0)
  235.         {
  236.           wsprintf(szParamStr, "%u", *(DWORD *)dwParamValue);
  237.           strcat(pszLogString, szParamStr);
  238.         }
  239.         else strcat(pszLogString, "?");
  240.  
  241.       break;
  242.  
  243.       case PARAM_PWORD:
  244.  
  245.         strcat(pszLogString, ":");
  246.  
  247.         if (IsBadReadPtr((PVOID)dwParamValue, 2) == 0)
  248.         {
  249.           wsprintf(szParamStr, "%u", LOWORD(*(WORD *)dwParamValue));
  250.           strcat(pszLogString, szParamStr);
  251.         }
  252.         else strcat(pszLogString, "?");
  253.  
  254.       break;
  255.  
  256.       case PARAM_PBYTE:
  257.  
  258.         strcat(pszLogString, ":");
  259.  
  260.         if (IsBadReadPtr((PVOID)dwParamValue, 1) == 0)
  261.         {
  262.           wsprintf(szParamStr, "%u", LOBYTE(*(BYTE *)dwParamValue));
  263.           strcat(pszLogString, szParamStr);
  264.         }
  265.         else strcat(pszLogString, "?");
  266.  
  267.       break;
  268.  
  269.       case PARAM_PWSTR:
  270.  
  271.         strcat(pszLogString, ":");
  272.  
  273.         if (IsBadReadPtr((PVOID)dwParamValue, 2) == 0 &&
  274.             IsBadStringPtrW((LPCWSTR)dwParamValue, MAX_TEXT_LEN) == 0)
  275.         {
  276.           WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)dwParamValue, MAX_TEXT_LEN, szUnicodeStr, sizeof(szUnicodeStr), NULL, NULL);
  277.           szUnicodeStr[MAX_TEXT_LEN] = '\0';
  278.           FormatString(szUnicodeStr, szParamStr, MAX_TEXT_LEN);
  279.           strcat(pszLogString, szParamStr);
  280.         }
  281.         else strcat(pszLogString, "?");
  282.  
  283.       break;
  284.     }
  285.  
  286.     strcat(pszLogString, ", ");
  287.   }
  288.  
  289.   if (pAPIInfo->ParamCount > 0)
  290.     pszLogString[strlen(pszLogString) - 2] = ')';
  291.   else
  292.     strcat(pszLogString, ")");
  293.  
  294.   va_end(Marker);
  295. }
  296.  
  297.  
  298. bool ParseAPIFile(PSTR pszFileName)
  299. {
  300.   HANDLE hFile;
  301.   HANDLE hMap;
  302.   DWORD dwIndex;
  303.   PSTR pszParameterList;
  304.   PSTR pszParameter;
  305.   PSTR pszModuleName;
  306.   PSTR pszAPIName;
  307.   PCHAR pcFile;
  308.   DWORD dwFileSize;
  309.   char cParamIndex;
  310.   tagAPIInfo *pAPIInfo;
  311.   char szAPIDefinition[1024];
  312.   
  313.   hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  314.                      OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  315.  
  316.   if (hFile == INVALID_HANDLE_VALUE)
  317.     return false;
  318.  
  319.   dwFileSize = GetFileSize(hFile, NULL);
  320.  
  321.   if (dwFileSize == 0xFFFFFFFF)
  322.     return false;
  323.  
  324.   hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  325.  
  326.   if (hMap == NULL) 
  327.   {
  328.     CloseHandle(hFile);
  329.     return false;
  330.   }
  331.  
  332.   pcFile = (PCHAR)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  333.  
  334.   if (pcFile == NULL) 
  335.   {
  336.     CloseHandle(hMap);
  337.     CloseHandle(hFile);
  338.     return false;
  339.   }
  340.  
  341.   while (dwFileSize)
  342.   {
  343.     for (dwIndex = 0; *pcFile != 13 && dwFileSize; dwIndex++)
  344.     {
  345.       szAPIDefinition[dwIndex] = *pcFile;
  346.       pcFile++;
  347.       dwFileSize--;
  348.     }
  349.     
  350.     szAPIDefinition[dwIndex] = '\0';
  351.  
  352.     if (szAPIDefinition[0] != '\0')
  353.     {
  354.       pszModuleName = szAPIDefinition;
  355.       pszAPIName = strchr(pszModuleName, ':');
  356.  
  357.       if (pszAPIName != NULL)
  358.       {
  359.         pszAPIName[0] = '\0';
  360.         pszAPIName++;
  361.         
  362.         pszParameterList = strchr(pszAPIName, '(');
  363.  
  364.         if (pszParameterList != NULL)
  365.         {
  366.           pszParameterList[0] = '\0';
  367.           pszParameterList++;
  368.  
  369.           pAPIInfo = HookAPIFunction(pszModuleName, pszAPIName, APILogFunction);
  370.  
  371.           if (pAPIInfo != NULL)
  372.           {
  373.             #ifdef WINNT
  374.  
  375.             pAPIInfo->szAPIName = (PSTR)malloc(strlen(pszAPIName) + 1);
  376.  
  377.             #endif
  378.  
  379.             if (pAPIInfo->szAPIName == NULL)
  380.             {
  381.               UnmapViewOfFile(pcFile);
  382.               CloseHandle(hMap);
  383.               CloseHandle(hFile);
  384.               return false;
  385.             }
  386.             
  387.             strcpy(pAPIInfo->szAPIName, pszAPIName);
  388.  
  389.             #ifdef WIN95
  390.  
  391.             pAPIInfo->hMutex = CreateMutex(NULL, FALSE, pszAPIName);
  392.  
  393.             #endif
  394.  
  395.             #ifdef WINNT
  396.  
  397.             InitializeCriticalSection(&pAPIInfo->CriticalSection);
  398.  
  399.             #endif
  400.  
  401.             cParamIndex = 0;
  402.  
  403.             pszParameter = strtok(pszParameterList, ",;)");
  404.  
  405.             while (pszParameter != NULL)
  406.             {
  407.  
  408.               pszParameter = TrimString(pszParameter);
  409.  
  410.               pAPIInfo->ParamList[cParamIndex] = GetParamType(pszParameter);
  411.  
  412.               cParamIndex++;
  413.  
  414.               if (cParamIndex == MAX_PARAM)
  415.                 break;
  416.  
  417.               pszParameter = strtok(NULL, ",;)");
  418.             }
  419.             
  420.             if (cParamIndex == MAX_PARAM)
  421.               UnhookAPIFunction(pAPIInfo);
  422.             else
  423.               pAPIInfo->ParamCount = cParamIndex;
  424.           }  
  425.         }
  426.       }
  427.     }
  428.  
  429.     if (dwFileSize == 0) 
  430.       break;
  431.  
  432.     pcFile += 2;
  433.     dwFileSize -= 2;
  434.   }
  435.  
  436.   UnmapViewOfFile(pcFile);
  437.   CloseHandle(hMap);
  438.   CloseHandle(hFile);
  439.  
  440.   return true;
  441. }
  442.  
  443.  
  444. void APIHandler()
  445. {
  446.   PBYTE pbAPI;
  447.   PDWORD pdwAPI;
  448.   tagAPIInfo *pAPIInfo;
  449.   PBYTE pbAfterCall;
  450.   PDWORD pdwParam;
  451.   DWORD dwParamSize;
  452.   PDWORD pdwESP;
  453.   void *pvReturnAddr;
  454.   DWORD dwReturnValue;
  455.   char szLogString[2048];
  456.  
  457.   #ifdef WIN95
  458.  
  459.   HANDLE hMutex;
  460.  
  461.   #endif
  462.  
  463.   _asm
  464.   {
  465.     Mov EAX, [EBP + 4]
  466.     Mov [pbAfterCall], EAX
  467.  
  468.     Mov EAX, [EBP + 8]
  469.     Mov [pvReturnAddr], EAX
  470.  
  471.     Lea EAX, [EBP + 12]
  472.     Mov [pdwParam], EAX
  473.   }
  474.  
  475.   pAPIInfo = Head;
  476.  
  477.   while (pAPIInfo != NULL)
  478.   {
  479.     if ((pbAfterCall - 5) == (PBYTE)pAPIInfo->APIAddress)
  480.     {
  481.  
  482.       #ifdef WIN95
  483.  
  484.       hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, pAPIInfo->szAPIName);
  485.  
  486.       if (hMutex)
  487.         WaitForSingleObject(hMutex, INFINITE);
  488.  
  489.       #endif
  490.  
  491.       #ifdef WINNT
  492.  
  493.       EnterCriticalSection(&pAPIInfo->CriticalSection);
  494.  
  495.       #endif
  496.       
  497.       memcpy(pAPIInfo->APIAddress, pAPIInfo->Opcodes, 5);
  498.  
  499.       break;
  500.     }
  501.  
  502.     pAPIInfo = pAPIInfo->Next;
  503.   }
  504.  
  505.   dwParamSize = pAPIInfo->ParamCount * 4;
  506.  
  507.   _asm
  508.   {
  509.     Sub ESP, [dwParamSize]
  510.     Mov [pdwESP], ESP
  511.   }
  512.  
  513.   memcpy(pdwESP, pdwParam, dwParamSize);
  514.  
  515.   pAPIInfo->APIEnterHandler(pAPIInfo, szLogString);
  516.   pAPIInfo->APIAddress();
  517.  
  518.   _asm
  519.   {
  520.     Push EAX
  521.     Mov [dwReturnValue], EAX
  522.   }
  523.   
  524.   AddLogEntry(GetCurrentProcessId(), szLogString, dwReturnValue, (PBYTE)pvReturnAddr - 5);
  525.  
  526.   pbAPI = (PBYTE)pAPIInfo->APIAddress;
  527.   pbAPI[0] = 0xE8;
  528.   pdwAPI = (DWORD *)&pbAPI[1];
  529.   pdwAPI[0] = (DWORD)APIHandler - (DWORD)pbAPI - 5;
  530.  
  531.   #ifdef WIN95
  532.  
  533.   if (hMutex)
  534.   {
  535.     ReleaseMutex(hMutex);
  536.     CloseHandle(hMutex);
  537.   }
  538.  
  539.   #endif
  540.  
  541.   #ifdef WINNT
  542.  
  543.   LeaveCriticalSection(&pAPIInfo->CriticalSection);
  544.   
  545.   #endif
  546.  
  547.   _asm
  548.   {
  549.     Pop EAX
  550.  
  551.     Mov ECX, [dwParamSize]
  552.     Mov EDX, [pvReturnAddr]
  553.     
  554.     Pop EDI
  555.     Pop ESI
  556.     Pop EBX
  557.     Mov ESP, EBP
  558.     Pop EBP
  559.     Add ESP, 8
  560.     Add ESP, ECX
  561.     Push EDX
  562.     Ret
  563.   }
  564. }
  565.  
  566.  
  567. bool RemoveProtection(PVOID pvAddress, tagAPIInfo *pAPIInfo)
  568. {
  569.   #ifdef WIN95
  570.  
  571.   bool Result;
  572.  
  573.   Result = RemovePageProtection(pvAddress);
  574.  
  575.   if (Result == false)
  576.     return false;
  577.  
  578.   #endif
  579.  
  580.   #ifdef WINNT
  581.  
  582.   MEMORY_BASIC_INFORMATION mbi;
  583.   DWORD dwProtectionFlags;
  584.   DWORD dwScratch;
  585.   BOOL Result;
  586.  
  587.   // Get page protection of API
  588.  
  589.   VirtualQuery(pvAddress, &mbi, sizeof(mbi));
  590.   dwProtectionFlags = mbi.Protect;
  591.   pAPIInfo->dwOldProtectionFlags = dwProtectionFlags;
  592.  
  593.   // Remove page protection from API
  594.  
  595.   dwProtectionFlags &= ~PAGE_READONLY;
  596.   dwProtectionFlags &= ~PAGE_EXECUTE_READ;
  597.   dwProtectionFlags |= PAGE_READWRITE;
  598.  
  599.   Result = VirtualProtect(pvAddress, 4096, dwProtectionFlags, &dwScratch);
  600.  
  601.   if (Result == FALSE)
  602.     return false;
  603.  
  604.   #endif
  605.  
  606.   return true;
  607. }
  608.  
  609.  
  610. tagAPIInfo *HookAPIFunction(PSTR pszModuleName,
  611.                             PSTR pszAPIName,
  612.                             tagHandlerAddr APIEnterHandler)
  613. {
  614.  
  615.   HMODULE hModule;
  616.   tagAPIInfo *pAPIInfo;
  617.   tagAPIInfo *pTempAPIInfo;
  618.   PBYTE pbAPI;
  619.   PDWORD pdwAPI;
  620.   bool Result;
  621.     
  622.   hModule = GetModuleHandle(pszModuleName);
  623.   
  624.   if (hModule == NULL)
  625.     return NULL;
  626.  
  627.   pbAPI = (PBYTE)GetProcAddress(hModule, pszAPIName);
  628.  
  629.   if (pbAPI == NULL)
  630.     return NULL;
  631.  
  632.   // Is it already hooked ?
  633.  
  634.   pTempAPIInfo = Head;
  635.  
  636.   while (pTempAPIInfo != NULL)
  637.   {
  638.     if (pTempAPIInfo->APIAddress == (tagAPIAddr)pbAPI)
  639.       return NULL;
  640.  
  641.     pTempAPIInfo = pTempAPIInfo->Next;
  642.   }
  643.  
  644.   // No, so add a new item
  645.  
  646.   pAPIInfo = AddItem();
  647.   
  648.   if (pAPIInfo == NULL)
  649.     return NULL;
  650.  
  651.   pAPIInfo->APIAddress = NULL;
  652.  
  653.   Result = RemoveProtection(pbAPI, pAPIInfo);
  654.  
  655.   if (Result == false)
  656.   {
  657.     #ifdef WINNT
  658.  
  659.     RemoveItem(pAPIInfo);
  660.  
  661.     #endif
  662.  
  663.     return NULL;
  664.   }
  665.  
  666.   // Save first 5 bytes of API
  667.  
  668.   memcpy(pAPIInfo->Opcodes, pbAPI, 5);
  669.   
  670.   pAPIInfo->APIAddress = (tagAPIAddr)pbAPI;
  671.   pAPIInfo->APIEnterHandler = APIEnterHandler;
  672.   
  673.   // Write a call to the hook function
  674.  
  675.   pbAPI[0] = 0xE8;
  676.   pdwAPI = (DWORD *)&pbAPI[1];
  677.   pdwAPI[0] = (DWORD)APIHandler - (DWORD)pbAPI - 5;
  678.  
  679.   return pAPIInfo;
  680. }
  681.  
  682.  
  683. void UnhookAPIFunction(tagAPIInfo *pAPIInfo)
  684. {
  685.   bool Result;
  686.  
  687.   Result = RemoveProtection(pAPIInfo->APIAddress, pAPIInfo);
  688.  
  689.   if (Result == true)
  690.     memcpy(pAPIInfo->APIAddress, pAPIInfo->Opcodes, 5);
  691.  
  692.   #ifdef WIN95
  693.  
  694.   SetPageProtection(pAPIInfo->APIAddress);
  695.  
  696.   if (pAPIInfo->hMutex)
  697.     CloseHandle(pAPIInfo->hMutex);
  698.  
  699.   #endif
  700.  
  701.   #ifdef WINNT
  702.  
  703.   DWORD dwScratch;
  704.  
  705.   DeleteCriticalSection(&pAPIInfo->CriticalSection);
  706.  
  707.   VirtualProtect(pAPIInfo->APIAddress, 4096, pAPIInfo->dwOldProtectionFlags, &dwScratch);
  708.   free(pAPIInfo->szAPIName);
  709.   RemoveItem(pAPIInfo);
  710.  
  711.   #endif
  712. }
  713.  
  714.  
  715. void UnhookAllAPIFunctions()
  716. {
  717.   tagAPIInfo *pAPIInfo;
  718.   tagAPIInfo *pTempAPIInfo;
  719.  
  720.   pAPIInfo = Head;
  721.  
  722.   while (pAPIInfo != NULL)
  723.   {
  724.     pTempAPIInfo = pAPIInfo->Next;
  725.     
  726.     UnhookAPIFunction(pAPIInfo);
  727.         
  728.     pAPIInfo = pTempAPIInfo;
  729.   }
  730. }
  731.  
  732.  
  733. PSTR TrimString(PSTR pszStr)
  734. {
  735.   PCHAR pcBlankChar;
  736.  
  737.   pcBlankChar = pszStr + strlen(pszStr) - 1;
  738.  
  739.   while (*pcBlankChar == ' ') 
  740.   {
  741.     pcBlankChar[0] = '\0';
  742.     pcBlankChar--;
  743.   }
  744.  
  745.   while (*pszStr == ' ') pszStr++;
  746.  
  747.   return pszStr;
  748. }
  749.  
  750.  
  751. char *GetParamFormat(tagParamType ParamType)
  752. {
  753.   char cIndex;
  754.  
  755.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  756.     if (ParamSpec[cIndex].ParamType == ParamType)
  757.       return ParamSpec[cIndex].ParamFormat;
  758.  
  759.   return ParamSpec[cIndex].ParamFormat;
  760. }
  761.  
  762.  
  763. char *GetParamName(tagParamType ParamType)
  764. {
  765.   char cIndex;
  766.  
  767.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  768.     if (ParamSpec[cIndex].ParamType == ParamType)
  769.       return ParamSpec[cIndex].ParamName;
  770.  
  771.   return ParamSpec[cIndex].ParamName;
  772. }
  773.  
  774.  
  775. tagParamType GetParamType(PSTR pszParameter)
  776. {
  777.   char cIndex;
  778.  
  779.   strupr(pszParameter);
  780.  
  781.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  782.     if (strcmp(pszParameter, ParamSpec[cIndex].ParamName) == 0)
  783.       return ParamSpec[cIndex].ParamType;
  784.  
  785.   return PARAM_UNKNOWN;
  786. }
  787.  
  788.  
  789. DWORD GetParamMask(tagParamType ParamType)
  790. {
  791.   char cIndex;
  792.  
  793.   for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
  794.     if (ParamSpec[cIndex].ParamType == ParamType)
  795.       return ParamSpec[cIndex].dwParamMask;
  796.  
  797.   return ParamSpec[cIndex].dwParamMask;
  798. }
  799.  
  800.  
  801. void FormatString(PSTR pszSrcStr, PSTR pszDstStr, DWORD dwMaxSize)
  802. {
  803.   DWORD dwDstSize = 0;
  804.  
  805.   if (IsBadStringPtr(pszSrcStr, dwMaxSize) != 0)
  806.   {
  807.     *pszDstStr++ = '?';
  808.     *pszDstStr = '\0';
  809.     return;
  810.   }
  811.  
  812.   *pszDstStr++ = '"';
  813.  
  814.   while (*pszSrcStr != '\0')
  815.   {
  816.     if (*pszSrcStr == '\n')
  817.     {
  818.       *pszDstStr++ = '\\';
  819.       *pszDstStr = 'n';
  820.     }
  821.     else if (*pszSrcStr == '\t')
  822.     {
  823.       *pszDstStr++ = '\\';
  824.       *pszDstStr = 't';
  825.     }
  826.     else if (*pszSrcStr == '\r')
  827.     {
  828.       *pszDstStr++ = '\\';
  829.       *pszDstStr = 'r';
  830.     }
  831.     else *pszDstStr = *pszSrcStr;
  832.  
  833.     dwDstSize++;
  834.     pszSrcStr++;
  835.     pszDstStr++;
  836.  
  837.     if (dwDstSize == dwMaxSize)
  838.     {
  839.       *pszDstStr++ = '.';
  840.       *pszDstStr++ = '.';
  841.       *pszDstStr++ = '.';
  842.  
  843.       break;
  844.     }
  845.   }
  846.  
  847.   *pszDstStr++ = '"';
  848.   *pszDstStr = '\0';
  849. }
  850.  
  851.  
  852. BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, PVOID pvReserved)
  853. {
  854.   DWORD dwResult;
  855.   char szAPIFileName[MAX_PATH];
  856.  
  857.   switch (dwReason)
  858.   {
  859.     case DLL_PROCESS_ATTACH:
  860.  
  861.       dwResult = GetWindowsDirectory(szAPIFileName, MAX_PATH);
  862.  
  863.       if (dwResult == 0) return false;
  864.  
  865.       strcat(szAPIFileName, "\\APISpy32.api");
  866.  
  867.       DisableThreadLibraryCalls(hInstDLL);
  868.  
  869.       ParseAPIFile(szAPIFileName);
  870.  
  871.     break;
  872.  
  873.     case DLL_PROCESS_DETACH:
  874.  
  875.       UnhookAllAPIFunctions();
  876.       
  877.     break;
  878.   }
  879.  
  880.   return TRUE;
  881. }
  882.