关于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. }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值