<address id="n1vvb"></address>
          <font id="n1vvb"></font>

            <thead id="n1vvb"></thead>

                Windows系统调用中的系统服务表描述符

                 Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

                Windows系统调用中的系统服务表描述符

                  在前面,我们将解过 系统服务表。可是,我们有个疑问,系统服务表存储在哪里呢?

                  答案就是:系统服务表 存储在 系统服务描述符表中。(其又称为 SSDT Service Descriptor Table)

                  分享图片

                 

                 

                 一、使用PELord函数从ntoskrnl.exe文件中查看SSDT导出函数

                  如图,可以看出KeServiceDescriptorTable导出函数。

                  通过该函数可以查找SSDT表的位置。

                  分享图片

                 

                二、通过Windbg来内存中查看SSDT表

                  使用Windbg,可以使用 kd> dd nt!KeServiceDescriptorTable 指令来查看SSDT表。

                  但该指令存在缺点,可以看到第二张表为0,说明如果使用KeServiceDescriptorTable这个公开的导出函数,我们无法看到win32k.sys这张表结构

                  kd> dd nt!KeServiceDescriptorTable
                    83f759c0  83e89d9c 00000000 00000191 83e8a3e4
                    83f759d0  00000000 00000000 00000000 00000000
                    83f759e0  83ee86af 00000000 0327aa43 000000bb
                    83f759f0  00000011 00000100 5385d2ba d717548f

                  为了解决上面这个问题,我们只能使用另外一个指令,该指令对应的是一个未公开导出的函数。

                  如下,可以看到其第二行,win32k.sys系统服务表已经可见。

                  kd> dd KeServiceDescriptorTableShadow
                    83f75a00  83e89d9c 00000000 00000191 83e8a3e4
                    83f75a10  83b66000 00000000 00000339 83b6702c
                    83f75a20  00000000 00000000 83f75a24 00000340
                    83f75a30  00000340 855e8440 00000007 00000000

                三、验证ReadMemory真正的内核实现部分

                  我们在这篇《Windows系统调用中API的三环部分(依据分析重写ReadProcessMemory函数)》中曾提到过直接使用快速调用来摒弃R3层层封装的API,其中给eax一个函数号,现在我们来实战刨析一下。

                mov eax, 0x115
                mov edx, 0X7FFE0300

                  如下,系统描述符的数据结构,其依次分别为

                  分享图片

                  其依次分别为 ServiceTable 83e89d9c,Count 00000000,ServiceLimit  00000191,ServiceTable 83e8a3e4 

                  使用Windbg来查看其115h序号的函数地址 115h*4 + 83e89d9c (ServiceTable)

                  得到函数地址为 8406c82c

                  kd> dd 115h*4 + 83e89d9c
                    83e8a1f0  8406c82c 840feb46 83fb488c 83fb6128 

                  再对此进行反汇编可得

                  kd > u 8406c82c   
                                nt!NtReadVirtualMemory:
                                8406c82c 6a18            push    18h
                                8406c82e 68282ae683      push    offset nt!? ? ::FNODOBFM::`string‘+0x3ea8 (83e62a28)
                                8406c833 e870e3e1ff      call    nt!_SEH_prolog4(83e8aba8)
                                8406c838 648b3d24010000  mov     edi, dword ptr fs : [124h]
                                8406c83f 8a873a010000    mov     al, byte ptr[edi + 13Ah]
                                8406c845 8845e4          mov     byte ptr[ebp - 1Ch], al
                                8406c848 8b7514          mov     esi, dword ptr[ebp + 14h]
                                8406c84b 84c0            test    al, al

                  之后,我们查看该nt!NtReadVirtualMemory函数的参数个数

                  kd > db 83e8a3e4 + 115
                                83e8a4f9  14 08 04 04 14 04 10 08 - 0c 04 14 18 08 08 08 0c
                                83e8a509  0c 08 10 14 08 08 0c 08 - 0c 0c 04 08 08 08 08 08  
                                83e8a519  08 0c 0c 24 00 08 08 08 - 0c 04 08 04 08 10 08 04  

                  

                四、通过修改SSDT表增添系统服务函数

                  我们在 Windows系统调用中API的三环部分(依据分析重写ReadProcessMemory函数) 调用的是 115h 号函数。

                  现在,我们将该函数地址放到 191 号函数处(之前一共有191个函数,占据0-190位)。

                  修改思路:

                  1)将 nt!NtReadVirtualMemory 函数地址 8406c82c 放到 191号处(83e89d9 + 191h*4)

                    kd> ed 83e89d9 + 191h*4 8406c82c 

                  2)  增大 服务表最大个数。 (因为我们上一节分析其反汇编代码的时候,发现其会进行最大个数的判断)

                    kd> ed 83f75a00+8 192

                  3)  修改参数个数表中对应的191号参数个数。(我们之前查阅过其为 14,以字节为单位)

                    kd> eb 83e8a3e4+191 14

                  4)  之后,我们运行下列代码。其与《Windows系统调用中API的三环部分(依据分析重写ReadProcessMemory函数)》唯一的不同调用函数号为192,最终效果完全一样。

                 1 #include "pch.h"
                 2 #include <iostream>
                 3 #include <algorithm>
                 4 #include <Windows.h>
                 5 void  ReadMemory(HANDLE hProcess, PVOID pAddr, PVOID pBuffer, DWORD dwSize, DWORD  *dwSizeRet)
                 6 {
                 7 
                 8     _asm
                 9     {
                10         lea     eax, [ebp + 0x14]
                11         push    eax
                12         push[ebp + 0x14]
                13         push[ebp + 0x10]
                14         push[ebp + 0xc]
                15         push[ebp + 8]
                16         sub esp, 4
                17         mov eax, 0x192  // 注意:修改的是这里
                18         mov edx, 0X7FFE0300   //sysenter不能直接调用,我间接call的
                19         CALL DWORD PTR[EDX]
                20         add esp, 24
                21 
                22     }
                23 }
                24 int main()
                25 {
                26     HANDLE hProcess = 0;
                27     int t = 123;
                28     DWORD pBuffer;
                29     //hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0,a);
                30     ReadMemory((HANDLE)-1, (PVOID)&t, &pBuffer, sizeof(int), 0);
                31     printf("%X\n", pBuffer);
                32     ReadProcessMemory((HANDLE)-1, &t, &pBuffer, sizeof(int), 0);
                33     printf("%X\n", pBuffer);
                34 
                35     getchar();
                36     return 0;
                37 }
                相关文章
                相关标签/搜索
                特马资料最准2019四肖期期准四肖三期内必出四肖期期准免费公开四肖中特1肖1码期期大公开