核心HOOK API类,理论上可以HOOK 任何使用STDCALL声明的API函数
// HookInfo.h: interface for the CHookInfo class. // //////////////////////////////////////////////////////////////////////
#if !defined(AFX_HOOKINFO_H__D44F115C_76F1_4CC7_BD61_4C393417DA10__INCLUDED_) #define AFX_HOOKINFO_H__D44F115C_76F1_4CC7_BD61_4C393417DA10__INCLUDED_
#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000
typedef struct _HOOKSTRUCT { FARPROC pfFunAddr; //用于保存API函数地址 BYTE OldCode[5]; //保存原API前5个字节 BYTE NewCode[5]; //JMP XXXX其中XXXXJMP的地址 }HOOKSTRUCT;
class CHookInfo { public: //HOOK 处理函数 CHookInfo(char *strDllName, char *strFunName, DWORD dwMyFunAddr); virtual ~CHookInfo(); //析构函数 HOOKSTRUCT *pHook; //HOOK结构 void HookStatus(BOOL blnHook); //关闭/打开HOOK状态 };
CHookInfo::CHookInfo(char *strDllName, char *strFunName, DWORD dwMyFunAddr) { pHook = new HOOKSTRUCT; HMODULE hModule = LoadLibrary(strDllName); //纪录函数地址 pHook->pfFunAddr = GetProcAddress(hModule,strFunName); FreeLibrary(hModule); if(pHook->pfFunAddr == NULL) return ; //备份原函数的前5个字节,一般的WIN32 API以__stdcall声明的API理论上都可以这样进行HOOK memcpy(pHook->OldCode, pHook->pfFunAddr, 5); pHook->NewCode[0] = 0xe9; //构造JMP DWORD dwJmpAddr = dwMyFunAddr - (DWORD)pHook->pfFunAddr - 5; //计算JMP地址 memcpy(&pHook->NewCode[1], &dwJmpAddr, 4); HookStatus(TRUE);//开始进行HOOK }
CHookInfo::~CHookInfo() { //关闭HOOK恢复原函数 HookStatus(FALSE); }
void CHookInfo::HookStatus(BOOL blnHook) { if(blnHook) WriteProcessMemory((HANDLE)-1, pHook->pfFunAddr, pHook->NewCode, 5, 0);//替换函数地址 else WriteProcessMemory((HANDLE)-1, pHook->pfFunAddr, pHook->OldCode, 5, 0);//还原函数地址 } #endif // !defined(AFX_HOOKINFO_H__1967D554_7A9F_40C5_9D86_5899019EB3CD__INCLUDED_)
DLL程序代码,消息传递使用了自定义消息的方式
// RegistryInfo.cpp : Defines the entry point for the DLL application. //
#include "stdafx.h" #include <stdlib.h> #include "HookInfo.h" #define STATUS_SUCCESS (0) #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) #define ObjectNameInformation (1) #define BLOCKSIZE (0x1000) #define CurrentProcessHandle ((HANDLE)(0xFFFFFFFF)) #define STATUS_INFO_LEN_MISMATCH 0xC0000004
typedef unsigned long NTSTATUS; typedef unsigned long SYSTEM_INFORMATION_CLASS; typedef unsigned long OBJECT_INFORMATION_CLASS;
typedef struct { USHORT Length; USHORT MaxLen; USHORT *Buffer; }UNICODE_STRING, *PUNICODE_STRING;
typedef struct _OBJECT_NAME_INFORMATION { // Information Class 1 UNICODE_STRING Name; } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
typedef NTSTATUS (WINAPI *NTSETVALUEKEY)(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName,IN ULONG TitleIndex,IN ULONG type1,IN PVOID Data,IN ULONG DataSize); NTSETVALUEKEY NtSetValueKey = NULL;
typedef NTSTATUS (WINAPI *NTDELETEVALUEKEY)(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName); NTDELETEVALUEKEY NtDeleteValueKey = NULL;
typedef NTSTATUS (WINAPI *NTDELETEKEY)(IN HANDLE KeyHandle); NTDELETEKEY NtDeleteKey = NULL;
typedef NTSTATUS (WINAPI *NTCREATEKEY)(OUT PHANDLE pKeyHandle,IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes,IN ULONG TitleIndex,IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions,OUT PULONG Disposition OPTIONAL); NTCREATEKEY NtCreateKey = NULL;
typedef NTSTATUS (WINAPI *NTQUERYOBJECT)(IN HANDLE ObjectHandle,IN OBJECT_INFORMATION_CLASS ObjectInformationClass,OUT PVOID ObjectInformation,IN ULONG ObjectInformationLength,OUT PULONG ReturnLength); NTQUERYOBJECT NtQueryObject = NULL; NTSTATUS WINAPI NtSetValueKeyCallback(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName,IN ULONG TitleIndex,IN ULONG type1,IN PVOID Data,IN ULONG DataSize); NTSTATUS WINAPI NtDeleteValueKeyCallback(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName); NTSTATUS WINAPI NtDeleteKeyCallback(IN HANDLE KeyHandle); NTSTATUS WINAPI NtCreateKeyCallback(OUT PHANDLE pKeyHandle,IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes,IN ULONG TitleIndex,IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions,OUT PULONG Disposition OPTIONAL); CHookInfo *ChookNtSetValueKey; CHookInfo *ChookNtDeleteKey; CHookInfo *ChookNtCreateKey; CHookInfo *ChookNtDeleteValueKey; HINSTANCE m_hinstDll; HWND m_hWnd; char *GetSidString(char *strUserName); char *mstrMachinePath="//registry//machine//software//microsoft//windows//currentversion//run"; char mstrUserPath[400]; char *mstrLogonPath="//registry//machine//software//microsoft//windows nt//currentversion//winlogon"; char mstrWinRegPath[260]; HHOOK m_hHook; DWORD m_ProcessId;
//初始NT系列的函数 VOID LoadNtDll() { HMODULE hMod = LoadLibrary("ntdll.dll"); NtDeleteKey = (NTDELETEKEY)GetProcAddress(hMod,"NtDeleteKey"); NtSetValueKey = (NTSETVALUEKEY)GetProcAddress(hMod,"NtSetValueKey"); NtDeleteValueKey = (NTDELETEVALUEKEY)GetProcAddress(hMod,"NtDeleteValueKey"); NtCreateKey = (NTCREATEKEY)GetProcAddress(hMod,"NtCreateKey"); NtQueryObject = (NTQUERYOBJECT)GetProcAddress(hMod,"NtQueryObject"); FreeLibrary(hMod); }
//DLL入口点函数 BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { m_hinstDll=hInstance; if (dwReason == DLL_PROCESS_ATTACH) { m_hWnd=FindWindow(NULL,"注册表监视"); if (!m_hWnd) return FALSE; GetWindowThreadProcessId(m_hWnd,&m_ProcessId); char strUserName[260],strSID[200]; DWORD dwSize; dwSize=260; GetUserName(strUserName,&dwSize); strcpy(mstrUserPath,"//registry//user//"); strcpy(strSID,GetSidString(strUserName)); strcat(mstrUserPath,strlwr(strSID)); strcat(mstrUserPath,"//"); strcpy(mstrWinRegPath,mstrUserPath); strcat(mstrUserPath,"software//microsoft//windows//currentversion//run"); strcat(mstrWinRegPath,"software//microsoft//windows nt//currentversion//windows"); //初始NTDLL LoadNtDll(); if (GetCurrentProcessId()!=m_ProcessId) { ChookNtSetValueKey = new CHookInfo("ntdll.dll","NtSetValueKey",(DWORD)NtSetValueKeyCallback); ChookNtDeleteKey = new CHookInfo("ntdll.dll","NtDeleteKey",(DWORD)NtDeleteKeyCallback); ChookNtCreateKey = new CHookInfo("ntdll.dll","NtCreateKey",(DWORD)NtCreateKeyCallback); ChookNtDeleteValueKey = new CHookInfo("ntdll.dll","NtDeleteValueKey",(DWORD)NtDeleteValueKeyCallback); } } else if (dwReason == DLL_PROCESS_DETACH) { if (GetCurrentProcessId()!=m_ProcessId) { delete ChookNtSetValueKey; delete ChookNtDeleteKey; delete ChookNtCreateKey; delete ChookNtDeleteValueKey; } } return TRUE; // ok }
//卸载钩子 BOOL WINAPI UninstallRegHook()//输出卸在钩子函数 { return(UnhookWindowsHookEx(m_hHook)); }
//钩子函数 LRESULT WINAPI Hook(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数 { return(CallNextHookEx(m_hHook,nCode,wParam,lParam)); }
//安装API钩子 BOOL WINAPI InstallRegHook(LPCTSTR strCheck) { if (strcmpi(strCheck,"http://blog.csdn.net/chenhui530/")!=0) return FALSE; m_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,m_hinstDll,0); if (!m_hHook) { MessageBoxA(NULL,"安装钩子失败","失败",MB_OK); return FALSE; } return TRUE; }
//通过句柄获取注册表路径 void GetPath(char *strPath,HANDLE hHandle) { HANDLE hHeap = GetProcessHeap(); DWORD dwSize = 0; POBJECT_NAME_INFORMATION pName = (POBJECT_NAME_INFORMATION)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 0x1000); NTSTATUS ns = NtQueryObject(hHandle, ObjectNameInformation, (PVOID)pName, 0x1000, &dwSize); DWORD i = 1; while(ns == STATUS_INFO_LEN_MISMATCH) { pName = (POBJECT_NAME_INFORMATION)HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, (LPVOID)pName, 0x1000 * i); ns = NtQueryObject(hHandle, ObjectNameInformation, (PVOID)pName, 0x1000, NULL); i++; } wsprintf(strPath, "%S", pName->Name.Buffer); HeapFree(hHeap,0,pName); }
NTSTATUS WINAPI NtSetValueKeyCallback(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName,IN ULONG TitleIndex,IN ULONG type1,IN PVOID Data,IN ULONG DataSize) { char strName[512]; GetPath(strName,KeyHandle); char strObjectPath[512] = {'/0'}; //获取注册表完整路径包括创建的键名 if(type1 == 4 || type1 == 5 || type1 == 11) wsprintf(strObjectPath, "%s//%S*value:%d,0x%X", strName, ValueName->Buffer, *(DWORD*)Data, *(DWORD*)Data); else if(type1 == 3) wsprintf(strObjectPath, "%s//%S", strName, ValueName->Buffer); else if(type1 == 8) wsprintf(strObjectPath, "%s//%S", strName, ValueName->Buffer); else wsprintf(strObjectPath, "%s//%S*value:%S", strName, ValueName->Buffer, Data); char strTmp[512]; strcpy(strTmp,strObjectPath); char *strLwr=strlwr(strObjectPath); //只监视启动项,这里大家可以自己设置 if (strstr(strLwr,mstrMachinePath) || strstr(strLwr,mstrUserPath) || strstr(strLwr,mstrLogonPath) || strstr(strLwr,mstrWinRegPath)) { COPYDATASTRUCT cds; //构造字符串好让监管程序分离,这里是按我自己特定的格式传过去的,大家可以根据自己的格式构造 char strInt[10]; itoa(type1,strInt,10); char strMsg[512]; strcpy(strMsg,"设置值:"); strcat(strMsg,strTmp); strcat(strMsg,"**"); strcat(strMsg,strInt); strcat(strMsg,"^^"); char strPath[260]; GetModuleFileName(NULL,strPath,sizeof(strPath)); strcat(strMsg,strPath); strcat(strMsg,"进程ID<"); itoa(::GetCurrentProcessId(),strInt,10); strcat(strMsg,strInt); strcat(strMsg,">"); cds.lpData = strMsg; cds.cbData = sizeof(strMsg); cds.dwData = 0; //发送消息给监管程序,如果同意就执行 LRESULT l=::SendMessage(m_hWnd,WM_COPYDATA,0,(LPARAM)&cds); if (l==1000) { ChookNtSetValueKey->HookStatus(FALSE); NTSTATUS hReturn = NtSetValueKey(KeyHandle,ValueName,TitleIndex,type1,Data,DataSize); ChookNtSetValueKey->HookStatus(TRUE); return hReturn; } } else { //没有监控的就让函数执行 ChookNtSetValueKey->HookStatus(FALSE); NTSTATUS hReturn = NtSetValueKey(KeyHandle,ValueName,TitleIndex,type1,Data,DataSize); ChookNtSetValueKey->HookStatus(TRUE); return hReturn; } //不同意的返回拒绝访问 return STATUS_ACCESS_DENIED; }
//注册表删除键值代理函数 NTSTATUS WINAPI NtDeleteValueKeyCallback(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName) { char strName[512]; GetPath(strName,KeyHandle); char strObjectPath[512] = {'/0'}; //获取注册表完整路径包括创建的键名 wsprintf(strObjectPath, "%s//%S", strName, ValueName->Buffer); char strTmp[512]; strcpy(strTmp,strObjectPath); strlwr(strObjectPath); //只监视启动项,这里大家可以自己设置 if (strstr(strObjectPath,mstrMachinePath) || strstr(strObjectPath,mstrUserPath) || strstr(strObjectPath,mstrLogonPath) || strstr(strObjectPath,mstrWinRegPath)) { COPYDATASTRUCT cds; //构造字符串好让监管程序分离,这里是按我自己特定的格式传过去的,大家可以根据自己的格式构造 char strMsg[512]; strcpy(strMsg,"删除值:"); strcat(strMsg,strTmp); strcat(strMsg,"^^"); char strPath[260]; GetModuleFileName(NULL,strPath,sizeof(strPath)); strcat(strMsg,strPath); strcat(strMsg,"进程ID<"); char strInt[10]; itoa(::GetCurrentProcessId(),strInt,10); strcat(strMsg,strInt); strcat(strMsg,">"); cds.lpData = strMsg; cds.cbData = sizeof(strMsg); cds.dwData = 0; //发送消息给监管程序,如果同意就执行 LRESULT l=::SendMessage(m_hWnd,WM_COPYDATA,0,(LPARAM)&cds); if (l==1000) { ChookNtDeleteValueKey->HookStatus(FALSE); NTSTATUS hReturn = NtDeleteValueKey(KeyHandle,ValueName); ChookNtDeleteValueKey->HookStatus(TRUE); return hReturn; } } else { //没有监控的就让函数执行 ChookNtDeleteValueKey->HookStatus(FALSE); NTSTATUS hReturn = NtDeleteValueKey(KeyHandle,ValueName); ChookNtDeleteValueKey->HookStatus(TRUE); return hReturn; } //不同意的返回拒绝访问 return STATUS_ACCESS_DENIED; }
//注册表删除项代理函数 NTSTATUS WINAPI NtDeleteKeyCallback(IN HANDLE KeyHandle) { char strObjectPath[512] = {'/0'}; GetPath(strObjectPath,KeyHandle); char strTmp[512]; strcpy(strTmp,strObjectPath); strlwr(strObjectPath); //排除非启动项 if (strstr(strObjectPath,mstrMachinePath) || strstr(strObjectPath,mstrUserPath) || strstr(strObjectPath,mstrLogonPath) || strstr(strObjectPath,mstrWinRegPath)) { COPYDATASTRUCT cds; //构造字符串好让监管程序分离,这里是按我自己特定的格式传过去的,大家可以根据自己的格式构造 char strMsg[512]; strcpy(strMsg,"删除项:"); strcat(strMsg,strTmp); strcat(strMsg,"^^"); char strPath[260]; GetModuleFileName(NULL,strPath,sizeof(strPath)); strcat(strMsg,strPath); char strInt[10]; strcat(strMsg,"进程ID<"); itoa(::GetCurrentProcessId(),strInt,10); strcat(strMsg,strInt); strcat(strMsg,">"); cds.lpData = strMsg; cds.cbData = sizeof(strMsg); cds.dwData = 0; //发送消息给监管程序,如果同意就执行 LRESULT l=::SendMessage(m_hWnd,WM_COPYDATA,0,(LPARAM)&cds); if (l==1000) { ChookNtDeleteKey->HookStatus(FALSE); NTSTATUS hReturn = NtDeleteKey(KeyHandle); ChookNtDeleteKey->HookStatus(TRUE); return hReturn; } } else { //没有监控的让它继续执行 ChookNtDeleteKey->HookStatus(FALSE); NTSTATUS hReturn = NtDeleteKey(KeyHandle); ChookNtDeleteKey->HookStatus(TRUE); return hReturn; } //不同意的返回拒绝访问 return STATUS_ACCESS_DENIED; }
//注册表创建项代理函数 NTSTATUS WINAPI NtCreateKeyCallback(OUT PHANDLE pKeyHandle,IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes,IN ULONG TitleIndex,IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions,OUT PULONG Disposition OPTIONAL) { char strName[512]; //获取创建的路径 GetPath(strName,ObjectAttributes->RootDirectory); char strObjectPath[512]; //获取注册表完整路径包括创建的键名 wsprintf(strObjectPath, "%s//%S",strName, ObjectAttributes->ObjectName->Buffer); if (lstrcmpi(strObjectPath,mstrMachinePath)==0 || lstrcmpi(strObjectPath,mstrUserPath)==0 || lstrcmpi(strObjectPath,mstrLogonPath)==0 || lstrcmpi(strObjectPath,mstrWinRegPath)==0) { ChookNtCreateKey->HookStatus(FALSE); NTSTATUS hReturn = hReturn = NtCreateKey(pKeyHandle,DesiredAccess,ObjectAttributes,TitleIndex,Class,CreateOptions,Disposition); ChookNtCreateKey->HookStatus(TRUE); return hReturn; } char strTmp[260]; strcpy(strTmp,strObjectPath); strlwr(strObjectPath); //只监视启动项,这里大家可以自己设置 if (strstr(strObjectPath,mstrMachinePath) || strstr(strObjectPath,mstrUserPath) || strstr(strObjectPath,mstrLogonPath) || strstr(strObjectPath,mstrWinRegPath)) { COPYDATASTRUCT cds; //构造字符串好让监管程序分离 char strMsg[512]; strcpy(strMsg,"新增项:"); strcat(strMsg,strTmp); strcat(strMsg,"^^"); char strPath[260]; GetModuleFileName(NULL,strPath,sizeof(strPath)); strcat(strMsg,strPath); strcat(strMsg,"进程ID<"); char strInt[10]; itoa(::GetCurrentProcessId(),strInt,10); strcat(strMsg,strInt); strcat(strMsg,">"); cds.lpData = strMsg; cds.cbData = sizeof(strMsg); cds.dwData = 0; //发送消息给监管程序,当返回1000表示同意 LRESULT l=::SendMessage(m_hWnd,WM_COPYDATA,0,(LPARAM)&cds); if (l==1000) { ChookNtCreateKey->HookStatus(FALSE); NTSTATUS hReturn = NtCreateKey(pKeyHandle,DesiredAccess,ObjectAttributes,TitleIndex,Class,CreateOptions,Disposition); ChookNtCreateKey->HookStatus(TRUE); return hReturn; } } else { //没有监控的就让函数执行 ChookNtCreateKey->HookStatus(FALSE); NTSTATUS hReturn = hReturn = NtCreateKey(pKeyHandle,DesiredAccess,ObjectAttributes,TitleIndex,Class,CreateOptions,Disposition); ChookNtCreateKey->HookStatus(TRUE); return hReturn; } //不同意的返回拒绝访问 return STATUS_ACCESS_DENIED; }
//获取指定用户的SID char *GetSidString(char *strUserName) { char szBuffer[200]; BYTE sidBuffer[100]; PSID pSid=(PSID)&sidBuffer; DWORD sidBufferSize = 100; char domainBuffer[80]; DWORD domainBufferSize = 80; SID_NAME_USE snu; LookupAccountName(NULL,strUserName,pSid,&sidBufferSize,domainBuffer,&domainBufferSize,&snu);
SID_IDENTIFIER_AUTHORITY *psia = GetSidIdentifierAuthority(pSid); DWORD dwTopAuthority = psia->Value[5]; wsprintf(szBuffer, "S-1-%lu", dwTopAuthority); TCHAR szTemp[32]; int iSubAuthorityCount = *(GetSidSubAuthorityCount(pSid)); for (int i = 0; i<iSubAuthorityCount; i++) { DWORD dwSubAuthority = *(GetSidSubAuthority(pSid, i)); wsprintf(szTemp, "%lu", dwSubAuthority); strcat(szBuffer, "-"); strcat(szBuffer, szTemp); } return &szBuffer[0]; }
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2079118