核心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