⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
 * DESCRIPTION
 *      Relocate a DLL's memory image.
 *
 * ARGUMENTS
 *
 * RETURN VALUE
 *
 * REVISIONS
 *
 * NOTE
 *
 */
static NTSTATUS
LdrPerformRelocations(PIMAGE_NT_HEADERS NTHeaders,
                      PVOID ImageBase)
{
  PIMAGE_DATA_DIRECTORY RelocationDDir;
  PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
  ULONG Count, ProtectSize, OldProtect, OldProtect2;
  PVOID Page, ProtectPage, ProtectPage2;
  PUSHORT TypeOffset;
  ULONG_PTR Delta;
  NTSTATUS Status;

  if (NTHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
    {
      return STATUS_UNSUCCESSFUL;
    }

  RelocationDDir =
    &NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

  if (RelocationDDir->VirtualAddress == 0 || RelocationDDir->Size == 0)
    {
      return STATUS_SUCCESS;
    }

  ProtectSize = PAGE_SIZE;
  Delta = (ULONG_PTR)ImageBase - NTHeaders->OptionalHeader.ImageBase;
  RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
                  RelocationDDir->VirtualAddress);
  RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)ImageBase +
                  RelocationDDir->VirtualAddress + RelocationDDir->Size);

  while (RelocationDir < RelocationEnd &&
         RelocationDir->SizeOfBlock > 0)
    {
      Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) /
              sizeof(USHORT);
      Page = (PVOID)((ULONG_PTR)ImageBase + (ULONG_PTR)RelocationDir->VirtualAddress);
      TypeOffset = (PUSHORT)(RelocationDir + 1);

      /* Unprotect the page(s) we're about to relocate. */
      ProtectPage = Page;
      Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                      &ProtectPage,
                                      &ProtectSize,
                                      PAGE_READWRITE,
                                      &OldProtect);
      if (!NT_SUCCESS(Status))
        {
          DPRINT1("Failed to unprotect relocation target.\n");
          return Status;
        }

      if (RelocationDir->VirtualAddress + PAGE_SIZE <
          NTHeaders->OptionalHeader.SizeOfImage)
        {
          ProtectPage2 = (PVOID)((ULONG_PTR)ProtectPage + PAGE_SIZE);
          Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                          &ProtectPage2,
                                          &ProtectSize,
                                          PAGE_READWRITE,
                                          &OldProtect2);
          if (!NT_SUCCESS(Status))
            {
              DPRINT1("Failed to unprotect relocation target (2).\n");
              NtProtectVirtualMemory(NtCurrentProcess(),
                                     &ProtectPage,
                                     &ProtectSize,
                                     OldProtect,
                                     &OldProtect);
              return Status;
            }
        }
      else
        {
          ProtectPage2 = NULL;
        }

      RelocationDir = LdrProcessRelocationBlock((ULONG_PTR)Page,
                                                Count,
                                                TypeOffset,
                                                Delta);
      if (RelocationDir == NULL)
        return STATUS_UNSUCCESSFUL;

      /* Restore old page protection. */
      NtProtectVirtualMemory(NtCurrentProcess(),
                             &ProtectPage,
                             &ProtectSize,
                             OldProtect,
                             &OldProtect);

      if (ProtectPage2 != NULL)
        {
          NtProtectVirtualMemory(NtCurrentProcess(),
                                 &ProtectPage2,
                                 &ProtectSize,
                                 OldProtect2,
                                 &OldProtect2);
        }
    }

  return STATUS_SUCCESS;
}

static NTSTATUS
LdrpGetOrLoadModule(PWCHAR SerachPath,
                    PCHAR Name,
                    PLDR_DATA_TABLE_ENTRY* Module,
                    BOOLEAN Load)
{
   UNICODE_STRING DllName;
   NTSTATUS Status;

   DPRINT("LdrpGetOrLoadModule() called for %s\n", Name);

   RtlCreateUnicodeStringFromAsciiz (&DllName, Name);

   Status = LdrFindEntryForName (&DllName, Module, Load);
   if (Load && !NT_SUCCESS(Status))
     {
       Status = LdrpLoadModule(SerachPath,
                               NtCurrentPeb()->Ldr->Initialized ? 0 : LDRP_PROCESS_CREATION_TIME,
                               &DllName,
                               Module,
                               NULL);
       if (NT_SUCCESS(Status))
         {
           Status = LdrFindEntryForName (&DllName, Module, FALSE);
         }
       if (!NT_SUCCESS(Status))
         {
           DPRINT1("failed to load %wZ\n", &DllName);
         }
     }
   RtlFreeUnicodeString (&DllName);
   return Status;
}

static NTSTATUS
LdrpProcessImportDirectoryEntry(PLDR_DATA_TABLE_ENTRY Module,
                                PLDR_DATA_TABLE_ENTRY ImportedModule,
                                PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
{
   NTSTATUS Status;
   PVOID* ImportAddressList;
   PULONG FunctionNameList;
   PVOID IATBase;
   ULONG OldProtect;
   ULONG Ordinal;
   ULONG IATSize;

   if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
     {
       return STATUS_UNSUCCESSFUL;
     }

   /* Get the import address list. */
   ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);

   /* Get the list of functions to import. */
   if (ImportModuleDirectory->OriginalFirstThunk != 0)
     {
       FunctionNameList = (PULONG) ((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
     }
   else
     {
       FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);
     }

   /* Get the size of IAT. */
   IATSize = 0;
   while (FunctionNameList[IATSize] != 0L)
     {
       IATSize++;
     }

   /* Unprotect the region we are about to write into. */
   IATBase = (PVOID)ImportAddressList;
   IATSize *= sizeof(PVOID*);
   Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                   &IATBase,
                                   &IATSize,
                                   PAGE_READWRITE,
                                   &OldProtect);
   if (!NT_SUCCESS(Status))
     {
       DPRINT1("Failed to unprotect IAT.\n");
       return(Status);
     }

   /* Walk through function list and fixup addresses. */
   while (*FunctionNameList != 0L)
     {
       if ((*FunctionNameList) & 0x80000000)
         {
           Ordinal = (*FunctionNameList) & 0x7fffffff;
           *ImportAddressList = LdrGetExportByOrdinal(ImportedModule->DllBase, Ordinal);
           if ((*ImportAddressList) == NULL)
             {
               DPRINT1("Failed to import #%ld from %wZ\n", Ordinal, &ImportedModule->FullDllName);
               return STATUS_UNSUCCESSFUL;
             }
         }
       else
         {
           IMAGE_IMPORT_BY_NAME *pe_name;
           pe_name = RVA(Module->DllBase, *FunctionNameList);
           *ImportAddressList = LdrGetExportByName(ImportedModule->DllBase, pe_name->Name, pe_name->Hint);
           if ((*ImportAddressList) == NULL)
             {
               DPRINT1("Failed to import %s from %wZ\n", pe_name->Name, &ImportedModule->FullDllName);
               return STATUS_UNSUCCESSFUL;
             }
         }
       ImportAddressList++;
       FunctionNameList++;
     }

   /* Protect the region we are about to write into. */
   Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                   &IATBase,
                                   &IATSize,
                                   OldProtect,
                                   &OldProtect);
   if (!NT_SUCCESS(Status))
     {
       DPRINT1("Failed to protect IAT.\n");
       return(Status);
     }

   return STATUS_SUCCESS;
}

static NTSTATUS
LdrpProcessImportDirectory(
   PLDR_DATA_TABLE_ENTRY Module,
   PLDR_DATA_TABLE_ENTRY ImportedModule,
   PCHAR ImportedName)
{
   NTSTATUS Status;
   PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
   PCHAR Name;
   ULONG Size;

   DPRINT("LdrpProcessImportDirectory(%p '%wZ', '%s')\n",
          Module, &Module->BaseDllName, ImportedName);


   ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
                             RtlImageDirectoryEntryToData(Module->DllBase,
                                                          TRUE,
                                                          IMAGE_DIRECTORY_ENTRY_IMPORT,
                                                          &Size);
   if (ImportModuleDirectory == NULL)
     {
       return STATUS_UNSUCCESSFUL;
     }

   while (ImportModuleDirectory->Name)
     {
       Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
       if (0 == _stricmp(Name, ImportedName))
         {
           Status = LdrpProcessImportDirectoryEntry(Module,
                                                    ImportedModule,
                                                    ImportModuleDirectory);
           if (!NT_SUCCESS(Status))
             {
               return Status;
             }
         }
       ImportModuleDirectory++;
     }


   return STATUS_SUCCESS;
}


static NTSTATUS
LdrpAdjustImportDirectory(PLDR_DATA_TABLE_ENTRY Module,
                          PLDR_DATA_TABLE_ENTRY ImportedModule,
                          PCHAR ImportedName)
{
   PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
   NTSTATUS Status;
   PVOID* ImportAddressList;
   PVOID Start;
   PVOID End;
   PULONG FunctionNameList;
   PVOID IATBase;
   ULONG OldProtect;
   ULONG Offset;
   ULONG IATSize;
   PIMAGE_NT_HEADERS NTHeaders;
   PCHAR Name;
   ULONG Size;

   DPRINT("LdrpAdjustImportDirectory(Module %p '%wZ', %p '%wZ', '%s')\n",
          Module, &Module->BaseDllName, ImportedModule, &ImportedModule->BaseDllName, ImportedName);

   ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
                              RtlImageDirectoryEntryToData(Module->DllBase,
                                                           TRUE,
                                                           IMAGE_DIRECTORY_ENTRY_IMPORT,
                                                           &Size);
   if (ImportModuleDirectory == NULL)
     {
       return STATUS_UNSUCCESSFUL;
     }

   while (ImportModuleDirectory->Name)
     {
       Name = (PCHAR)Module->DllBase + ImportModuleDirectory->Name;
       if (0 == _stricmp(Name, (PCHAR)ImportedName))
         {

           /* Get the import address list. */
           ImportAddressList = (PVOID *)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);

           /* Get the list of functions to import. */
           if (ImportModuleDirectory->OriginalFirstThunk != 0)
             {
               FunctionNameList = (PULONG) ((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->OriginalFirstThunk);
             }
           else
             {
               FunctionNameList = (PULONG)((ULONG_PTR)Module->DllBase + (ULONG_PTR)ImportModuleDirectory->FirstThunk);
             }

           /* Get the size of IAT. */
           IATSize = 0;
           while (FunctionNameList[IATSize] != 0L)
             {
               IATSize++;
             }

           /* Unprotect the region we are about to write into. */
           IATBase = (PVOID)ImportAddressList;
           IATSize *= sizeof(PVOID*);
           Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                           &IATBase,
                                           &IATSize,
                                           PAGE_READWRITE,
                                           &OldProtect);
           if (!NT_SUCCESS(Status))
             {
               DPRINT1("Failed to unprotect IAT.\n");
               return(Status);
             }

           NTHeaders = RtlImageNtHeader (ImportedModule->DllBase);
           Start = (PVOID)NTHeaders->OptionalHeader.ImageBase;
           End = (PVOID)((ULONG_PTR)Start + ImportedModule->SizeOfImage);
           Offset = (ULONG)((ULONG_PTR)ImportedModule->DllBase - (ULONG_PTR)Start);

           /* Walk through function list and fixup addresses. */
           while (*FunctionNameList != 0L)
             {
               if (*ImportAddressList >= Start && *ImportAddressList < End)
                 {
                   (*ImportAddressList) = (PVOID)((ULONG_PTR)(*ImportAddressList) + Offset);
                 }
               ImportAddressList++;
               FunctionNameList++;
             }

           /* Protect the region we are about to write into. */
           Status = NtProtectVirtualMemory(NtCurrentProcess(),
                                           &IATBase,
                                           &IATSize,
                                           OldProtect,
                                           &OldProtect);
           if (!NT_SUCCESS(Status))
             {
               DPRINT1("Failed to protect IAT.\n");
               return(Status);
             }
         }
       ImportModuleDirectory++;
     }
   return STATUS_SUCCESS;
}


/**********************************************************************
 * NAME                                                         LOCAL
 *      LdrFixupImports
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -