hook源码52破解(hook 破解)
本文目录一览:
求易语言钩子注入dll及home呼出源码
易语言钩子DLL注入源码及源码说明2010-04-06 13:52[所有要使用到的API]
.版本 2
.DLL命令 LoadLibraryA, 整数型,"kernel32.dll","LoadLibraryA"
.参数 lpLibFileName, 文本型
.DLL命令 SetWindowsHookExA, 整数型, "user32.dll", "SetWindowsHookExA", 公开, SetWindowsHookEx
.参数 钩子类型, 整数型, , idHook
.参数 回调函数地址, 整数型, , lpfn
.参数 实例句柄, 整数型, , hmod
.参数 线程ID, 整数型, , dwThreadId
.DLL命令 FreeLibrary, 整数型, "kernel32.dll", "FreeLibrary", , 释放指定的动态链接库,它们早先是用LoadLibrary ;API函数装载的 非零表示成功,零表示失败。会设置GetLastError
.参数 库句柄, 整数型, , hLibModule,要释放的一个库句柄,在VB里使用只能用这个函数释放那些由应用程序明确装载的DLL。对LoadLibrary的每一次调用都应该有一个对应的FreeLibrary调用;
.DLL命令 UnhookWindowsHookEx, 整数型, "user32.dll", "UnhookWindowsHookEx", , UnhookWindowsHookEx
.参数 钩子句柄, 整数型, , hHook
.DLL命令 CallNextHookEx, 整数型, "user32.dll", "CallNextHookEx", 公开, CallNextHookEx
.参数 钩子句柄, 整数型, , hHook
.参数 代码值, 整数型, , ncode
.参数 附加参数1, 整数型, , wParam
.参数 附加参数2, 整数型, 传址, lParam
.DLL命令 GetProcAddress, 整数型, "kernel32.dll", "GetProcAddress", , 取进程路径
.参数 模块句柄, 整数型, , hModule
.参数 进程名称, 文本型, , lpProcName
.DLL命令 GetCurrentThreadId, 整数型, "kernel32.dll", "GetCurrentThreadId"
.DLL命令 获取特别文件夹位置_, 整数型, "shell32.dll", "SHGetSpecialFolderLocation"
.参数 窗口句柄, 整数型, , hwndOwner
.参数 文件夹位置, 整数型, , nFolder
.参数 结构, 项目标识符列表_, 传址, pIdl
.DLL命令 从列表id取路径_, 整数型, "shell32.dll", "SHGetPathFromIDListA", , $(b)
.参数 结构指针, 整数型, , pIdl
.参数 路径, 文本型, 传址, pszPath
.DLL命令 CallWindowProcA, 整数型, "user32.dll", "CallWindowProcA"
.参数 动态调用代码, 字节集, , 一定要用本人编写的
.参数 子程序, 子程序指针, , 子程序指针
.参数 参数, 整数型, 数组, 为整数数组,参数1为成员1…类推;文本型和字节集型(自定义结构)为指针
.参数 参数数目, 整数型, , 一定要和参数数组相符,不然会出错
.参数 是否C调用, 整数型, , 真为cdecl调用方式,假为stdcall调用方式(即标准WINAPI方式)
[这里函数所有代码和一个自定义类型,API代码在左边]
.版本 2
.程序集 程序集1
.程序集变量 临时呼出热键, 整数型
.程序集变量 临时载入窗口, 窗口
.程序集变量 钩子模块句柄, 整数型, , "1000"
.程序集变量 钩子句柄, 整数型, , "1000"
.程序集变量 钩子IDx, 整数型
.程序集变量 x, 整数型
.程序集变量 钩子句柄1, 整数型
.程序集变量 temp目录, 文本型
.程序集变量 xxx, 整数型
.程序集变量 热键钩子句柄, 整数型
.程序集变量 第一次, 逻辑型
.子程序 调用_调用子程序, 整数型, 公开, 呼叫某个函数 可以传入无限个参数 返回函数返回值
.参数 子程序指针, 子程序指针, , 指定函数
.参数 参数, 整数型, 可空 数组, 指定参数 可以不写, 参数为数组 格式为 参数[1]=xxx 参数[2]=xxx 文本型或字节集请用 转换指针 格式2 加入成员(参数,xxx)
.局部变量 动态调用代码, 字节集
动态调用代码 = { 85, 139, 236, 86, 139, 117, 16, 141, 78, 255, 133, 201, 124, 21, 139, 69, 12, 141, 4, 136, 65, 139, 16, 137, 85, 16, 255, 117, 16, 131, 232, 4, 73, 117, 242, 255, 85, 8, 137, 69, 12, 139, 69, 20, 133, 192, 116, 13, 141, 4, 181, 0, 0, 0, 0, 137, 69, 16, 3, 101, 16, 139, 69, 12, 94, 93, 194, 16, 0 }
返回 (CallWindowProcA (动态调用代码, 子程序指针, 参数, 取数组成员数 (参数), 0))
.子程序 操作_取特定目录, 文本型, 公开, 取特定的目录(返回所要取的指定目录名 无效返回空)
.参数 欲获取目录类型, 整数型, 可空, 0我的桌面 1临时目录 5我的文档 6我的收藏夹 7我的启动 11我的开始菜单 20系统字体 36Windows安装目录 37系统目录 [99更多]
.局部变量 路径, 文本型
.局部变量 标示结构, 项目标识符列表_
.局部变量 目录类型, 整数型
.如果真 (欲获取目录类型 = 99)
输出调试文本 (“0我的桌面 2我的程序 5我的文档 6我的收藏夹 7我的启动 8我最近的文档 9我的发送到 11我的开始菜单 13我的音乐 14我的视频 16我的桌面 20系统字体 22开始菜单组 23程序组 24启动组 25桌面 31收藏夹 32我的浏览器临时目录 33我的Cookies 34我的历史记录 36Windows安装目录 37系统目录 38文件安装目录 39我的图片 40用户目录 41系统目录 46文档 47管理工具 48我的管理工具 53音乐 54图片 55视频”)
.如果真结束
.如果 (欲获取目录类型 = 1)
目录类型 = 34
.否则
目录类型 = 欲获取目录类型
.如果结束
获取特别文件夹位置_ (0, 目录类型, 标示结构)
路径 = 取空白文本 (255)
从列表id取路径_ (标示结构.结构大小, 路径)
.如果真 (路径 = “”)
返回 (“”)
.如果真结束
.如果真 (欲获取目录类型 = 1)
路径 = 子文本替换 (路径, “History”, “Temp”, , , 真)
.如果真结束
返回 (路径 + “\”)
.子程序 注入_安装钩子DLL, 整数型, 公开, DLL注入 返回0=失败 整数型 DLL接口(代码值,参数1,参数2)
.参数 线程ID, 整数型, , -1 全局钩子
.参数 DLL全名, 文本型, , DLL全名
.参数 DLL接口, 文本型, 可空, 默认 整数型 钩子接口(代码值,参数1,参数2)
.局部变量 临时变量, 整数型
.局部变量 目录, 文本型
.局部变量 窗口句柄, 整数型
.如果真 (是否为空 (DLL接口) = 真)
DLL接口 = “钩子接口”
.如果真结束
.如果真 (线程ID = 0)
返回 (0)
.如果真结束
.如果真 (线程ID = -1)
线程ID = 0
.如果真结束
钩子IDx = 钩子IDx + 1
钩子模块句柄 [钩子IDx] = LoadLibraryA (DLL全名)
钩子句柄 [钩子IDx] = SetWindowsHookExA (3, GetProcAddress (钩子模块句柄 [钩子IDx], DLL接口), 钩子模块句柄 [钩子IDx], 线程ID)
目录 = 操作_取特定目录 (1)
写配置项 (目录 + “ada.ini”, “ada”, “钩子句柄”, 到文本 (钩子句柄 [钩子IDx]))
输出调试文本 (钩子IDx, 钩子模块句柄 [钩子IDx], 钩子句柄 [钩子IDx])
返回 (钩子IDx)
.版本 2
.子程序 注入_卸载钩子DLL, 逻辑型, 公开
.参数 钩子ID, 整数型, 可空, 卸载所有时无效
.参数 卸载所有, 逻辑型, 可空
.局部变量 xx, 整数型
.如果真 (卸载所有)
.如果真 (钩子IDx > 0)
.计次循环首 (钩子IDx, xx)
.如果真 (钩子模块句柄 [xx] ≠ 0)
FreeLibrary (钩子模块句柄 [xx])
UnhookWindowsHookEx (钩子句柄 [xx])
.如果真结束
.计次循环尾 ()
.如果真结束
返回 (真)
.如果真结束
.如果真 (钩子ID > 0)
.如果真 (钩子模块句柄 [钩子ID] ≠ 0)
FreeLibrary (钩子模块句柄 [钩子ID])
UnhookWindowsHookEx (钩子句柄 [钩子ID])
返回 (真)
.如果真结束
.如果真结束
返回 (假)
.子程序 注入_初始化钩子DLL, 整数型, 公开, DLL用.
.参数 代码值, 整数型
.参数 参数1, 整数型
.参数 参数2, 整数型
.参数 初始, 子程序指针
.局部变量 xxxx, 整数型
.如果真 (钩子句柄1 = 0)
temp目录 =操作_取特定目录 (1)
钩子句柄1 = 到整数 (读配置项 (temp目录 + “ada.ini”, “ada”, “钩子句柄”, ))
.如果真结束
.如果真 (第一次 = 假)
第一次 = 真
调用_调用子程序 (初始)
.如果真结束
返回 (CallNextHookEx (钩子句柄1, 代码值, 参数1, 参数2))
.子程序 注入_设置呼出窗口, 逻辑型, 公开
.参数 设置热键, 整数型
.参数 呼出窗口, 窗口
临时呼出热键 = 设置热键
临时载入窗口 = 呼出窗口
热键钩子句柄 = SetWindowsHookExA (2, 到整数 (呼出键接口), 0, GetCurrentThreadId ())
.如果真 (热键钩子句柄 > 0)
返回 (真)
.如果真结束
返回 (假)
.子程序 呼出键接口, 整数型
.参数 一, 整数型
.参数 二, 整数型
.参数 三, 整数型
.如果真 (一 = 0 且 二 = 临时呼出热键 且 三 > 0)
.如果 (是否已创建 (临时载入窗口))
.如果 (临时载入窗口.可视)
临时载入窗口.可视= 假
.否则
临时载入窗口.可视= 真
.如果结束
.否则
载入 (临时载入窗口, , 假)
临时载入窗口.Esc键关闭= 假
临时载入窗口.最小化按钮= 真
.如果结束
.如果真结束
返回 (CallNextHookEx (热键钩子句柄, 一, 二, 三))
.版本 2
.数据类型 项目标识符列表_, , ITEMIDLIST
.成员 结构大小, 整数型, , , cb
.成员 标识符长度, 字节型, , "255", abID
此函数是用来调用指针函数的.就是CALL
取目录用这个我就不解释了
下面是源码主要函数
函数解释:
本函数参数1为要HOOK的线程ID,参数2为要注入的DLL名,参数3[可空]为DLL接口名字空则为"钩子接口".
下面解释是如何实现的:
1.首先使用LoadLibraryA获取DLL模块地址.
2.然后设置SetWindowsHookExA
参数一为HOOK类型,使用WH_GETMESSAGE(3) Hook来监视从GetMessage or PeekMessage函数返回息。
参数二为接口地址,就是说把消息返回转接到的位置,当然我们这里所使用的是我们DLL所公开的那个函数
参数三为接口模块的句柄即DLL的句柄(地址)
参数四为将要被HOOK的线程ID(0为全局HOOK,不推荐使用全局HOOK)
3.设置完后将钩子句柄写配置项到临时目录(后面将要使用).
说白了其实这个才是真正的接口(DLL里的接口只是在做转接而已),
我先讲这个函数是如何实现的(上面已经说了这才是真正的接口).
1,钩子句柄是一个程序集变量,先判断这个变量是否为0,如果等于0那么就是说这个函数第一次被使用,
第一次使用将读去上个函数写在临时目录的钩子句柄.
2.用一个逻辑变量(程序集变量或全局变量),来判断这个消息钩子是否第一次运行(为了防止后面调用
子程序被多次调用),是的话调用一个子程序(自己设置)
3.使用CallNextHookEx(呼叫下一个钩子)把当前HOOK的信息在传送回被HOOK的钩子里,那个钩子我们
就不用管了.
下来说下到底如何使用
首先在你的EXE程序里写这个(我就不多说这是干吗的了).
然后在DLL里写上这个代码(有人可能觉得眼熟,好像在什么地方见过,对了这个代码和
外挂作坊的钩子注入差不多)
下来说明下按键呼出窗口的函数
用变量把当前参数存起来(主要方便接口调用)
1.为当前运行线程设置一个键盘钩子
2.[接口]设置按键判断,如果按下我们设置的键将呼出窗口,如果这个窗口没创建将判断创建,
如果已经创建再次按下则会隐藏,
载入后的窗口把用ESC关闭的属性弄成假,不需要ESC关闭
3.最后就是再呼叫下以前的钩子.
最后就是卸载钩子DLL了.
判断是否要卸载全部的钩子,如果是就循环将现有钩子DLL全部卸载.
不是就按着ID来卸载
卸载方法:
1.FreeLibrary就是卸载一个载入的DLL
2.UnhookWindowsHookEx乃是卸载这个HOOK
-.-OK了这就是 钩子DLL注入,谢谢大家阅读,如果看不明白,
如何Hook一个函数
从LUA的文档来看: The statement function f () ... end translates to f = function () ... end 那意味着任意一个函数能被其它的任意一个函数通过一个简单的分配所替代。把这个记在心里,它将变得很容易去“Hook”,或者是添加你自己的函数到一个预先定义好的函数中。 # Hook 有钩住,钩子的意思。 警告:这个部分包含过时的信息。比如说我们想显示那些我们级别高很多的玩家和怪的级别来替代骷髅。隐藏级别的函数是TargetFrame_CheckLevel(),因此我们需要hook那个函数来让它不要隐藏级别。 让我们假设我们的插件被命名为"MyAddOn",并且有一个OnLoad处理器被它的XML 事件所调用。在Lua的文档中我们应该有: local MyAddOn_Orig_TargetFrame_CheckLevel; function MyAddOn_OnLoad() MyAddOn_Orig_TargetFrame_CheckLevel = TargetFrame_CheckLevel; -- 存储原始的函数 TargetFrame_CheckLevel = MyAddOn_TargetFrame_CheckLevel; -- Hook进我们的 end 因此上面所做的就是它存储原始"TargetFrame_CheckLevel" 的参量到"MyAddOn_Orig_TargetFrame_CheckLevel"。接着它用我们的函数替换了原始的,因此现在任何人调用TargetFrame_CheckLevel()时实际上得到的是被MyAddOn_TargetFrame_CheckLevel()所替代的。 下一步就是创建我们的MyAddOn_TargetFrame_CheckLevel()。让我们假设我们想要它显示目标的级别。 function MyAddOn_TargetFrame_CheckLevel() local retval = MyAddOn_Orig_TargetFrame_CheckLevel(); -- 调用原始的函数 TargetLevelText:Show(); TargetHighLevelTexture:Hide(); return retval; end 因此在这个函数中,我们首先调用老的函数让它做它必需做的。接着,显示级别并且隐藏骷髅。非常简单不是吗? 这只是一个怎么样hook的例子,它不是真的为你显示级别。 --影子而矣 很容易就能Hook一个函数吗? 如你有Sea库,那么你能hook一个函数用Sea.util.hook。 Sea.util.hook("OldFunctionName", "NewFunctionName", "before|after|hide|replace"); 如果你指明代替,那么老的函数将只在新的函数返回真时被调用。 如果你使用Sea.util.hook,那么你也能在此过后用Sea.util.unhook移去hook。 Sea.util.unhook("OldFunctionName, "NewFunctionName"); 使用Sea.util.hook 要小心参数的传递,优先权,链接并且你能确保在此过后你能清掉这些。 有选择的使用Sea 如果你不想你的插件依赖Sea,但是你又想当它可用时获益,你可以检测它的存在: local MyAddOn_Old_FunctionToHook = function() end; if Sea then Sea.util.hook("FunctionToHook", "ReplacementFunction", "after"); else MyAddOn_Old_FunctionToHook = FunctionToHook; FunctionToHook = ReplacementFunction; end function ReplacementFunction() MyAddOn_Old_FunctionToHook(); ... end 这些编码允许你在你的TOC中列出Sea做为一个OptionalDep。这能帮你防止将来用户安装Sea时其它的插件完全替换老的函数所引起的冲突。 其它Hooking库 Stubby 用Stubby你能hook函数如Stubby.HookFunctionStubby.RegisterFunctionHook("FunctionToHook", position, replacementFunction [, hook1, hook2, .., hookN]) “FunctionToHook”是一个字符串用做你想hook进的hook名字。即:"GameTooltip.SetOwner" (#游戏工具提示.设置所有者) “position”是一个负数或正数定义着插件的真实调用次序。更小或负数,它被你的hookFunction调用的越早,大的数字则反之。实际上初始的(hooked)函数被调用是在position 0,因此如果你的插件被hook在一个负的position,你返回的值表(看下面)将包括在Stubby调用链中以前的函数的值。 你传递(用参量)你的函数一个你想做为替代的函数被调用。这个函数将被下面的参数调用:hookFunction(hookParams, returnValue, hook1, hook2 .. hookN) “hookParams”是一个包括附加参数表被传递到RegisterFunctionHook function (the "hook1, hook2, .., hookN" params) “returnValue”是一个在你进入Stubby调用链或如果没有为空值时被调用函数返回值的数组。 “hook1..hookN”是在初始次序被hook函数的初始参数。 有特殊处理的情况时你能有选择的返回下列字符串到Stubby。 "abort" 将中止调用链(将不会调用任何在你自己所有之后的其它函数计划表)。 "killorig"将不再调用初始的函数,但是将继续调用链。 "setparams"将用你所指定一个列表中的你函数的第二返回值来替换函数的调用参数。 "setreturn" 将用你所指定一个列表中的你函数的第二返回值来改变在Stubby调用链中下一个函数的返回值。 Ace Ace2 到什么地方去调用老的函数 这是很有技巧的,并且真的依赖于你现在正在写的。缺省的情况下你应该有可能首先调用到老的函数,接着做你任何你需要做的。然而,有的时候,你想最后调用老的函数,有条件地调用它,或者根本就不调用它。 注意:不要调用有热门效果的老函数假设另一个插件在你之前hook它。接着什么是你将做的呢,就是不要让插件看见函数调用。这个是hook库真的帮的上忙的地方。 函数带参数 如果你的一个函数带参数,确信你的新函数也带同样的参数,并且它能传递它。 因此举个例子假设我们想hook ActionButton_GetPagedID( id )我们的函数定义应该象: function New_ActionButton_GetPagedID( id ) Old_ActionButton_GetPagedID( id ); ... end 函数使用全局变量 一些函数使用全局变量,并且能在执行过程中改变这些全局变量。例如,GameTooltip_OnEvent()就是这样的函数,在其中它使用全局事件变量,并且在执行过程中改变它。在这种情况中,重要的是在调用老函数前做一个变量的拷贝。好象: function New_GameTooltip_OnEvent() local myEvent =event; Old_GameTooltip_OnEvent(); if ( myEvent = ... ) then ... end end Hook 链 警告:这个部分包含过时的信息。这有点技巧,但是起作用。我们说这有两个单独的的插件,一个附加玩家工具提示到鼠标,以及另一个被用来替换?的玩家级别。一个插件被称做“AnchorToolTip--锚定工具提示”,另一个被称为“ShowLevel--显示级别”。 如果的AnchorToolTip编码是: local Pre_AnchorToolTip_GameTooltip_OnEvent; function AnchorToolTip_OnLoad() Pre_AnchorToolTip_GameTooltip_OnEvent = GameTooltip_OnEvent; GameTooltip_OnEvent = AnchorToolTip_GameTooltip_OnEvent; end function AnchorToolTip_GameTooltip_OnEvent() Pre_AnchorToolTip_GameTooltip_OnEvent(); ... end 以及ShowLevel的编码是: local Pre_ShowLevel_GameTooltip_OnEvent; function ShowLevel_OnLoad() Pre_ShowLevel_GameTooltip_OnEvent = GameTooltip_OnEvent; GameTooltip_OnEvent = ShowLevel_GameTooltip_OnEvent; end function ShowLevel_GameTooltip_OnEvent() Pre_ShowLevel_GameTooltip_OnEvent(); ... end 这真的将起作用。然而,我们说你不仅想Anchor(锚定)tooltip到鼠标当shift 键被按下时。一个小的简单改变好象: function AnchorToolTip_GameTooltip_OnEvent() if ( isShiftKeyDown() ) then Pre_AnchorToolTip_GameTooltip_OnEvent(); ... end end 有可能打断hook链取决于哪个插件先加裁。因而,千万千万小心当你决定什么时候在什么地方调用老函数。
求助,易语言反HOOK源码,防止其他程序DLL注入
腾讯电脑管家可以帮助修复
a进入管家的首页后,点击右上角的“工具箱”按钮,点击“电脑诊所”
b进入“电脑诊所”找到“软件硬件”点击“丢失dll文件”最后“一键修复”界面
可以根据自己弹出的对话框中显示的无法启动程序是丢失的何种dll文件,找到对应的后,鼠标轻轻放在该项上,当出现了“立即修复”按钮后点击“立即修复”按钮。
完成以上步骤后,系统便自行修复了dll文件丢失的故障了,完成了修复
谁比较了解HOOK技术帮一下
Hook解释
Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,中文译为“挂钩”或“钩子”。在对特定的系统事件进行hook后,一旦发生已hook事件,对该事件进行hook的程序就会受到系统的通知,这时程序就能在第一时间对该事件做出响应。
另一解释:
钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
Hook原理
每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。
钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。
系统钩子与线程钩子
SetWindowsHookEx()函数的最后一个参数决定了此钩子是系统钩子还是线程钩子。
线程勾子用于监视指定线程的事件消息。线程勾子一般在当前线程或者当前线程派生的线程内。
系统勾子监视系统中的所有线程的事件消息。因为系统勾子会影响系统中所有的应用程序,所以勾子函数必须放在独立的动态链接库(DLL) 中。系统自动将包含“钩子回调函数”的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程。
几点说明:
(1)如果对于同一事件(如鼠标消息)既安装了线程勾子又安装了系统勾子,那么系统会自动先调用线程勾子,然后调用系统勾子。
(2)对同一事件消息可安装多个勾子处理过程,这些勾子处理过程形成了勾子链。当前勾子处理结束后应把勾子信息传递给下一个勾子函数。
(3)勾子特别是系统勾子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装勾子,在使用完毕后要及时卸载。
Hook的应用模式
观察模式
最为常用,像Windows提供的SetWindowHook就是典型地为这类应用准备的。而且这也是最普遍的用法。
这个模式的特点是,在事情发生的时候,发出一个通知信息。观察者只可以查看过程中的信息,根据自己关心的内容处理自己的业务,但是不可以更改原来的流程。
如全局钩子中,经常使用的鼠标消息、键盘消息的监视等应用。金山词霸屏幕取词的功能是一个典型的应用(具体技术可以参考此类文章)。
注入模式
这个模式和观察模式最大的不一样的地方在于,注入的代码是为了扩展原始代码的功能业务。插件模式是此类模式的典型案例。
不管瘦核心的插件系统(如Eclipse)还是胖核心的插件系统(如Delphi、Visual Studio等IDE环境),其对外提供的插件接口都是为了扩展本身系统的功能的。
这种扩展的应用方式的典型特点,就是新的扩展代码和原来的代码会协调处理同类业务。
替换模式
如果针对应用目的不同,可以叫修复模式或破解模式。前者是为了修改系统中的BUG,后者是为了破解原有系统的限制。
很多黑客使用此种模式,将访问加密锁的DLL中的导出表,替换成自己的函数,这样跳过对软件的控制代码。这类应用的难点是,找出函数的参数。
这类模式的特点是,原有的代码会被新的代码所替换。
前面三个是基本模式,还有很多和实际应用相关的模式。
集权模式
此类模式的出现,大都是为了在全部系统中,统一处理某类事情。它的特点不在于注入的方式,而在于处理的模式。
这个模式,大都应用到某类服务上,比如键盘服务,鼠标服务,打印机服务等等特定服务上。通过统一接管此类服务的访问,限制或者协调对服务的访问。
比如键盘锁功能的实现,就是暂时关闭键盘的所有应用。
这类模式的特点主要会和特点服务有关联。
修复模式
替换模式的一种,这里强调的是其应用的目的是为了修复或扩展原有系统的功能。
破解模式
替换模式的一种,这里强调的是其应用的目的是为了跳过原有系统的一部分代码。如加密检测代码,网络检测代码等等。
插件模式
注入模式的一种,在系统的内部直接依靠HOOK机制进行扩展业务功能。
共享模式
这类应用中,经常是为了获取对方的数据。必然我希望获取对方系统中,所有字符串的值。可以通过替换对方的内存管理器,导出所有字符串。
这个应用比较特殊。不过其特点在于,目的是达到系统之间的数据共享。
其实现,可能是观察模式,也可能是替换模式。
VB中的Hook技术应用
一、Hook简介
Hook这个东西有时令人又爱又怕,Hook是用来拦截系统某些讯息之用,例如说,我们想
让系统不管在什么地方只要按个Ctl-B便执行NotePad,或许您会使用Form的KeyPreview
,设定为True,但在其他Process中按Ctl-B呢?那就没有用,这是就得设一个Keyboard
Hook来拦截所有Key in的键;再如:MouseMove的Event只在该Form或Control上有效,如果希望在Form的外面也能得知Mouse Move的讯息,那只好使用Mouse Hook来栏截Mouse
的讯息。再如:您想记录方才使用者的所有键盘动作或Mosue动作,以便录巨集,那就
使用JournalRecordHook,如果想停止所有Mosue键盘的动作,而放(执行)巨集,那就
使用JournalPlayBack Hook;Hook呢,可以是整个系统为范围(Remote Hook),即其他
Process的动作您也可以拦截,也可以是LocalHook,它的拦截范围只有Process本身。
Remote Hook的Hook Function要在.Dll之中,Local Hook则在.Bas中。
在VB如何设定Hook呢?使用SetWindowsHookEx()
Declare Function SetWindowsHookEx Lib 'user32' Alias 'SetWindowsHookExA' _
(ByVal idHook As Long, _
ByVal lpfn As Long, _
ByVal hmod As Long, _
ByVal dwThreadId As Long) As Long
idHook代表是何种Hook,有以下几种
Public Const WH_CALLWNDPROC = 4
Public Const WH_CALLWNDPROCRET = 12
Public Const WH_CBT = 5
Public Const WH_DEBUG = 9
Public Const WH_FOREGROUNDIDLE = 11
Public Const WH_GETMESSAGE = 3
Public Const WH_HARDWARE = 8
Public Const WH_JOURNALPLAYBACK = 1
Public Const WH_JOURNALRECORD = 0
Public Const WH_KEYBOARD = 2
Public Const WH_MOUSE = 7
Public Const WH_MSGFILTER = (-1)
Public Const WH_SHELL = 10
Public Const WH_SYSMSGFILTER = 6
lpfn代表Hook Function所在的Address,这是一个CallBack Fucnction,当挂上某个
Hook时,我们便得定义一个Function来当作某个讯息产生时,来处理它的Function
,这个Hook Function有一定的叁数格式
Private Function HookFunc(ByVal ncode As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
nCode 代表是什么请况之下所产生的Hook,随Hook的不同而有不同组的可能值
wParam lParam 传回值则随Hook的种类和nCode的值之不同而不同。
因这个叁数是一个 Function的Address所以我们固定将Hook Function放在.Bas中,
并以AddressOf HookFunc传入。至于Hook Function的名称我们可以任意给定,不一
定叫 HookFunc
hmod 代表.DLL的hInstance,如果是Local Hook,该值可以是Null(VB中可传0进去),
而如果是Remote Hook,则可以使用GetModuleHandle('.dll名称')来传入。
dwThreadId 代表执行这个Hook的ThreadId,如果不设定是那个Thread来做,则传0(所以
一般来说,Remote Hook传0进去),而VB的Local Hook一般可传App.ThreadId进去
值回值如果SetWindowsHookEx()成功,它会传回一个值,代表目前的Hook的Handle,
这个值要记录下来。
因为A程式可以有一个System Hook(Remote Hook),如KeyBoard Hook,而B程式也来设一
个Remote的KeyBoard Hook,那么到底KeyBoard的讯息谁所拦截?答案是,最后的那一个
所拦截,也就是说A先做keyboard Hook,而后B才做,那讯息被B拦截,那A呢?就看B的
Hook Function如何做。如果B想让A的Hook Function也得这个讯息,那B就得呼叫
CallNextHookEx()将这讯息Pass给A,于是产生Hook的一个连线。如果B中不想Pass这讯息
给A,那就不要呼叫CallNextHookEx()。
Declare Function CallNextHookEx Lib 'user32' _
(ByVal hHook As Long, _
ByVal ncode As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
hHook值是SetWindowsHookEx()的传回值,nCode, wParam, lParam则是Hook Procedure
中的三个叁数。
最后是将这Hook去除掉,请呼叫UnHookWindowHookEx()
Declare Function UnhookWindowsHookEx Lib 'user32' (ByVal hHook As Long) As Long
hHook便是SetWindowsHookEx()的传回值。此时,以上例来说,B程式结束Hook,则换A可
以直接拦截讯息。
KeyBoard Hook的范例
Hook Function的三个叁数
nCode wParam lParam 传回值
HC_ACTION 表按键Virtual Key 与WM_KEYDOWN同 若讯息要被处理传0
或 反之传1
HC_NOREMOVE
Public hHook As Long
Public Sub UnHookKBD()
If hnexthookproc lt;gt; 0 Then
UnhookWindowsHookEx hHook
hHook = 0
End If
End Sub
Public Function EnableKBDHook()
If hHook lt;gt; 0 Then
Exit Function
End If
hHook = SetWindowsHookEx(WH_KEYBOARD, AddressOf MyKBHFunc, App.hInstance, App.ThreadID)
End Function
Public Function MyKBHFunc(ByVal iCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
MyKBHFunc = 0 '表示要处理这个讯息
If wParam = vbKeySnapshot Then '侦测 有没有按到PrintScreen键
MyKBHFunc = 1 '在这个Hook便吃掉这个讯息
End If
Call CallNextHookEx(hHook, iCode, wParam, lParam) '传给下一个Hook
End Function
只要将上面代码放在VB的模块中,用标准VB程序就可以了,当运行该程序后,就能拦截所有键盘操作。