• 关于SSDT


    百度上比较好的解释是:SSDT的全称是System Services Descriptor Table,系统服务描述符表。这个表就是一个把ring3的Win32 API和ring0的内核API联系起来。SSDT并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。

            说白了,SSDT就是把系统两个不同级别的函数给关联起来,因为为了安全需要,我们平常所使用的API函数基本都是在ring3下的函数,ring3的级别比较低,但是有些涉及到系统底层的函数怎么办呢?Windows就给出一个SSDT表,把ring3和ring0的函数给关联起来,这样,我们就通过使用ring3的函数就可以直接做一些底层操作了。        

            好吧,既然有这个东西,谁最关心呢?当然是杀毒软件最关心了,因为为了阻止某些病毒不让他破坏系统的底层,杀毒软件会把SSDT中的地址给修改并转向,这样,当病毒或程序调用这些函数的时候,就无法找到真正的对应函数,从而调用失败。

            不过这玩意已经没有什么神秘的了,道高一尺魔高一丈,现在的病毒已经可以绕过SSDT去直接调用底层函数了,或者说可以找出底层函数的真实地址了,这里,我们就简单利用KeServiceDescriptorTable这个函数来读取系统的SSDT表吧。

           完整代码如下:

    001.#include "stdafx.h"
    002.#include <windows.h>
    003.#include <iostream>
    004.using namespace std;
    005.  
    006.#define RVATOVA(base,offset)             ((PVOID)((DWORD)(base)+(DWORD)(offset)))
    007.#define ibaseDD *(PDWORD)&ibase
    008.#define STATUS_INFO_LENGTH_MISMATCH      ((NTSTATUS)0xC0000004L)
    009.#define NT_SUCCESS(Status)               ((NTSTATUS)(Status) >= 0)
    010.  
    011.  
    012.typedef struct {
    013.    WORD    offset:12;
    014.    WORD    type:4;
    015.} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
    016.  
    017.  
    018.typedef LONG NTSTATUS;
    019.  
    020.long ( __stdcall *NtQuerySystemInformation )( DWORD, PVOID, DWORD, DWORD );
    021.  
    022.typedef struct _SYSTEM_MODULE_INFORMATION {//Information Class 11
    023.    ULONG    Reserved[2];
    024.    PVOID    Base;
    025.    ULONG    Size;
    026.    ULONG    Flags;
    027.    USHORT    Index;
    028.    USHORT    Unknown;
    029.    USHORT    LoadCount;
    030.    USHORT    ModuleNameOffset;
    031.    CHAR    ImageName[256];
    032.}SYSTEM_MODULE_INFORMATION,*PSYSTEM_MODULE_INFORMATION;
    033.  
    034.typedef struct {
    035.    DWORD    dwNumberOfModules;
    036.    SYSTEM_MODULE_INFORMATION    smi;
    037.} MODULES, *PMODULES;
    038.  
    039.#define    SystemModuleInformation    11
    040.  
    041.  
    042.  
    043.  
    044.DWORD GetHeaders(PCHAR ibase,
    045.                 PIMAGE_FILE_HEADER *pfh,
    046.                 PIMAGE_OPTIONAL_HEADER *poh,
    047.                 PIMAGE_SECTION_HEADER *psh)
    048.                   
    049.{
    050.    PIMAGE_DOS_HEADER mzhead=(PIMAGE_DOS_HEADER)ibase;
    051.      
    052.    if    ((mzhead->e_magic!=IMAGE_DOS_SIGNATURE) ||        
    053.        (ibaseDD[mzhead->e_lfanew]!=IMAGE_NT_SIGNATURE))
    054.        return FALSE;
    055.      
    056.    *pfh=(PIMAGE_FILE_HEADER)&ibase[mzhead->e_lfanew];
    057.    if (((PIMAGE_NT_HEADERS)*pfh)->Signature!=IMAGE_NT_SIGNATURE) 
    058.        return FALSE;
    059.    *pfh=(PIMAGE_FILE_HEADER)((PBYTE)*pfh+sizeof(IMAGE_NT_SIGNATURE));
    060.      
    061.    *poh=(PIMAGE_OPTIONAL_HEADER)((PBYTE)*pfh+sizeof(IMAGE_FILE_HEADER));
    062.    if ((*poh)->Magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    063.        return FALSE;
    064.      
    065.    *psh=(PIMAGE_SECTION_HEADER)((PBYTE)*poh+sizeof(IMAGE_OPTIONAL_HEADER));
    066.    return TRUE;
    067.}
    068.  
    069.  
    070.DWORD FindKiServiceTable(HMODULE hModule,DWORD dwKSDT)
    071.{
    072.    PIMAGE_FILE_HEADER    pfh;
    073.    PIMAGE_OPTIONAL_HEADER    poh;
    074.    PIMAGE_SECTION_HEADER    psh;
    075.    PIMAGE_BASE_RELOCATION    pbr;
    076.    PIMAGE_FIXUP_ENTRY    pfe;    
    077.      
    078.    DWORD    dwFixups=0,i,dwPointerRva,dwPointsToRva,dwKiServiceTable;
    079.    BOOL    bFirstChunk;
    080.      
    081.    GetHeaders((char *)hModule,&pfh,&poh,&psh);
    082.      
    083.    // loop thru relocs to speed up the search
    084.    if ((poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) &&
    085.        (!((pfh->Characteristics)&IMAGE_FILE_RELOCS_STRIPPED))) {
    086.          
    087.        pbr=(PIMAGE_BASE_RELOCATION)RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,hModule);
    088.          
    089.        bFirstChunk=TRUE;
    090.        // 1st IMAGE_BASE_RELOCATION.VirtualAddress of ntoskrnl is 0
    091.        while (bFirstChunk || pbr->VirtualAddress) {
    092.            bFirstChunk=FALSE;
    093.              
    094.            pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION));
    095.              
    096.            for (i=0;i<(pbr->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))>>1;i++,pfe++) {
    097.                if (pfe->type==IMAGE_REL_BASED_HIGHLOW) {
    098.                    dwFixups++;
    099.                    dwPointerRva=pbr->VirtualAddress+pfe->offset;
    100.                    // DONT_RESOLVE_DLL_REFERENCES flag means relocs aren't fixed
    101.                    dwPointsToRva=*(PDWORD)((DWORD)hModule+dwPointerRva)-(DWORD)poh->ImageBase;
    102.                      
    103.                    // does this reloc point to KeServiceDescriptorTable.Base?
    104.                    if (dwPointsToRva==dwKSDT) {
    105.                        // check for mov [mem32],imm32. we are trying to find 
    106.                        // "mov ds:_KeServiceDescriptorTable.Base, offset _KiServiceTable"
    107.                        // from the KiInitSystem.
    108.                        if (*(PWORD)((DWORD)hModule+dwPointerRva-2)==0x05c7) {
    109.                            // should check for a reloc presence on KiServiceTable here
    110.                            // but forget it
    111.                            dwKiServiceTable=*(PDWORD)((DWORD)hModule+dwPointerRva+4)-poh->ImageBase;
    112.                            return dwKiServiceTable;
    113.                        }
    114.                    }
    115.                      
    116.                
    117.            }
    118.            *(PDWORD)&pbr+=pbr->SizeOfBlock;
    119.        }
    120.    }    
    121.      
    122.      
    123.      
    124.    return 0;
    125.}
    126.  
    127.  
    128.int EnumSSDT()
    129.{
    130.    HMODULE  hKernel;
    131.    DWORD    dwKSDT;                // rva of KeServiceDescriptorTable
    132.    DWORD    dwKiServiceTable;    // rva of KiServiceTable
    133.    PMODULES    pModules=(PMODULES)&pModules;
    134.    DWORD    dwNeededSize,rc;
    135.    DWORD    dwKernelBase,dwServices=0;
    136.    PCHAR    pKernelName;
    137.    PDWORD    pService;
    138.    PIMAGE_FILE_HEADER    pfh;
    139.    PIMAGE_OPTIONAL_HEADER    poh;
    140.    PIMAGE_SECTION_HEADER    psh;
    141.    NtQuerySystemInformation = (long(__stdcall*)(DWORD,PVOID,DWORD,DWORD))GetProcAddress( GetModuleHandle( "ntdll.dll" ),"NtQuerySystemInformation" ); 
    142.    //通过NtQuerySystemInformation取得系统内核文件,判断为是ntoskrnl.exe ntkrnlmp.exe ntkrnlpa.exe
    143.    rc=NtQuerySystemInformation(SystemModuleInformation,pModules,4,(ULONG)&dwNeededSize);
    144.    if (rc==STATUS_INFO_LENGTH_MISMATCH) //如果内存不够
    145.    {
    146.        pModules=(PMODULES)GlobalAlloc(GPTR,dwNeededSize) ; //重新分配内存
    147.        rc=NtQuerySystemInformation(SystemModuleInformation,pModules,dwNeededSize,NULL); //系统内核文件是总是在第一个,枚举1次
    148.    
    149.      
    150.    if (!NT_SUCCESS(rc))
    151.    {
    152.        cout << "NtQuerySystemInformation() Failed !\n"; //NtQuerySystemInformation执行失败,检查当前进程权限
    153.        return 0;
    154.    }
    155.      
    156.    dwKernelBase=(DWORD)pModules->smi.Base;   // imagebase
    157.    pKernelName=pModules->smi.ModuleNameOffset+pModules->smi.ImageName;
    158.    hKernel=LoadLibraryEx(pKernelName,0,DONT_RESOLVE_DLL_REFERENCES);     // 映射ntoskrnl //高 
    159.    if (!hKernel)
    160.    {
    161.        cout << "Failed to load \n";
    162.        return 0;        
    163.    }
    164.    GlobalFree(pModules);
    165.    if (!(dwKSDT=(DWORD)GetProcAddress(hKernel,"KeServiceDescriptorTable"))) //在内核文件中查找KeServiceDescriptorTable地址
    166.    {
    167.        cout << "Can't find KeServiceDescriptorTable\n";
    168.        return 0;
    169.    }
    170.      
    171.    dwKSDT-=(DWORD)hKernel;       // 获取 KeServiceDescriptorTable RVA
    172.    if (!(dwKiServiceTable=FindKiServiceTable(hKernel,dwKSDT)))   // 获取KiServiceTable地址
    173.    {
    174.        cout << "Can't find KiServiceTable...\n";
    175.        return 0;
    176.    }
    177.      
    178.    GetHeaders((char *)hKernel,&pfh,&poh,&psh); 
    179.      
    180.    int dwIndex=0;
    181.    for (pService=(PDWORD)((DWORD)hKernel+dwKiServiceTable);
    182.        *pService-poh->ImageBase<poh->SizeOfImage;
    183.        pService++,dwServices++,dwIndex++)
    184.    {
    185.        printf("0x%03X-0x%08X\n",dwIndex,*pService-poh->ImageBase+dwKernelBase);   //SSDT索引和地址
    186.    }
    187.    FreeLibrary(hKernel);
    188.    return 1;
    189.}
    190.  
    191.  
    192.  
    193.int main()
    194.{
    195.    EnumSSDT();
    196.  
    197.    system("pause");
    198.    return 0;
    199.}
  • 相关阅读:
    K-Means原理及代码实现
    Windows 10安装Tomcat
    Maven笔记四:在Eclipse中创建java web项目
    Maven笔记三:使用Ecplise创建一个Maven项目
    Maven笔记二:Maven仓库
    Windows 10 安装Eclipse
    Maven笔记一:Maven安装与配置(Windows 10)
    Docker学习笔记五:Dockerfile
    Docker学习笔记五:docker简单实践(Docker部署Java应用)
    Zabbix笔记三:zabbix监控指标
  • 原文地址:https://www.cnblogs.com/lzjsky/p/2184872.html
Copyright © 2020-2023  润新知