首页资源分类嵌入式系统安卓 > HOOK API详解

HOOK API详解

已有 445464个资源

下载专区

上传者其他资源

    文档信息举报收藏

    标    签:hook

    分    享:

    文档简介

    hook api的简单应用介绍

    文档预览

    网 络 安 全 API Hook 关键技术解析 刘克胜   王忠寿 解放军电子工程学院网络工程系信息安全教研室   安徽   230037 摘要:本文分析了 API Hook 系统的实现结构和系统涉及的 DLL 注入和 API 拦截两项关键技术的多种实现途径,并结合 应用给出了编程实现的方法。 关键词:A P I   H O O K ;关键技术;解析 0  引言 2.2  建立系统范围的Windows钩子 API Hook  是一项实用的 WINDOWS 系统编程技术,应 Windows 全局钩子一般在 DLL 中实现,通过调用 SetWin- 用领域十分广泛。API Hook 通过对应用程序内存映像 API 调 dowsHookEx 函数在系统中安装。当某个进程产生了钩子服务 用的重定向,改变应用程序流程,从而实现对 API 函数调用 器(Hook Server)指定的某种类型消息,操作系统将自动把钩子 的监视和控制。 1  API Hook系统一般框架 通常,我们把拦截 API 调用的过程称为安装 API Hook。 一个 A P I   H o o k 主要由两个模块组成:钩子服务器( H o o k Server)模块,一般为 EXE 的形式;钩子驱动器(Hook Driver) 模块,一般为 DLL 的形式。钩子服务器主要负责向目标进程 注入钩子驱动器,使得钩子驱动器运行在目标进程的地址空 间,而钩子驱动器则负责实际的 API 拦截处理工作,实现我 们期望的功能。上述关于 API Hook 的两个部分,分别涉及两 项关键技术的实现:DLL 注入技术和 API 拦截技术。 驱动器 DLL 映射到该进程的地址空间,从而使得消息回调函 数(在SetWindowsHookEx的参数中指定)能够对此消息进行适 当的处理。为了使钩子句柄 HHook 能在被挂钩的进程之间共 享,必须把它存储在一个共享的数据区域。在 VC++ 中我们可 以采用预编译指令#pragma data_seg在DLL文件中创建一个新 的段,并在DEF 文件中把该段的属性设置为"shared",这样就 建立了一个共享数据段。 这种 D L L 注入方式有两个优点:一是这种机制在 W i n NT/2K/XP 中都予以支持;二是钩子 DLL 可以在不需要的时 候,由我们主动地调用 UnHookWindowsHookEx 来卸载。缺 点是: 首先,Windows 钩子将会降低整个系统的性能,因为 它额外增加了系统在消息处理方面的时间;其次,只有当目 标进程准备接受某种消息时,钩子驱动器(Hook Driver)才会 图 1  API HOOK 系统实现结构 2  DLL 注入技术 2.1  利用注册表注入DLL 被系统映射到该进程的地址空间,因此如果我们要对进程整 个生命周期内的 API 调用情况进行监控,用这种方法会遗漏 某些 API 的调用 。  2.3  远程线程技术 当准备拦截的目标进程连接了 User32.dll,也即使用了 User32.dll 中的 API(一般图形界面的应用程序都符合这个条 件),可以采用注册表启动的方法。即在 HKEY_LOCAL_MA- CHINE\Software\Microsoft\WindowsNT\CurrentVersion\Windows \AppInit_DLLs 键值中定义钩子驱动器。该键值标识的 DLL 将 在符合条件的应用程序启动时自动加载。这是 Windows 操作 系统内建的机制。这种注入方式存在的缺点是:仅适用于 NT/ 2K 操作系统;如果需要激活或停止钩子的注入,只有重新启 动Windows ;不能用此方法向没有使用User32.dll的应用程序 注入 DLL ,例如控制台应用程序等;钩子驱动器 DLL 将注入 每一个 GUI 应用程序,导致整个系统性能下降。 远程线程技术指的是通过CreateRemoteThread在另一个 进程内创建新线程,使被创建的远程线程可以共享远程进程 的地址空间。主要步骤如下: 首先,通过 OpenProcess 来打开试图嵌入的进程(如果 不允许打开,往往是由于权限不够引起的,例如进程受系统 保护) hRemoteProcess=OpenProcess(PROCESS_CREATE_THREA D|// 允许远程创建线程 PROCESS_VM_OPERATION |// 允许远 程 V M 操作 PROCESS_VM_WRITE, // 允许远程 VM 写 FALSE,dwRemoteProcessId); 作者简介:刘克胜( 1 9 6 7 - ) , 男, 解放军电子工程学院信息安全教研室主任, 副教授, 硕士生导师。 王忠寿( 1 9 7 3 - ) , 男, 解放军电子工程学院硕士研究生, 研究方向:网络安全。 48 2006.11 网 络 安 全 由于后面需要写入远程进程的内存地址空间并建立远程线 程,所以需要申请足够的权限(PROCESS_CREATE_THREAD 、 V M _ O P E R A T I O N 、V M _ W R I T E )。 然后,建立 LoadLibraryW 这个线程来启动我们的 DLL。 LoadLibraryW函数是在kernel32.dll中定义的,用来加载DLL 文件,它只有一个参数:DLL 文件的绝对路径名 pszLibFile Name(也就是 DLL 的全路径文件名)。由于 DLL 是在远程进程 内调用的,所以首先还需要将这个文件名复制到远程地址空 间:(否则远程线程读不到这个参数) // 计算 DLL 路径名需要的内存空间 int cb=(1+lstrlenW(pszLibFileName))*sizeof(WCHAR); //使用VirtualAllocEx函数在远程进程的内存地址空间分 配 DLL 文件名缓冲区 pszLibFileRemote=(PWSTR) VirtualAllocEx(hRemoteProcess, NULL,cb,MEM_COMMIT, PAGE_READWRITE); // 使用WriteProcessMemory 函数将DLL的路径名复制到 远程进程的内存空间 iReturnCode=WriteProcessMemory(hRemoteProcess, pszLibFileRemote,(PVOID)pszLibFileName,cb,NULL); //计算LoadLibraryW的入口地址 PTHREAD_START_ROUTINE pfnStartAddr= (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); 说明一下,上面计算的其实是本进程内 LoadLibraryW 的 入口地址,但由于kernel.dll模块在所有进程内的地址都是相同 的(属于内核模块),所以这个入口地址同样适用于远程进程。 最后,我们通过建立远程线程时的地址pfnStartAddr(实 际上就是LoadLibraryW的入口地址)和传递的参数pszLibFile Remote(我们复制到远程进程内存空间的木马 DLL 的全路径文 件名)在远程进程内启动钩子驱动器 DLL : // 启动远程线程 LoadLibraryW,通过远程线程调用用户 的 D L L 文件 hRemoteThread=CreateRemoteThread(hRemoteProcess,//被 嵌入的远程进程NULL,0,pfnStartAddr,         //LoadLibraryW的 入口地址 pszLibFileRemote,//DLL的全路径文件名 0,NULL); 2.4  通过 BHO 来注入 DLL 如果注入DLL的对象仅仅是Internet Explorer,则可以利 用 Windows 操作系统提供的归档方法—— Browser Helper Objects(BHO)。一个 BHO 是一个在 DLL 中实现的 COM 对象。 它主要实现了一个 I0bjectWithSite 接口,每当 IE 运行时,它 会自动加载所有实现了该接口的 C O M 对象。 3  API拦截技术 在 API Hook 应用的系统级别方面,有两类 API 拦截的机 制——内核级的拦截和用户级的拦截。内核级的钩子主要是 通过一个内核模式的驱动程序来实现,能捕捉到系统活动的 任何细节,不在本文的探讨范围之内。而用户级的钩子则通 常是在普通的 DLL 中实现整个 API 的拦截工作,一般有以下 几种方法。 3.1  代理DLL(特洛伊木马) 特洛伊 DLL 的工作原理是使用木马 DLL 替换常用的 DLL 文件,通过函数转发器将正常的调用转发给原 DLL,截获并 处理特定的消息。譬如,我们知道 WINDOWS 的 Socket1.x 的 函数存放在wsock32.dll中,我们另写一个wsock32.dll木马文 件,替换原来的 wsock32.dll(将原先的 DLL 文件重命名为 wsockold.dll)。木马DLL遇到不认识的调用,使用函数转发器 forward交给wsockold.dll;遇到特殊的请求(事先约定的)就解 码并处理。目前对于特洛伊 DLL 技术,微软已有防范: Win2K 的system32目录下设立dllcache目录,这个目录中存放着大量 的 DLL 文件(也包括一些重要的 exe 文件),一旦操作系统发现 被保护的 D L L 文件被篡改( 数字签名技术) ,它就会自动从 dllcache中恢复这个文件。虽然说有方法可以绕过DLL保护(例 如先更改 dllcache 目录中的备份再修改 DLL 文件、或者利用 KnownDLLs 键值更改 DLL 的默认启动路径等),但是可以预 见,未来微软必将更加小心地保护重要的 DLL 文件。 3.2  改写执行代码 有许多拦截的方法是基于可执行代码的改写,第一种方 法是改变在 C A L L 指令中使用的函数地址。它的基本思路是 检索出目标进程需要拦截的 API 的 C A L L 指令,然后把原先 的地址改成为我们在钩子驱动器中提供的函数地址。第二种 方法就是常用的 J M P   X X X 的方法。主要的实现步骤是先找 到原先的 API 函数的地址,然后把该函数开始的几个字节用 JMP 指令代替,从而使得对该 API 函数的调用能够转向我们 自定义的函数调用。 3.3  改写 PE 文件的输入地址表 PE 文件的结构如图 2 所示。开始是一段 DOS 程序,当你 的程序在不支持 Windows 的环境中运行时,它会显示警告语 句:"This Program cannot be run in DOS mode";接下来一段是 表头 I M A G E _ N T _ H E A D E R 的数据,其中包括整个 PE 文件的 消息。表头尾端是Data Directory数据表,通过它能快速定位 PE 文件段(section)的地址;在这段数据之后,是 IMAGE_SE- CTION_HEADER 列表,其中详细描述了各段的相关信息;最 后是 PE 文件数据段,存放执行代码、数据和资源信息。 其中输入数据段.idata包含输入地址表(IAT,Import Ad- dress Table)。每个以隐式方式加载的DLL 都有一个IAT与之 对应, IAT表项中含有 API调用的地址。当一个应用程序加载 到内存中后,针对每一个 API 函数调用,相应的产生如下的 汇编指令: 2006.11 49 网 络 安 全 JMP DWORD PTR [XXXXXXXX] 都对应一个这样的结构 如果在VC++中使用了_delcspec(import),那么相应的指 ImportDesc:=ImageDirectoryEntryToData(Pointer(HTargetMo- 令就成为: dule),true,IMAGE_DIRECTORY_ENTRY_IMPORT,sz); CALL DWORD PTR [XXXXXXXX]。 while Pointer(ImportDesc.Name)<>nil do begin //判断是否是所需的DLL输入描述 if StrIComp(PChar(DllName),PChar(HTargetModule+Import Desc.Name))=0 then begin // 得到 IAT 的首地址 FirstThunk:=PIMAGE_THUNK_DATA32(HTargetModule +ImportDesc.FirstThunk); while FirstThunk.Func<>nil do begin if FirstThunk.Func=OldAddressOfAPI then begin //找到了匹配的API地址 ...... 图 2  PE 文件的结构 // 改写 API 的地址 上述方括号中的地址,指向输入地址表表项,其中含有 break; API 函数在内存中的真正地址。因此,我们要拦截一个 API 的 end; 调用,只要将表项中函数调用地址改为我们自定义函数的地 Inc(FirstThunk); 址,那么所有关于这个 API 的调用将转到我们自定义的函数 end; 中,从而成功实现 API 拦截。这里要注意的是,自定义函数 end; 的调用约定应为stdcall。 Inc(ImportDesc); 因此,拦截 API 调用,首先需要得到相应 IAT 地址。当 end ; 系统把一个进程模块加载到内存时, PE 文件映射到进程的地 end ; 址空间,通过模块句柄 HModule 返回模块映像在内存中的地 如果我们手工执行钩子 DLL 退出目标进程,那么在退出 址。PE 文件中数据项的地址,都是相对于 HModule 的偏移量, 前应该把函数调用地址改回原先的地址,也就是 API 的真正 称为相对虚拟地址(RVA,Relative Virtual Address)。 地址。因为一旦你的 DLL 退出,改写的新的地址将指向一个 据此,我们可以从HModule 开始,检索 IAT 的偏移地址。一 毫无意义的内存区域,如果此时目标进程再使用这个函数将 个比较好的方法是使用现有API函数ImageDirectoryEntryToData 会出现一个非法操作。 帮助定位 IAT。这个 API 函数由 DbgHelp.dll 输出(这是从 Win 4  结束语 2K 开始有的,之前由 ImageHlp.dll 提供),有关这个函数的详 细介绍可参见 M S D N 。 在找到 IAT 之后,我们只需在其中遍历,找到我们需要 的 API 地址,然后用我们自己的函数地址去覆盖它,下面给 出一段对应的源码: procedure RedirectApiCall; var ImportDesc:PIMAGE_IMPORT_DESCRIPTOR; FirstThunk:PIMAGE_THUNK_DATA32;sz:DWORD; API Hook 是一种拦截应用程序 API 函数调用的通用机制, 通过建立 API Hook 可以监视和改变应用程序的行为。A P I Hook 技术常用于屏幕取词、网络防火墙、病毒木马等领域。 参考文献 [1]理查特.Windows核心编程.机械工业出版社.2000. [2]冉林仓.Windows API编程.清华大学出版社.2005. [3]侯俊杰.Windows 95 系统程式设计.1996. begin //得到一个输入描述结构列表的首地址,每个DLL The Analysis of API Hook Central Technique Liu Kesheng,Wang Zhongshou Abstract:this paper analyze implemental framework of API HOOK system,and several kinds of implemental ways of DLL injection and API interception ,which is the central technique of the API Hook system,then pvovide the approaching methods of programming in practice. Keywords:API HOOK;central technique;analysis 50 2006.11

    Top_arrow
    回到顶部
    EEWORLD下载中心所有资源均来自网友分享,如有侵权,请发送举报邮件到客服邮箱bbs_service@eeworld.com.cn 或通过站内短信息或QQ:273568022联系管理员 高进,我们会尽快处理。