找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 8407|回复: 4

BUG:SSDT函数名获取SSDT函数号

[复制链接]

5

主题

103

回帖

0

精华

铜牌会员

积分
252
发表于 2015-7-25 19:38:07 | 显示全部楼层 |阅读模式
一个有BUG的SSDT函数名返回SSDT函数序列号。

一运行就蓝屏。不知道是怎的。大神如果有空帮我看看。然后就是你的代码了,你可以拿去用,谢谢!

这样测试

  1. __try
  2.         {
  3.                 KdPrint(("ZwOpenProcess的函数服务号为:%d", GetFunctionId("NtOpenProcess")));
  4.         }
  5.         __except (EXCEPTION_EXECUTE_HANDLER)
  6.         {
  7.                 KdPrint(("GetFunctionId出错了!"));
  8.         }
复制代码

  1. ULONG GetFunctionId(char* FunctionName)
  2. /*++

  3. Routine Description:

  4.         [已删除,请勿再提任何无理要求。]

  5. Arguments:

  6.         FunctionName - 导出的函数名.

  7. Return Value:

  8.         函数的服务号的地址.

  9. --*/
  10. {
  11.         NTSTATUS ntstatus;
  12.         HANDLE hFile = NULL;
  13.         HANDLE hSection = NULL;
  14.         OBJECT_ATTRIBUTES object_attributes;
  15.         IO_STATUS_BLOCK io_status = { 0 };
  16.         PVOID baseaddress = NULL;
  17.         SIZE_T size = 0;
  18.         //模块基址
  19. //        PVOID ModuleAddress = NULL;
  20.         //偏移量
  21.         ULONG dwOffset = 0;

  22.         PIMAGE_DOS_HEADER dos = NULL;
  23. #ifdef _WIN64
  24.         PIMAGE_NT_HEADERS64 nt = NULL;
  25. #else
  26.         PIMAGE_NT_HEADERS nt = NULL;
  27. #endif

  28.        
  29.         PIMAGE_DATA_DIRECTORY expdir = NULL;
  30.         PIMAGE_EXPORT_DIRECTORY exports = NULL;

  31.         ULONG addr;
  32.         ULONG Size;

  33.         PULONG functions;
  34.         PSHORT ordinals;
  35.         PULONG names;

  36.         ULONG max_name;
  37.         ULONG max_func;
  38.         ULONG i;

  39.         ULONG pFunctionAddress = 0;

  40.         ULONG ServiceId;

  41.         UNICODE_STRING DllName;
  42.         RtlInitUnicodeString(&DllName, L"\\SystemRoot\\system32\\ntdll.dll");
  43.         //初始化OBJECT_ATTRIBUTES结构
  44.         InitializeObjectAttributes(
  45.                 &object_attributes,
  46.                 &DllName,
  47.                 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  48.                 NULL,
  49.                 NULL);
  50.         //打开文件
  51.         ntstatus = ZwCreateFile(
  52.                 &hFile,
  53.                 FILE_EXECUTE | SYNCHRONIZE,
  54.                 &object_attributes,
  55.                 &io_status,
  56.                 NULL,
  57.                 FILE_ATTRIBUTE_NORMAL,
  58.                 FILE_SHARE_READ,
  59.                 FILE_OPEN,
  60.                 FILE_NON_DIRECTORY_FILE |
  61.                 FILE_RANDOM_ACCESS |
  62.                 FILE_SYNCHRONOUS_IO_NONALERT,
  63.                 NULL,
  64.                 0);
  65.         if (!NT_SUCCESS(ntstatus))
  66.         {
  67.                 KdPrint(("[GetFunctionAddress] error0\n"));
  68.                 KdPrint(("[GetFunctionAddress] ntstatus = 0x%x\n", ntstatus));
  69.                 return 0;
  70.         }
  71.         //创建区段
  72.         InitializeObjectAttributes(
  73.                 &object_attributes,
  74.                 NULL,
  75.                 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  76.                 NULL,
  77.                 NULL);
  78. #ifndef SEC_IMAGE
  79. #define SEC_IMAGE 0x1000000
  80. #endif
  81.         ntstatus = ZwCreateSection(
  82.                 &hSection,
  83.                 SECTION_ALL_ACCESS,
  84.                 &object_attributes,
  85.                 0,
  86.                 PAGE_EXECUTE,
  87.                 SEC_IMAGE,
  88.                 hFile);
  89.         if (!NT_SUCCESS(ntstatus))
  90.         {
  91.                 KdPrint(("[GetFunctionAddress] error1\n"));
  92.                 KdPrint(("[GetFunctionAddress] ntstatus = 0x%x\n", ntstatus));
  93.                 return 0;
  94.         }
  95.         //映射区段到进程虚拟空间
  96.         ntstatus = ZwMapViewOfSection(
  97.                 hSection,
  98.                 NtCurrentProcess(), //ntddk.h定义的宏用来获取当前进程句柄
  99.                 &baseaddress,
  100.                 0,
  101.                 1000,
  102.                 0,
  103.                 &size,
  104.                 (SECTION_INHERIT)1,
  105.                 MEM_TOP_DOWN,
  106.                 PAGE_READWRITE);
  107.         if (!NT_SUCCESS(ntstatus))
  108.         {
  109.                 KdPrint(("[GetFunctionAddress] error2\n"));
  110.                 KdPrint(("[GetFunctionAddress] ntstatus = 0x%x\n", ntstatus));
  111.                 return 0;
  112.         }
  113.         //得到模块基址
  114.         dwOffset = (ULONG)baseaddress;
  115.         //验证基址
  116.         //KdPrint(("[GetFunctionAddress] BaseAddress:0x%x\n", dwOffset));
  117.         dos = (PIMAGE_DOS_HEADER)baseaddress;
  118. #ifdef _WIN64
  119.         nt = (PIMAGE_NT_HEADERS64)((ULONG)baseaddress + dos->e_lfanew);
  120. #else
  121.         nt = (PIMAGE_NT_HEADERS)((ULONG)baseaddress + dos->e_lfanew);
  122. #endif
  123.        
  124.         expdir = (PIMAGE_DATA_DIRECTORY)(nt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT);

  125.         addr = expdir->VirtualAddress;//数据块起始RVA
  126.         Size = expdir->Size;    //数据块长度

  127.         exports = (PIMAGE_EXPORT_DIRECTORY)((ULONG)baseaddress + addr);

  128.         functions = (PULONG)((ULONG)baseaddress + exports->AddressOfFunctions);
  129.         ordinals = (PSHORT)((ULONG)baseaddress + exports->AddressOfNameOrdinals);
  130.         names = (PULONG)((ULONG)baseaddress + exports->AddressOfNames);

  131.         max_name = exports->NumberOfNames;
  132.         max_func = exports->NumberOfFunctions;


  133.         for (i = 0; i < max_name; i++)
  134.         {
  135.                 ULONG ord = ordinals[i];
  136.                 if (i >= max_name || ord >= max_func)
  137.                 {
  138.                         return 0;
  139.                 }
  140.                 if (functions[ord] < addr || functions[ord] >= addr + Size)
  141.                 {
  142.                         if (strncmp((PCHAR)baseaddress + names[i], FunctionName, strlen(FunctionName)) == 0)
  143.                         {
  144.                                 pFunctionAddress = (ULONG)((ULONG)baseaddress + functions[ord]);
  145.                                 break;
  146.                         }
  147.                 }
  148.         }


  149.         //KdPrint(("[GetFunctionAddress] %s:0x%x\n",FunctionName, pFunctionAddress));
  150.         ServiceId = *(PSHORT)(pFunctionAddress + 1);
  151.         //打印导出函数服务号
  152.         //KdPrint(("[GetServiceId] ServiceId:0x%x\n",ServiceId));
  153.         //卸载区段,释放内存,关闭句柄
  154.         ZwUnmapViewOfSection(NtCurrentProcess(), baseaddress);
  155.         ZwClose(hSection);
  156.         ZwClose(hFile);
  157.        
  158.         return ServiceId;
  159. }
复制代码

78

主题

190

回帖

9

精华

贵宾会员

积分
15605
发表于 2015-7-25 21:16:23 | 显示全部楼层
我发过动态取得SSDT函数的帖子的,地址:http://www.m5home.com/bbs/thread-8518-1-1.html
就是像ZwProtectVirtualMemory这样的未导出函数不好用。思路很简单,获取对应的ZwXXX函数的地址,从第二个字节开始读四个字节,该数据就是服务编号了

78

主题

190

回帖

9

精华

贵宾会员

积分
15605
发表于 2015-7-25 21:21:47 | 显示全部楼层
额。。。那是32位的,64位的也有办法,用反汇编引擎解析出每一条指令,并判断指令的机器码是不是0xB8。第一个0xB8(mov)指令后面的四个字节就是这个函数的服务号

857

主题

2632

回帖

2

精华

管理员

此生无悔入华夏,  长居日耳曼尼亚。  

积分
36130
发表于 2015-7-25 23:15:19 | 显示全部楼层
KernelLoadLibary+KernelGetProcAddress。获得的地址虽然是“假的”(可以简单理解为一个随机BASE+RVA),但数据是“真的”。足以从中提取出INDEX。

3

主题

19

回帖

1

精华

金牌会员

积分
1262
发表于 2017-3-24 09:51:12 | 显示全部楼层
和baseaddress 相关的计算,不能直接使用ULONG强制转换,需要使用ULONG_PTR。
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表