MmGetSystemRoutineAddress和MiFindExportedRoutineByName函數的實現代碼

來源:互聯網
上載者:User

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;          ERESOURCE PsLoadedModuleResource; /* 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;      }  

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

MmGetSystemRoutineAddress實際調用的MiFindExportedRoutineByName

PVOIDMiFindExportedRoutineByName (    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;}

在模組中定位指定函數名的地址,這個演算法挺不錯的

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.