首页
社区
课程
招聘
[求助]SSDT表函数名
发表于: 2013-12-8 18:26 8226

[求助]SSDT表函数名

2013-12-8 18:26
8226
typedef struct _SDT_ENTRY
{
        PVOID *ServiceTableBase;
        PULONG ServiceCounterTableBase; //Used only in checked build
        ULONG NumberOfServices;
        PUCHAR ParamTableBase;
} SDT_ENTRY, *PSDT_ENTRY;

刚接内核,想问一下能否通过这个结构体来获得SSDT表的函数名?

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 97
活跃值: (141)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
在32位内核中,可以使用KeServiceDescriptorTable 这个公开的变量得到SSDT 地址
2013-12-8 20:37
0
雪    币: 110
活跃值: (34)
能力值: (RANK:50 )
在线值:
发帖
回帖
粉丝
3
SSDT中并不直接带有函数名,如果SSDT中的函数未导出的话,并不能直接得到函数名。
需要根据服务号预先准备一张SSDT函数名表或者使用调试符号
2013-12-8 20:55
0
雪    币: 58
活跃值: (72)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
4
是的,SSDT中并不包含函数名。
2013-12-8 22:57
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
5
这个是可以的,我已经做出来了,提供一个思路给你,就是分析Ntdll.dll的Nt和Zw系列导出函数,它们上面的第二个指令就是mov eax,SSDT序列号,由这个指令可以得到序列号,再由Ntdll.dll的导出表得到对应函数的名字,这样就可以了
2013-12-9 00:19
0
雪    币: 183
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
这样的话,该如何去分析呢
2013-12-9 11:18
0
雪    币: 183
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
这样的话,该如何去加载NTDLL.DLL呢
2013-12-9 11:52
0
雪    币: 183
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
 ULONG GetSSDTName()
{
 KdBreakPoint();
 if (KeGetCurrentIrql() > PASSIVE_LEVEL)
 {
  return STATUS_UNSUCCESSFUL;
 }
 //设置NTDLL路径
 UNICODE_STRING uniFileName;
 RtlInitUnicodeString(&uniFileName, L"[URL="file://\\SystemRoot\\system32\\ntdll.dll"]\\SystemRoot\\system32\\ntdll.dll[/URL]");
 
 //初始化打开文件的属性
 OBJECT_ATTRIBUTES objectAttributes;
 InitializeObjectAttributes(&objectAttributes, &uniFileName,
        OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
  ////创建文件
 NTSTATUS Status;
 HANDLE FileHandle;
 Status = IoCreateFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &objectAttributes,
       &ioStatus, 0, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT,
       NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING);
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("IoCreateFile failed!status:0x%08x\n", Status);
  return 0;
 }
  //获取文件信息
 IO_STATUS_BLOCK ioStatus;
 FILE_STANDARD_INFORMATION FileInformation;
 Status = ZwQueryInformationFile(FileHandle, &ioStatus, &FileInformation,
         sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation);
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("ZwQueryInformationFile failed!status:0x%08x\n", Status);
  ZwClose( FileHandle );
  return 0;
 }
  //判断文件大小是否过大
 if (FileInformation.EndOfFile.HighPart != 0)
 {
  DbgPrint("File Size Too High");
  ZwClose(FileHandle);
  return 0;
 }
  //取文件大小
 ULONG uFileSize = FileInformation.EndOfFile.LowPart;
  //分配内存
 PVOID pBuffer = ExAllocatePoolWithTag(PagedPool, uFileSize, (ULONG)"NTDLL");
 if (pBuffer == NULL)
 {
  DbgPrint("ExAllocatePoolWithTag() == NULL");
  ZwClose(FileHandle);
  return 0;
 }
  //从头开始读取文件
 LARGE_INTEGER byteOffset;
 byteOffset.LowPart = 0;
 byteOffset.HighPart = 0;
 Status = ZwReadFile(FileHandle, NULL, NULL, NULL, &ioStatus, pBuffer, uFileSize, &byteOffset, NULL);
 if (!NT_SUCCESS(Status))
 {
  DbgPrint("ZwReadFile failed!status:0x%08x\n", Status);
  ZwClose(FileHandle);
  return 0;
 }
  //取出导出表
 PIMAGE_DOS_HEADER  pDosHeader;
 PIMAGE_NT_HEADERS  pNtHeaders;
 PIMAGE_SECTION_HEADER pSectionHeader;
 ULONG     FileOffset;
 PIMAGE_EXPORT_DIRECTORY pExportDirectory;
 //DLL内存数据转成DOS头结构
 pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
 //取出PE头结构
 pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG)pBuffer + pDosHeader->e_lfanew);
 //判断PE头导出表表是否为空
 if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
 {
  DbgPrint("VirtualAddress == 0");
  return 0;
 }
 //取出导出表偏移
 FileOffset = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
 
 //取出节头结构
 pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(IMAGE_NT_HEADERS));
 PIMAGE_SECTION_HEADER pOldSectionHeader = pSectionHeader;
 //遍历节结构进行地址运算
 for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
 {
  if (pSectionHeader->VirtualAddress <= FileOffset &&
   FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
  {
   FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
  }
 }
 //导出表地址
 pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG)pBuffer + FileOffset);
  //取出导出表函数地址
 PULONG AddressOfFunctions;
 FileOffset = pExportDirectory->AddressOfFunctions;
 //遍历节结构进行地址运算
 pSectionHeader = pOldSectionHeader;
 for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
 {
  if (pSectionHeader->VirtualAddress <= FileOffset &&
   FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
  {
   FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
  }
 }
  AddressOfFunctions = (PULONG)((ULONG)pBuffer + FileOffset);
 
 //取出导出表函数名字
 PUSHORT AddressOfNameOrdinals;
 FileOffset = pExportDirectory->AddressOfNameOrdinals;
 //遍历节结构进行地址运算
 pSectionHeader = pOldSectionHeader;
 for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
 {
  if (pSectionHeader->VirtualAddress <= FileOffset &&
   FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
  {
   FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
  }
 }
 AddressOfNameOrdinals = (PUSHORT)((ULONG)pBuffer + FileOffset);
  //取出导出表函数序号
 PULONG AddressOfNames;
 FileOffset = pExportDirectory->AddressOfNames;
 //遍历节结构进行地址运算
 pSectionHeader = pOldSectionHeader;
 for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
 {
  if (pSectionHeader->VirtualAddress <= FileOffset &&
   FileOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
  {
   FileOffset = FileOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
  }
 }
 AddressOfNames = (PULONG)((ULONG)pBuffer + FileOffset);
  //分析导出表
 ULONG uNameOffset;
 ULONG uOffset;
 LPSTR FunName;
 PVOID pFuncAddr;
 ULONG uServerIndex;
 ULONG uAddressOfNames;
 for (ULONG uIndex = 0; uIndex < pExportDirectory->NumberOfNames; uIndex++, AddressOfNames++, AddressOfNameOrdinals++)
 {
  uAddressOfNames = *AddressOfNames;
  pSectionHeader = pOldSectionHeader;
  for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
  {
   if (pSectionHeader->VirtualAddress <= uAddressOfNames &&
    uAddressOfNames <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
   {
    uOffset = uAddressOfNames - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
   }
  } 
   FunName = (LPSTR)((ULONG)pBuffer + uOffset);
   if (FunName[0] == 'Z' && FunName[1] == 'w')
  {
   pSectionHeader = pOldSectionHeader;
   uOffset = (ULONG)AddressOfFunctions[*AddressOfNameOrdinals];
   for (WORD Index = 0; Index < pNtHeaders->FileHeader.NumberOfSections; Index++, pSectionHeader++)
   {
    if (pSectionHeader->VirtualAddress <=  uOffset&&
     uOffset <= pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData)
    {
     uNameOffset = uOffset - pSectionHeader->VirtualAddress + pSectionHeader->PointerToRawData;
    }
   } 
   pFuncAddr = (PVOID)((ULONG)pBuffer + uNameOffset);
   uServerIndex = *(PULONG)((ULONG)pFuncAddr + 1);
   FunName[0] = 'N';
   FunName[1] = 't';
   KdPrint(("函数名为: %s 序列号为:%d\n", FunName, uServerIndex));
   
  }
 }
 ExFreePoolWithTag(pBuffer , (ULONG)"NTDLL");
 ZwClose(FileHandle);
 return 1;
}
 
2013-12-10 01:23
0
雪    币: 213
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
楼上威武!感谢以上所有人!
2013-12-10 08:09
0
雪    币: 77
活跃值: (48)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
好人多,呵呵呵
2013-12-11 11:49
0
游客
登录 | 注册 方可回帖
返回
//