MmGetSystemRoutineAddress实现
Posted Yuri800
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MmGetSystemRoutineAddress实现相关的知识,希望对你有一定的参考价值。
MmGetSystemRoutineAddress这个函数也是比较有用的,是得到系统导出函数的地址,不过网上都是写了一堆汇编代码在哪里,根本没有可读性,还不如用IDA看呢。
下面的函数是摘自ReactOS项目的代码:
- PVOID
- NTAPI
- MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)
- PVOID ProcAddress = NULL;
- ANSI_STRING AnsiRoutineName;
- NTSTATUS Status;
- PLIST_ENTRY NextEntry;
- PLDR_DATA_TABLE_ENTRY LdrEntry;
- BOOLEAN Found = FALSE;
- UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
- UNICODE_STRING HalName = RTL_CONSTANT_STRING(L"hal.dll");
- ULONG Modules = 0;
- /* Convert routine to ansi name */
- Status = RtlUnicodeStringToAnsiString(&AnsiRoutineName,
- SystemRoutineName,
- TRUE);
- if (!NT_SUCCESS(Status)) return NULL;
- /* Lock the list */
- KeEnterCriticalRegion();
- ExAcquireResourceSharedLite(&PsLoadedModuleResource, TRUE);
- /* Loop the loaded module list */
- NextEntry = PsLoadedModuleList.Flink;
- while (NextEntry != &PsLoadedModuleList)
- /* Get the entry */
- LdrEntry = CONTAINING_RECORD(NextEntry,
- LDR_DATA_TABLE_ENTRY,
- InLoadOrderLinks);
- /* Check if it's the kernel or HAL */
- if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE))
- /* Found it */
- Found = TRUE;
- Modules++;
- else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE))
- /* Found it */
- Found = TRUE;
- Modules++;
- /* Check if we found a valid binary */
- if (Found)
- /* Find the procedure name */
- ProcAddress = MiFindExportedRoutineByName(LdrEntry->DllBase,
- &AnsiRoutineName);
- /* Break out if we found it or if we already tried both modules */
- if (ProcAddress) break;
- if (Modules == 2) break;
- /* Keep looping */
- NextEntry = NextEntry->Flink;
- /* Release the lock */
- ExReleaseResourceLite(&PsLoadedModuleResource);
- KeLeaveCriticalRegion();
- /* Free the string and return */
- RtlFreeAnsiString(&AnsiRoutineName);
- return ProcAddress;
-
- PVOID
- MiFindExportedRoutineByName (
- IN PVOID DllBase,
- IN PANSI_STRING AnsiImageRoutineName
- )
- USHORT OrdinalNumber;
- PULONG NameTableBase;
- PUSHORT NameOrdinalTableBase;
- PULONG Addr;
- LONG High;
- LONG Low;
- LONG Middle;
- LONG Result;
- ULONG ExportSize; // 保存表项的大小
- PVOID FunctionAddress;
- PIMAGE_EXPORT_DIRECTORY ExportDirectory;
- PAGED_CODE();
- ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) RtlImageDirectoryEntryToData (
- DllBase,
- TRUE,
- IMAGE_DIRECTORY_ENTRY_EXPORT,
- &ExportSize);
- if (ExportDirectory == NULL)
- return NULL;
- NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
- NameOrdinalTableBase = (PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
- //二分查找法
- Low = 0;
- Middle = 0;
- High = ExportDirectory->NumberOfNames - 1;
- while (High >= Low)
- Middle = (Low + High) >> 1;
- Result = strcmp (AnsiImageRoutineName->Buffer,
- (PCHAR)DllBase + NameTableBase[Middle]);
- if (Result < 0)
- High = Middle - 1;
- else if (Result > 0)
- Low = Middle + 1;
- else
- break;
- // 如果High < Low,表明没有在EAT中找到这个函数;否则,返回此函数的索引
- if (High < Low)