////////////////////////////////////////////////////// Static Methods. // public static unsafe void Initialize() { Platform p = Platform.ThePlatform; IoMemory pages = IoMemory.MapPhysicalMemory((UIntPtr)p.KernelDllFirstPage, 4096, true, false); kernel = new PEImage(pages); pages = IoMemory.MapPhysicalMemory((UIntPtr)p.KernelDllBase, kernel.loadedSize, true, false); kernelExports = kernel.GetExportTable(pages); DebugStub.WriteLine("PEImage.Initialize: Notify KD of kernel load."); DebugStub.LoadedBinary(pages.VirtualAddress, kernel.sizeOfImage, #if ISA_ARM "kernel.arm", #elif ISA_IX64 "kernel.x64", #elif ISA_IX86 "kernel.x86", #endif kernel.checkSum, kernel.timeDateStamp, false); // This breakpoint is triggered by a "-d" to windbg. if (DebugStub.PollForBreak()) { DebugStub.Break(); } #if GENERATE_ABI_SHIM DebugStub.WriteLine(" InitializeMpAbi() *****"); InitializeMpAbi(); #endif }
public void ResolveImports(ExportTable exports) { if (entry.size == 0) { Tracing.Log(Tracing.Debug, "// No imports to resolve."); return; } int importOffset = (int)entry.virtualAddress; //Tracing.Log(Tracing.Debug, " import offset={0:x8}", importOffset); // // start at the importOffset specified above creating and filling out ImportDescriptors // There is no indication in the header as to how many descriptors are present. // In the last descriptor all fields will be 0; this code checks just the firstChunk field. // for (;;) { ImportDescriptor importDescriptor = new ImportDescriptor(mem, ref importOffset); if (importDescriptor.firstChunk == 0) { return; } ushort hint = 0; String name = null; if (importDescriptor.name != 0) { name = mem.ReadAsciiZeroString((int)importDescriptor.name); } #if verbose Tracing.Log(Tracing.Debug, "// {0}", name); importDescriptor.DumpToStream("// "); Tracing.Log(Tracing.Debug, "//"); #endif UIntPtr offsetHintTable = UIntPtr.Zero; if (0 == importDescriptor.characteristics) { offsetHintTable = (UIntPtr)importDescriptor.characteristics; } else { offsetHintTable = (UIntPtr)importDescriptor.firstChunk; } UIntPtr offsetIAT = (UIntPtr)importDescriptor.firstChunk; #if PTR_SIZE_64 // // AIFIX: Add hint logic. // for (;;) { ulong ImportEntry = (ulong)mem.Read64((int)offsetIAT); if (ImportEntry == 0) { break; } if ((ImportEntry >> 63) != 0) { throw new BadImageFormatException("Import Ordinal encountered"); } name = mem.ReadAsciiZeroString(((int)(ImportEntry & 0x7FFFFFFF)) + 2); UIntPtr Address; Address = exports.Resolve(hint, name); if (Address == 0) { throw new BadImageFormatException("Import not found"); } mem.Write64((int)offsetIAT, (ulong)Address); offsetIAT += 8; } #else for (;;) { // read elements in the hint array for processing // the hint array terminates when the its content is 0 int importByNameEntry = (int)mem.Read32((int)offsetHintTable); if (importByNameEntry == 0) { break; } #if verbose Tracing.Log(Tracing.Debug, "importByName entry is {0:x8}", importByNameEntry); #endif int nameStringOffset = importByNameEntry & 0x7fffffff; if ((importByNameEntry & 0x8000000) != 0) { // should never happen in Singularity (no Ordinals) throw new BadImageFormatException("Import Ordinal encountered"); } else { name = mem.ReadAsciiZeroString((int)nameStringOffset + 2); hint = mem.Read16Unchecked(nameStringOffset); //Tracing.Log(Tracing.Debug, " function to lookup is {0}", name); UIntPtr addr = exports.Resolve(hint, name); if (0 != addr) { //Overwrite ptr in IAT with address of function in the // IAT thunk table #if verbose int meth = name.IndexOf('@'); int rest = name.IndexOf('@', meth + 1) + 1; int clas = name.LastIndexOf('_', rest, rest - meth) + 1; Tracing.Log(Tracing.Debug, " import: {1:x8} is {2:x8} {0}", name.Substring(0, meth) + "@" + name.Substring(clas, rest - clas) + "@" name.Substring(rest) (uint) offsetIAT, (uint)addr); #endif mem.Write32((int)offsetIAT, (uint)addr); } else { Tracing.Log(Tracing.Debug, " Import not found: {0}", name); throw new BadImageFormatException("Import not found"); } } // increment "array indices" offsetIAT += 4; offsetHintTable += 4; } //Tracing.Log(Tracing.Debug, ""); #endif } //throw new BadImageFormatException(""); }
public static PEImage Load(Process process, IoMemory rawMemory, out IoMemory loadedMemory, bool isForMp, bool inKernelSpace) { UIntPtr entryPoint = UIntPtr.Zero; loadedMemory = null; DiagnosisService.DeferedUpdateNotification(); if (null == rawMemory || 0 == rawMemory.Length) { DebugStub.WriteLine("No PXE image to load!"); return(null); } // // Allocate memory and copy the PXE image from memory to memory // #if verbose Tracing.Log(Tracing.Debug, " PXE at {0:x8}, Length ={1:x8}", (uint)rawMemory.VirtualAddress, rawMemory.Length); #endif Kernel.Waypoint(580); Tracing.Log(Tracing.Debug, "Loading:"); PEImage image = new PEImage(rawMemory); image.DumpLimitedToStream(); #if verbose Tracing.Log(Tracing.Debug, " Loaded Size={0:x8}", image.loadedSize); #endif Kernel.Waypoint(581); if (0 == image.loadedSize) { throw new BadImageFormatException("Invalid PE, no content"); } try { if (inKernelSpace) { loadedMemory = IoMemory.AllocateFixed( (UIntPtr)image.loadedSize, process, PageType.System); } else { // Situate the process image in the user range loadedMemory = IoMemory.AllocateUserFixed( (UIntPtr)image.loadedSize, process, PageType.System); } Kernel.Waypoint(582); #if verbose Tracing.Log(Tracing.Debug, " loaded at {0:x8}, Length ={1:x8}", (uint)loadedMemory.VirtualAddress, loadedMemory.Length); #endif // Copy the header so the debugger can find it. IoMemory.Copy(rawMemory, 0, loadedMemory, 0, (int)image.sizeOfHeaders); #if verbose image.DumpLimitedToStream(); #endif Kernel.Waypoint(583); // load sections into memory where they belong. for (int i = 0; i < image.numberOfSections; i++) { if (image.sections[i].IsDiscardable || image.sections[i].sizeOfRawData == 0) { continue; } int targetOffset = (int)image.sections[i].virtualAddress; int sourceOffset = (int)image.sections[i].pointerToRawData; uint rawSize = Math.Min(image.sections[i].sizeOfRawData, image.sections[i].virtualSize); #if verbose Tracing.Log(Tracing.Debug, "section[{0}] source={1:x8}..{2:x8} target={3:x8}..{4:x8}", i, sourceOffset, sourceOffset + rawSize, targetOffset, targetOffset + rawSize); #endif if (image.sections[i].virtualSize > image.sections[i].sizeOfRawData) { // The memory allocated for the new image is not zeroed, therefore // we need to clear the remaining region of a section that is not getting // copied from the source. NOTE BSS sections rely on this to be zeroed // This is fixing some random bugs with uninitialized variables in unmanaged code unsafe { byte *dest = (byte *)loadedMemory.VirtualAddress + targetOffset + image.sections[i].sizeOfRawData; uint length = image.sections[i].virtualSize - image.sections[i].sizeOfRawData; Buffer.ZeroMemory(dest, length); } } IoMemory.Copy(rawMemory, sourceOffset, loadedMemory, targetOffset, (int)rawSize); } Kernel.Waypoint(584); // // Handle Relocations // int relocationTableOffset = (int)image.GetRelocationsRaw(); UIntPtr diff = (UIntPtr)loadedMemory.VirtualAddress - (UIntPtr)image.imageBase; image.VirtualAddress = loadedMemory.VirtualAddress; #if verbose Tracing.Log(Tracing.Debug, " Base loaded={0:x8}, relocated ={1:x8} diff={2:x8}", image.imageBase, (uint)loadedMemory.VirtualAddress, diff); Tracing.Log(Tracing.Debug, " relocationTableOffset ={0:x8} ", relocationTableOffset); #endif if (relocationTableOffset > 0) { Relocations.FixupBlocks(rawMemory, (int)relocationTableOffset, loadedMemory, diff); // TODO: We should probably zero the relocation table. } Kernel.Waypoint(585); // // Resolve Imports // ImportTable it = image.GetImportTable(loadedMemory); Kernel.Waypoint(586); #if !PAGING #if GENERATE_ABI_SHIM if (it != null) { #endif //it.DumpIAT("Import directory"); // if this is loading for remote processor // then solve the imports with abi stub if (isForMp) { it.ResolveImports(mpAbiExports); } else { it.ResolveImports(kernelExports); } //DumpIAT(loadedMemory, "Import Address Table", // ref image.directory[12]); #if GENERATE_ABI_SHIM } #endif #else if (it != null) { // Ring-3 protection domains come with a set of // stubs that accomplish the ring3-to-ring0 ABI // transitions. Use these when called for. ExportTable abiStubs = process.Domain.ABIStubs; if (abiStubs != null) { it.ResolveImports(abiStubs); } else { it.ResolveImports(kernelExports); } } #endif Kernel.Waypoint(587); // // Dump Exports // ExportTable et = image.GetExportTable(loadedMemory); if (et != null) { et.Dump(); } Kernel.Waypoint(588); entryPoint = (UIntPtr)loadedMemory.VirtualAddress + image.addressOfEntryPoint; Tracing.Log(Tracing.Debug, " Loaded: {0:x8}..{1:x8}, Entry: {2:x8}", (ulong)loadedMemory.VirtualAddress, (ulong)(loadedMemory.VirtualAddress + loadedMemory.Length), (ulong)(entryPoint)); } finally { if (entryPoint == UIntPtr.Zero && loadedMemory != null) { // TODO: Need to dispose of target Range. loadedMemory = null; } } return(image); }