示例#1
0
 protected Address ReadSegmentedCodeAddress(int byteSize, EndianImageReader rdr, ProcessorState state)
 {
     if (byteSize == PrimitiveType.Word16.Size)
     {
         return(CreateSegmentedAddress(state.GetRegister(Registers.cs).ToUInt16(), rdr.ReadLeUInt16()));
     }
     else
     {
         ushort off = rdr.ReadLeUInt16();
         ushort seg = rdr.ReadLeUInt16();
         return(CreateSegmentedAddress(seg, off));
     }
 }
示例#2
0
        public override void ApplyRelocation(Address baseOfImage, uint page, EndianImageReader rdr, RelocationDictionary relocations)
        {
            ushort  fixup  = rdr.ReadLeUInt16();
            Address offset = baseOfImage + page + (fixup & 0x0FFFu);
            var     arch   = program.Architecture;
            var     imgR   = program.CreateImageReader(arch, offset);
            var     imgW   = program.CreateImageWriter(arch, offset);

            switch (fixup >> 12)
            {
            case RelocationAbsolute:
                // Used for padding to 4-byte boundary, ignore.
                break;

            case RelocationHighLow:
            {
                uint n = (uint)(imgR.ReadUInt32() + (baseOfImage - program.ImageMap.BaseAddress));
                imgW.WriteUInt32(n);
                relocations.AddPointerReference(offset.ToLinear(), n);
                break;
            }

            case 0xA:
                break;

            default:
                dcSvc.Warn(
                    dcSvc.CreateAddressNavigator(program, offset),
                    string.Format(
                        "Unsupported i386 PE fixup type: {0:X}",
                        fixup >> 12));
                break;
            }
        }
示例#3
0
        public override bool MatchJump(EndianImageReader rdr, uint opcode, out uint target)
        {
            target = 0;
            ushort sopcode = (ushort)opcode;
            var    offset  = rdr.Offset;

            if (((sopcode & 0xFF00) == 0xEF00) // GOTO n
                &&
                rdr.IsValidOffset(rdr.Offset + 2u))
            {
                ushort word2 = rdr.ReadLeUInt16();
                if ((word2 & 0xF000U) == 0xF000U)
                {
                    target = (uint)(sopcode.Extract(0, 8) | (word2.Extract(0, 12) << 8));
                    return(true);
                }
            }
            if ((sopcode & 0xF800) == 0xD000) // BRA n
            {
                var off = (int)sopcode.ExtractSignExtend(0, 11);
                target = (uint)((long)rdr.Address.ToLinear() + 2 + (off * 2));
                return(true);
            }
            if ((sopcode & 0xF800) == 0xE000) // Bcond n
            {
                var off = (sbyte)(sopcode.ExtractSignExtend(0, 8));
                target = (uint)((long)rdr.Address.ToLinear() + 2 + (off * 2));
                return(true);
            }
            rdr.Offset = offset;
            return(false);
        }
示例#4
0
        // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
        public override void ApplyRelocation(Address baseOfImage, uint page, EndianImageReader rdr, RelocationDictionary relocations)
        {
            ushort  fixup  = rdr.ReadLeUInt16();
            var     rt     = (Arm64Rt)(fixup >> 12);
            Address offset = baseOfImage + page + (fixup & 0x0FFFu);

            DebugEx.Verbose(PeImageLoader.trace, "  {0:X4} {1}", fixup, rt);
            var imgR = program.CreateImageReader(program.Architecture, offset);
            var imgW = program.CreateImageWriter(program.Architecture, offset);

            switch (rt)
            {
            case Arm64Rt.IMAGE_REL_ARM64_ABSOLUTE:
                break;

            case Arm64Rt.IMAGE_REL_ARM64_SECREL_HIGH12A:
                var uInstr = imgR.ReadLeUInt32();
                break;

            default:
                eventListener.Warn(
                    eventListener.CreateAddressNavigator(program, offset),
                    string.Format(
                        "Unsupported AArch64 PE fixup type: {0:X}",
                        fixup >> 12));
                break;
            }
        }
示例#5
0
 // Read a section of the file, considering endian issues
 void readFileSection(ushort[] p, int len, EndianImageReader rdr)
 {
     int pp = 0;
     for (int i = 0; i < len; i += 2)
     {
         p[pp++] = rdr.ReadLeUInt16();
     }
 }
示例#6
0
        public short ReadCoffHeader(EndianImageReader rdr)
        {
            this.machine = rdr.ReadLeUInt16();
            short expectedMagic = GetExpectedMagic(machine);

            arch        = CreateArchitecture(machine);
            platform    = CreatePlatform(machine, Services, arch);
            innerLoader = CreateInnerLoader(machine);

            sections = rdr.ReadLeInt16();
            rdr.ReadLeUInt32();                         // timestamp.
            rdr.ReadLeUInt32();                         // COFF symbol table.
            rdr.ReadLeUInt32();                         // #of symbols.
            optionalHeaderSize = rdr.ReadLeInt16();
            this.fileFlags     = rdr.ReadLeUInt16();
            rvaSectionTable    = (uint)((int)rdr.Offset + optionalHeaderSize);
            return(expectedMagic);
        }
示例#7
0
        // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format
        public override void ApplyRelocation(Address baseOfImage, uint page, EndianImageReader rdr, RelocationDictionary relocations)
        {
            ushort fixup = rdr.ReadLeUInt16();
            var    rt    = (ArmRt)(fixup >> 12);

            DebugEx.Verbose(PeImageLoader.trace, "  {0:X4} {1}", fixup, rt);
            switch (fixup)
            {
            }
        }
示例#8
0
        /// <summary>
        /// Apply relocations to a segment.
        /// </summary>
        private bool ApplyRelocations(EndianImageReader rdr, int cRelocations, NeSegment seg)
        {
            Address           address = null;
            NeRelocationEntry rep;

            Debug.Print("== Relocating segment {0}", seg.Address);
            for (int i = 0; i < cRelocations; i++)
            {
                rep = new NeRelocationEntry
                {
                    address_type    = (NE_RADDR)rdr.ReadByte(),
                    relocation_type = (NE_RELTYPE)rdr.ReadByte(),
                    offset          = rdr.ReadLeUInt16(),
                    target1         = rdr.ReadLeUInt16(),
                    target2         = rdr.ReadLeUInt16(),
                };
                Debug.Print("  {0}", WriteRelocationEntry(rep));

                // Get the target address corresponding to this entry.

                // If additive, there is no target chain list. Instead, add source
                //  and target.
                bool additive = (rep.relocation_type & NE_RELTYPE.ADDITIVE) != 0;
                Tuple <Address, ImportReference> impRef;
                uint   lp;
                string module = "";
                switch (rep.relocation_type & (NE_RELTYPE)3)
                {
                case NE_RELTYPE.ORDINAL:
                    module = moduleNames[rep.target1 - 1];
                    // Synthesize an import
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new OrdinalImportReference(address, module, rep.target2, SymbolType.ExternalProcedure)));
                        addrImportStubs += 8;
                    }
                    break;

                case NE_RELTYPE.NAME:
                    module = moduleNames[rep.target1 - 1];
                    uint offName      = lfaNew + this.offImportedNamesTable + rep.target2;
                    var  nameRdr      = new LeImageReader(RawImage, offName);
                    byte fnNameLength = nameRdr.ReadByte();
                    var  abFnName     = nameRdr.ReadBytes(fnNameLength);
                    // Synthesize the import.
                    lp = ((uint)rep.target1 << 16) | rep.target2;
                    if (importStubs.TryGetValue(lp, out impRef))
                    {
                        address = impRef.Item1;
                    }
                    else
                    {
                        address = addrImportStubs;
                        string fnName = Encoding.ASCII.GetString(abFnName);
                        importStubs.Add(lp, new Tuple <Address, ImportReference>(
                                            address,
                                            new NamedImportReference(address, module, fnName, SymbolType.ExternalProcedure)));
                        addrImportStubs += 8;
                    }
                    break;

                case NE_RELTYPE.INTERNAL:
                    if ((rep.target1 & 0xff) == 0xff)
                    {
                        address = this.entryPoints[rep.target2 - 1].Address;
                    }
                    else
                    {
                        address = segments[rep.target1 - 1].Address + rep.target2;
                    }
                    Debug.Print("    {0}: {1:X4}:{2:X4} {3}",
                                i + 1,
                                address.Selector.Value,
                                address.Offset,
                                "");
                    break;

                case NE_RELTYPE.OSFIXUP:
                    /* Relocation type 7:
                     *
                     *    These appear to be used as fixups for the Windows
                     * floating point emulator.  Let's just ignore them and
                     * try to use the hardware floating point.  Linux should
                     * successfully emulate the coprocessor if it doesn't
                     * exist.
                     */
                    /*
                     * TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
                     *   i + 1, rep->relocation_type, rep->offset,
                     *   rep->target1, rep->target2,
                     *   NE_GetRelocAddrName( rep->address_type, additive ) );
                     */
                    continue;
                }
                ushort offset = rep.offset;

                // Apparently, high bit of address_type is sometimes set;
                // we ignore it for now.
                if (rep.address_type > NE_RADDR.OFFSET32)
                {
                    listener.Error(
                        string.Format(
                            "Module {0}: unknown relocation address type {1:X2}. Please report",
                            module, rep.address_type));
                    return(false);
                }

                if (additive)
                {
                    var sp = seg.Address + offset;
                    Debug.Print("    {0} (contains: {1:X4})", sp, mem.ReadLeUInt16(sp));
                    byte   b;
                    ushort w;
                    switch (rep.address_type & (NE_RADDR)0x7f)
                    {
                    case NE_RADDR.LOWBYTE:
                        b = mem.ReadByte(sp);
                        mem.WriteByte(sp, (byte)(b + address.Offset));
                        break;

                    case NE_RADDR.OFFSET16:
                        w = mem.ReadLeUInt16(sp);
                        mem.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        break;

                    case NE_RADDR.POINTER32:
                        w = mem.ReadLeUInt16(sp);
                        mem.WriteLeUInt16(sp, (ushort)(w + address.Offset));
                        mem.WriteLeUInt16(sp + 2, address.Selector.Value);
                        break;

                    case NE_RADDR.SELECTOR:
                        // Borland creates additive records with offset zero. Strange, but OK.
                        w = mem.ReadLeUInt16(sp);
                        if (w != 0)
                        {
                            listener.Error(string.Format("Additive selector to {0:X4}. Please report.", w));
                        }
                        else
                        {
                            mem.WriteLeUInt16(sp, address.Selector.Value);
                        }
                        break;

                    default:
                        goto unknown;
                    }
                }
                else
                {
                    // Non-additive fixup.
                    do
                    {
                        var    sp          = seg.Address + offset;
                        ushort next_offset = mem.ReadLeUInt16(sp);
                        Debug.Print("    {0} (contains: {1:X4})", sp, next_offset);
                        switch (rep.address_type & (NE_RADDR)0x7f)
                        {
                        case NE_RADDR.LOWBYTE:
                            mem.WriteByte(sp, (byte)address.Offset);
                            break;

                        case NE_RADDR.OFFSET16:
                            mem.WriteLeUInt16(sp, (ushort)address.Offset);
                            break;

                        case NE_RADDR.POINTER32:
                            mem.WriteLeUInt16(sp, (ushort)address.Offset);
                            mem.WriteLeUInt16(sp + 2, address.Selector.Value);
                            break;

                        case NE_RADDR.SELECTOR:
                            mem.WriteLeUInt16(sp, address.Selector.Value);
                            break;

                        default:
                            goto unknown;
                        }
                        if (next_offset == offset)
                        {
                            break;                         // avoid infinite loop
                        }
                        if (next_offset >= seg.Alloc)
                        {
                            break;
                        }
                        offset = next_offset;
                    } while (offset != 0xffff);
                }
            }
            return(true);

unknown:
            listener.Warn("{0}: unknown ADDR TYPE {1},  " +
                          "TYPE {2},  OFFSET {3:X4},  TARGET {4:X4} {5:X4}",
                          seg.Address.Selector, rep.address_type, rep.relocation_type,
                          rep.offset, rep.target1, rep.target2);
            return(false);
        }
示例#9
0
        public void ReadOptionalHeader(EndianImageReader rdr, short expectedMagic)
        {
            if (optionalHeaderSize <= 0)
            {
                throw new BadImageFormatException("Optional header size should be larger than 0 in a PE executable image file.");
            }

            short magic = rdr.ReadLeInt16();

            if (magic != expectedMagic)
            {
                throw new BadImageFormatException("Not a valid PE Header.");
            }
            rdr.ReadByte();                     // Linker major version
            rdr.ReadByte();                     // Linker minor version
            rdr.ReadLeUInt32();                 // code size (== .text section size)
            rdr.ReadLeUInt32();                 // size of initialized data
            rdr.ReadLeUInt32();                 // size of uninitialized data
            rvaStartAddress = rdr.ReadLeUInt32();
            uint rvaBaseOfCode = rdr.ReadLeUInt32();

            preferredBaseOfImage = innerLoader.ReadPreferredImageBase(rdr);
            rdr.ReadLeUInt32();                         // section alignment
            rdr.ReadLeUInt32();                         // file alignment
            rdr.ReadLeUInt16();                         // OS major version
            rdr.ReadLeUInt16();                         // OS minor version
            rdr.ReadLeUInt16();                         // Image major version
            rdr.ReadLeUInt16();                         // Image minor version
            rdr.ReadLeUInt16();                         // Subsystem major version
            rdr.ReadLeUInt16();                         // Subsystem minor version
            rdr.ReadLeUInt32();                         // reserved
            uint   sizeOfImage   = rdr.ReadLeUInt32();
            uint   sizeOfHeaders = rdr.ReadLeUInt32();
            uint   checksum      = rdr.ReadLeUInt32();
            ushort subsystem     = rdr.ReadLeUInt16();
            ushort dllFlags      = rdr.ReadLeUInt16();
            var    stackReserve  = innerLoader.ReadWord(rdr);
            var    stackCommit   = innerLoader.ReadWord(rdr);
            var    heapReserve   = innerLoader.ReadWord(rdr);
            var    heapCommit    = innerLoader.ReadWord(rdr);

            rdr.ReadLeUInt32();                                 // loader flags
            uint dictionaryCount = rdr.ReadLeUInt32();

            if (dictionaryCount == 0)
            {
                return;
            }
            this.rvaExportTable  = rdr.ReadLeUInt32();
            this.sizeExportTable = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaImportTable = rdr.ReadLeUInt32();
            uint importTableSize = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaResources = rdr.ReadLeUInt32();             // resource address
            rdr.ReadLeUInt32();                                 // resource size

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaExceptionTable  = rdr.ReadLeUInt32();                       // exception address
            this.sizeExceptionTable = rdr.ReadLeUInt32();                       // exception size

            if (--dictionaryCount == 0)
            {
                return;
            }
            rdr.ReadLeUInt32();                                 // certificate address
            rdr.ReadLeUInt32();                                 // certificate size

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaBaseRelocationTable  = rdr.ReadLeUInt32();
            this.sizeBaseRelocationTable = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaDebug = rdr.ReadLeUInt32();
            uint cbDebug  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaArchitecture = rdr.ReadLeUInt32();
            uint cbArchitecture  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaGlobalPointer = rdr.ReadLeUInt32();
            uint cbGlobalPointer  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaTls = rdr.ReadLeUInt32();
            uint cbTls  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaLoadConfig = rdr.ReadLeUInt32();
            uint cbLoadConfig  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaBoundImport = rdr.ReadLeUInt32();
            uint cbBoundImport  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            uint rvaIat = rdr.ReadLeUInt32();
            uint cbIat  = rdr.ReadLeUInt32();

            if (--dictionaryCount == 0)
            {
                return;
            }
            this.rvaDelayImportDescriptor = rdr.ReadLeUInt32();
            uint cbDelayImportDescriptor = rdr.ReadLeUInt32();
        }
示例#10
0
        public override Address ReadCodeAddress(int size, EndianImageReader rdr, ProcessorState state)
        {
            ushort uAddr = rdr.ReadLeUInt16();

            return(Address.Ptr16(uAddr));
        }