首页
社区
课程
招聘
[求助]Rootkit.chm上的疑惑,关于Inline Hook
发表于: 2008-10-7 09:05 5238

[求助]Rootkit.chm上的疑惑,关于Inline Hook

2008-10-7 09:05
5238
看Comjiang大牛写的代码,里面有很多他没有详细介绍,也许是他假定对方已经有基础了,当然我最近几天一直都直接看代码,然后查ddk document,并没有参照任何电子书.如果有什么好的入门学习kernel hook的书,希望各位朋友给推荐下.

下面是代码,我自己添加了部分代码,不知道对不对啊,如果错了,还请大牛们客气的指正哦.

//Current Code Inline Hook KiINsertQueueApc Function
//Include Head File To Current Source File
#include <ntddk.h>
#include <ntifs.h>

ULONG g_KiInsertQueueApc;  //保存KiInsertQueueApc地址
char g_oricode[8];  //保存KiInsertQueueApc前8字节
ULONG g_uCr0;
char *non_paged_memory;  //保存KiInsertQueueApc副本

void WPOFF()
{
   
    ULONG uAttr;
   
    _asm
    {
        push eax;
        mov eax, cr0;
        mov uAttr, eax;
        and eax, 0FFFEFFFFh; // CR0 16 BIT = 0
        mov cr0, eax;
        pop eax;
        cli
    };
   
    g_uCr0 = uAttr; //保存原有的 CRO 屬性
   
}

VOID WPON()
{
   
    _asm
    {
        sti
        push eax;
        mov eax, g_uCr0; //恢復原有 CR0 屬性
        mov cr0, eax;
        pop eax;
    };
   
}

__declspec(naked) my_function_detour_KiInsertQueueApc()
{
  __asm
  {   
    mov edi,edi
    push ebp
    mov  ebp, esp
    push ecx
    mov eax,ecx
    _emit 0xEA
    _emit 0xAA
    _emit 0xAA
    _emit 0xAA
    _emit 0xAA
    _emit 0x08
    _emit 0x00
  }
}

ULONG GetFunctionAddr( IN PCWSTR FunctionName)
{
    UNICODE_STRING UniCodeFunctionName;
    RtlInitUnicodeString( &UniCodeFunctionName, FunctionName );
    return (ULONG)MmGetSystemRoutineAddress( &UniCodeFunctionName );   

}

//根据特征值,从KeInsertQueueApc搜索中搜索KiInsertQueueApc
ULONG FindKiInsertQueueApcAddress()
{
  char * Addr_KeInsertQueueApc = 0;
  int i = 0;
  
  //特征值
  char Findcode[] = {
          0xE8,  //call
          0xcc,  //short
          0x29,  //offset
          0x00,
          0x00
  };  
  ULONG Addr_KiInsertQueueApc = 0;
  
  //获得KeInsertQueueApc地址
  Addr_KeInsertQueueApc = (char *) GetFunctionAddr(L"KeInsertQueueApc");
   
  for(i = 0; i < 100; i ++)  //0到99 循环100次
  {
        if(
                        //判断是否匹配特征值
                        //特征值是一个函数调用指令
                        Addr_KeInsertQueueApc[i + 0] == Findcode[0] &&
                        Addr_KeInsertQueueApc[i + 1] == Findcode[1] &&
                        Addr_KeInsertQueueApc[i + 2] == Findcode[2] &&
                        Addr_KeInsertQueueApc[i + 3] == Findcode[3] &&
                        Addr_KeInsertQueueApc[i + 4] == Findcode[4]
      )
    {
          //获得KiInsertQueueApc地址
      Addr_KiInsertQueueApc = (ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
      break;
    }
  }
  return Addr_KiInsertQueueApc;
}

VOID DetourFunctionKiInsertQueueApc()
{

  char *actual_function = (char *)g_KiInsertQueueApc;  //获得KiInsertQueueApc函数地址
  unsigned long detour_address;
  unsigned long reentry_address;
  KIRQL oldIrql;
  int i = 0;

  //用于覆盖KiInsertQueueApc前8字节
  char newcode[] = { 0xEA, 0x44, 0x33, 0x22, 0x11, 0x08, 0x00, 0x90 };

  //获得KiInsertQueueApc第8个字节地址
  reentry_address = ((unsigned long)actual_function) + 8;

  //分配256字节内存空间
  non_paged_memory = ExAllocatePool(NonPagedPool, 256);
  
  for(i=0;i<256;i++)  //循环256次,从0到255
  {
          //难道是备份KiInsertQueueApc函数到non_paged_memory ?
    ((unsigned char *)non_paged_memory)[i] =
                ((unsigned char *)my_function_detour_KiInsertQueueApc)[i];
  }

  //detour_address指向KiInsertQueueApc函数副本
  detour_address = (unsigned long)non_paged_memory;
  
  //detour_address覆盖到newcode[1]也就替换0x44
  *( (unsigned long *)(&newcode[1]) ) = detour_address;

  //循环200次,0到199
  for(i=0;i<200;i++)
  {
    if(
            (0xAA == ((unsigned char *)non_paged_memory)[i+0]) &&
                (0xAA == ((unsigned char *)non_paged_memory)[i+1]) &&
                (0xAA == ((unsigned char *)non_paged_memory)[i+2]) &&
                (0xAA == ((unsigned char *)non_paged_memory)[i+3])
          )
    {
          //跳到KiInsertQueueApc之后代码继续执行
      *( (unsigned long *)(&non_paged_memory[i]) ) = reentry_address;
      break;
    }
  }

    oldIrql = KeRaiseIrqlToDpcLevel();
  
  //0到7,循环8次       
  for(i=0;i < 8;i++)
  {
        //actual_function == KiInsertQueueApc
        //备份KiInsertQueueApc前8字节
    g_oricode[i] = actual_function[i];
    actual_function[i] = newcode[i];  //开始覆盖KiInsertQueueApc前8字节
  }
  KeLowerIrql(oldIrql);
}

VOID UnDetourFunction()
{
  //获得KiInsertQueueApc地址
  char *actual_function = (char *)g_KiInsertQueueApc;
  KIRQL oldIrql;
  int i = 0;
  
  WPOFF();
  oldIrql = KeRaiseIrqlToDpcLevel();

  //0到7,循环8次
  for(i=0;i < 8;i++)
  {
        //恢复KiInsertQueueApc函数前8字节
    actual_function[i] = g_oricode[i];
  }
  KeLowerIrql(oldIrql);
  WPON();
  
  //释放non_paged_memory
  ExFreePool(non_paged_memory);
}

//The Routine Unload Driver
VOID OnUnload( IN PDRIVER_OBJECT DriverObject )
{
  DbgPrint("In DriverUnload Routine\n");
  UnDetourFunction();
}

//Current Driver EntryPoint
NTSTATUS DriverEntry(
                                         IN PDRIVER_OBJECT DriverObject,
                                         IN PUNICODE_STRING RegistryPath)
{
        DbgPrint("In DriverEntry Routine\n");

        //Set Current Driver Unload Routine
        DriverObject->DriverUnload=OnUnload;
   
        //返回KiInsertQueueApc地址
        g_KiInsertQueueApc=FindKiInsertQueueApcAddress();
       
        DetourFunctionKiInsertQueueApc();
        return STATUS_SUCCESS;
}

下面是我的几点疑惑,希望高手有时间的话,尽量给简单讲下.

我知道non_paged_memory这个全局变量分配了256字节内存,但是它最终保存的是什么啊,难道是KiInsertQueueApc函数的副本吗?

my_function_detour_KiInsertQueueApc这个函数是作什么的啊,我看不懂,希望知道的兄弟给简单说下就行,谢谢.

WPOFF和WPON这2个函数是否是去除写保护与恢复写保护,呵呵,我猜测的.

Addr_KiInsertQueueApc = (ULONG)&Addr_KeInsertQueueApc[i] + 0x29cc + 5;
上面的是从KeInsertQueueApc中查特征码,然后根据一个表达式计算出KiInsertQueueApc的地址,我想知道,这个表达式是怎么知道的,难道是用windbg看到了吗?

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 87
活跃值: (41)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
。。。。。。
2008-12-5 20:46
0
游客
登录 | 注册 方可回帖
返回
//