MmGetSystemRoutineAddress和MiFindExportedRoutineByName函数的实现代码

来源:互联网 发布:有了源码怎么架设游戏 编辑:程序博客网 时间:2024/06/08 10:24

MmGetSystemRoutineAddress这个函数也是比较有用的,是得到系统导出函数的地址,不过网上都是写了一堆汇编代码在哪里,根本没有可读性,还不如用IDA看呢。

下面的函数是摘自ReactOS项目的代码:

[cpp] view plaincopy
  1.     PVOID    
  2.     NTAPI    
  3.     MmGetSystemRoutineAddress(IN PUNICODE_STRING SystemRoutineName)    
  4.     {    
  5.         PVOID ProcAddress = NULL;    
  6.         ANSI_STRING AnsiRoutineName;    
  7.         NTSTATUS Status;    
  8.         PLIST_ENTRY NextEntry;    
  9.         PLDR_DATA_TABLE_ENTRY LdrEntry;    
  10.         BOOLEAN Found = FALSE;    
  11.         UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");    
  12.         UNICODE_STRING HalName = RTL_CONSTANT_STRING(L"hal.dll");    
  13.         ULONG Modules = 0;    
  14.         ERESOURCE PsLoadedModuleResource;  
  15.   
  16.  /* Convert routine to ansi name */    
  17.         Status = RtlUnicodeStringToAnsiString(&AnsiRoutineName,    
  18.                                               SystemRoutineName,    
  19.                                               TRUE);    
  20.         if (!NT_SUCCESS(Status)) return NULL;    
  21.         
  22.         /* Lock the list */    
  23.         KeEnterCriticalRegion();    
  24.         ExAcquireResourceSharedLite(&PsLoadedModuleResource, TRUE);    
  25.         
  26.         /* Loop the loaded module list */    
  27.         NextEntry = PsLoadedModuleList.Flink;    
  28.         while (NextEntry != &PsLoadedModuleList)    
  29.         {    
  30.             /* Get the entry */    
  31.             LdrEntry = CONTAINING_RECORD(NextEntry,    
  32.                                          LDR_DATA_TABLE_ENTRY,    
  33.                                          InLoadOrderLinks);    
  34.         
  35.             /* Check if it's the kernel or HAL */    
  36.             if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE))    
  37.             {    
  38.                 /* Found it */    
  39.                 Found = TRUE;    
  40.                 Modules++;    
  41.             }    
  42.             else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName, TRUE))    
  43.             {    
  44.                 /* Found it */    
  45.                 Found = TRUE;    
  46.                 Modules++;    
  47.             }    
  48.         
  49.             /* Check if we found a valid binary */    
  50.             if (Found)    
  51.             {    
  52.                 /* Find the procedure name */    
  53.                 ProcAddress = MiFindExportedRoutineByName(LdrEntry->DllBase,    
  54.                                                           &AnsiRoutineName);    
  55.         
  56.                 /* Break out if we found it or if we already tried both modules */    
  57.                 if (ProcAddress) break;    
  58.                 if (Modules == 2) break;    
  59.             }    
  60.         
  61.             /* Keep looping */    
  62.             NextEntry = NextEntry->Flink;    
  63.         }    
  64.         
  65.         /* Release the lock */    
  66.         ExReleaseResourceLite(&PsLoadedModuleResource);    
  67.         KeLeaveCriticalRegion();    
  68.         
  69.         /* Free the string and return */    
  70.         RtlFreeAnsiString(&AnsiRoutineName);    
  71.         return ProcAddress;    
  72.     }    


MiFindExportedRoutineByName——EAT中定位到指定函数

MmGetSystemRoutineAddress实际调用的MiFindExportedRoutineByName

[cpp] view plaincopy
  1. PVOID  
  2. MiFindExportedRoutineByName (  
  3.     IN PVOID DllBase,  
  4.     IN PANSI_STRING AnsiImageRoutineName  
  5.     )  
  6. {  
  7.     USHORT OrdinalNumber;  
  8.     PULONG NameTableBase;  
  9.     PUSHORT NameOrdinalTableBase;  
  10.     PULONG Addr;  
  11.     LONG High;  
  12.     LONG Low;  
  13.     LONG Middle;  
  14.     LONG Result;  
  15.     ULONG ExportSize;   // 保存表项的大小  
  16.     PVOID FunctionAddress;  
  17.     PIMAGE_EXPORT_DIRECTORY ExportDirectory;  
  18.   
  19.     PAGED_CODE();  
  20.   
  21.     ExportDirectory = (PIMAGE_EXPORT_DIRECTORY) RtlImageDirectoryEntryToData (  
  22.                                 DllBase,  
  23.                                 TRUE,  
  24.                                 IMAGE_DIRECTORY_ENTRY_EXPORT,  
  25.                                 &ExportSize);  
  26.   
  27.     if (ExportDirectory == NULL) {  
  28.         return NULL;  
  29.     }  
  30.   
  31.     NameTableBase = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNames);  
  32.     NameOrdinalTableBase = (PUSHORT)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);  
  33.   
  34.     //二分查找法  
  35.     Low = 0;  
  36.     Middle = 0;  
  37.     High = ExportDirectory->NumberOfNames - 1;  
  38.   
  39.     while (High >= Low) {  
  40.         Middle = (Low + High) >> 1;  
  41.   
  42.         Result = strcmp (AnsiImageRoutineName->Buffer,  
  43.                          (PCHAR)DllBase + NameTableBase[Middle]);  
  44.   
  45.         if (Result < 0) {  
  46.             High = Middle - 1;  
  47.         }  
  48.         else if (Result > 0) {  
  49.             Low = Middle + 1;  
  50.         }  
  51.         else {  
  52.             break;  
  53.         }  
  54.     }  
  55.   
  56.     // 如果High < Low,表明没有在EAT中找到这个函数;否则,返回此函数的索引  
  57.     if (High < Low) {  
  58.         return NULL;  
  59.     }  
  60.   
  61.     OrdinalNumber = NameOrdinalTableBase[Middle];  
  62.   
  63.     // 如果索引值大于EAT中已有的函数数量,则查找失败  
  64.     if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions) {  
  65.         return NULL;  
  66.     }  
  67.   
  68.     Addr = (PULONG)((PCHAR)DllBase + (ULONG)ExportDirectory->AddressOfFunctions);  
  69.   
  70.     FunctionAddress = (PVOID)((PCHAR)DllBase + Addr[OrdinalNumber]);  
  71.     ASSERT ((FunctionAddress <= (PVOID)ExportDirectory) ||  
  72.             (FunctionAddress >= (PVOID)((PCHAR)ExportDirectory + ExportSize)));  
  73.   
  74.     return FunctionAddress;  
  75. }  

在模块中定位指定函数名的地址,这个算法挺不错的

0 0
原创粉丝点击