当前位置:编程学习 > 网站相关 >>

挂钩KeUsermodeCallback函数来实现自己的“财产保镖“

作 者: liukeblue 
通过挂钩KeUserModeCallback这个未公开的函数可以实现对Ke_LoadLibrary、WH_KEYBOARD_LL等进行拦截,这个函数也可以用来在Ring0下调用Ring3代码,如果需要更进一步了解,可以去黑月教主的百度blog上去看看。下面我们来实现拦截dll注入的功能,解决两个问题:
一、  如何挂钩KeUserModeCallback函数,有两种方式IAT HOOK(QQ电脑管家)、inline HOOK(360保险箱)。
二、  如何拦截DLL注入,这个功能在KeUserModeCallback挂钩函数里实现。
实现的代码主要来源于对QQ电脑管家驱动文件TCSafeBox.sys的逆向分析,所以我尽量试着去还原TCSafeBox.sys的代码,核心代码如下:
ULONG StartHook(IN  PVOID fake_funcaddrss,OUT PULONG Original_funcaddrss)
{
    ULONG win32k_base;
  ULONG result; 
   if (fake_funcaddrss &&  Original_funcaddrss)
     {
        win32k_base = GetModuleBase("win32k.sys");
      if ( win32k_base>0 )                                 
       result = IATHook((PVOID)win32k_base,"ntoskrnl.exe", "KeUserModeCallback",fake_funcaddrss,Original_funcaddrss); 
   }
   else
      result = 0;
   return result; 
}
 
ULONG GetModuleBase(IN PCHAR ModuleName)
{
   ULONG result;
   ULONG   dwNeedSize=0;
   NTSTATUS status;
   PMODULES pModules;
   int i;
   char imagename[255]={0};
 
  ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&dwNeedSize);
  pModules = ExAllocatePoolWithTag(NonPagedPool,dwNeedSize,0);
  if (pModules)
  {
    memset(pModules,0,dwNeedSize);   
    status = ZwQuerySystemInformation(SystemModuleInformation,pModules,dwNeedSize,NULL);
 
  if (NT_SUCCESS(status))
  {
    
      i = 0;
    while ( i<pModules->dwNumberOfModules )
      {
        strcpy(imagename,pModules->smi[i].ImageName + pModules->smi[i].ModuleNameOffset);
 
      if (!strncmp(imagename,ModuleName,strlen(ModuleName)))
      {
          result = (ULONG)pModules->smi[i].Base;
        break;
    }
   
      i++;
    }
  }
     ExFreePoolWithTag(pModules,0);
  }
return result;
}
 
ULONG IATHook(IN PVOID ModlueBase,IN PCHAR ImportName,IN PCHAR ApiName,IN ULONG fakeFunctionAddr,OUT PULONG originalFuncAddr)
{
   ULONG reslut; 
   ULONG size;
   PIMAGE_IMPORT_DESCRIPTOR pImportModuleDirectory;
   DWORD dwRVAModuleName;
   PCHAR ModuleName;
   CHAR RvAModuleNameIsZory;
   ULONG *OriginalFirstThunk;
   ULONG *FirstThunk;
   int i;
   PIMAGE_IMPORT_BY_NAME Imageimportbyname;
   ULONG result;
 
   result = 0;
   if (ModlueBase && ImportName && ApiName && fakeFunctionAddr && originalFuncAddr && !KeGetCurrentIrql())
   {
  __try
  {
     size = 0;
     pImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(ModlueBase,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);  
 
     if (pImportModuleDirectory)
     {
        while (pImportModuleDirectory && pImportModuleDirectory->Name)
        {
            dwRVAModuleName = pImportModuleDirectory->Name;    //模块的dll名称
          RvAModuleNameIsZory = ((CHAR *)ModlueBase + dwRVAModuleName) == 0;
            ModuleName = (CHAR *)ModlueBase + dwRVAModuleName;
         
        //先找到模块,再在模块里查找函数
        if (!RvAModuleNameIsZory && !_strnicmp(ModuleName,ImportName,sizeof(ImportName)))
              {
                   //得到输入表结构里指向INT和IAT的VA
           OriginalFirstThunk    = (ULONG *)((CHAR *)ModlueBase + pImportModuleDirectory->OriginalFirstThunk);
           FirstThunk            = (ULONG *)((CHAR *)ModlueBase + pImportModuleDirectory->FirstThunk);
                
             for (i=0;FirstThunk[i];i++)
             {
                Imageimportbyname =  OriginalFirstThunk[i];    
 
            if ( Imageimportbyname < (ULONG)ModlueBase )
                Imageimportbyname += (ULONG)ModlueBase;
              if (Imageimportbyname)
              {
              //以函数名称方式输入
              if ( !_strnicmp((PCHAR)&Imageimportbyname->Name[0],ApiName,strlen(ApiName))
                && MmIsAddressValid(FirstThunk[i]))
                 {      
                                
              /* DbgPrint("i=%d,funcname=[%s]----hookfunc=[%s]\n",i,(PCHAR)&Imageimportbyname->Name[0],ApiName);
                  这里请注意Imageimportbyname->Name得到的是函数名称的首字母*/
        &nb
补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,