zoukankan      html  css  js  c++  java
  • 关于SSDT 分类: windows驱动程序WDM 2013-09-25 14:51 339人阅读 评论(0) 收藏

    百度上比较好的解释是: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.usingnamespace 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.typedefstruct {
    013.    WORD   offset:12;
    014.    WORD   type:4;
    015.} IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
    016.  
    017.  
    018.typedefLONG NTSTATUS;
    019.  
    020.long( __stdcall *NtQuerySystemInformation )( DWORD,PVOID, DWORD,DWORD );
    021.  
    022.typedefstruct _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.typedefstruct {
    035.    DWORD   dwNumberOfModules;
    036.    SYSTEM_MODULE_INFORMATION    smi;
    037.} MODULES, *PMODULES;
    038.  
    039.#define    SystemModuleInformation    11
    040.  
    041.  
    042.  
    043.  
    044.DWORDGetHeaders(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.        returnFALSE;
    055.      
    056.    *pfh=(PIMAGE_FILE_HEADER)&ibase[mzhead->e_lfanew];
    057.    if(((PIMAGE_NT_HEADERS)*pfh)->Signature!=IMAGE_NT_SIGNATURE) 
    058.        returnFALSE;
    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.        returnFALSE;
    064.      
    065.    *psh=(PIMAGE_SECTION_HEADER)((PBYTE)*poh+sizeof(IMAGE_OPTIONAL_HEADER));
    066.    returnTRUE;
    067.}
    068.  
    069.  
    070.DWORDFindKiServiceTable(HMODULEhModule,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.                            returndwKiServiceTable;
    113.                        }
    114.                    }
    115.                      
    116.                
    117.            }
    118.            *(PDWORD)&pbr+=pbr->SizeOfBlock;
    119.        }
    120.    }    
    121.      
    122.      
    123.      
    124.    return0;
    125.}
    126.  
    127.  
    128.intEnumSSDT()
    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 ! ";//NtQuerySystemInformation执行失败,检查当前进程权限
    153.        return0;
    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 ";
    162.        return0;        
    163.    }
    164.    GlobalFree(pModules);
    165.    if(!(dwKSDT=(DWORD)GetProcAddress(hKernel,"KeServiceDescriptorTable")))//在内核文件中查找KeServiceDescriptorTable地址
    166.    {
    167.        cout <<"Can't find KeServiceDescriptorTable ";
    168.        return0;
    169.    }
    170.      
    171.    dwKSDT-=(DWORD)hKernel;      // 获取 KeServiceDescriptorTable RVA
    172.    if(!(dwKiServiceTable=FindKiServiceTable(hKernel,dwKSDT)))   // 获取KiServiceTable地址
    173.    {
    174.        cout <<"Can't find KiServiceTable... ";
    175.        return0;
    176.    }
    177.      
    178.    GetHeaders((char*)hKernel,&pfh,&poh,&psh); 
    179.      
    180.    intdwIndex=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 ",dwIndex,*pService-poh->ImageBase+dwKernelBase);  //SSDT索引和地址
    186.    }
    187.    FreeLibrary(hKernel);
    188.    return1;
    189.}
    190.  
    191.  
    192.  
    193.intmain()
    194.{
    195.    EnumSSDT();
    196.  
    197.    system("pause");
    198.    return0;
    199.}
     

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    使用zipkin2在SpringCloud2.0环境下追踪服务调用情况
    Spring Cloud负载均衡:使用Feign作客户端负载均衡
    Spring Cloud负载均衡:使用zuul作服务器端负载均衡
    Word模板替换
    【转】Eureka集群
    巧用JavaScript语言特性解耦页面间调用(观察者模式)
    MySQL 视图触发器事务存储过程函数
    MySQL py模块的链接Navicat可视化工具
    MySQL 单表查询多表查询
    MySQL 表与表之间建立关系
  • 原文地址:https://www.cnblogs.com/mao0504/p/4706782.html
Copyright © 2011-2022 走看看