杀死IceSword

作者: 计算机网络技术  发布:2019-11-30

Posted By Inking      

标 题: 【原创】SSDT Hook的妙用-对抗ring0 inline hook
作 者: 堕落天才
时 间: 2007-03-10,15:18
链 接:

        此文为学习 《Rootkit...》 以致 SSDT Hook的妙用-对抗ring0 inline hook 后的成果。依照SSDT Hook的妙用-对抗ring0 inline hook 里说的,IceSword inline Hook 了 NtOpenProcess(卡塔尔(英语:State of Qatar)函数,但是当自个儿要好写出代码的时候怎么也不能得逞关闭IceSword,后来通过调节和测量试验才察觉笔者的 IceSword 在Hook了 NtOpenProcess() 函数的还要也 Hook 了 NtTerminateProcess(卡塔尔 函数,并且也是 inline Hook,可是出于在数 NtTerminateProcess()在SSDT中的偏移的时候范了个谬误,以致花了全体一天手艺够窥见,真是累人啊。

*******************************************************
*标题:【原创】SSDT Hook的妙用-对抗ring0 inline hook  *
*作者:堕落天才                                        *
*日期:2007年3月10号                                   *
*声称:本作品的目标仅为技巧交换商讨                    *
*******************************************************

        代码基本上和 SSDT Hook的妙用-对抗ring0 inline hook 一文很相似,只是扩大了 Hook NtTerminateProcess(卡塔尔国 的片段。在写 Hook NtTerminateProcess(卡塔尔国 时也遭逢了个难点:不通晓怎么获得NtTerminateProcess(卡塔尔(英语:State of Qatar) 的地址。笔者那边是涵养 SSDT 的开始和结果来贯彻的,可是这种格局并不是很好,倘若以前 SSDT 的剧情早就被改换过了如何做呢?本人也找了相关质地,可是好疑似由此扫描 NtTerminateProcess(卡塔尔(قطر‎ 的特征码来贯彻的,不理解有未有越来越好的诀要。

1,SSDT
     SSDT即系统服务描述符表,它的布局如下(参谋《Undocument Windows 2001 Secretes》第二章卡塔尔国:
     typedef struct _SYSTEM_SERVICE_TABLE
     {
       PVOID   瑟维斯TableBase;        //这一个针对系统服务函数地址表
       PULONG  ServiceCounterTableBase;
       ULONG   NumberOfService;         //服务函数的个数,NumberOfService*4 正是全部地址表的大大小小
       ULONG   ParamTableBase;
     }SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;   
     
     typedef struct _SERVICE_DESCRIPTOR_TABLE
     {
       SYSTEM_SERVICE_TABLE   ntoskrnel;  //ntoskrnl.exe的服务函数
       SYSTEM_SERVICE_TABLE   win32k;     //win32k.sys的劳务函数,(gdi.dll/user.dll的木本扶植卡塔尔(قطر‎
       SYSTEM_SERVICE_TABLE   NotUsed1;
       SYSTEM_SERVICE_TABLE   NotUsed2;
     }SYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE;
     
     内核中有四个种类服务描述符表,一个是KeServiceDescriptorTable(由ntoskrnl.exe导出卡塔尔,三个是 KeServieDescriptorTableShadow(未有导出卡塔尔(英语:State of Qatar)。两者的区分是,Ke瑟维斯DescriptorTable只有ntoskrnel少年老成项,KeServieDescriptorTableShadow富含了ntoskrnel以致win32k。经常的 Native API的劳务地方由Ke瑟维斯DescriptorTable分派,gdi.dll/user.dll的内核API调用服务地点由 KeServieDescriptorTableShadow分派。还会有要知道一些的是win32k.sys独有在GUI线程中才加载,日常景观下是不加载的,所以要Hook KeServieDescriptorTableShadow的话,平时是用一个GUI程序通过IoControlCode来触发 (想当初不知底那点,蓝屏死机了N次都想不知底是怎么回事卡塔尔(英语:State of Qatar)。
 
 2,SSDT HOOK 
    SSDT HOOK 的规律其实非常轻巧,大家先实际看看KeServiceDescriptorTable是哪些的。    
    lkd> dd KeServiceDescriptorTable
    8055ab80  804e3d20 00000000 0000011c 804d9f48
    8055ab90  00000000 00000000 00000000 00000000
    8055aba0  00000000 00000000 00000000 00000000
    8055abb0  00000000 00000000 00000000 00000000   
    在windbg.exe中大家就看得相比较清楚,KeServiceDescriptorTable中就独有首先项有数量,别的都是0。在那之中804e3d20正是
KeServiceDescriptorTable.ntoskrnel.ServiceTableBase,服务函数个数为0x11c个。大家再看看804e3d二十一个人置里是怎样事物:
    lkd> dd 804e3d20
    804e3d20  80587691 805716ef 8057ab71 80581b5c
    804e3d30  80599ff7 80637b80 80639d05 80639d4e
    804e3d40  8057741c 8064855b 80637347 80599539
    804e3d50  8062f4ec 8057a98c 8059155e 8062661f
    如上,80587691 805716ef 8057ab71 80581b5c 那几个正是系统服务函数的地址了。比方当大家在ring3调用 OpenProcess时,步向sysenter的ID是0x7A(XP SP2卡塔尔,然后系统查KeServiceDescriptorTable,大致是这么 KeServiceDescriptorTable.ntoskrnel.ServiceTableBase(804e3d20卡塔尔(英语:State of Qatar) + 0x7A * 4 = 804E3F08, 然后804E3F08 ->8057559e 那几个便是OpenProcess系统服务函数所在,大家再追踪看看:
    lkd> u 8057559e
    nt!NtOpenProcess:
    8057559e 68c4000000      push    0C4h
    805755a3 6860b54e80      push    offset nt!ObReferenceObjectByPointer+0x127 (804eb560)
    805755a8 e8e5e4f6ff      call    nt!InterlockedPushEntrySList+0x79 (804e3a92)
    805755ad 33f6            xor     esi,esi
    原本8057559e正是NtOpenProcess函数所在的苗子地址。  
    嗯,即便大家把8057559e改为指向我们函数之处呢?举例 MyNtOpenProcess,那么系统就能够间接调用MyNtOpenProcess,实际不是原来的NtOpenProcess了。那正是SSDT HOOK 原理所在。

工程文件(包括笔者的IceSword版本,幸免版本分化等引致的尝试不只怕成功)请点击这里下载,由于还未有写驱动加载和了结IceSword的代码,所以测量检验时请先用其余工具加载驱动,然后尝试在任务微型机里关闭IceSword。

  3, ring0 inline hook
     ring0 inline hook 跟ring3的没什么差异了,若是硬说有的话,那么正是ring3发出哪些错误的话程序会挂掉,ring0爆发什么样错误的话系统就挂掉,所以必然要超级小心。inline hook的基本思维便是在目的函数中JMP到温馨的监视函数,做一些论断然后再JMP回去。日常都以改过函数头,不过再别的地点JMP也是足以的。下边大家来点实际的吧:
     lkd> u nt!NtOpenProcess
     nt!NtOpenProcess:
     8057559e e95d6f4271      jmp     f199c500
     805755a3 e93f953978      jmp     f890eae7
     805755a8 e8e5e4f6ff      call    nt!InterlockedPushEntrySList+0x79 (804e3a92)
     ...
     同不常间开发“冰刃”跟“Rootkit Unhooker”我们就能够在NtOpenProcess函数头见到这么的“奇观”,第二个jmp是“冰刃”的,第三个jmp是“Rootkit Unhooker”的。他们这么是堤防被恶意程序通过TerminateProcess关闭。当然“冰刃”还 Hook了NtTerminateProcess等函数。

By Inking 此文为上学 《Rootkit...》 甚至SSDT Hook的妙用-对抗ring0 inline hook 后的结晶。依照SSDT Hook的妙用-对抗ring0 inline hook 里说的,...

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
    好了,道理就说罢了,下边就进去本文正题。
    对付ring0 inline hook的基本思路是这么的,本人写叁个替换的内核函数,以NtOpenProcess为例,正是MyNtOpenProcess。然后校勘SSDT表,让系统服务步入自身的函数MyNtOpenProcess。而MyNtOpenProcess要做的事就是,达成NtOpenProcess前10字节指令,然后再JMP到原本的NtOpenProcess的十字节后。那样NtOpenProcess 函数头写的JMP都失效了,在ring3平昔调用OpenProcess再也不用影响。
***************************************************************************************************************************
#include<ntddk.h>

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
  PVOID   ServiceTableBase;
  PULONG  ServiceCounterTableBase;
  ULONG   NumberOfService;
  ULONG   ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable唯有风流倜傥项,这里就轻易点了
extern PSERVICE_DESCRIPTOR_TABLE    KeServiceDescriptorTable;//KeServiceDescriptorTable为导出函数

/////////////////////////////////////
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
//////////////////////////////////////
ULONG JmpAddress;//跳转到NtOpenProcess里之处
ULONG OldServiceAddress;//原本NtOpenProcess的劳务地点
//////////////////////////////////////
__declspec(naked) NTSTATUS __stdcall MyNtOpenProcess(PHANDLE ProcessHandle,
               ACCESS_MASK DesiredAccess,
               POBJECT_ATTRIBUTES ObjectAttributes,
               PCLIENT_ID ClientId) 
{
  DbgPrint("NtOpenProcess() called");
  __asm{
    push    0C4h
    push    804eb560h  //共13个字节
    jmp     [JmpAddress]     
  }
}
///////////////////////////////////////////////////
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
  DriverObject->DriverUnload = OnUnload;
  DbgPrint("Unhooker load");
  Hook();
  return STATUS_SUCCESS;
}
/////////////////////////////////////////////////////
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
  DbgPrint("Unhooker unload!");
  Unhook();
}
/////////////////////////////////////////////////////
VOID Hook()
{
  ULONG  Address;
  Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;//0x7A为NtOpenProcess服务ID
  DbgPrint("Address:0x%08X",Address);

  OldServiceAddress = *(ULONG*卡塔尔(英语:State of Qatar)Address;//保存原本NtOpenProcess的地址
  DbgPrint("OldServiceAddress:0x%08X",OldServiceAddress);

  DbgPrint("MyNtOpenProcess:0x%08X",MyNtOpenProcess);

  JmpAddress = (ULONG卡塔尔(قطر‎NtOpenProcess + 10; //跳转到NtOpenProcess函数头+10的地点,那样在其面前写的JMP都失效了
  DbgPrint("JmpAddress:0x%08X",JmpAddress);
    
  __asm{//去掉内存珍惜
    cli
         mov  eax,cr0
    and  eax,not 10000h
    mov  cr0,eax
  }

  *((ULONG*)Address) = (ULONG)MyNtOpenProcess;//HOOK SSDT

  __asm{//恢复生机内部存款和储蓄器保护  
          mov  eax,cr0
    or   eax,10000h
    mov  cr0,eax
    sti
  }
}
//////////////////////////////////////////////////////
VOID Unhook()
{
  ULONG  Address;
  Address = (ULONG)KeServiceDescriptorTable->ServiceTableBase + 0x7A * 4;//查找SSDT

  __asm{
    cli
          mov  eax,cr0
    and  eax,not 10000h
    mov  cr0,eax
  }

  *((ULONG*)Address) = (ULONG)OldServiceAddress;//还原SSDT

  __asm{  
         mov  eax,cr0
    or   eax,10000h
    mov  cr0,eax
    sti
  }

  DbgPrint("Unhook");
}
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
    就这样多了,可能有些许人会说,没须求那么复杂,间接过来NtOpenProcess不就行了吗?对于象“冰刃”“Rookit Unhooker”这一个“和善”之辈的话是没难点的,然而象NP这么些“如狼似虎”之流的话,它会一再检查实验NtOpenProcess是或不是早就被写回去,是的话,嘿嘿,机器立刻重启。那也是这种方法的一小点妙用。

本文由今晚买四不像发布于计算机网络技术,转载请注明出处:杀死IceSword

关键词:

上一篇:代码笔记
下一篇:没有了