自动获取 NT 系统服务描述表与函数名映射表
来源:互联网 发布:女友是韩国人知乎 编辑:程序博客网 时间:2024/06/07 03:15
转自Flier's sky
http://www.cnblogs.com/flier/archive/2004/07/08/22311.html
经历过DOS时代人朋友一定还记得内存开始处那个神奇的ISR映射表,其实NT内部的系统服务描述表(System Service Descriptor Table)也起着类似的作用。用户态程序调用系统服务时,通过某种机制(以前是INT 2EH,XP/2003改为SYSENTER/SYSCALL指令)进入核心态,然后系统根据系统服务号查表调用相应函数。
以前碰到要查一个服务号对应函数名时,都是Ctrl+D启动SoftICE,然后加载相应符号库手工查询。前段时间重装2003系统后,使用SoftICE一直有各种各样莫名其妙的问题,搞得很是不爽。为了查一个服务号的函数名,还得跑到别人机器上,麻烦得要死。于是响应毛主席号召,自己动手丰衣足食,呵呵,写了一个小程序自动获取 NT 系统服务描述表与函数名映射表。
实现思路起始很简单,每一步的技术也都没什么难度,就是...麻烦...sigh
1.定位内核的ntoskrnl.exe模块
2.载入调试符号并查找KeServiceDescriptorTable符号地址
3.读取KeServiceDescriptorTable内容并定位描述表地址
4.打印描述表,对每个入口地址通过符号库查询响应函数名
下面具体说说每一步的实现思路
1.定位ntoskrnl.exe模块
最简单的方法莫过于使用NTDLL提供的ZwQuerySystemInformation函数查询SystemModuleInformation信息,一次性将内核态所有模块的信息读入,呵呵,后面查询函数入口地址时也会用到这些信息。
以下为引用:
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL);typedef struct _SYSTEM_MODULE_INFORMATION { // Information Class 11
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
相关使用方法网上讨论很多,或请参考NT Native API一书,这儿就不再罗嗦。
2.载入调试符号并查找KeServiceDescriptorTable符号地址
MS提供的DbgHelp库还是很好用的,呵呵,直接载入你安装的符号库,查询符号信息。
首先用SymInitialize函数初始化一下符号库引擎,对应最后需要用SymCleanup函数清除;然后用SymSetSearchPath函数设置符号库搜索路径,也可以使用_NT_SYMBOL_PATH环境变量指定;对需要载入符号库的模块,调用SymLoadModule函数载入对应符号库,并使用SymGetModuleInfo函数获取符号库信息;再使用SymEnumSymbols函数枚举模块中的符号;对我们需要的符号,可以通过SYMBOL_INFO.Address得到符号在内存中的地址。
3.读取KeServiceDescriptorTable内容并定位描述表地址
KeServiceDescriptorTable符号指向一个KSERVICE_TABLE_DESCRIPTOR结构,定义系统服务描述表的函数入口表和参数表的地址:
以下为引用:
typedef struct _KSERVICE_TABLE_DESCRIPTOR {
PULONG_PTR Base;
PULONG Count;
ULONG Limit;
PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
Limit存储此服务描述表中有多少项;
Base指向函数入口表地址,每个表项是一个DWORD,表示一个函数入口地址;
Number指向函数参数表地址,每个表项是一个UCHAR,表示一个函数参数长度。
但因为此结构存储在2G以上地址空间中,为核心态内存,无法在用户态访问,所以我们必须想办法直接读取核心态内存。
思路起始也很简单,呵呵,将KeServiceDescriptorTable符号所指向的虚拟空间地址转换为物理地址,然后通过读取DevicePhysicalMemory设备直接访问物理内存。网上以前也有过很多讨论文章。
虚拟地址向物理地址转换的方法,webcrazy以前有过精彩论述《小议Windows NT/2000分页机制》。但因为我的程序不准备在核心态跑,所以使用一个简化的经验转换算法。具体原理请参考webcrazy的文章和MmGetPhysicalAddress函数(ntosmmiosup.c:5490)的实现代码。
以下为引用:
PHYSICAL_ADDRESS TPhysicalMemoryMapping::LinearAddressToPhysicalAddress(LPCVOID lpVirtualAddress)
{
PHYSICAL_ADDRESS addr = { 0, 0 };if((DWORD)lpVirtualAddress < 0x80000000L || (DWORD)lpVirtualAddress >= 0xA0000000L)
addr.QuadPart = (DWORD)lpVirtualAddress & 0x0FFFF000;
else
addr.QuadPart = (DWORD)lpVirtualAddress & 0x1FFFF000;return addr;
}
读取物理内存实际上就是使用NtOpenSection函数打开NT内建/Device/PhysicalMemory,然后将此Section中需要访问的内存页用NtMapViewOfSection函数映射到用户态空间中,就可以直接读取。最后再相应调用NtUnmapViewOfSection函数和NtClose函数关闭映射。
4.打印描述表,对每个入口地址通过符号库查询响应函数名
将描述表读取后,就可以根据每个函数入口地址,先定位到某个模块,再使用SymFromAddr函数定位到某个符号。
几个相关工具短期内可以在这里下载http://flier.5i4k.net/KernelExplorer.rar
- 自动获取 NT 系统服务描述表与函数名映射表
- 使用WinDbg获取SSDT 系统服务描述表的函数服务号(索引)
- 另一种获取系统服务描述表入口地址的方法
- 系统服务描述符表
- Sql Server 2008获取表的注释,字段名,字段类型,字段描述等,代码自动生成必备
- 枚举NT系统服务
- 获取SSDT表函数名
- asp.net获取SQL所有数据库名、所有表名、所有字段名、列描述
- 获取SQL数据库中的数据库名、所有表名、所有字段名、列描述
- asp.net获取SQL所有数据库名、所有表名、所有字段名、列描述
- [轉]获取SQL数据库中的数据库名、所有表名、所有字段名、列描述
- SQL获取表名、列名、数据类型、描述、表最后修改时间
- SQL 获取列名 利用系统表
- 利用存储过程获取系统表名
- oracle下通过表名查找字段名、字段类型、与字段描述
- 获取数据库所有表名与字段名
- 获取数据库所有表名与字段名
- 获取数据库所有表名与字段名
- DOS命令大全(经典收藏)
- AVI audio frame duration
- sql优化
- ASP.NET文件下载函数使用浅析
- ADSL上网速度慢经常掉线原因分析
- 自动获取 NT 系统服务描述表与函数名映射表
- 我写的存储过程报表sql2000
- J2ME编程--实现手机屏幕的切换
- vc中调用Com组件的方法详解
- USB标准请求
- URL中一些字符的特殊含义
- 关于View中焦点获取的一些问题
- wince USB驱动结构
- COM中的可连接对象与连接点机制及其MFC程序实现