閱讀829 返回首頁    go 阿裏雲 go 技術社區[雲棲]


關於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.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 !\n";//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 \n";
162.        return0;        
163.    }
164.    GlobalFree(pModules);
165.    if(!(dwKSDT=(DWORD)GetProcAddress(hKernel,"KeServiceDescriptorTable")))//在內核文件中查找KeServiceDescriptorTable地址
166.    {
167.        cout <<"Can't find KeServiceDescriptorTable\n";
168.        return0;
169.    }
170.      
171.    dwKSDT-=(DWORD)hKernel;      // 獲取 KeServiceDescriptorTable RVA
172.    if(!(dwKiServiceTable=FindKiServiceTable(hKernel,dwKSDT)))   // 獲取KiServiceTable地址
173.    {
174.        cout <<"Can't find KiServiceTable...\n";
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\n",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.}
 

最後更新:2017-04-03 15:21:51

  上一篇:go Java麵向對象高級--抽象類的基本概念------abstract
  下一篇:go 數據庫(mysql oracle)學習小結