API Hook应用简介

许久未写博客了,整个5月份与6月份都在做未知病毒检测的相关课题,其中的核心技术就是API Hook与支持向量机算法(SVM),大体的做法就是使用API Hook得到可疑进程的API调用序列,然后以API 调用序列为特征输入SVM系统来判断该程序是否疑似病毒。本文主要就API Hook的一些技术做了简介,其中重点是如何对正在运行的进程注入Hook函数。

 

1、概述

windows系统下的编程,消息message的传递是贯穿其始终的。hook与消息有着非常密切的联系,它的中文含义是“钩子”,这样理解起来我们不难得出“hook是消息处理中的一个环节,用于监控消息在系统中的传递,并在这些消息到达最终的消息处理过程前,处理某些特定的消息”。这也是hook分为不同种类的原因。 hook的这个本领,使它能够将自身的代码“融入”被hook住的程序的进程中,成为目标进程的一个部分。在windows2000以后的系统中,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是hook的出现给我们开拓了解决此类问题的道路。

在windows系统下编程,会接触到api函数的使用,常用的api函数大概有2000个左右。最初有些人对某些api函数的功能不太满意,就产生了如何修改这些api,使之更好的服务于程序的想法,这样API Hook就自然而然的出现了。我们可以通过API Hook,改变一个系统api的原有功能。基本的方法就是通过hook“接触”到需要修改的api函数入口点,改变它的地址指向新的自定义的函数。

 

2、API Hook的基本方法

如何进行API Hook,常用的方法有如下四种:

1)使用注册表HKLM/Software/Microsoft/Windows NT/CurrentVersion/Windows/AppInit _DLLs

2)调用SetWindowsHookEx(WH_GETMESSAGE, …, 0) 设置全局的消息钩子;

3)使用CreateRemoteThread函数在目标进程中创建远程线程

4)如果你只是要挂接某个特定进程的并且情况允许你自己来创建此进程,你可以调用CreateProcess(…, CREATE_SUSPENDED)创建子进程并暂停运行,然后修改入口代码使之调用LoadLibrary加载自己的DLL。该方法在不同CPU之间显然是无法移植的。

方法1可以指定多个DLL,用空格隔开。这些DLL会被任何用到User32.dll的所有程序自动加载。当User32.dll加载的时候,User32.dll的DllMain会收到一个DLL_PROCESS_ATTACH通知,User32在这个时候读取注册表项中的值,调用LoadLibrary加载各个DLL。显然使用这种方法要求设置注册表之后立刻重起系统,不过一般情况下这不是大问题。这种方法的主要问题在于,只有用到User32.dll的应用程序才会被Inject。所有的GUI和少部分CUI程序会用到User32.dll,所以如果你的API Hook程序不打算监视CUI程序的话,那么可能问题并不太大。但是如果你的API Hook程序需要监视系统中所有进程的话,这种方法的限制将是非常致命的。

方法2使用SetWindowsHookEx(WH_GETMESSAGE, …, 0) 设置全局的消息钩子,虽然可能你的程序并不用到消息钩子,但是钩子的一个副作用是会将对应的DLL加载到所有的GUI线程之中。类似的,只有用到GUI的进程才会被挂接。虽然有这种限制,这种方法仍然是最常用的挂接进程的方法。

方法3可以在任意的目标进程中创建一个远程线程,远程线程中可以执行任意代码,这样便可以做到把我们的代码Inject到目标进程中。这种方法具有最大的灵活性,但是难度也最高:1、远程线程代码必须可以自重定位;2、要能够监视进程的启动和结束,这样才可以挂接到所有进程。这两个问题都是可以解决的,在本文中将重点讲述该方法的实现。

 

3、API Hook的相关工具包

关于API Hook的工具包有很多,其中最有名的就是微软公司的Detour了。Detour有32位机的版本和64位机的版本,其中32位机的版本是免费的,64位需要支付1000美元的费用才可使用。另外比较新的而且免费的API Hook工具是Easy Hook(主页:http://easyhook.codeplex.com/),目前国内介绍Easy Hook的相关资料很不多,大多数还停留在使用Detour上,本文也以Detour为例进行介绍。

Detours使用一个无条件转移指令来替换目标函数的最初几条指令,将控制流转移到一个用户提供的截获函数。而目标函数中的一些指令被保存在一个被称为“trampoline” (译注:英文意为蹦床,杂技)的函 数中。这些指令包括目标函数中被替换的代码以及一个重新跳转到目标函数的无条件分支。而截获函数可以替换目标函数,或者通过执行“trampoline”函数的时候将目标函数作为子程序来调用的办法来扩展功能。

Detours是执行时被插入 的。内存中的目标函数的代码不是在硬盘上被修改的,因而可以在一个很好的粒度上使得截获二进制函数的执行变得更容易。例如,一个应用程序执行时加载的 DLL中的函数过程可以被插入一段截获代码(detoured),与此同时,这个DLL还可以被其他应用程序按正常情况执行(译注:也就是按照不被截获的 方式执行,因为DLL二进制文件没有被修改,所以发生截获时不会影响其他进程空间加载这个DLL)。不同于DLL的重新链接或者静态重定向,Detours库中使用的这种中断技术确保不会影响到应用程序中的方法或者系统代码对目标函数的定位。 Detour提供了向运行中的应用程序注入Detour函数和在二进制文件基础上注入Detour函数两种方式。关于如何在二进制文件的基础上注入Detour函数的方法例子很多,相关的介绍也很多(可以参见《Detour开发包之API拦截技术》),而对于如何向运行中的应用程序中注入Detour函数的方法以及实例讲解非常少,在下面的一节中将主要介绍如何向运行中的应用程序注入Detour函数。

 

4、Detour的动态加载

Detours的提供的API 接口可以作为一个共享DLL给外部程序调用,这样我们就可以在Detours Dll中 的DLLMain中完成对目标函数的Detour,然后通过远程注入的方式将我们编写的Detours DLL加载进一个正在运行的进程中,这样就可以对一个正在运行的进程实现API Hook。以下以实现Hook recv函数为例进行说明。

1)Detours DLL的编写

Detour中常用的函数有下面几个:

DetourTransactionBegin() :开始一次Hook或者Unhook过程。

DetourUpdateThread() :列入一个在DetourTransaction过程中要进行update的线程。

DetourAttach() :添加一个要Hook的函数。

DetourDetach () :添加一个要Unhook的函数。

DetourTransactionCommit() :执行当前的Transaction过程。

在这个函数中才会真正进行Hook或者Unhook操作。前面三个函数都只是做一些记录工作。 在使用的时候,这几个函数的调用步骤基本上也是按照上面列出来的顺序。

首先调用DETOUR_TRAMPOLINE宏定义被hook的函数以及替代函数,然后定义替代函数的函数体,如下所示:

 

也可按照Detour工具包中的sample文件夹下的traceapi所示的例子进行定义:

 

然后在DLLMain函数中定义API Hook操作与unHook操作,在DLL_PROCESS_ATTACH消息中定义Hook操作,在DLL_PROCESS_DETACH消息中定义unHook操作。注意调用DetourAttach定义Detour操作的函数是Real_recv和Mine_recv,负责会陷入无限循环hook。如下所示:

 

至此,Detour DLL已经写好。

2)远程注入DLL

DLL的远程注入技术目前也是Win32病毒广泛使用的一种技术。使用这种技术的病毒体通常位于一个DLL中,在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如explorer.exe)中运行。 这样一来,普通的进程管理器就很难发现这种病毒了,而且即使发现了也很难清除,因为只要病毒寄生的进程不终止运行,那么这个DLL就不会在内存中卸载,用户也就无法在资源管理器中删除这个DLL文件。

远程注入相关的函数如下:

OpenProcess:用于打开要寄生的目标进程;

VirtualAllocEx/VirtualFreeEx:用于在目标进程中分配/释放内存空间;

WriteProcessMemory:用于在目标进程中写入要加载的DLL名称;

CreateRemoteThread:远程加载DLL的核心内容,用于控制目标进程调用API函数;

LoadLibrary:目标进程通过调用此函数来加载病毒DLL。

首先需要知道目标进程的进程ID,如果不知道目标进程的ID,但是知道进程名字,可以通过CreateToolhelp32Snapshot函数获取进程快照与Process32Next函数遍历进程来获取,如下所示:

 

得到进程进程ID后就可以调用OpenProcess来打开目标进程了:

HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessID );

在Win32系统下,每个进程都拥有自己的4G虚拟地址空间,各个进程之间都相互独立。如果一个进程需要完成跨进程的工作的话,那么它必须拥有目标进程的相应操作权限。在这里,PROCESS_CREATE_THREAD表示可以通过返回的进程句柄在该进程中创建新的线程,也就是调用CreateRemoteThread的权限;同理,PROCESS_VM_OPERATION则表示在该进程中分配/释放内存的权限,也就是调用VirtualAllocEx/VirtualFreeEx的权限;PROCESS_VM_WRITE表示可以向该进程的地址空间写入数据,也就是调用WriteProcessMemory的权限。当然,也可以用PROCESS_ALL_ACCESS(取得所有权限)来代替。下面进行远程注入,首先在目标进程中分配一段内存空间,然后向这段空间写入我要加载的DLL名称,最后再调用CreateRemoteThread。如下所示:

 

最后需要进行收尾工作:

至此,完成了DLL的远程注入,目标进程在调用recv函数时,就会转到我们定义的Mine_recv函数入口地址,执行Mine_recv函数。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值