首页
官方解析
影视大全
星源影视
搜索
登录
搜索
nohacks
累计撰写
29
篇文章
累计收到
0
条评论
首页
官方解析
影视大全
星源影视
作者 【1】 的文章
2016-3-19
EKeyTool PE文件强制签名工具 V1.0
简介: 主要是给易语言静态编译用来强制签名。 调用格式: 复制本程序签名: EKeyTool.exe a 文件名 复制源程序签名: EKeyTool.exe c 源文件 目标文件 获取签名数据: EKeyTool.exe g 源文件 目标文件 写入签名数据: EKeyTool.exe w 源文件 目标文件 使用说明 将tools复制到易语言安装目录,即可实现静态编译时自动调用UPX压缩和强制签名。 易语言链接器插件的配置文件,支持调用外部接口,命令行程序很方便调用: linker="\VC98linker\bin\link.exe" post_link_action1=$(ECHO) 正在调用UPX压缩: post_link_action2=$(E_TOOLS)\upx.exe $(TARGET) post_link_action1=$(ECHO) 正在调用ekeytool强制签名: post_link_action2=$(E_TOOLS)\ekeytool.exe a $(TARGET) 下载地址:EKeyTool 相关下载:易语言
2016年-3月-19日
1424 阅读
0 评论
开源作品
2016-3-12
EasyLoad 简易软件部署工具 V1.4
EasyLoad 是一款简易软件部署工具,不同EasySteup是桌面环境调用,EasyLoad适合在系统封装中静默调用,由 nohacks.cn 原创,转载请注明出处!
2016年-3月-12日
1591 阅读
0 评论
开源作品
2016-3-8
ROS API 中文开发文档 (易语言版)
前言 ROS 是 一个比较流行的软路由系统,它的强大在于它的高度定制性,它提供了应用程序编程使用的API接口,是它应用更加灵活,我们可以自己开发软件或WEB程序来操控ROS,比较实用的例子就是当用ROS管理小区网络时,我们用自己写的软件来管理上网账号,安全又方便,总之好处多多,本文基于官方API文档: HYPERLINK “http://wiki.mikrotik.com/wiki/API" http://wiki.mikrotik.com/wiki/API 翻译而成,结合了作者的理解,水平有限,难免有错漏的地方,望大家批评指正,由nohacks.cn原创,转载请注明出处! 因为篇幅较长,请移步网盘下载: ROS API 中文开发文档 提取码: kyb5
2016年-3月-8日
2422 阅读
0 评论
开源作品
2016-3-8
超级防锁专家 V1.04(网吧免费上网利器)
概述 很早以前玩windows 内核时的产物,可以用来网吧免费上网,不过现在系统都是 64 位了,虽然不能用来免费上网了,但是用来上班摸鱼还是好用的,由 nohacks.cn 原创,转载请注明出处! 原理 网管类程序锁定电脑的时候,都会有一个会员登陆窗口,我们可以先开一个短时,启动软件虚拟一个新桌面,然后驱动级禁止关机,就能实现免费上网。 更新记录: 2014.9.8 中秋 发布 1.04 版 1.增加电源按钮为桌面切换的快捷键。 2.其他细节优化。 简介: 主要功能:创建一个虚拟桌面防止被锁定并禁止系统关机。 用途: 办公室或者网吧等场合。 使用方法: 用ctrl+Tab组合键或者电源按钮在两个桌面间切换,WIN+0退出程序 注意事项: 驱动版当前只支持WINXP3以及32位的WIN7,无驱版可适用32位和 64 位 windows 系统,适合办公环境,用来快速隐藏 下载地址:超级防锁专家 参考链接:网管软件玩隐身,API巧破网管软件 (驱动版)
2016年-3月-8日
1081 阅读
0 评论
开源作品
2011-9-30
Windows Hook 易核心编程<1>勾子基本概念
本期导读 什么叫勾子,勾子又起什么作用,它有那些类别,怎么使用,等等这些问题将在本期找到答案 基本概念 钩子(Hook),是Windows消息处理机制的一个平台,应用程序可以在上面设置子程以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控 制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。 运行机制 钩子链表和钩子子程 每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。 Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。 钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。 钩子子程必须按照以下的语法: LRESULT CALLBACK HookProc ( int nCode, WPARAM wParam, LPARAM lParam ); 当然上面是在C语言中的声明,意思是说这个自定义的钩子子程必须有3个参数,在易语言中则是这样声明: .子程序 HookProc, 整数型, 公开, 钩子回调函数 .参数 ncode, 整数型 .参数 wParam, 整数型 .参数 lParam, 整数型 HookProc是应用程序定义的名字。 nCode参数是Hook代码,Hook子程使用这个参数来确定任务。这个参数的值依赖于Hook类型,每一种Hook都有自己的Hook代码特征字符集。 wParam和lParam参数的值依赖于Hook代码,但是它们的典型值是包含了关于发送或者接收消息的信息。 钩子的安装与释放 钩子的安装 使用API函数SetWindowsHookEx()把一个应用程序定义的钩子子程安装到钩子链表中。SetWindowsHookEx函数总是在Hook链的开头安装Hook子程。当指定类型的Hook监视的事件发生时,系统就调用与这个Hook关联的Hook链的开头的Hook子程。每一个Hook链中的Hook子程都决定是否把这个事件传递到下一个Hook子程。Hook子程传递事件到下一个Hook子程需要调用CallNextHookEx函数。 HOOK SetWindowsHookEx( int idHook, //参数<1> HOOKPROC lpfn, //参数<2> HINSTANCE hMod, //参数<3> DWORD dwThreadId //参数<4> ); 在易中则这样声明DLL: .DLL命令 api_SetWindowsHookExA, 整数型, , "SetWindowsHookExA" .参数 idHook, 整数型 .参数 lpfn, 子程序指针 .参数 nMod, 整数型 .参数 dwThreadID, 整数型 参数idHook是钩子的类型,即它处理的消息类型 参数lpfn是钩子子程的地址指针。如果dwThreadId参数为0,或是一个由别的进程创建的线程的标识 lpfn必须指向DLL中的钩子子程。除此以外,lpfn可以指向当前进程的一段钩子子程代码。 参数nMod是应用程序实例的句柄。标识包含lpfn所指的子程的DLL,如果dwThreadId 标识当前进程创建的一个线程,而且子程代码位于当前进程,hMod必须为NULL。可以很简单的设定其为本 应用程序的实例句柄。 参数dwThreadID:与安装的钩子子程相关联的线程的标识符, 如果为0,钩子子程与所有的线程关联即为全局钩子。函数成功则返回钩子子程的句柄,失败返回(NULL)0。 钩子的循环 以上所说的钩子子程与线程相关联是指在一钩子链表中发给该线程的消息同时发送给钩子子程,且被钩子子程先处理。在钩子子程中调用得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx来传递它,以执行钩子链表所指的下一个钩子子程。这个函数成功时返回钩子链中下一个钩子过程的返回值,返回值的类型依赖于钩子的类型。这个函数的原型如下: LRESULT CallNextHookEx ( HHOOK hhook; int nCode; WPARAM wParam; LPARAM lParam; ); 易语言版本: .DLL命令 CallNextHookEx, 整数型, , "CallNextHookEx" .参数 hhook, 整数型 .参数 nCode, 整数型 .参数 wParam, 整数型 .参数 lParam, 整数型 hhook为当前钩子的句柄,由SetWindowsHookEx()函数返回。 NCode为传给钩子过程的事件代码。 wParam和lParam 分别是传给钩子子程的wParam值,其具体含义与钩子类型有关。 钩子函数也可以通过直接返回(TRUE)真来丢弃该消息,并阻止该消息的传递。否则的话,其他安装了钩子的应用程序将不会接收到钩子的通知而且还有可能产生不正确的结果。 钩子的卸载 钩子在使用完之后需要用UnHookWindowsHookEx()卸载,否则会造成麻烦。释放钩子比较简单,UnHookWindowsHookEx()只有一个参数。函数原型如下: UnHookWindowsHookEx ( HHOOK hhk; ); 易语言版本: .DLL命令 api_UnhookWindowsHookEx, 逻辑型, , "UnhookWindowsHookEx" .参数 hhook, 整数型 函数成功返回(TRUE)真,否则返回(FALSE)假。 一些运行机制 在Win16环境中,DLL的全局数据对每个载入它的进程来说都是相同的;而在Win32环境中,情况却发生了变化,DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。当进程在载入DLL时,操作系统自动把DLL地址映射到该进程的私有空间,也就是进程的虚拟地址空间,而且也复制该DLL的全局数据的一份拷贝到该进程空间。也就是说每个进程所拥有的相同的DLL的全局数据,它们的名称相同,但其值却并不一定是相同的,而且是互不干涉的。 因此,在Win32环境下要想在多个进程中共享数据,就必须进行必要的设置。在访问同一个Dll的各进程之间共享存储器是通过存储器映射文件技术实现的。也可以把这些需要共享的数据分离出来,放置在一个独立的数据段里,并把该段的属性设置为共享。必须给这些变量赋初值,否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。 pragma data_seg预处理指令用于设置共享数据段。例如: #pragma data_seg(“SharedDataName”) HHOOK hHook=NULL; #pragma data_seg() 在#pragma data_seg(“SharedDataName”)和#pragma data_seg()之间的所有变量将被访问该Dll的所有进程看到和共享。再加上一条指令#pragma comment(linker,”/section:.SharedDataName,rws”),那么这个数据节中的数据可以在所有DLL的实例之间共享。所有对这些数据的操作都针对同一个实例的,而不是在每个进程的地址空间中都有一份。 当进程隐式或显式调用一个动态库里的函数时,系统都要把这个动态库映射到这个进程的虚拟地址空间里(以下简称”地址空间”)。这使得DLL成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈。 系统钩子与线程钩子 SetWindowsHookEx()函数的最后一个参数决定了此钩子是系统钩子还是线程钩子。 线程勾子用于监视指定线程的事件消息。线程勾子一般在当前线程或者当前线程派生的线程内。 系统勾子监视系统中的所有线程的事件消息。因为系统勾子会影响系统中所有的应用程序,所以勾子函数必须放在独立的动态链接库(DLL) 中。系统自动将包含”钩子回调函数”的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程。 几点说明: (1)如果对于同一事件(如鼠标消息)既安装了线程勾子又安装了系统勾子,那么系统会自动先调用线程勾子,然后调用系统勾子。 (2)对同一事件消息可安装多个勾子处理过程,这些勾子处理过程形成了勾子链。当前勾子处理结束后应把勾子信息传递给下一个勾子函数。 (3)勾子特别是系统勾子会消耗消息处理时间,降低系统性能。只有在必要的时候才安装勾子,在使用完毕后要及时卸载。 钩子类型 每一种类型的Hook可以使应用程序能够监视不同类型的系统消息处理机制。下面描述所有可以利用的Hook类型。 WH_CALLWNDPROC(4)和WH_CALLWNDPROCRET Hooks(12) WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以监视发送到窗口过程的消息。系统在消息发送到接收窗口过程之前调用WH_CALLWNDPROC Hook子程,并且在窗口过程处理完消息之后调用WH_CALLWNDPROCRET Hook子程。 WH_CALLWNDPROCRET Hook传递指针到CWPRETSTRUCT结构,再传递到Hook子程。 CWPRETSTRUCT结构包含了来自处理消息的窗口过程的返回值,同样也包括了与这个消息关联的消息参数。 WH_CBT(5) Hook 在以下事件之前,系统都会调用WH_CBT Hook子程,这些事件包括: 激活,建立,销毁,最小化,最大化,移动,改变尺寸等窗口事件; 完成系统指令; 来自系统消息队列中的移动鼠标,键盘事件; 设置输入焦点事件; 同步系统消息队列事件。 Hook子程的返回值确定系统是否允许或者防止这些操作中的一个。 WH_DEBUG(9) Hook 在系统调用系统中与其他Hook关联的Hook子程之前,系统会调用WH_DEBUG Hook子程。你可以使用这个Hook来决定是否允许系统调用与其他Hook关联的Hook子程。 WH_FOREGROUNDIDLE(11) Hook 当应用程序的前台线程处于空闲状态时,可以使用WH_FOREGROUNDIDLE Hook执行低优先级的任务。当应用程序的前台线程大概要变成空闲状态时,系统就会调用WH_FOREGROUNDIDLE Hook子程。 WH_GETMESSAGE(3) Hook 应用程序使用WH_GETMESSAGE Hook来监视从GetMessage or PeekMessage函数返回的消息。你可以使用WH_GETMESSAGE Hook去监视鼠标和键盘输入,以及其他发送到消息队列中的消息。 WH_JOURNALPLAYBACK(1) Hook WH_JOURNALPLAYBACK Hook使应用程序可以插入消息到系统消息队列。可以使用这个Hook回放通过使用WH_JOURNALRECORD Hook记录下来的连续的鼠标和键盘事件。只要WH_JOURNALPLAYBACK Hook已经安装,正常的鼠标和键盘事件就是无效的。 WH_JOURNALPLAYBACK Hook是全局Hook,它不能象线程特定Hook一样使用。 WH_JOURNALPLAYBACK Hook返回超时值,这个值告诉系统在处理来自回放Hook当前消息之前需要等待多长时间(毫秒)。这就使Hook可以控制实时事件的回放。 WH_JOURNALPLAYBACK是system-wide local hooks,它們不會被注射到任何行程位址空間。 WH_JOURNALRECORD(0) Hook WH_JOURNALRECORD Hook用来监视和记录输入事件。典型的,可以使用这个Hook记录连续的鼠标和键盘事件,然后通过使用WH_JOURNALPLAYBACK Hook来回放。 WH_JOURNALRECORD Hook是全局Hook,它不能象线程特定Hook一样使用。 WH_JOURNALRECORD是system-wide local hooks,它們不會被注射到任何行程位址空間。 WH_KEYBOARD(2) Hook 在应用程序中,WH_KEYBOARD Hook用来监视WM_KEYDOWN and WM_KEYUP消息,这些消息通过GetMessage or PeekMessage function返回。可以使用这个Hook来监视输入到消息队列中的键盘消息。 WH_KEYBOARD_LL(13) Hook WH_KEYBOARD_LL Hook监视输入到线程消息队列中的键盘消息。 WH_MOUSE(7) Hook WH_MOUSE Hook监视从GetMessage 或者 PeekMessage 函数返回的鼠标消息。使用这个Hook监视输入到消息队列中的鼠标消息。 WH_MOUSE_LL(14) Hook WH_MOUSE_LL Hook监视输入到线程消息队列中的鼠标消息。 WH_MSGFILTER(-1) 和 WH_SYSMSGFILTER(6) Hooks WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以监视菜单,滚动条,消息框,对话框消息并且发现用户使用ALT+TAB or ALT+ESC 组合键切换窗口。WH_MSGFILTER Hook只能监视传递到菜单,滚动条,消息框的消息,以及传递到通过安装了Hook子程的应用程序建立的对话框的消息。WH_SYSMSGFILTER Hook监视所有应用程序消息。 WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我们可以在模式循环期间过滤消息,这等价于在主消息循环中过滤消息。 通过调用CallMsgFilter function可以直接的调用WH_MSGFILTER Hook。通过使用这个函数,应用程序能够在模式循环期间使用相同的代码去过滤消息,如同在主消息循环里一样。 WH_SHELL Hook(10) 外壳应用程序可以使用WH_SHELL Hook去接收重要的通知。当外壳应用程序是激活的并且当顶层窗口建立或者销毁时,系统调用WH_SHELL Hook子程。 WH_SHELL 共有5钟情況: 只要有个top-level、unowned 窗口被产生、起作用、或是被摧毁; 当Taskbar需要重画某个按钮; 当系统需要显示关于Taskbar的一个程序的最小化形式; 当目前的键盘布局状态改变; 当使用者按Ctrl+Esc去执行Task Manager(或相同级别的程序)。 按照惯例,外壳应用程序都不接收WH_SHELL消息。所以,在应用程序能够接收WH_SHELL消息之前,应用程序必须调用SystemParametersInfo function注册它自己。 本章总结 呵呵,有点昏昏的感觉吗?不要紧的,多看几次就会好的! 好了,这期的勾子基本概念就算讲完了,让我们来总结一下: 钩子的基本概念及作用 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。 使用API函数SetWindowsHookEx()安装钩子. 在易中则这样声明DLL: .DLL命令 SetWindowsHookExA, 整数型, , "SetWindowsHookExA" .参数 idHook, 整数型 .参数 lpfn, 子程序指针 .参数 nMod, 整数型 .参数 dwThreadID, 整数型 用API函数CallNextHookEx来传递钩子 .DLL命令 CallNextHookEx, 整数型, , "CallNextHookEx" .参数 hhook, 整数型 .参数 nCode, 整数型 .参数 wParam, 整数型 .参数 lParam, 整数型 用API函数UnHookWindowsHookEx()来卸载钩子 .DLL命令 api_UnhookWindowsHookEx, 逻辑型, , "UnhookWindowsHookEx" .参数 hhook, 整数型 我们拿最常用的上面的第5个WH_GETMESSAGE(3) Hook 来说明一下: 看看下面这段易代码你就会明白的: hMod = LoadLibraryA (取运行目录 () + “\HookDLL.dll” ) '装载动态链接库 lpProc =GetProcAddress (hMod, “GetMsgProc”) '定位钩子回调函数函数 hhook = SetWindowsHookExA (#WH_GETMESSAGE, lpProc, hMod, 0) '安装钩子 好了,这期的理论知识就到这了,请关注下期的精彩内容. 下期预告 下期我们将用易源码实例来讲解,怎样用钩子技术和内存文件映射共享技术来 实现远程线程插入资源管理器进程(explorer.exe),
2011年-9月-30日
1187 阅读
0 评论
开源作品
2007-7-8
汇编ring3下实现HOOK API(二次修改版)
概述 很早以前发表在看雪论坛的一篇关于hook api的文章,由nohacks原创,转载请注明出处。 目录 1.概述 2.目录 3. 介绍 3.1 什么叫Hook API? 3.2 API Hook的应用介绍 3.3 API Hook的原则 4.挂钩方法 4.1 改写IAT导入表法 4.2 改写内存地址JMP法 5.汇编实现 5.1. 代码 5.2. 分析 6.结束语 介绍 这篇文章是有关在OS Windows下挂钩API函数的方法。所有例子都在基于NT技术的Windows版本NT4.0及以上有效(Windows NT 4.0, Windows 2000, Windows XP,可能在其它Windows系统也会有效。你应该比较熟悉Windows下的进程、汇编器、和一些API函数,才能明白这篇文章里的内容。 什么叫Hook API? 所谓Hook就是钩子的意思,而API是指Windows开放给程序员的编程接口,使得在用户级别下可以对操作系统进行控制,也就是一般的应用程序都需要调用API来完成某些功能,Hook API的意思就是在这些应用程序调用真正的系统API前可以先被截获,从而进行一些处理再调用真正的API来完成功能。 API Hook的应用介绍 API Hook技术应用广泛,常用于屏幕取词,网络防火墙,病毒木马,加壳软件,串口红外通讯,游戏外挂,internet通信等领域API HOOK的中文意思就是钩住API,对API进行预处理,先执行我们的函数,例如我们用API Hook技术挂接ExitWindowsEx API函数使关机失效,挂接ZwOpenProcess函数隐藏进程等等…… API Hook的原则 HOOK API有一个原则,这个原则就是:被HOOK的API的原有功能不能受到任何影响。就象医生救人,如果把病人身体里的病毒杀死了,病人也死了,那么这个“救人”就没有任何意义了。如果你HOOK API之后,你的目的达到了,但API的原有功能失效了,这样不是HOOK,而是REPLACE,操作系统的正常功能就会受到影响,甚至会崩溃。 挂钩方法 总的来说,常用的挂钩API方法有以下两种: 改写IAT导入表法 修改可执行文件的IAT表(即输入表)因为在该表中记录了所有调用API的函数地址,则只需将这些地址改为自己函数的地址即可,但是这样有一个局限,因为有的程序会加壳,这样会隐藏真实的IAT表,从而使该方法失效。 改写内存地址JMP法 直接跳转,改变API函数的入口或出口的几个字节,使程序跳转到自己的函数,该方法不受程序加壳的限制。这种技术,说起来也不复杂,就是改变程序流程的技术。在CPU的指令里,有几条指令可以改变程序的流程:JMP,CALL,INT,RET,RETF,IRET等指令。理论上只要改变API入口和出口的任何机器码,都可以HOOK,下面我就说说常用的改写API入口点的方法: 因为工作在Ring3模式下,我们不能直接修改物理内存,只能一个一个打开修改,但具体的方法又分成好几种,我给大家介绍几种操作思路: 首先改写API首字节,要实现原API的功能需要调用API时先还原被修改的字节,然后再调用原API,调用完后再改回来,这样实现有点麻烦,但最简单,从理论上说有漏HOOK的可能,因为我们先还原了API,如果在这之前程序调用了API,就有可能逃过HOOK的可能! 把被覆盖的汇编代码保存起来,在替代函数里模拟被被覆盖的功能,然后调用原函数(原地址+被覆盖长度).但这样会产生一个问题,不同的汇编指令长度是不一样的(比如说我们写入的JMP指令占用5个字节,而我们写入的这5个字节占用的位置不一定正好是一个或多个完整的指令,有可能需要保存7个字节,才不能打乱程序原有的功能,需要编写一个庞大的判断体系来判断指令长度,网上已经有这样的汇编程序(Z0MBiE写的LDE32),非常的复杂! 把被HOOK的函数备份一下,调用时在替代函数里调用备份函数.为了避免麻烦,可以直接备份整个DLL缺点就是太牺牲内存,一般不推荐使用这种方法! 汇编实现 本文就是建立在第2种方法改写内存地址JMP法之上的!本着先易后难的原则,今天我们先来说说它的第1种操作思路. 我们拿API函数ExitWindowsEx来说明,下面是我在OD里拦下的ExitWindowsEx原入口部分 77D59E2D $ 8BFF mov edi,edi 77D59E2F . 55 push ebp 77D59E30 . 8BEC mov ebp,esp 77D59E32 . 83EC 18 sub esp,18 如果我们把ExitWindowsEx的入口点改为下面的,会出现什么情况? 77D59E2D B8 00400000 mov eax,4000 77D59E32 FFE0 jmp eax 我们可想而知,程序执行到77D59E32处就会改变流程跳到00400000的地方 如果我们的00400000处是这样的子程: ======================= MyAPI proc bs:DWORD ,dwReserved:DWORD ;和ExitWindowsEx一样带2个参数 ;做你想做的事 ...... ;这里放API入口点改回原机器码的代码 ;如果你是备份的整个DLL,就直接调用备份API,不用改来改去了,不会有漏勾API的可能! invoke ExitWindowsEx,bs,dwReserved ;这里放HOOK API的代码 .endif mov eax,TRUE ret 这里的MyAPI是和ExitWindowsEx参数一样的的子程,因为程序是在API的入口部分跳转的,根据stdcall约定(参数数据从右向左依次压栈,恢复堆栈的工作交由被调用者),此时堆栈还没有恢复,我们 在子程里取出的参数数据依然有效,我们可以在这里执行自己的代码,你可以决定是否继续按原参数或改变参数后再调用原API,也可以什么都不做,当然在调用之前,我们要先还原我们修改过的API(可以事先用 API函数ReadProcessMemory读出原API的前几个字节备份之),调用完后再改回来继续HOOKAPI,不过这种方法有漏API的可能原因前面已经说了),你如果觉得这个方法不妥,因为一般系统DLL都不大,你可以 备份整个DLL. 下面我就列出ring3下HOOK API的几个步骤: 1.得到要挂勾API的入口点 2.修改API的入口点所在页的页面保护为可读写模式 3.用ReadProcessMemory读出API的入口点开始的几字节备份 4.用WriteProcessMemory修改API的入口点象这样的形式: mov eax,4000 jmp eax 其中的4000要用和原API参数一样的子程序地址代替 在这个子程序里我们决定用什么参数再调用原API,不过调用之前要用备份的前8字节改回来 调用之后在挂勾,如此反复. 代码 前面所讲的是本进程挂勾,我们要挂勾所有进程,可以用全局勾子,需要单独的一个DLL,我们可以在DLL的DLL_PROCESS_ATTACH事件里来HOOK API =================================hookdll.dll========================== .486 .model flat,stdcall ;参数的传递约定是stdcall(从右到左,恢复堆栈的工作交由被调用者) option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib HOOKAPI struct a byte ? PMyapi DWORD ? d BYTE ? e BYTE ? HOOKAPI ends ;子程序声明 WriteApi proto :DWORD ,:DWORD,:DWORD,:DWORD MyAPI proto :DWORD ,:DWORD GetApi proto :DWORD,:DWORD ;已初始化数据 .data hInstance dd 0 WProcess dd 0 hacker HOOKAPI <> CommandLine LPSTR ? Papi1 DWORD ? Myapi1 DWORD ? ApiBak1 db 10 dup(?) DllName1 db "user32.dll",0 ApiName1 db "ExitWindowsEx",0 mdb db "下面的程序想关闭计算机,要保持阻止吗?",0 ;未初始化数据 .data? hHook dd ? hWnd dd ? ;程序代码段 .code DllEntry proc hInst:HINSTANCE, reason:DWORD, reserved1:DWORD .if reason==DLL_PROCESS_ATTACH ;当DLL加载时产生此事件 push hInst pop hInstance invoke GetCommandLine mov CommandLine,eax ;取程序命令行 ;初始化 mov hacker.a,0B8h ;mov eax, ;mov hacker.d PMyapi ;0x000000 mov hacker.d,0FFh ;jmp mov hacker.e, 0E0h ;eax invoke GetCurrentProcess ;取进程伪句柄 mov WProcess ,eax invoke GetApi,addr DllName1,addr ApiName1 ;取API地址 mov Papi1,eax ;保存API地址 invoke ReadProcessMemory,WProcess,Papi1,addr ApiBak1,8,NULL ;备份原API的前8字节 mov hacker.PMyapi,offset MyAPI ;0x0000,这里设置替代API的函数地址 invoke WriteApi,WProcess,Papi1, addr hacker ,size HOOKAPI ;HOOK API .endif .if reason==DLL_PROCESS_DETACH invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8 ;还原API .endif mov eax,TRUE ret DllEntry Endp GetMsgProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD invoke CallNextHookEx,hHook,nCode,wParam,lParam mov eax,TRUE ret GetMsgProc endp InstallHook proc invoke SetWindowsHookEx,WH_GETMESSAGE,addr GetMsgProc,hInstance,NULL mov hHook,eax ret InstallHook endp UninstallHook proc invoke UnhookWindowsHookEx,hHook invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8 ret UninstallHook endp GetApi proc DllNameAddress:DWORD,ApiNameAddress:DWORD invoke GetModuleHandle,DllNameAddress ;取DLL模块句柄 .if eax==NULL invoke LoadLibrary ,DllNameAddress ;加载DLL .endif invoke GetProcAddress,eax,ApiNameAddress ;取API地址 mov eax,eax ret GetApi endp ;============================下面是核心部分========================= WriteApi proc Process:DWORD ,Papi:DWORD,Ptype:DWORD,Psize:DWORD LOCAL mbi:MEMORY_BASIC_INFORMATION LOCAL msize:DWORD ;返回页面虚拟信息 invoke VirtualQueryEx,Process, Papi,addr mbi,SIZEOF MEMORY_BASIC_INFORMATION ;修改为可读写模式 invoke VirtualProtectEx,Process, mbi.BaseAddress,8h,PAGE_EXECUTE_READWRITE,addr mbi.Protect ;开始写内存 invoke WriteProcessMemory,Process, Papi, Ptype,Psize ,NULL PUSH eax ;改回只读模式 invoke VirtualProtectEx,Process,mbi.BaseAddress,8h,PAGE_EXECUTE_READ,addr mbi.Protect pop eax ret WriteApi endp ;替代的API,参数要和原来一样 MyAPI proc bs:DWORD ,dwReserved:DWORD invoke MessageBox, NULL, CommandLine, addr mdb, MB_YESNO ;弹出信息框选择是否阻止 .if eax==7 ;如果选择否 invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8 ;先还原API invoke ExitWindowsEx,bs,dwReserved ;再调用API invoke WriteApi,WProcess,Papi1, addr hacker ,sizeof HOOKAPI ;调用完后再改回来 .endif mov eax,TRUE ret MyAPI endp End DllEntry ===============================hookdll.def============================= LIBRARY hookdll EXPORTS InstallHook EXPORTS UninstallHook 分析 HOOKAPI struct a byte ? PMyapi DWORD ? d BYTE ? e BYTE ? HOOKAPI ends 为了便于理解和使用,我定义了一个结构:这个结构有4个成员,第一个成员a,是个字节型,我用来放0B8h(mov eax),PMyapi一个整数型,用来放我们的替代API函数的地址(0X000),第3个和第4个成员我分别用来放JMP和EAX(jmp eax)那么连起来就是 mov,0X0000 ; jmp eax .if reason==DLL_PROCESS_ATTACH push hInst pop hInstance invoke GetCommandLine mov CommandLine,eax ;初始化 mov hacker.a,0B8h ;mov eax, ;mov hacker.d PMyapi ;0x0000 mov hacker.d,0FFh ;jmp mov hacker.e, 0E0h ;eax invoke GetCurrentProcess mov WProcess ,eax 当DLL加载时,我们先保存模块句柄,读取程序命令行,然后初始化HOOKAPI结构,写入我们要写到内存的指令(PMyapi以后写入)并调用GetCurrentProcess取出进程伪句柄方便以后写内存. invoke GetApi,addr DllName1,addr ApiName1 mov Papi1,eax invoke ReadProcessMemory,WProcess,Papi1,addr ApiBak1,8,NULL mov hacker.PMyapi,offset MyAPI ;0x0000 invoke WriteApi,WProcess,Papi1, addr hacker ,size HOOKAPI ;HOOK API 接下来用子程GetApi取出要挂勾API的入口点,并用ReadProcessMemory读出入口点8字节备份之,写入PMyapi调用子程WriteApi改写API的入口点,这个子程我不准备详细说了,它非常的简单,无非就是几个API的调用.它的核心就是通过WriteProcessMemory改写内存. .if reason==DLL_PROCESS_DETACH invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8 .endif mov eax,TRUE ret 如果这个DLL被卸载了,那么那个在DLL里的替代函数(MyAPI)将是无效的,如果这个时候程序再调用这个API,将出现非法操作,因此在DLL卸载前,我们必须还原API. 总结一下,现在只要程序加载这个DLL,这个程序的ExitWindowsEx就会被我们勾住,接下来要怎样才能让所有的程序都加载这个DLL呢?这就需要安装全局勾子: InstallHook proc invoke SetWindowsHookEx,WH_GETMESSAGE,addr GetMsgProc,hInstance,NULL invoke WriteApi,WProcess,Papi1, addr hacker ,sizeof HOOKAPI mov hHook,eax ret InstallHook endp 通过SetWindowsHookEx安装勾子,最后一个参数可以决定该钩子是局部的还是系统范围的。如果该值为NULL,那么该钩子将被解释成系统范围内的,那它就可以监控所有的进程及它们的线程。 如果该函数调用成功的话,将在eax中返回钩子的句柄,否则返回NULL。我们必须保存该句柄,因为后面我们还要它来卸载钩子,可以看出,我们创建的Hook类型是WH_CALLWNDPROC类型,该类型的Hook在进 程与系统一通信时就会被加载到进程空间,从而调用dll的初始化函数完成真正的Hook,值得一提的是:因为要调用SetWindowsHookEx来安装钩子,我们GUI程序的这个DLL不会被UnhookWidowHookEx卸载 ,也就只有一次DLL_PROCESS_ATTACH事件,因此这里再要HOOK API一次! 我们回头来看看钩子回调函数: GetMsgProc proc nCode:DWORD,wParam:DWORD,lParam:DWORD invoke CallNextHookEx,hHook,nCode,wParam,lParam mov eax,TRUE ret GetMsgProc endp 可以看到这里只是调用CallNextHookEx将消息交给Hook链中下一个环节处理,因为这里API函数SetWindowsHookEx的唯一作用就是让进程加载我们的dll。 UninstallHook proc invoke UnhookWindowsHookEx,hHook invoke WriteApi,WProcess,Papi1, addr ApiBak1 ,8 ret UninstallHook endp 要卸载一个钩子时调用UnhookWidowHookEx函数,该函数仅有一个参数,就是欲卸载的钩子的句柄。钩子卸载后我们也要还原我们GUI程序的API. LIBRARY hookdll EXPORTS InstallHook EXPORTS UninstallHook 我们公开DLL里的InstallHook和UninstallHook函数,方便程序调用,这样我们只要在另外的程序中调用InstallHook便可安装全局勾子,勾住所有程序中的API:ExitWindowsEx,执行我们自定的子程!如果不需要了,可以调用UninstallHook卸载全局勾子. 请注意:对于远程钩子,钩子函数必须放到DLL中,它们将从DLL中映射到其它的进程空间中去。当WINDOWS映射DLL到其它的进程空间中去时,不会把数据段也进行映射。简言之,所有的进程仅共享DLL的代码,至于数据段,每一个进程都将有其单独的拷贝。这是一个很容易被忽视的问题。您可能想当然的以为,在DLL中保存的值可以在所有映射该DLL的进程之间共享。在通常情况下,由于每一个映射该DLL的进程都有自己的数据段,所以在大多数的情况下您的程序运行得都不错。但是钩子函数却不是如此。对于钩子函数来说,要求DLL的数对所有的进程也必须相同。这样您就必须把数据段设成共享的: 一般来说, 目标文件有三个段, 分别是 text/data/bss 段. .text 段放置代码, 是只读且可运行段 .data 段放置静态数据, 这些数据会被放置入 exe 文件. 这个段是可读写, 但是不能运行的. .bss 段放置动态数据, 这些数据不被放入 exe 文件, 在exe文件被加载入内存后才分配的空间. 你可以通过在链接开关中指定段的属性来实现: /SECTION:name, 其中S表示共享,已初期化的段名是.data,未初始化的段名是.bss。假如您想要写一个包含钩子函数的DLL,而且想使它的未初始化的数据段在所有进程间共享,您必须这么做: link /section:.bss /DLL /SUBSYSTEM:WINDOWS ………. 否则,您的全局勾子将不能正常工作! 结束语 我欢迎任何人提出更多的这里没有提到的挂钩方法,我肯定那会有很多。同样欢迎补充我介绍得不是很详细的方法。也可以把我懒得写的其它方法完成,把源代码发给我。这篇文档的目的是演示挂钩技术的细节,我希望我做到了。 相关链接 看雪原贴:https://bbs.pediy.com/thread-28895.htm
2007年-7月-8日
1464 阅读
0 评论
原创作品
1
2
3