API HOOK技术详解

    你们有没有想过,一些系统监控软件是如何得知咱们所进行的操做的?杀软启发式分析是如何对病毒行为进行拦截和监控的?外挂又是如何读取到游戏的内部数据的?这些功能的实现,基本都有API HOOK存在。API HOOK分为ring0和ring3层,这里咱们以ring3层API HOOK 进行讲解分析。 app

    API HOOK 在ring 3的实现,分为inline 和修改导入表2种方法,所谓inline,是指直接写入并覆盖函数开头字节汇编码的方法,这种方法有一个问题,即是他被杀软重点监控,成功率极低,而修改导入表的方法,则是指直接经过修改导入表,拦截特定函数调用序列的方法,优缺点不一,因为本文只关注过导入表修改法的API HOOK,所以本文重点讲解修改导入表方法。
ide

    首先让咱们讲讲导入表的结构吧,这种表的目的是记录外部DLL导入函数地址的,经过修改导入表的表项指针, 可以使用户的实际调用序列转入你的函数中,此时对用户来讲,你的函数即是他要调用的“API”,映像数据目录的结构以下:
函数

typedef struct _IMAGE_DATA_DIRECTORY 
{
  DWORD VirtualAddress;
  DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

    根据这个结构,咱们知道,导入表每个项,有2个数据构成,一个是相对虚拟地址的地址,一个表项的大小,导入表的结构是: 编码

typedef struct _IMAGE_THUNK_DATA32 {
    union {
        PBYTE  ForwarderString;
        PDWORD Function;
        DWORD Ordinal;
        PIMAGE_IMPORT_BY_NAME  AddressOfData;
    } u1;
} IMAGE_THUNK_DATA32;

导入表分别记录着: spa

  • ForwarderString 指向一个转向者字符串的RVA
  • Function 被输入的函数的内存地
  • Ordinal 被输入的API的序数
  • AddressOfData 指向IMAGE_IMPORT_BY_NAME

首先,第一个问题来了,如何获取IMAGE_DATA_DIRECTORY的指针呢,能够经过ImageDirectoryEntryToData获取,该函数定义为 操作系统

PVOID WINAPI ImageDirectoryEntryToData(
  _In_  PVOID   Base,
  _In_  BOOLEAN MappedAsImage,
  _In_  USHORT  DirectoryEntry,
  _Out_ PULONG  Size
);

函数一共4个参数分别为一下含义:
线程

  • Base:映像基地址 指针

  • MappedAsImage:它为true时,系统将该模块以映像文件的形式映射,不然以数据文件的形式映射。 blog

  • DirectoryEntry:要得到的段的索引,能够为如下值 索引

  • Size:这是一个输出参数,表示输出的信息的 大小

        根据函数形式,咱们将执行

 Import=(PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(Module,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&Size);

如今,咱们获得了导入表,若是返回值有效,咱们将执行一个循环以进行遍历导入表,首先先看看这个循环:

while(Import->Name)
{			
    PSTR ModuleName=(PSTR)((PBYTE)Module+Import->Name);	
    if(lstrcmpA(ModuleName,APIModuleName)==0)
    {
        PIMAGE_THUNK_DATA Thunk=(PIMAGE_THUNK_DATA)((PBYTE)Module+Import->FirstThunk);
     while(Thunk->u1.Function)
	{
	    PROC *Proc=(PROC *)&Thunk->u1.Function;
	    BOOL bFound=(*Proc==APIFunName);
	    if(bFound)
	    {
	        if(!WriteProcessMemory(GetCurrentProcess(),Proc,&Function,sizeof(Function),NULL)&&(ERROR_NOACCESS==GetLastError()))
		{
		    DWORD OldProtect=0;
            if(VirtualProtect(Proc,sizeof(Function),PAGE_WRITECOPY,&OldProtect))
			{
			    WriteProcessMemory(GetCurrentProcess(),Proc,&Function,sizeof(Function),NULL);
                 VirtualProtect(Proc,sizeof(Function),OldProtect,&OldProtect);
			}
		}
		break;
	   }
	   Thunk++;
      }
   }
   Import++;
}

这段代码转换成UML活动图是:

wKioL1Vi6N3T5fDDAAGsIxgoUuU722.jpg

    至此,一个API HOOK基本逻辑已经被实现,但是这段代码仅对本程序有效,那么,如何让其余程序有效呢?这就须要DLL注入技术,实现DLL注入的方法不少,能够利用操做系统消息钩子、远程线程注入等多种方法完成注入,舒适提示,要注入到远程进程进行拦截,由于须要DLL注入技术,所以须要将API HOOK 代码写入DLL后,经过远程加载DLL完成拦截操做,是非DLL以前记得恢复API HOOK设置,不然将致使异常。

    看到这里,相信你们大体已经知道API HOOK技术实现的具体细节了,如今动动你的手指,相信你也能够本身实现一个API HOOK

相关文章
相关标签/搜索