MmGetSystemRoutineAddress实际调用的MiFindExportedRoutineByName
- 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) {
- return NULL;
- }
- OrdinalNumber = NameOrdinalTableBase[Middle];
- // 如果索引值大于EAT中已有的函数数量,则查找失败
- if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {
- return NULL;
- }
- Addr = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);
- FunctionAddress = (PVOID)((PCHAR)DllBase + Addr[OrdinalNumber]);
- ASSERT ((FunctionAddress <= (PVOID)ExportDirectory) ||
- (FunctionAddress >= (PVOID)((PCHAR)ExportDirectory + ExportSize)));
- return FunctionAddress;
- }
在模块中定位指定函数名的地址,这个算法挺不错的