Menu
Woocommerce Menu

0x01.3522vip靠谱吗粗看不同处理器进入系统调用,进入系统服务分发器

0 Comment


浅谈系统服务分发,浅谈分发

    接待转发,转发请表明出处:

0x00.说在近日

  就大家所知,Windows操作系统内核的牢笼管理器会分发中断、卓殊和类别服务调用,这里我们就个中的系统服务分发轻松深入分析一下。

 

0x01.粗看分歧计算机步向系统调用

  (1).在PentiumII
此前的x86管理器上,Windows使用int2e指令发出五个骗局,导致实践线程转到内核形式,步向系统服务分发器,eax保存种类服务号,edx指向参数列表。最终通过iret指令回到用户形式;

    
  大家查阅IDT的2e成员,得知该成员保存的地方是系统调用分发器的地点,紧接着u一下KiSystemService,会发觉在保存完贮存器等情事之后,他走到了Ki法斯特CallEntry里面!(在Win7
x86下测验)

      3522vip靠谱吗 1

  (2).在x86Pentium II
管理器上,Windows使用了sysenter指令,内核的种类服务分发器例程的地点保存在与该指令相关联的多个MS揽胜极光中,eax,edx保存与int2e一样的内容。最终通过sysexit指令再次来到用户格局;

     这里读取MS兰德酷路泽的0x176处,在那之中蕴含了系统服务分发器地址,开采实际调用的就是KiFastCallEntry(入口)!(在Win7
x86下测量检验)

      3522vip靠谱吗 2

  (3).在x64连串架构上,Windows使用syscall指令,将系统调用号保存在eax中,前两个参数放在贮存器(rcx/rdx/r8/r9)中,剩下的参数在栈中。

    六13位平台读取MS奥迪Q3的0xC00000082处,里面保存的是六11人的syscall,当大家u一下这些地点,发掘这几个正是x64系统调用分发的进口KiSystemCall64(在Win7
x64下测验)

      3522vip靠谱吗 3

    Ps:通过KiSystemCall64的地方能够经过硬编码获得SSDT、SSSDT地址

 ……

3522vip靠谱吗 4

 

   大家发掘,33人下,系统调用分发操作都会走到Ki法斯特CallEntry里面,而64人下,系统调用分发操作会走到KiSystemCall64,然后去做到相应的体系服务调用。那么大家有个难点,系统是怎么进去到这一个种类调用的啊?

 

0x02.比方查看系统调用怎样发生

  这里以Win7 x86 平台下的
NtOpenProcess为例,切换成一个历程内(如explorer.exe),u一下NtOpenProcess,这里体现的是ntdll里的NtOpenProcess的反汇编:

  3522vip靠谱吗 5

  大家有多少个得到,一个是看看了系统服务号放在了eax里了,另四个是它呼叫了二个地点,call指令将实施由基础建设构造起来的连串服务分发代码,该地点保存在ntdll!_KUSER_SHARED_DATA+0x300处,我们跟着进那些地方看看:

  3522vip靠谱吗 6

  大家仿佛有了点儿眉目了,系统调用在ntdll里面产生了,也正是说,在ntdll里面完结了从ring3到ring0的切换,在那之中eax保存服务号,edx保存参数列表首地址,通过服务号可以在SSDT中一定指标服务例程

  34位下的KeServiceDescriptorTable每一种成员正是目标种类服务的相对地址,六十位下的靶子连串服务真正地址是Ke瑟维斯DescriptorTable每一种成员保存的偏移量(右移4位后的)+KeServiceDescriptorTable集散地址;

  一同首线程的系统服务表地址指向Ntoskrnl.exe中的SSDT表,但当调用了叁个USE奇骏或GDI服务时,服务表地址被更动成指向win32k.sys中的系统服务表。 

 

0x03.从用户层到内核层完整的调用进度

  (1).
当三个Windows应用程序调用Kernel32.dll中的OpenProcess时,其导入并调用了API-MS-Win-Core-File-L1-1-0.dll(一个MinWin重定向Dll)中的NtOpenProcess函数;

  (2).
接着上述的NtOpenProcess函数又会调用KernelBase.dll中的OpenProcess函数,这里是函数的实在落成,它会对子系统有关的参数做了检查;

  (3).
然后KernelBase!OpenProcess就能调用ntdll.dll中的NtOpenProcess函数,在那时就能够触发系统调用(ntdll!Ki法斯特SystemCall),传递NtOpenProcess的系统服务号和参数列表;

  (4).
系统服务分发器(Ntoskrnl.exe中的KiSystemService函数)就能够调用真正的NtOpenProcess函数来拍卖该I/O乞请。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0x04.基石形式下的系统一分配发

  在系统调用中,假设原先进范例式为用户情势,在给系统服务传递的参数指向了用户空间缓冲区时,内核方式代码在操作该缓冲区前会检查是否可以访问该缓冲区,而原先进楷模式正是基础情势的时候,私下认可参数有效,则不会对参数实行检讨。而既然已经在基础格局了,那就无需int2e中断大概sysenter之类的操作了,但假使直接像调用API一般直接调用NtOpenProcess之类的体系服务函数时,内核保存的本来格局值仍旧是用户方式(进基本从前当然是用户格局咯~),但又检验到传递来的地址是一个水源形式地址(因为在日前基础情势下调用),于是会招致调用失利(STATUS_ACCESS_VIOLATION)。

  这里要介绍内核的Zw连串函数了,他们非不过Nt版本函数的小名或包装,而是对应Nt类别系统调用的翻版,使用了同样的系统调用分发机制。他们会创建二个假的间歇栈(CPU在暂停后变卦的栈),并直接调用KiSystemService例程,这几个进程就在模拟CPU中断,就疑似调用来自用户形式相似,而在检验到该调用的实际特权级后将原本方式修改为基石格局,这样也节约了参数校验,成功调用到NtOpenProcess!

  3522vip靠谱吗 7

 

 0x05.轻巧小结

   Ring3 —> Ring0 的系统调用:
Kernel32.dll(API)—>ntdll.dll(Nt/Zw)—>用户形式转内核形式—>Ntoskrnl.exe(Nt)—>完毕I/O恳求(原路再次回到)

   Ring0 —> Ring0
的系统调用:Ntoskrnl.exe(Zw)—>Ntoskrnl.exe(Nt)

   以上知情仿照效法自《深入解析Windows操作系统6》第三章,若是有不科学的地方还请提出,作者将谦虚请教!

应接转发,转发请评释出处:
0x00.说在前面 就大家所知,Windows操作系统…

    
 3522vip靠谱吗 8

 

0x03 SSDT hook原理

从地方的解析中大家能够看来SSDT数组中保存了系统服务的地点,如Ring0下的NtQuerySystemInformation系统服务地点,就保存在KeServiceDescriptorTable[ADh]中,既然hook正是抽取那一个地址后替换上大家的hook函数,在hook函数中实行原函数就可以。

参谋文献:

http://www.cnblogs.com/boyxiao/archive/2011/09/03/2164574.html

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

      3522vip靠谱吗 9

0x04.基础格局下的连串分发

0x00 Hook技术

hook技巧分为两块:

  • Ring3层的Hook,俗称应用层hook技艺
  • Ring0层的Hook,俗称内核层Hook才干

Ring3层的hook又分为两连串型

  • Windows消息的hook
  • WindowsAPI的hook

正如图所示:

3522vip靠谱吗 10

hook1

3522vip靠谱吗 11

hook2

3522vip靠谱吗 12

hook1

关于Windows新闻的Hook,相信广大恋人都有接触过的,因为二个SetWindowsHookEx即能够完结新闻Hook,在那边差不离介绍一下消息 Hook,消息 Hook
是通过SetWindowsHookEx能够落成将自个儿的钩插入到钩子链的最前端,而对此发送给被
Hook 的窗口(也许有十分的大可能是有着的窗口,即全局
Hook)的音信都会被大家的钩子管理函数所抓获到,相当于大家可以事先于窗体先捕获到那么些音信,Windows
消息 Hook 能够实现为经过内消息 Hook 和全局消息 Hook,对于进程内音信Hook,则足以归纳的将 Hook 管理函数直接写在那几个进度内,就是自身 Hook
本人,而对于用途尤其常见的大局新闻 Hook,则须求将 Hook 管理函数写在叁个DLL 中,那样才得以让您的管理函数被全数的进度所加载(进程自动加载富含 Hook
音信管理函数的 DLL)。

对于 Windows 音信 Hook
呢,能够有个简易的邪恶应用,正是记录键盘按钮音讯,进而达到监视用户输入的键值音信的目的,那样,对于有些简便的用户通过键盘输入的密码就能够被
Hook 获取到,因为没当用户按下贰个键时,Windows
都会发生贰个开关音讯(当然有按下,弹起等新闻的区别),然后大家能够 Hook
到那几个按钮信息,那样就能够在 Hook
的消息管理函数中收获到用户按下的是何许键了。

可是音讯的hook不是本文的主要。

正文要讲的SSDT hook呢其实是属于内核Hook,常见于病毒以及杀软中。

下图显示了内核hook的多少个基本项目。

3522vip靠谱吗 13

Kernel hook

  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等函数。

  3522vip靠谱吗 14

 

0x01 SSDT简介

SSDT全称System Service Descriptor
Table(系统描述符表),这些表用于将Ring3的Win32API和基本的API联系起来。

SSDT并不唯有只满含三个庞然大物的地点索引表,它还包罗部分可行的新闻,如地址索引的基地址,服务函数的个数等。通过修改此表能够完毕对有个别关注的系统动作实行过滤以及监督的指标。

在NT4.0的windows操作系统中,默许存在四个系统服务描述符表,那八个描述符表对应了两类差异的种类服务,那三个表为:KeServiceDescriptorTable(SSDT)和KeServiceDescriptorTable(SSDT
Shadow)。在那之中SSDT担当管理来自Ring3层的Kernel32.dll的系统调用。而SSDT
Shadow则器重处理来自User32.dll和GDI32.dll的系统调用。同一时候SSDT在ntoskrnl.exe中是导出的,而SSDT
Shadow如其名是未被Windows所导出的,而有关SSDT的全部内容皆以通KeServiceDescriptorTable来形成的。

以下截图注解,KeServiceDescriptorTable是在ntoskrnl.exe中被导出的:

3522vip靠谱吗 15

Export1

继之我们看看看看Windows操作系统的源码中什么定义KeServiceDescriptorTable的,通过观望W普拉多K可知,

3522vip靠谱吗 16

KeServiceDescriptorTable in WRK

如此看依然有一点点蛋疼呀。改写以下变量的称号吧。

    typedef struct _KSYSTEM_SERVICE_TABLE{
        PULONG ServiceTableBase;            //SSDT的基地址指针
        PULONG ServiceCounterTableBase; //SSDT中每个服务被调用次数表的基地址指针
        ULONG NumberOfService;              //服务函数个数,NumberOfService*4就是整个地址表的大小
        ULONG ParamTableBase;               //SSPT的基地址
    }KSYSTEM_SERVICE_TABLE,*PKSYSTEM_SERVICE_TABLE;
    typedef struct _KSERVICE_TABLE_DESCRIPTOR{
        KSYSTEM_SERVICE_TABLE ntoskrnl;     //ntoskrnl.exe的服务函数
        KSYSTEM_SERVICE_TABLE win32k;       //win32k.sys的服务函数(GDI32/User32)
        KSYSTEM_SERVICE_TABLE notUsed1;
        KSYSTEM_SERVICE_TABLE notUsed2;
    }KSERVICE_TABLE_DESCRIPTOR,*PKSERVICE_TABLE_DESCRIPTOR;
    //导出由ntoskrnl.exe所导出的SSDT
    extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

从上述介绍能够,Ke瑟维斯DescriptorTable能够当做是一个数组,是4个KSYSTEM_SERVICE_TABLE结构产生的数组,而各种KSYSTEM_SERVICE_TABLE对应多少个PE文件导出的服务描述符表,依据那些服务描述符表大家得以博得进一步详实的劳务消息。在应用层ntdll.dll中的API在这一个系统服务描述表中都留存三个与之对应的劳务,当我们的应用程序调用ntdll.dll里的API时最终得以调用对应的种类服务函数,公告给基础一个目录,内核通过该索引在SSDT中搜索对应的劳务,内核调用服务做到应用的API调用诉求。

  DbgPrint(“Unhook”);
}
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
    就这么多了,也许有些人会说,没供给那么复杂,直接回复NtOpenProcess不就行了吗?对于象“冰刃”“Rookit Unhooker”这一个“善良”之辈的话是没难题的,不过象NP那么些“穷凶极恶”之流的话,它会四处检查实验NtOpenProcess是或不是现已被写回去,是的话,嘿嘿,机器立即重启。那也是这种方法的一丝丝妙用。

     这里读取MS凯雷德的0x176处,个中包涵了系统服务分发器地址,发现实际调用的正是KiFastCallEntry(入口)!(在Win7
x86下测验)

  (2).在x86Pentium II
管理器上,Windows使用了sysenter指令,内核的系统服务分发器例程的地点保存在与该指令相关联的三个MS宝马7系中,eax,edx保存与int2e同样的剧情。最后通过sysexit指令重临用户形式;

0x02 详解SSDT

那节内大家用WinDbg来调治XP系统,借此验证SSDT是个什么样鬼。
据我们上文的组织定义可见,KeServiceDescriptorTable是多个对准4个KSYSTEM_SERVICE_TABLE结构首地址的指针,以下图为例吧。

3522vip靠谱吗 17

dd KeServiceDescriptorTable

这里的0x80563520这一行正是ntoskrnl对应的劳务描述符表结构KSYSTEM_SERVICE_TABLE。那么首先个三12位的0x804e58a0则是对应ntoskrnl对应的KSYSTEM_SERVICE_TABLE中的SSDT
Base
,即服务描述符表的首地址。通过对该首地址的dump,大家能够观察多数以1贰十五位为一组排列的服务描述符,每一个描述符中的第多个三十九位(0x80591bfb)对应着系统服务的输入地址。通过对该入口地址的反汇编,能够看来那是SSDT第三个系统服务NtAcceptConnectPort函数。如图:

3522vip靠谱吗 18

NtAcceptConnectPort

那么明亮了SSDT首地址,同一时间领悟了目录,那么我们就足以因此索引来找到呼应的系统服务入口地址了。通过测算“SSDT中系统服务地方所在的地点= SSDT首地址 + 4 *
索引值”,能够推算出NtQuerySystemInformation的序曲地址位0x80586ff1,对该地址进行反汇编,可得下图:

3522vip靠谱吗 19

NtQuerySystemInformation

测算,SSDT正是个保存Windows系统服务地点的数组。

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

 

 

应用层调用Win32API流程

有了上述的SSDT基础后,大家再来看看在应用层调用Win32API(首要指ntdll.dll中的API)的流程,大家最重要针对ntdll.dll中的NtQuerySystemInformation那几个API的调用流程来拓展演讲。

此地存在八个近乎的API。

3522vip靠谱吗 20

4APIs

再提交这个API的调用流程。

3522vip靠谱吗 21

calling way

此间大家能够看出ntdll.dll中的nt和zw都会进去内核层去调用ntoskrnl的zw函数,而zw最终会调用nt函数,那些函数作为内核API最后去乞求系统服务的试行。
用exescope工具得以张开ntdll.dll,看到NtQuerySystemInformation以及ZwQuerySystemInformation。

3522vip靠谱吗 22

ntdll1

3522vip靠谱吗 23

ntdll2

而精神上zw和nt都以同一函数,指向同一区域,入口地址同样。

故此Ntdll.dll中的API都以对内核API的卷入,当Kernel32.dll中的API通过Ntdll.dll去调用系统API时,会实行参数检查,并调用中断(int
2Eh或SysEnter),从而从Ring3进来Ring0,并将所要调用的服务号,即SSDT数组的索引值,贮存进贮存器EAX中,並且将参数地址放到内定的存放器EDX中,再复制参数到基础地址空间,依据贮存在EAX中的索引值来在SSDT数组中调用钦点的劳动。

经过地点步骤大家赶到Ring0层。使用exescope看看ntoskrnl.exe中的ZwQuerySystemInformation以及NtQuerySystemInformation。

3522vip靠谱吗 24

ntoskrnl1

3522vip靠谱吗 25

ntoskrnl2

再反汇编ntoskrnl那么些文件能够见见Zw函数中调用KiSystemService系统服务分发函数时往EAX中寄放了索引号ADh。如图:

3522vip靠谱吗 26

ZwQSystemInfor

随后根据该索引值检索SSDT项,最终遵照该SSDT项中所寄放的系统服务地点来调用这些种类服务。在此处正是调用Ke瑟维斯DescriptorTable[ADh]处保存的地点对应的体系服务。那就是Ring0下的NtQuerySystemInformation。

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

  叁十一位下的KeServiceDescriptorTable各类成员即便目的种类服务的相对化地址,六二十一位下的靶子种类服务实际地址是KeServiceDescriptorTable每一个成员保存的偏移量(右移4位后的)+KeServiceDescriptorTable集散地址;

 

  JmpAddress = (ULONG)NtOpenProcess + 10; //跳转到NtOpenProcess函数头+10的地方,这样在其眼下写的JMP都失效了
  DbgPrint(“JmpAddress:0x%08X”,JmpAddress);
    
  __asm{//去掉内部存款和储蓄器保养
    cli
         mov  eax,cr0
    and  eax,not 10000h
    mov  cr0,eax
  }

 3522vip靠谱吗 27

  30位下的KeServiceDescriptorTable每种成员正是指标种类服务的相对化地址,64人下的靶子类别服务实际地址是KeServiceDescriptorTable每一个成员保存的偏移量(右移4位后的)+KeServiceDescriptorTable基地址;

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

  (2).
接着上述的NtOpenProcess函数又会调用KernelBase.dll中的OpenProcess函数,这里是函数的真正贯彻,它会对子系统相关的参数做了自己争论;

    Ps:通过KiSystemCall64的地方能够透过硬编码获得SSDT、SSSDT地址

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

  (3).
然后KernelBase!OpenProcess就能调用ntdll.dll中的NtOpenProcess函数,在那儿就能够接触系统调用(ntdll!Ki法斯特SystemCall),传递NtOpenProcess的种类服务号和参数列表;

 

/////////////////////////////////////
VOID Hook();
VOID Unhook();
VOID OnUnload(IN PDRIVER_OBJECT DriverObject);
//////////////////////////////////////
ULONG JmpAddress;//跳转到NtOpenProcess里的地址
ULONG Old瑟维斯Address;//原本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  //共10个字节
    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);

    陆15个人平台读取MSRAV4的0xC0000082处,里面保存的是64人的syscall,当大家u一下那个地方,发掘这么些就是x64系统调用分发的进口KiSystemCall64(在Win7
x64下测量检验)

  (1).
当四个Windows应用程序调用Kernel32.dll中的OpenProcess时,其导入并调用了API-MS-Win-Core-File-L1-1-0.dll(贰个MinWin重定向Dll)中的NtOpenProcess函数;

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

    接待转发,转发请申明出处:

    
 3522vip靠谱吗 8

typedef struct _SERVICE_DESCRIPTOR_TABLE
{
  PVOID   ServiceTableBase;
  PULONG  ServiceCounterTableBase;
  ULONG   NumberOfService;
  ULONG   ParamTableBase;
}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; //由于KeServiceDescriptorTable独有一项,这里就大概点了
extern PSERVICE_DESCRIPTOR_TABLE    Ke瑟维斯DescriptorTable;//KeServiceDescriptorTable为导出函数

 

    六19个人平台读取MSLacrosse的0xC0000082处,里面保存的是陆拾肆人的syscall,当大家u一下那一个地点,开掘那么些正是x64系统调用分发的输入KiSystemCall64(在Win7
x64下测量检验)

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

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图