大理寺少卿 发表于 前天 23:17

驱动开发与系统原理-动态获取索引号

动态获取主要操作就是把ntdll.dll加载到驱动中,去函数地址读取汇编中的索引号

![](https://raw.githubusercontent.com/Whitebird0/tuchuang/main/QQ%E6%88%AA%E5%9B%BE20211217182932.png)

代码:

```
      #include<ntifs.h>
      #include<ntimage.h>
      PULONG g_PageMapMenmory = NULL;

      typedef struct _SSDTService
      {
            PULONG ServiceTableBase;      // SSDT基址
            PVOID ServiceCounterTableBase;// SSDT中服务被调用次数计数器,一般由sysenter 更新
            ULONG NumberOfService;      // 索引总数
            PVOID ParamTableBase;         // 系统服务参数表基址-系统服务参数表SSPT
      }SYSTEM_SERVICE_TABLE, * PSYSTEM_SERVICE_TABLE;

      typedef struct _SSDTable
      {
            SYSTEM_SERVICE_TABLE KernelApi;
            SYSTEM_SERVICE_TABLE GuiApi;
      }SYSTEM_DESCRIPTOR_TABLE, * PSYSTEM_DESCRIPTOR_TABLE;

      EXTERN_C PSYSTEM_DESCRIPTOR_TABLE KeServiceDescriptorTable;

      typedef NTSTATUS(NTAPI* WbOpenProcess)(//类型定义
            PHANDLE            ProcessHandle,
            ACCESS_MASK      DesiredAccess,
            POBJECT_ATTRIBUTES ObjectAttributes,
            PCLIENT_ID         ClientId
            );

      WbOpenProcessNtOpenProcessOldFunAddress = NULL;//用来保存原来的函数

      NTSTATUS NtOpenProcess(//hook的函数
            PHANDLE            ProcessHandle,
            ACCESS_MASK      DesiredAccess,
            POBJECT_ATTRIBUTES ObjectAttributes,
            PCLIENT_ID         ClientId
      ) {
            DbgPrint("此函数已被Hook!");
            return NtOpenProcessOldFunAddress(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
      }


      ULONG GetSSDTIndex(UNICODE_STRING usDLLFileName, PCHAR pFunctionName) {//获取SSDT中的Index
            NTSTATUS ntStatus = STATUS_SUCCESS;
            //打开dll的句柄
            HANDLE hFile = NULL;
            //节句柄
            HANDLE hSection = NULL;
            //对象属性
            OBJECT_ATTRIBUTES objectAttributes = { 0 };
            //状态块
            IO_STATUS_BLOCK ioStatus = { 0 };
            //在映射后的dll基址
            PVOID pBaseAddress = NULL;
            ULONG viewSize = 0;
            //用来保存索引
            ULONG ulFunctionIndex = 0;
            //初始化对象
            InitializeObjectAttributes(&objectAttributes, &usDLLFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
            ntStatus = ZwOpenFile(&hFile, GENERIC_READ, &objectAttributes, &ioStatus, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
            if (!NT_SUCCESS(ntStatus))
            {
                DbgPrint("ZwOpenFile Error!");
                return 0;
            }
            //初始化节对象
            ntStatus = ZwCreateSection(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, 0, PAGE_READWRITE, 0x1000000, hFile);
            if (!NT_SUCCESS(ntStatus))
            {
                ZwClose(hFile);
                DbgPrint("ZwCreateSection Error!");
                return 0;
            }
            //创建一个节对象, 以 PE 结构中的 SectionALignment 大小对齐映射文件
            ntStatus = ZwMapViewOfSection(hSection, NtCurrentProcess(), &pBaseAddress, 0, 1024, 0, &viewSize, ViewShare, MEM_TOP_DOWN, PAGE_READWRITE);
            if (!NT_SUCCESS(ntStatus))
            {
               ZwClose(hFile);
               ZwClose(hSection);
                DbgPrint("ZwCreateSection Error!");
                return 0;
            }   
                // Dos Header
            PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;      
                // NT Header
            PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + pDosHeader->e_lfanew);
            //导出表地址
            PIMAGE_EXPORT_DIRECTORY pExportable = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)pDosHeader + pNtHeaders->OptionalHeader.DataDirectory.VirtualAddress);
            //获得有名字的函数的个数
            ULONG nlNumberForNames = pExportable->NumberOfNames;
            //获得函数地址表的地址
            PULONG lpNameAddress = (PULONG)((PUCHAR)pDosHeader + pExportable->AddressOfNames);
            PCHAR lpFuncName = NULL;
            for (ULONG i = 0; i < nlNumberForNames; i++)
            {
                lpFuncName = (PCHAR)((PUCHAR)pDosHeader + lpNameAddress);
                // 判断是否查找的函数
                if (0 == _strnicmp(pFunctionName, lpFuncName, strlen(pFunctionName)))
                {
                  // 获取导出函数地址
                  USHORT uHint = *(USHORT*)((PUCHAR)pDosHeader + pExportable->AddressOfNameOrdinals + 2 * i);
                  ULONG ulFuncAddr = *(PULONG)((PUCHAR)pDosHeader + pExportable->AddressOfFunctions + 4 * uHint);
                  PVOID lpFuncAddr = (PVOID)((PUCHAR)pDosHeader + ulFuncAddr);
                  // 获取 SSDT 函数 Index
                  ulFunctionIndex = *(ULONG*)((PUCHAR)lpFuncAddr + 1);
                  break;
                }
            }
            ZwClose(hSection);
            ZwClose(hFile);
            return ulFunctionIndex;
      }

      NTSTATUS SetHook(ULONG ulFunAddr, PCHAR pFunctionName) {
            ULONG ulFunctionIndex = 0;
            NTSTATUS status = STATUS_SUCCESS;
            UNICODE_STRING usDllFileName;
            RtlInitUnicodeString(&usDllFileName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
            //获得ssdt中的index
            ulFunctionIndex = GetSSDTIndex(usDllFileName, pFunctionName);
            if (ulFunctionIndex == 0)
            {
                DbgPrint("GetSSDTIndex Error!");
                return status;
            }
            //打印出index
            DbgPrint("0x%X", ulFunctionIndex);
            //内存映射文件-SSDT表
            PHYSICAL_ADDRESS pHyAddress = MmGetPhysicalAddress(KeServiceDescriptorTable->KernelApi.ServiceTableBase);
            g_PageMapMenmory = MmMapIoSpace(pHyAddress, PAGE_SIZE, MmCached);
            //保存原来的函数地址
            NtOpenProcessOldFunAddress = g_PageMapMenmory;
            //将索引的地址改为我们HOOK的函数
            g_PageMapMenmory = ulFunAddr;
            return status;
      }

      NTSTATUS UnHook(ULONG ulFunAddr, PCHAR pFunctionName) {
            ULONG ulFunctionIndex = 0;
            NTSTATUS status = STATUS_SUCCESS;
            UNICODE_STRING usDllFileName;
            RtlInitUnicodeString(&usDllFileName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
            ////获得ssdt中的index
            ulFunctionIndex = GetSSDTIndex(usDllFileName, pFunctionName);
            if (ulFunctionIndex == 0)
            {
                DbgPrint("GetSSDTIndex Error!");
                return status;
            }
            DbgPrint("0x%X", ulFunctionIndex);
            //内存映射文件-SSDT表
            PHYSICAL_ADDRESS pHyAddress = MmGetPhysicalAddress(KeServiceDescriptorTable->KernelApi.ServiceTableBase);
            g_PageMapMenmory = MmMapIoSpace(pHyAddress, PAGE_SIZE, MmCached);
            //将索引的地址改为我们保存的地址
            g_PageMapMenmory = ulFunAddr;
            return status;
      }
      VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
            //解除hook   
            UnHook((ULONG)NtOpenProcessOldFunAddress, "NtOpenProcess");
            MmUnmapIoSpace(g_PageMapMenmory, PAGE_SIZE);
            DbgPrint("Driver UnLoad Success!");
      }
      NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath) {
            DbgPrint("Driver Load Success!");
            //进行hook
            SetHook((ULONG)NtOpenProcess, "NtOpenProcess");
            //卸载函数
            pDriverObject->DriverUnload = DriverUnload;
            return STATUS_SUCCESS;
      }
```

![](https://raw.githubusercontent.com/Whitebird0/tuchuang/main/QQ%E6%88%AA%E5%9B%BE20211217184313.png)
页: [1]
查看完整版本: 驱动开发与系统原理-动态获取索引号