Exemple #1
0
        ////////////////////////////////////////////////////// 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("");
        }
Exemple #3
0
        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);
        }