关于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.
}
关于SSDT的更多相关文章
- [教程] [授权翻译] 使用补丁修改DSDT/SSDT [DSDT/SSDT综合教程]
[教程] [授权翻译] 使用补丁修改DSDT/SSDT [DSDT/SSDT综合教程] http://bbs.pcbeta.com/viewthread-1571455-1-1.html [教程] [ ...
- SSDT旧版本对于xml数据的处理BUG
在早期版本中,CLR中声明sqlxml时,SSDT会将CLR函数中使用的类型解析为NVARCHAR(4000),最终导致传向CLR函数的数据不完整
- About SSDT BI
Welcome to Microsoft Marketing Speak hell. With the 2012 release of SQL Server, the BIDS, Business I ...
- Shadow SSDT详解、WinDbg查看Shadow SSDT
一.获取ShadowSSDT 好吧,我们已经在R3获取SSDT的原始地址及SDT.SST.KiServiceTbale的关系里面提到:所有的SST都保存在系统服务描述表(SDT)中.系统中一共有两个S ...
- 两种方法获取shadow ssdt
ULONG GetShadowSsdtCurrentAddresses( PSSDT_ADDRESS AddressInfo, PULONG Length ) { PSYSTEM ...
- Using MSBuild to publish a VS 2012 SSDT .sqlproj database project
http://blog.danskingdom.com/using-msbuild-to-publish-a-vs-2012-ssdt-sqlproj-database-project-the-sam ...
- SSDT Hook实现简单的进程隐藏和保护【转载】
原文链接:http://www.blogfshare.com/ssdthook-hide-protect.html 原文作者:AloneMonkey SSDT Hook实现简单的进程隐藏和保护 Alo ...
- Headless MSBuild Support for SSDT (*.sqlproj) Projects
http://sqlproj.com/index.php/2012/03/headless-msbuild-support-for-ssdt-sqlproj-projects/ Update: bre ...
- 菜鸟开始学习SSDT HOOK((附带源码)
看了梦无极的ssdt_hook教程,虽然大牛讲得很细,但是很多细节还是要自己去体会,才会更加深入.在这里我总结一下我的分析过程,若有不对的地方,希望大家指出来.首先我们应该认识 ssdt是什么?从梦无 ...
- SSDT Hook
一.效果图 二.分析 这里对NtCreateProcessEx做拦截,用WinDbg来定位该函数在SSDT中的记录地址: : kd> dd KeServiceDescriptorTable 80 ...
随机推荐
- execl列数据成等差递增递减
如上图若想以10,20,30...这样递增: 1).首先需选中10,20所在的单元格,鼠标移至20所在的单元格右下角 2).此时会出现一个十字"十"符号,点击直向下拖动至某个地方, ...
- 使用facebook和twitter进行分享经验总结
凤凰涅槃,浴火重生. 在传说当中,凤凰是人世间幸福的使者,每五百年,它就要背负着积累于在人间的所有痛苦和恩怨情仇,投身于熊熊烈火中自焚,以生命和美丽的终结换取人世的祥和与幸福.同样在肉体经受了巨大的痛 ...
- Oracle-Linux安装配置python3.6环境
最近公司更换了linux系统的版本,从Ubuntu改为了oracle linux,相关的Python环境也要重新配置,记录一下基本配置的过程. 相关环境 系统:oracle linux7.3 系统自带 ...
- C#之DataTable转List与List转Datatable
闲来无事,只有写代码啦,以下为DataTable转List与List转DataTable的两个方法,主要技术点用到了反射原理: /// <summary> /// 模型转换类 /// &l ...
- ABP官方文档翻译 4.2 数据传输对象
数据传输对象 DTOs的必要性 领域层的抽象 数据隐藏 序列化和懒加载问题 DTO转换和验证 示例 DTOs和实体间的自动映射 辅助接口和类 数据传输对象用来在应用层和展示层之间传输数据. 展示层调用 ...
- python3 爬取百合网的女人们和男人们
学Python也有段时间了,目前学到了Python的类.个人感觉Python的类不应称之为类,而应称之为数据类型,只是数据类型而已!只是数据类型而已!只是数据类型而已!重要的事情说三篇. 据书上说一个 ...
- ZOJ 3229 Shoot the Bullet [上下界最大流]
ZOJ 3229 Shoot the Bullet 题意:此生无悔入东方 上下界最大流 spj挂掉了我也不知道对不对,把代码放这里吧以后正常了可能会评测一下 #include <iostream ...
- BZOJ 2839: 集合计数 [容斥原理 组合]
2839: 集合计数 题意:n个元素的集合,选出若干子集使得交集大小为k,求方案数 先选出k个\(\binom{n}{k}\),剩下选出一些集合交集为空集 考虑容斥 \[ 交集为\emptyset = ...
- CF154D. Flatland Fencing [博弈论 对称 平局]
传送门 题意: 背景是$knights' tournament$,好棒的样子! 这道题不一样很恶心的地方就是有平局的存在 首先判断能不能一步杀 不能的话,如果可以走$0$步或者$a,b$一负一正那么一 ...
- 对.Net Core结合Docker和Jexus的实践
本文基于上次尝试之后的进一步尝试,加入Docker容器.编写Dockerfile,并且jexus结合Docker的使用,总结下自己的个人感想. 一.环境介绍 当前的场景有两种方式将Demo实现运行,一 ...