反病毒工具之注册表监视器(VC DLL源码)

来源:互联网 发布:ingress是什么软件 编辑:程序博客网 时间:2024/06/05 16:49

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

//获取指定用户的SIDchar *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