Bitdefender Hypervisor Memory Introspection
loader.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 Bitdefender
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 #include "loader.h"
6 #include "drivers.h"
7 #include "winpe.h"
8 
9 
12  _In_ PBYTE RawPe,
13  _In_ DWORD RawSize,
14  _Out_ DWORD *VirtualSize,
15  _Out_ DWORD *EntryPoint
16  )
33 {
35  DWORD i;
36  INTSTATUS status;
37  INTRO_PE_INFO peInfo = { 0 };
38 
39  if (NULL == RawPe)
40  {
42  }
43 
44  if (NULL == VirtualSize)
45  {
47  }
48 
49  if (NULL == EntryPoint)
50  {
52  }
53 
54  status = IntPeValidateHeader(0, RawPe, RawSize, &peInfo, 0);
55  if (!INT_SUCCESS(status))
56  {
57  ERROR("[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
58  return status;
59  }
60 
61  *VirtualSize = peInfo.SizeOfImage;
62  *EntryPoint = peInfo.EntryPoint;
63 
64  // By default, use the PE entry point, but if we have the ENTRYP section, use that entry point.
65  pSec = (IMAGE_SECTION_HEADER *)(RawPe + peInfo.SectionOffset);
66  for (i = 0; i < peInfo.NumberOfSections; i++, pSec++)
67  {
68  if (0 == memcmp(pSec->Name, "ENTRYP", sizeof("ENTRYP")))
69  {
70  TRACE("[INFO] Found 'ENTRYP' section at 0x%08x, will use it as an EP!\n", pSec->VirtualAddress);
71  *EntryPoint = pSec->VirtualAddress;
72  break;
73  }
74  }
75 
76  return INT_STATUS_SUCCESS;
77 }
78 
79 
80 static INTSTATUS
82  _In_ PBYTE RawImage,
83  _In_ DWORD RawImageSize,
84  _In_ PBYTE VirtualImage,
85  _In_ DWORD VirtualImageSize,
86  _In_ DWORD NumberOfSections,
88  )
112 {
113  DWORD i, minSection;
114 
115  if (NULL == RawImage)
116  {
118  }
119 
120  if (NULL == VirtualImage)
121  {
123  }
124 
125  if (NULL == Sections)
126  {
128  }
129 
130  // Initialize the virtual image with nulls.
131  memset(VirtualImage, 0, VirtualImageSize);
132 
133  // Copy the headers - we copy everything from the raw image, inside the virtual image, up until the first section.
134  minSection = 0xFFFFFFFF;
135 
136  // Note for the readers: the order in which the sections lie inside the file doesn't need to reflect the order in
138  for (i = 0; i < NumberOfSections; i++)
139  {
140  if (Sections[i].PointerToRawData < minSection &&
141  !(Sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
142  {
143  minSection = Sections[i].PointerToRawData;
144  }
145  }
146 
147  if (RawImageSize < minSection)
148  {
149  ERROR("[ERROR] The headers span outside the image: 0x%08x\n", minSection);
151  }
152 
153  if (VirtualImageSize < minSection)
154  {
155  ERROR("[ERROR] The first section starts beyond the end of the image!: 0x%08x\n", minSection);
157  }
158 
159  memcpy(VirtualImage, RawImage, minSection);
160 
161  // Copy the sections - one by one - from the raw address, to their virtual address
162  for (i = 0; i < NumberOfSections; i++)
163  {
164  // Make sure that the boundaries of this raw section are within the raw image
165  if ((RawImageSize < Sections[i].PointerToRawData + Sections[i].SizeOfRawData) ||
166  (RawImageSize < Sections[i].SizeOfRawData) ||
167  (RawImageSize <= Sections[i].PointerToRawData))
168  {
169  ERROR("[ERROR] Section %d at 0x%08x:0x%08x overflows the raw image!\n",
170  i, Sections[i].PointerToRawData, Sections[i].SizeOfRawData);
172  }
173 
174  // Make sure the virtual boundaries of the section lie within the virtual, loaded image
175  if ((VirtualImageSize < Sections[i].VirtualAddress + Sections[i].Misc.VirtualSize) ||
176  (VirtualImageSize < Sections[i].Misc.VirtualSize) ||
177  (VirtualImageSize <= Sections[i].VirtualAddress))
178  {
179  ERROR("[ERROR] Section %d at 0x%08x:0x%08x overflows the virtual image!\n",
180  i, Sections[i].VirtualAddress, Sections[i].Misc.VirtualSize);
182  }
183 
184  if (VirtualImage + Sections[i].VirtualAddress + Sections[i].SizeOfRawData > VirtualImage + VirtualImageSize)
185  {
186  ERROR("[ERROR] Section %d does not fit inside the virtual image [%p, %p): "
187  "va = 0x%08x raw data size = 0x%08x\n", i, VirtualImage, VirtualImage + VirtualImageSize,
188  Sections[i].VirtualAddress, Sections[i].SizeOfRawData);
190  }
191 
192  if (RawImage + Sections[i].PointerToRawData + Sections[i].SizeOfRawData > RawImage + RawImageSize)
193  {
194  ERROR("[ERROR] Section %d does not fit inside the raw image [%p, %p): "
195  "pointer to raw data = 0x%08x raw data size = 0x%08x\n", i, RawImage, RawImage + RawImageSize,
196  Sections[i].PointerToRawData, Sections[i].SizeOfRawData);
198  }
199 
200  // Copy the section to its new location
201  memcpy(VirtualImage + Sections[i].VirtualAddress,
202  RawImage + Sections[i].PointerToRawData,
203  Sections[i].SizeOfRawData);
204  }
205 
206  return INT_STATUS_SUCCESS;
207 }
208 
209 
210 static INTSTATUS
212  _In_ PBYTE VirtualImage,
213  _In_ DWORD VirtualImageSize,
214  _In_ QWORD Delta,
215  _In_ PIMAGE_DATA_DIRECTORY BaseRelocations
216  )
229 {
230  DWORD i;
231  IMAGE_BASE_RELOCATION reloc;
232  QWORD relocRva, relocSize;
233 
234  if (NULL == VirtualImage)
235  {
237  }
238 
239  if (NULL == BaseRelocations)
240  {
242  }
243 
244  i = 0;
245 
246  // Fetch the relocation directory.
247  relocRva = BaseRelocations->VirtualAddress;
248  relocSize = BaseRelocations->Size;
249 
250  // Make sure we have relocs before moving on.
251  if ((0 == relocRva ) || (0 == relocSize))
252  {
253  // If there are no relocations, we can safely leave. Nonexistent relocations doesn't mean that the driver is
254  // invalid or can't run.
255  return INT_STATUS_SUCCESS;
256  }
257 
258  // Make sure the relocs are valid before moving on.
259  if ((VirtualImageSize <= relocRva) || (VirtualImageSize < relocSize) || (VirtualImageSize < relocRva + relocSize))
260  {
261  // This is a problem... we have relocs, but they point out of the image...
263  }
264 
265  // By now, the VirtualImageBase contains the pre-loaded image: all the sections are in their correct, virtual,
266  // locations.
267  while (i + sizeof(IMAGE_BASE_RELOCATION) <= relocSize)
268  {
269  DWORD j;
270 
271  // Fetch the next relocation entry.
272  reloc = *(PIMAGE_BASE_RELOCATION)(VirtualImage + relocRva + i);
273 
274  // Make sure the virtual address is page aligned. If it is not, we're probably dealing with a bad PE.
275  if (0 != (reloc.VirtualAddress & 0xFFF))
276  {
277  // Bad RVA - not page aligned.
279  }
280 
281  // Make sure this relocation doesn't overflow the virtual image!
282  if ((VirtualImageSize < reloc.VirtualAddress) ||
283  (VirtualImageSize < reloc.VirtualAddress + 0x1000))
284  {
285  // This page lies outside the image; probably bad PE.
287  }
288 
289  // Make sure the relocation entries are all inside the image.
290  if (VirtualImageSize < relocRva + i + reloc.SizeOfBlock)
291  {
292  // The relocation entries overflow the image. Bad PE. Bad.
294  }
295 
296  // Make sure the relocation entries are inside the relocation directory.
297  if (relocSize < (QWORD)i + reloc.SizeOfBlock)
298  {
299  // The entry lies outside the relocation directory...
301  }
302 
303  if (reloc.SizeOfBlock < sizeof(IMAGE_BASE_RELOCATION))
304  {
305  WARNING("Invalid relocation for RVA 0x%016llxx: SizeOfBlock is: 0x%08x\n", relocRva, reloc.SizeOfBlock);
307  }
308 
309  TRACE("[LOADER] Applying relocations for RVA page 0x%08x\n", reloc.VirtualAddress);
310 
311  // pReloc->BlockSize - sizeof(IMAGE_BASE_RELOCATION) bytes follow, which contain the page offsets
312  // inside the VA page pReloc->VirtualAddress for which the relocation must be applied.
313  j = 0;
314  while (j < reloc.SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))
315  {
316  // Each entry inside the block is a word. The high 4 bit indicate the reloc type, the low 12 bit indicate
317  // the offset inside the pReloc->VirtualAddress page where the relocation should be applied.
318  WORD desc, type, offset;
319 
320  desc = *((WORD *)(VirtualImage + relocRva + i + sizeof(IMAGE_BASE_RELOCATION) + j));
321 
322  type = (desc >> 12) & 0xF;
323 
324  offset = desc & 0xFFF;
325 
326  TRACE("[LOADER] -> Relocationg offset 0x%08x of type %d...\n", offset, type);
327 
328  // Apply this relocation.
329  switch (type)
330  {
332  // Basic x86 relocation.
333  *((DWORD *)(VirtualImage + reloc.VirtualAddress + offset)) += (DWORD)Delta;
334  break;
336  // x64 relocation.
337  *((QWORD *)(VirtualImage + reloc.VirtualAddress + offset)) += Delta;
338  break;
340  // This relocation type is just for padding.
341  break;
342  default:
343  break;
344  }
345 
346  j += sizeof(WORD);
347  }
348 
349  // Skip to the next relocation entry.
350  i += reloc.SizeOfBlock;
351  }
352 
353  return INT_STATUS_SUCCESS;
354 }
355 
356 
357 static INTSTATUS
359  _In_ PBYTE VirtualImage,
360  _In_ DWORD VirtualImageSize,
361  _In_ BOOLEAN Is64,
362  _In_ PIMAGE_DATA_DIRECTORY ImportTable
363  )
383 {
384  INTSTATUS status;
385  PIMAGE_IMPORT_DESCRIPTOR pImpDesc;
386  QWORD importsRva, importsSize, i;
387 
388  if (NULL == VirtualImage)
389  {
391  }
392 
393  if (NULL == ImportTable)
394  {
396  }
397 
398  i = 0;
399 
400  // Parse the import descriptors.
401  importsRva = ImportTable->VirtualAddress;
402  importsSize = ImportTable->Size;
403 
404  // Validate the imports. If RVA or Size is zero, then we don't have any imports
405  if ((0 == importsRva) || (0 == importsSize))
406  {
407  return INT_STATUS_SUCCESS;
408  }
409 
410  // Make sure the import directory is inside the virtual image.
411  if ((VirtualImageSize < importsRva) || (VirtualImageSize < importsRva + importsSize))
412  {
414  }
415 
416  pImpDesc = (PIMAGE_IMPORT_DESCRIPTOR)(VirtualImage + importsRva);
417 
418  while ((i < importsSize / sizeof(IMAGE_IMPORT_DESCRIPTOR)) &&
419  ((pImpDesc->FirstThunk != 0 ) && (pImpDesc->u.Characteristics != 0)))
420  {
421  char *modName;
422  DWORD *names32;
423  QWORD *names64;
424  DWORD *iat32;
425  QWORD *iat64;
426  DWORD rva;
427  SIZE_T len, j;
428  QWORD modBase, namesBase, iatBase, count;
429  WCHAR *wModuleName;
430 
431  count = 0;
432  wModuleName = NULL;
433 
434  if (pImpDesc->Name >= VirtualImageSize)
435  {
436  ERROR("[ERROR] Import name outside the image: 0x%08x\n", pImpDesc->Name);
438  }
439 
440  // Get the current DLL name. That is actually a RVA that points to the actual name.
441  modName = (char *)(VirtualImage + pImpDesc->Name);
442 
443  len = strnlen(modName, VirtualImageSize - pImpDesc->Name);
444 
445  // Name too lung, or overflowing the image - bail out.
446  if (len >= 512 || len >= VirtualImageSize - pImpDesc->Name)
447  {
449  }
450 
451  // len + 2 OK: len is not longer than 512.
452  wModuleName = HpAllocWithTag((len + 1ull) * 2ull, IC_TAG_DRNU);
453  if (NULL == wModuleName)
454  {
456  }
457 
458  j = 0;
459 
460  while (j < len + 1)
461  {
462  wModuleName[j] = modName[j];
463 
464  j++;
465  }
466 
467  TRACE("[LOADER] Fixing imports for imported library %s...\n", modName);
468 
469  if (0 == strcmp(modName, "ntoskrnl.exe"))
470  {
472  if (NULL == pDriver)
473  {
474  ERROR("[ERROR] IntWinDriverFindByLoadOrder failed for %s\n", modName);
475  HpFreeAndNullWithTag(&wModuleName, IC_TAG_DRNU);
476  goto _continue;
477  }
478 
479  modBase = pDriver->BaseVa;
480  }
481  else if (0 == strcmp(modName, "hal.dll"))
482  {
484  if (NULL == pDriver)
485  {
486  ERROR("[ERROR] IntWinDriverFindByLoadOrder failed for %s\n", modName);
487  HpFreeAndNullWithTag(&wModuleName, IC_TAG_DRNU);
488  goto _continue;
489  }
490 
491  modBase = pDriver->BaseVa;
492  }
493  else
494  {
495  KERNEL_DRIVER *pDriver = IntDriverFindByName(wModuleName);
496  if (NULL == pDriver)
497  {
498  ERROR("[ERROR] IntWinDriverFindByName failed for %s\n", modName);
499  HpFreeAndNullWithTag(&wModuleName, IC_TAG_DRNU);
500  goto _continue;
501  }
502 
503  modBase = pDriver->BaseVa;
504  }
505 
506  HpFreeAndNullWithTag(&wModuleName, IC_TAG_DRNU);
507 
508  // Make sure this import is valid: each function must reside within the image.
509  if (pImpDesc->u.Characteristics >= VirtualImageSize)
510  {
512  }
513 
514  // Parse every imported function.
515  names32 = (DWORD *)(VirtualImage + pImpDesc->u.Characteristics);
516  names64 = (QWORD *)(VirtualImage + pImpDesc->u.Characteristics);
517  namesBase = pImpDesc->u.Characteristics;
518 
519  // We'll use only one, depending on the module architecture.
520  iat32 = (DWORD *)(VirtualImage + pImpDesc->FirstThunk);
521  iat64 = (QWORD *)(VirtualImage + pImpDesc->FirstThunk);
522  iatBase = pImpDesc->FirstThunk;
523 
524  // Now parse & map the exports of the imported module. We do this inline, rather than creating a different
525  // function, because of performance problems - if we'd map the exports separately for each imported function,
526  // we'd kill performance.
527 
528  if (!Is64)
529  {
530  // Parse each imported symbol...
531  while ((namesBase + count * 4 + 4 <= VirtualImageSize) && (iatBase + count * 4 + 4 <= VirtualImageSize) &&
532  (0 != *names32))
533  {
534  PIMAGE_IMPORT_BY_NAME pImpName;
535  DWORD impAddr;
536 
537  count++;
538 
539  // Make sure the current name is inside the image.
540  if ((VirtualImageSize < *names32) && (0 == (*names32 & 0x80000000)))
541  {
543  }
544 
545  // Check if this is an import by ordinal.
546  if (0 != (*names32 & 0x80000000))
547  {
548  // This is an import by ordinal. These are not supported.
549  impAddr = 0;
550  }
551  else
552  {
553  DWORD l;
554 
555  l = 0;
556 
557  // Import by name.
558  pImpName = (PIMAGE_IMPORT_BY_NAME)(VirtualImage + *names32);
559 
560  if (*names32 + sizeof(IMAGE_IMPORT_BY_NAME) > VirtualImageSize)
561  {
563  }
564 
565  // Make sure the entire name is within the image.
566  while ((*names32 + 2 + l < VirtualImageSize) && (pImpName->Name[l] != 0))
567  {
568  l++;
569  }
570 
571  if (*names32 + 2 + l >= VirtualImageSize)
572  {
574  }
575 
576  status = IntPeFindExportByName(modBase, NULL, (char *)pImpName->Name, &rva);
577  if (!INT_SUCCESS(status))
578  {
579  ERROR("[ERROR] IntPeFindExportByName failed: 0x%08x\n", status);
580  }
581 
582  impAddr = (DWORD)modBase + rva;
583  }
584 
585  *iat32 = impAddr;
586 
587  // Skip to the next entry, both in IDT and IAT.
588  names32++;
589 
590  iat32++;
591  }
592  }
593  else
594  {
595  // Parse each imported symbol...
596  while ((namesBase + count * 8 + 8 <= VirtualImageSize) && (iatBase + count * 8 + 8 <= VirtualImageSize) &&
597  (0 != *names64))
598  {
599  PIMAGE_IMPORT_BY_NAME pImpName;
600  QWORD impAddr;
601 
602  count++;
603 
604  // Make sure the current name is inside the image.
605  if ((VirtualImageSize < *names64) && (0 == (*names64 & 0x8000000000000000ULL)))
606  {
608  }
609 
610  // Check if this is an import by ordinal.
611  if (0 != (*names64 & 0x8000000000000000ULL))
612  {
613  // This is an import by ordinal. These are not supported.
614  impAddr = 0;
615  }
616  else
617  {
618  DWORD k;
619 
620  k = 0;
621 
622  // Import by name.
623  pImpName = (PIMAGE_IMPORT_BY_NAME)(VirtualImage + *names64);
624 
625  if (*names64 + sizeof(IMAGE_IMPORT_BY_NAME) > VirtualImageSize)
626  {
628  }
629 
630  while ((*names64 + 2 + k < VirtualImageSize) && (pImpName->Name[k] != 0))
631  {
632  k++;
633  }
634 
635  if (*names64 + 2 + k >= VirtualImageSize)
636  {
638  }
639 
640  status = IntPeFindExportByName(modBase, NULL, (char *)pImpName->Name, &rva);
641  if (!INT_SUCCESS(status))
642  {
643  ERROR("[ERROR] IntPeFindExportByName failed: 0x%08x\n", status);
644  }
645 
646  impAddr = modBase + rva;
647  }
648 
649  *iat64 = impAddr;
650 
651  // Skip to the next entry, both in IDT and IAT.
652  names64++;
653 
654  iat64++;
655  }
656  }
657 
658 _continue:
659  // Skip to the next entry.
660  pImpDesc++;
661 
662  i++;
663  }
664 
665  return INT_STATUS_SUCCESS;
666 }
667 
668 
669 INTSTATUS
671  _In_ PBYTE RawPe,
672  _In_ DWORD RawPeSize,
673  _In_ QWORD GuestVirtualAddress,
674  _Inout_ PBYTE LoadedPe,
675  _In_ DWORD VirtualPeSize,
676  _In_ DWORD Flags
677  )
699 {
700  INTSTATUS status;
701  PIMAGE_SECTION_HEADER pSections;
703  QWORD delta;
704  INTRO_PE_INFO peInfo = { 0 };
705 
706  if (NULL == RawPe)
707  {
709  }
710 
711  if (NULL == LoadedPe)
712  {
714  }
715 
716  status = IntPeValidateHeader(0, RawPe, RawPeSize, &peInfo, 0);
717  if (!INT_SUCCESS(status))
718  {
719  ERROR("[ERROR] IntPeValidateHeader failed: 0x%08x\n", status);
721  }
722 
723  TRACE("[LOADER] Preparing image for execution...\n");
724 
725  // Get the image type and invoke the PE parser, in order to load the PE in memory and prepare it for execution
726  if (peInfo.Machine == IMAGE_FILE_MACHINE_AMD64)
727  {
728  // x64 PE (PE64)
729 
730  // Make sure the image is native.
731  if (peInfo.Subsystem != IMAGE_SUBSYSTEM_NATIVE)
732  {
733  WARNING("[WARNING] The image is not native: %d\n", peInfo.Subsystem);
734  }
735 
736  pSections = (PIMAGE_SECTION_HEADER)(RawPe + peInfo.SectionOffset);
737 
738  // Preload the PE.
739  status = IntLdrPreLoadImage(RawPe, RawPeSize, LoadedPe, VirtualPeSize,
740  (DWORD)peInfo.NumberOfSections, pSections);
741  if (!INT_SUCCESS(status))
742  {
743  ERROR("[ERROR] IntLdrPreLoadImage failed: 0x%08x\n", status);
744  return status;
745  }
746 
747 
748  if (0 != (Flags & LDR_FLAG_FIX_RELOCATIONS))
749  {
750  // Apply relocations.
751  delta = GuestVirtualAddress - peInfo.ImageBase;
752 
753  status = IntPeGetDirectory(0, RawPe, IMAGE_DIRECTORY_ENTRY_BASERELOC, &dir);
754  if (!INT_SUCCESS(status) && status != INT_STATUS_NOT_FOUND)
755  {
756  ERROR("[ERROR] IntPeGetDirectory failed: 0x%08x\n", status);
757  }
758 
759  status = IntLdrFixRelocations(LoadedPe, VirtualPeSize, delta, &dir);
760  if (!INT_SUCCESS(status))
761  {
762  ERROR("[ERROR] IntLdrFixRelocations failed: 0x%08x\n", status);
763  }
764  }
765 
766 
767  if (0 != (Flags & LDR_FLAG_FIX_IMPORTS))
768  {
769  // Resolve imports.
770  status = IntPeGetDirectory(0, RawPe, IMAGE_DIRECTORY_ENTRY_IMPORT, &dir);
771  if (!INT_SUCCESS(status) && status != INT_STATUS_NOT_FOUND)
772  {
773  ERROR("[ERROR] IntPeGetDirectory failed: 0x%08x\n", status);
774  }
775 
776  status = IntLdrFixImports(LoadedPe, VirtualPeSize, TRUE, &dir);
777  if (!INT_SUCCESS(status))
778  {
779  ERROR("[ERROR] IntLdrFixImports failed: 0x%08x\n", status);
780  }
781  }
782  }
783  else if (peInfo.Machine == IMAGE_FILE_MACHINE_I386)
784  {
785  // i386 PE (32 bit PE)
786 
787  // Make sure the image is native.
788  if (peInfo.Subsystem != IMAGE_SUBSYSTEM_NATIVE)
789  {
790  WARNING("[WARNING] The image is not native: %d\n", peInfo.Subsystem);
791  }
792 
793  pSections = (PIMAGE_SECTION_HEADER)(RawPe + peInfo.SectionOffset);
794 
795  // Preload the PE.
796  status = IntLdrPreLoadImage(RawPe, RawPeSize, LoadedPe, VirtualPeSize,
797  (DWORD)peInfo.NumberOfSections, pSections);
798  if (!INT_SUCCESS(status))
799  {
800  ERROR("[ERROR] IntLdrPreLoadImage failed: 0x%08x\n", status);
801  return status;
802  }
803 
804 
805  if (0 != (Flags & LDR_FLAG_FIX_RELOCATIONS))
806  {
807  // Apply relocations.
808  delta = GuestVirtualAddress - peInfo.ImageBase;
809 
810  status = IntPeGetDirectory(0, RawPe, IMAGE_DIRECTORY_ENTRY_BASERELOC, &dir);
811  if (!INT_SUCCESS(status) && status != INT_STATUS_NOT_FOUND)
812  {
813  ERROR("[ERROR] IntPeGetDirectory failed: 0x%08x\n", status);
814  }
815 
816  status = IntLdrFixRelocations(LoadedPe, VirtualPeSize, delta, &dir);
817  if (!INT_SUCCESS(status))
818  {
819  ERROR("[ERROR] IntLdrFixRelocations failed: 0x%08x\n", status);
820  }
821  }
822 
823 
824  if (0 != (Flags & LDR_FLAG_FIX_IMPORTS))
825  {
826  // Resolve the imports.
827  status = IntPeGetDirectory(0, RawPe, IMAGE_DIRECTORY_ENTRY_IMPORT, &dir);
828  if (!INT_SUCCESS(status) && status != INT_STATUS_NOT_FOUND)
829  {
830  ERROR("[ERROR] IntPeGetDirectory failed: 0x%08x\n", status);
831  }
832 
833  status = IntLdrFixImports(LoadedPe, VirtualPeSize, FALSE, &dir);
834  if (!INT_SUCCESS(status))
835  {
836  ERROR("[ERROR] IntLdrFixImports failed: 0x%08x\n", status);
837  }
838  }
839  }
840  else
841  {
842  ERROR("[ERROR] Unsupported machine type: %d\n", peInfo.Machine);
843 
845  }
846 
847  TRACE("[LOADER] The image should be loaded & prepared for execution!\n");
848 
849  return INT_STATUS_SUCCESS;
850 }
KERNEL_DRIVER * IntDriverFindByLoadOrder(DWORD LoadOrder)
Searches a driver by its module load order.
Definition: drivers.c:235
#define IMAGE_DIRECTORY_ENTRY_BASERELOC
Definition: winpe.h:25
_Bool BOOLEAN
Definition: intro_types.h:58
#define _Out_
Definition: intro_sal.h:22
#define _In_
Definition: intro_sal.h:21
INTSTATUS IntPeGetDirectory(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD DirectoryEntry, IMAGE_DATA_DIRECTORY *Directory)
Validate & return the indicated image data directory.
Definition: winpe.c:552
#define LDR_FLAG_FIX_RELOCATIONS
If flag is set, the relocations will be applied.
Definition: loader.h:11
#define INT_STATUS_SUCCESS
Definition: introstatus.h:54
#define IMAGE_SUBSYSTEM_NATIVE
Definition: winpe.h:513
uint16_t WORD
Definition: intro_types.h:48
#define IMAGE_FILE_MACHINE_I386
Definition: winpe.h:480
static INTSTATUS IntLdrFixRelocations(PBYTE VirtualImage, DWORD VirtualImageSize, QWORD Delta, PIMAGE_DATA_DIRECTORY BaseRelocations)
This function will parse the relocations of the PE and apply them where needed.
Definition: loader.c:211
#define IMAGE_REL_BASED_HIGHLOW
Definition: winpe.h:313
INTSTATUS IntPeFindExportByName(QWORD ImageBase, BYTE *ImageBaseBuffer, CHAR *Name, DWORD *ExportRva)
Find the export name a Rva lies in.
Definition: winpe.c:1783
QWORD BaseVa
The guest virtual address of the kernel module that owns this driver object.
Definition: drivers.h:41
#define INT_SUCCESS(Status)
Definition: introstatus.h:42
QWORD SectionOffset
Offset of the first section header.
Definition: winpe.h:602
#define ERROR(fmt,...)
Definition: glue.h:62
#define HpAllocWithTag(Len, Tag)
Definition: glue.h:516
WORD Subsystem
Subsystem.
Definition: winpe.h:597
int INTSTATUS
The status data type.
Definition: introstatus.h:24
#define INT_STATUS_NOT_FOUND
Definition: introstatus.h:284
#define LDR_FLAG_FIX_IMPORTS
If flag is set, the imports will be fixed.
Definition: loader.h:12
struct _IMAGE_IMPORT_BY_NAME * PIMAGE_IMPORT_BY_NAME
Describes a kernel driver.
Definition: drivers.h:30
KERNEL_DRIVER * IntDriverFindByName(const void *Name)
Searches for a driver by its name.
Definition: drivers.c:266
static INTSTATUS IntLdrFixImports(PBYTE VirtualImage, DWORD VirtualImageSize, BOOLEAN Is64, PIMAGE_DATA_DIRECTORY ImportTable)
Fix the imports of the provided PE image.
Definition: loader.c:358
#define _Inout_
Definition: intro_sal.h:20
union _IMAGE_IMPORT_DESCRIPTOR::@223 u
INTSTATUS IntLdrGetImageSizeAndEntryPoint(PBYTE RawPe, DWORD RawSize, DWORD *VirtualSize, DWORD *EntryPoint)
Returns the entry point and the virtual size for the provided module.
Definition: loader.c:11
#define IMAGE_REL_BASED_ABSOLUTE
Definition: winpe.h:310
uint8_t * PBYTE
Definition: intro_types.h:47
unsigned long long QWORD
Definition: intro_types.h:53
WORD Machine
Machine type.
Definition: winpe.h:598
IMAGE_IMPORT_DESCRIPTOR * PIMAGE_IMPORT_DESCRIPTOR
Definition: winpe.h:248
#define TRUE
Definition: intro_types.h:30
#define INT_STATUS_INVALID_PARAMETER_4
Definition: introstatus.h:71
static INTSTATUS IntLdrPreLoadImage(PBYTE RawImage, DWORD RawImageSize, PBYTE VirtualImage, DWORD VirtualImageSize, DWORD NumberOfSections, PIMAGE_SECTION_HEADER Sections)
Pre-load the given raw PE image at the indicated virtual address.
Definition: loader.c:81
UINT32 VirtualAddress
Definition: winpe.h:85
QWORD NumberOfSections
Number of sections.
Definition: winpe.h:603
#define HpFreeAndNullWithTag(Add, Tag)
Definition: glue.h:517
#define TRACE(fmt,...)
Definition: glue.h:58
#define WARNING(fmt,...)
Definition: glue.h:60
#define IMAGE_FILE_MACHINE_AMD64
Definition: winpe.h:505
UINT32 VirtualAddress
Definition: winpe.h:290
#define IMAGE_REL_BASED_DIR64
Definition: winpe.h:323
uint16_t WCHAR
Definition: intro_types.h:63
uint32_t DWORD
Definition: intro_types.h:49
INTSTATUS IntLdrLoadPEImage(PBYTE RawPe, DWORD RawPeSize, QWORD GuestVirtualAddress, PBYTE LoadedPe, DWORD VirtualPeSize, DWORD Flags)
Load the provided PE image at the provided guest virtual address, and return it in LoadedPe...
Definition: loader.c:670
DWORD EntryPoint
Entry point (RVA).
Definition: winpe.h:601
INTSTATUS IntPeValidateHeader(QWORD ImageBase, BYTE *ImageBaseBuffer, DWORD ImageBaseBufferSize, INTRO_PE_INFO *PeInfo, QWORD Cr3)
Validates a PE header.
Definition: winpe.c:131
#define INT_STATUS_INVALID_PARAMETER_6
Definition: introstatus.h:77
#define INT_STATUS_INVALID_OBJECT_TYPE
Definition: introstatus.h:145
QWORD ImageBase
Image base.
Definition: winpe.h:605
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA
Definition: winpe.h:427
struct _IMAGE_SECTION_HEADER * PIMAGE_SECTION_HEADER
IMAGE_BASE_RELOCATION * PIMAGE_BASE_RELOCATION
Definition: winpe.h:294
#define INT_STATUS_INVALID_PARAMETER_1
Definition: introstatus.h:62
#define INT_STATUS_NOT_SUPPORTED
Definition: introstatus.h:287
UINT8 Name[IMAGE_SIZEOF_SHORT_NAME]
Definition: winpe.h:79
DWORD SizeOfImage
Size of the image.
Definition: winpe.h:599
#define IC_TAG_DRNU
Guest loaded module name buffer (Unicode)
Definition: memtags.h:11
#define IMAGE_DIRECTORY_ENTRY_IMPORT
Definition: winpe.h:21
size_t SIZE_T
Definition: intro_types.h:60
#define FALSE
Definition: intro_types.h:34
#define INT_STATUS_INSUFFICIENT_RESOURCES
Definition: introstatus.h:281
#define INT_STATUS_INVALID_PARAMETER_3
Definition: introstatus.h:68