APISpy32.cpp
资源名称:apispy32.zip [点击查看]
上传用户:tzh4061
上传日期:2007-01-08
资源大小:309k
文件大小:18k
源码类别:
钩子与API截获
开发平台:
Visual C++
- // ----------------------------------- //
- // APISpy32 v2.0 //
- // Copyright 1999 Yariv Kaplan //
- // WWW.INTERNALS.COM //
- // ----------------------------------- //
- #include <windows.h>
- #include "APISpy32.h"
- #include "LinkList.h"
- #include "LogAPI.h"
- #pragma check_stack(off)
- #ifdef WIN95
- #pragma comment(linker, "/section:.data,RWS /section:.idata,RWS /section:.bss,RWS")
- #pragma comment(linker, "/base:0xBFF70000")
- #include "Ring0.h"
- #endif
- PSTR TrimString(PSTR pszStr);
- char *GetParamFormat(tagParamType ParamType);
- char *GetParamName(tagParamType ParamType);
- tagParamType GetParamType(PSTR pszParameter);
- DWORD GetParamMask(tagParamType ParamType);
- void FormatString(PSTR pszSrcStr, PSTR pszDstStr, DWORD dwMaxSize);
- tagParamSpec ParamSpec[] = {{"INT", PARAM_INT, "%d", 0xFFFFFFFF},
- {"DWORD", PARAM_DWORD, "%u", 0xFFFFFFFF},
- {"WORD", PARAM_WORD, "%u", 0x0000FFFF},
- {"BYTE", PARAM_BYTE, "%u", 0x000000FF},
- {"PSTR", PARAM_PSTR, "%#x", 0xFFFFFFFF},
- {"PVOID", PARAM_PVOID, "%#x", 0xFFFFFFFF},
- {"PINT", PARAM_PINT, "%#x", 0xFFFFFFFF},
- {"PDWORD", PARAM_PDWORD, "%#x", 0xFFFFFFFF},
- {"PWORD", PARAM_PWORD, "%#x", 0xFFFFFFFF},
- {"PBYTE", PARAM_PBYTE, "%#x", 0xFFFFFFFF},
- {"HANDLE", PARAM_HANDLE, "%#x", 0xFFFFFFFF},
- {"HWND", PARAM_HWND, "%#x", 0xFFFFFFFF},
- {"BOOL", PARAM_BOOL, "%u", 0xFFFFFFFF},
- {"PWSTR", PARAM_PWSTR, "%#x", 0xFFFFFFFF},
- {"UNKNOWN",PARAM_UNKNOWN,"%u", 0xFFFFFFFF}};
- #ifdef WIN95
- __declspec(naked) void Ring0ModifyPageProtection()
- {
- _asm
- {
- Mov EAX, ECX
- Shr EAX, 22
- Test DWORD PTR [0FFBFE000h + EAX * 4], 1
- Jz Fail
- Mov EAX, ECX
- Shr EAX, 12
- Mov EBX, EAX
- Mov EAX, DWORD PTR [0FF800000h + EAX * 4]
- Test EAX, 1
- Jz Fail
- Mov EAX, 1
- Cmp EDX, PAGE_READWRITE
- Je PageReadWrite
- And DWORD PTR [0FF800000h + EBX * 4], 0xFFFFFFFD
- Jmp Done
- PageReadWrite:
- Or DWORD PTR [0FF800000h + EBX * 4], 2
- Jmp Done
- Fail:
- Xor EAX, EAX
- Done:
- Retf
- }
- }
- bool CallRing0(PVOID pvRing0FuncAddr, PVOID pvAddr, DWORD dwPageProtection)
- {
- GDT_DESCRIPTOR *pGDTDescriptor;
- GDTR gdtr;
- bool Result;
- _asm Sgdt [gdtr]
- // Skip the null descriptor
- pGDTDescriptor = (GDT_DESCRIPTOR *)(gdtr.dwGDTBase + 8);
- // Search for a free GDT descriptor
- for (WORD wGDTIndex = 1; wGDTIndex < (gdtr.wGDTLimit / 8); wGDTIndex++)
- {
- if (pGDTDescriptor->Type == 0 &&
- pGDTDescriptor->System == 0 &&
- pGDTDescriptor->DPL == 0 &&
- pGDTDescriptor->Present == 0)
- {
- // Found one !
- // Now we need to transform this descriptor into a callgate.
- // Note that we're using selector 0x28 since it corresponds
- // to a ring 0 segment which spans the entire linear address
- // space of the processor (0-4GB).
- CALLGATE_DESCRIPTOR *pCallgate;
- pCallgate = (CALLGATE_DESCRIPTOR *) pGDTDescriptor;
- pCallgate->Offset_0_15 = LOWORD(pvRing0FuncAddr);
- pCallgate->Selector = 0x28;
- pCallgate->ParamCount = 0;
- pCallgate->Unused = 0;
- pCallgate->Type = 0xc;
- pCallgate->System = 0;
- pCallgate->DPL = 3;
- pCallgate->Present = 1;
- pCallgate->Offset_16_31 = HIWORD(pvRing0FuncAddr);
- // Prepare the far call parameters
- WORD CallgateAddr[3];
- CallgateAddr[0] = 0x0;
- CallgateAddr[1] = 0x0;
- CallgateAddr[2] = (wGDTIndex << 3) | 3;
- // Please fasten your seat belts!
- // We're about to make a hyperspace jump into RING 0.
- _asm
- {
- Mov ECX, [pvAddr]
- Mov EDX, [dwPageProtection]
- Cli
- Call FWORD PTR [CallgateAddr]
- Sti
- Mov DWORD PTR [Result], EAX
- }
- // Now free the GDT descriptor
- memset(pGDTDescriptor, 0, 8);
- return Result;
- }
- // Advance to the next GDT descriptor
- pGDTDescriptor++;
- }
- // Whoops, the GDT is full
- return false;
- }
- bool RemovePageProtection(PVOID pvAddr)
- {
- return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READWRITE);
- }
- bool SetPageProtection(PVOID pvAddr)
- {
- return CallRing0((PVOID)Ring0ModifyPageProtection, pvAddr, PAGE_READONLY);
- }
- #endif
- void APILogFunction(tagAPIInfo *pAPIInfo, PSTR pszLogString, ...)
- {
- va_list Marker;
- DWORD dwParamValue;
- char szParamStr[MAX_TEXT_LEN + 6];
- char szUnicodeStr[MAX_TEXT_LEN + 1];
- char cIndex;
- va_start(Marker, pszLogString);
- strcpy(pszLogString, pAPIInfo->szAPIName);
- strcat(pszLogString, "(");
- for (cIndex = 0; cIndex < pAPIInfo->ParamCount; cIndex++)
- {
- dwParamValue = va_arg(Marker, DWORD);
- dwParamValue &= GetParamMask(pAPIInfo->ParamList[cIndex]);
- strcat(pszLogString, GetParamName(pAPIInfo->ParamList[cIndex]));
- strcat(pszLogString, ":");
- wsprintf(szParamStr, GetParamFormat(pAPIInfo->ParamList[cIndex]), dwParamValue);
- strcat(pszLogString, szParamStr);
- switch (pAPIInfo->ParamList[cIndex])
- {
- case PARAM_PSTR:
- strcat(pszLogString, ":");
- FormatString((PSTR)dwParamValue, szParamStr, MAX_TEXT_LEN);
- strcat(pszLogString, szParamStr);
- break;
- case PARAM_PINT:
- strcat(pszLogString, ":");
- if (IsBadReadPtr((PVOID)dwParamValue, 4) == 0)
- {
- wsprintf(szParamStr, "%d", *(int *)dwParamValue);
- strcat(pszLogString, szParamStr);
- }
- else strcat(pszLogString, "?");
- break;
- case PARAM_PDWORD:
- strcat(pszLogString, ":");
- if (IsBadReadPtr((PVOID)dwParamValue, 4) == 0)
- {
- wsprintf(szParamStr, "%u", *(DWORD *)dwParamValue);
- strcat(pszLogString, szParamStr);
- }
- else strcat(pszLogString, "?");
- break;
- case PARAM_PWORD:
- strcat(pszLogString, ":");
- if (IsBadReadPtr((PVOID)dwParamValue, 2) == 0)
- {
- wsprintf(szParamStr, "%u", LOWORD(*(WORD *)dwParamValue));
- strcat(pszLogString, szParamStr);
- }
- else strcat(pszLogString, "?");
- break;
- case PARAM_PBYTE:
- strcat(pszLogString, ":");
- if (IsBadReadPtr((PVOID)dwParamValue, 1) == 0)
- {
- wsprintf(szParamStr, "%u", LOBYTE(*(BYTE *)dwParamValue));
- strcat(pszLogString, szParamStr);
- }
- else strcat(pszLogString, "?");
- break;
- case PARAM_PWSTR:
- strcat(pszLogString, ":");
- if (IsBadReadPtr((PVOID)dwParamValue, 2) == 0 &&
- IsBadStringPtrW((LPCWSTR)dwParamValue, MAX_TEXT_LEN) == 0)
- {
- WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)dwParamValue, MAX_TEXT_LEN, szUnicodeStr, sizeof(szUnicodeStr), NULL, NULL);
- szUnicodeStr[MAX_TEXT_LEN] = ' ';
- FormatString(szUnicodeStr, szParamStr, MAX_TEXT_LEN);
- strcat(pszLogString, szParamStr);
- }
- else strcat(pszLogString, "?");
- break;
- }
- strcat(pszLogString, ", ");
- }
- if (pAPIInfo->ParamCount > 0)
- pszLogString[strlen(pszLogString) - 2] = ')';
- else
- strcat(pszLogString, ")");
- va_end(Marker);
- }
- bool ParseAPIFile(PSTR pszFileName)
- {
- HANDLE hFile;
- HANDLE hMap;
- DWORD dwIndex;
- PSTR pszParameterList;
- PSTR pszParameter;
- PSTR pszModuleName;
- PSTR pszAPIName;
- PCHAR pcFile;
- DWORD dwFileSize;
- char cParamIndex;
- tagAPIInfo *pAPIInfo;
- char szAPIDefinition[1024];
- hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
- OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
- if (hFile == INVALID_HANDLE_VALUE)
- return false;
- dwFileSize = GetFileSize(hFile, NULL);
- if (dwFileSize == 0xFFFFFFFF)
- return false;
- hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
- if (hMap == NULL)
- {
- CloseHandle(hFile);
- return false;
- }
- pcFile = (PCHAR)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
- if (pcFile == NULL)
- {
- CloseHandle(hMap);
- CloseHandle(hFile);
- return false;
- }
- while (dwFileSize)
- {
- for (dwIndex = 0; *pcFile != 13 && dwFileSize; dwIndex++)
- {
- szAPIDefinition[dwIndex] = *pcFile;
- pcFile++;
- dwFileSize--;
- }
- szAPIDefinition[dwIndex] = ' ';
- if (szAPIDefinition[0] != ' ')
- {
- pszModuleName = szAPIDefinition;
- pszAPIName = strchr(pszModuleName, ':');
- if (pszAPIName != NULL)
- {
- pszAPIName[0] = ' ';
- pszAPIName++;
- pszParameterList = strchr(pszAPIName, '(');
- if (pszParameterList != NULL)
- {
- pszParameterList[0] = ' ';
- pszParameterList++;
- pAPIInfo = HookAPIFunction(pszModuleName, pszAPIName, APILogFunction);
- if (pAPIInfo != NULL)
- {
- #ifdef WINNT
- pAPIInfo->szAPIName = (PSTR)malloc(strlen(pszAPIName) + 1);
- #endif
- if (pAPIInfo->szAPIName == NULL)
- {
- UnmapViewOfFile(pcFile);
- CloseHandle(hMap);
- CloseHandle(hFile);
- return false;
- }
- strcpy(pAPIInfo->szAPIName, pszAPIName);
- #ifdef WIN95
- pAPIInfo->hMutex = CreateMutex(NULL, FALSE, pszAPIName);
- #endif
- #ifdef WINNT
- InitializeCriticalSection(&pAPIInfo->CriticalSection);
- #endif
- cParamIndex = 0;
- pszParameter = strtok(pszParameterList, ",;)");
- while (pszParameter != NULL)
- {
- pszParameter = TrimString(pszParameter);
- pAPIInfo->ParamList[cParamIndex] = GetParamType(pszParameter);
- cParamIndex++;
- if (cParamIndex == MAX_PARAM)
- break;
- pszParameter = strtok(NULL, ",;)");
- }
- if (cParamIndex == MAX_PARAM)
- UnhookAPIFunction(pAPIInfo);
- else
- pAPIInfo->ParamCount = cParamIndex;
- }
- }
- }
- }
- if (dwFileSize == 0)
- break;
- pcFile += 2;
- dwFileSize -= 2;
- }
- UnmapViewOfFile(pcFile);
- CloseHandle(hMap);
- CloseHandle(hFile);
- return true;
- }
- void APIHandler()
- {
- PBYTE pbAPI;
- PDWORD pdwAPI;
- tagAPIInfo *pAPIInfo;
- PBYTE pbAfterCall;
- PDWORD pdwParam;
- DWORD dwParamSize;
- PDWORD pdwESP;
- void *pvReturnAddr;
- DWORD dwReturnValue;
- char szLogString[2048];
- #ifdef WIN95
- HANDLE hMutex;
- #endif
- _asm
- {
- Mov EAX, [EBP + 4]
- Mov [pbAfterCall], EAX
- Mov EAX, [EBP + 8]
- Mov [pvReturnAddr], EAX
- Lea EAX, [EBP + 12]
- Mov [pdwParam], EAX
- }
- pAPIInfo = Head;
- while (pAPIInfo != NULL)
- {
- if ((pbAfterCall - 5) == (PBYTE)pAPIInfo->APIAddress)
- {
- #ifdef WIN95
- hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, pAPIInfo->szAPIName);
- if (hMutex)
- WaitForSingleObject(hMutex, INFINITE);
- #endif
- #ifdef WINNT
- EnterCriticalSection(&pAPIInfo->CriticalSection);
- #endif
- memcpy(pAPIInfo->APIAddress, pAPIInfo->Opcodes, 5);
- break;
- }
- pAPIInfo = pAPIInfo->Next;
- }
- dwParamSize = pAPIInfo->ParamCount * 4;
- _asm
- {
- Sub ESP, [dwParamSize]
- Mov [pdwESP], ESP
- }
- memcpy(pdwESP, pdwParam, dwParamSize);
- pAPIInfo->APIEnterHandler(pAPIInfo, szLogString);
- pAPIInfo->APIAddress();
- _asm
- {
- Push EAX
- Mov [dwReturnValue], EAX
- }
- AddLogEntry(GetCurrentProcessId(), szLogString, dwReturnValue, (PBYTE)pvReturnAddr - 5);
- pbAPI = (PBYTE)pAPIInfo->APIAddress;
- pbAPI[0] = 0xE8;
- pdwAPI = (DWORD *)&pbAPI[1];
- pdwAPI[0] = (DWORD)APIHandler - (DWORD)pbAPI - 5;
- #ifdef WIN95
- if (hMutex)
- {
- ReleaseMutex(hMutex);
- CloseHandle(hMutex);
- }
- #endif
- #ifdef WINNT
- LeaveCriticalSection(&pAPIInfo->CriticalSection);
- #endif
- _asm
- {
- Pop EAX
- Mov ECX, [dwParamSize]
- Mov EDX, [pvReturnAddr]
- Pop EDI
- Pop ESI
- Pop EBX
- Mov ESP, EBP
- Pop EBP
- Add ESP, 8
- Add ESP, ECX
- Push EDX
- Ret
- }
- }
- bool RemoveProtection(PVOID pvAddress, tagAPIInfo *pAPIInfo)
- {
- #ifdef WIN95
- bool Result;
- Result = RemovePageProtection(pvAddress);
- if (Result == false)
- return false;
- #endif
- #ifdef WINNT
- MEMORY_BASIC_INFORMATION mbi;
- DWORD dwProtectionFlags;
- DWORD dwScratch;
- BOOL Result;
- // Get page protection of API
- VirtualQuery(pvAddress, &mbi, sizeof(mbi));
- dwProtectionFlags = mbi.Protect;
- pAPIInfo->dwOldProtectionFlags = dwProtectionFlags;
- // Remove page protection from API
- dwProtectionFlags &= ~PAGE_READONLY;
- dwProtectionFlags &= ~PAGE_EXECUTE_READ;
- dwProtectionFlags |= PAGE_READWRITE;
- Result = VirtualProtect(pvAddress, 4096, dwProtectionFlags, &dwScratch);
- if (Result == FALSE)
- return false;
- #endif
- return true;
- }
- tagAPIInfo *HookAPIFunction(PSTR pszModuleName,
- PSTR pszAPIName,
- tagHandlerAddr APIEnterHandler)
- {
- HMODULE hModule;
- tagAPIInfo *pAPIInfo;
- tagAPIInfo *pTempAPIInfo;
- PBYTE pbAPI;
- PDWORD pdwAPI;
- bool Result;
- hModule = GetModuleHandle(pszModuleName);
- if (hModule == NULL)
- return NULL;
- pbAPI = (PBYTE)GetProcAddress(hModule, pszAPIName);
- if (pbAPI == NULL)
- return NULL;
- // Is it already hooked ?
- pTempAPIInfo = Head;
- while (pTempAPIInfo != NULL)
- {
- if (pTempAPIInfo->APIAddress == (tagAPIAddr)pbAPI)
- return NULL;
- pTempAPIInfo = pTempAPIInfo->Next;
- }
- // No, so add a new item
- pAPIInfo = AddItem();
- if (pAPIInfo == NULL)
- return NULL;
- pAPIInfo->APIAddress = NULL;
- Result = RemoveProtection(pbAPI, pAPIInfo);
- if (Result == false)
- {
- #ifdef WINNT
- RemoveItem(pAPIInfo);
- #endif
- return NULL;
- }
- // Save first 5 bytes of API
- memcpy(pAPIInfo->Opcodes, pbAPI, 5);
- pAPIInfo->APIAddress = (tagAPIAddr)pbAPI;
- pAPIInfo->APIEnterHandler = APIEnterHandler;
- // Write a call to the hook function
- pbAPI[0] = 0xE8;
- pdwAPI = (DWORD *)&pbAPI[1];
- pdwAPI[0] = (DWORD)APIHandler - (DWORD)pbAPI - 5;
- return pAPIInfo;
- }
- void UnhookAPIFunction(tagAPIInfo *pAPIInfo)
- {
- bool Result;
- Result = RemoveProtection(pAPIInfo->APIAddress, pAPIInfo);
- if (Result == true)
- memcpy(pAPIInfo->APIAddress, pAPIInfo->Opcodes, 5);
- #ifdef WIN95
- SetPageProtection(pAPIInfo->APIAddress);
- if (pAPIInfo->hMutex)
- CloseHandle(pAPIInfo->hMutex);
- #endif
- #ifdef WINNT
- DWORD dwScratch;
- DeleteCriticalSection(&pAPIInfo->CriticalSection);
- VirtualProtect(pAPIInfo->APIAddress, 4096, pAPIInfo->dwOldProtectionFlags, &dwScratch);
- free(pAPIInfo->szAPIName);
- RemoveItem(pAPIInfo);
- #endif
- }
- void UnhookAllAPIFunctions()
- {
- tagAPIInfo *pAPIInfo;
- tagAPIInfo *pTempAPIInfo;
- pAPIInfo = Head;
- while (pAPIInfo != NULL)
- {
- pTempAPIInfo = pAPIInfo->Next;
- UnhookAPIFunction(pAPIInfo);
- pAPIInfo = pTempAPIInfo;
- }
- }
- PSTR TrimString(PSTR pszStr)
- {
- PCHAR pcBlankChar;
- pcBlankChar = pszStr + strlen(pszStr) - 1;
- while (*pcBlankChar == ' ')
- {
- pcBlankChar[0] = ' ';
- pcBlankChar--;
- }
- while (*pszStr == ' ') pszStr++;
- return pszStr;
- }
- char *GetParamFormat(tagParamType ParamType)
- {
- char cIndex;
- for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
- if (ParamSpec[cIndex].ParamType == ParamType)
- return ParamSpec[cIndex].ParamFormat;
- return ParamSpec[cIndex].ParamFormat;
- }
- char *GetParamName(tagParamType ParamType)
- {
- char cIndex;
- for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
- if (ParamSpec[cIndex].ParamType == ParamType)
- return ParamSpec[cIndex].ParamName;
- return ParamSpec[cIndex].ParamName;
- }
- tagParamType GetParamType(PSTR pszParameter)
- {
- char cIndex;
- strupr(pszParameter);
- for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
- if (strcmp(pszParameter, ParamSpec[cIndex].ParamName) == 0)
- return ParamSpec[cIndex].ParamType;
- return PARAM_UNKNOWN;
- }
- DWORD GetParamMask(tagParamType ParamType)
- {
- char cIndex;
- for (cIndex = 0; ParamSpec[cIndex].ParamType != PARAM_UNKNOWN; cIndex++)
- if (ParamSpec[cIndex].ParamType == ParamType)
- return ParamSpec[cIndex].dwParamMask;
- return ParamSpec[cIndex].dwParamMask;
- }
- void FormatString(PSTR pszSrcStr, PSTR pszDstStr, DWORD dwMaxSize)
- {
- DWORD dwDstSize = 0;
- if (IsBadStringPtr(pszSrcStr, dwMaxSize) != 0)
- {
- *pszDstStr++ = '?';
- *pszDstStr = ' ';
- return;
- }
- *pszDstStr++ = '"';
- while (*pszSrcStr != ' ')
- {
- if (*pszSrcStr == 'n')
- {
- *pszDstStr++ = '\';
- *pszDstStr = 'n';
- }
- else if (*pszSrcStr == 't')
- {
- *pszDstStr++ = '\';
- *pszDstStr = 't';
- }
- else if (*pszSrcStr == 'r')
- {
- *pszDstStr++ = '\';
- *pszDstStr = 'r';
- }
- else *pszDstStr = *pszSrcStr;
- dwDstSize++;
- pszSrcStr++;
- pszDstStr++;
- if (dwDstSize == dwMaxSize)
- {
- *pszDstStr++ = '.';
- *pszDstStr++ = '.';
- *pszDstStr++ = '.';
- break;
- }
- }
- *pszDstStr++ = '"';
- *pszDstStr = ' ';
- }
- BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, PVOID pvReserved)
- {
- DWORD dwResult;
- char szAPIFileName[MAX_PATH];
- switch (dwReason)
- {
- case DLL_PROCESS_ATTACH:
- dwResult = GetWindowsDirectory(szAPIFileName, MAX_PATH);
- if (dwResult == 0) return false;
- strcat(szAPIFileName, "\APISpy32.api");
- DisableThreadLibraryCalls(hInstDLL);
- ParseAPIFile(szAPIFileName);
- break;
- case DLL_PROCESS_DETACH:
- UnhookAllAPIFunctions();
- break;
- }
- return TRUE;
- }