예제 #1
0
        /// <summary>
        /// Initialize the common information about a Burn engine.
        /// </summary>
        /// <param name="reader">Binary reader open against a Burn engine.</param>
        /// <returns>True if initialized.</returns>
        protected bool Initialize(BinaryReader reader)
        {
            if (!GetWixburnSectionInfo(reader))
            {
                return(false);
            }

            reader.BaseStream.Seek(this.wixburnDataOffset, SeekOrigin.Begin);
            byte[] bytes  = reader.ReadBytes((int)BURN_SECTION_SIZE);
            UInt32 uint32 = 0;

            uint32 = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_MAGIC);
            if (BURN_SECTION_MAGIC != uint32)
            {
                Messaging.Instance.OnMessage(WixErrors.InvalidBundle(this.fileExe));
                return(false);
            }

            this.Version = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_VERSION);
            if (BURN_SECTION_VERSION != this.Version)
            {
                Messaging.Instance.OnMessage(WixErrors.BundleTooNew(this.fileExe, this.Version));
                return(false);
            }

            uint32 = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_FORMAT); // We only know how to deal with CABs right now
            if (1 != uint32)
            {
                Messaging.Instance.OnMessage(WixErrors.InvalidBundle(this.fileExe));
                return(false);
            }

            this.StubSize                = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_STUBSIZE);
            this.OriginalChecksum        = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALCHECKSUM);
            this.OriginalSignatureOffset = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALSIGNATUREOFFSET);
            this.OriginalSignatureSize   = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ORIGINALSIGNATURESIZE);

            this.ContainerCount = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_COUNT);
            this.UXAddress      = this.StubSize;
            this.UXSize         = BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_UXSIZE);

            // If there is an original signature use that to determine the engine size.
            if (0 < this.OriginalSignatureOffset)
            {
                this.EngineSize = this.OriginalSignatureOffset + this.OriginalSignatureSize;
            }
            else if (0 < this.SignatureOffset && 2 > this.ContainerCount) // if there is a signature and no attached containers, use the current signature.
            {
                this.EngineSize = this.SignatureOffset + this.SignatureSize;
            }
            else // just use the stub and UX container as the size of the engine.
            {
                this.EngineSize = this.StubSize + this.UXSize;
            }

            this.AttachedContainerAddress = this.ContainerCount > 1 ? this.EngineSize : 0;
            this.AttachedContainerSize    = this.ContainerCount > 1 ? BurnCommon.ReadUInt32(bytes, BURN_SECTION_OFFSET_ATTACHEDCONTAINERSIZE) : 0;

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Checks for a valid DOS header in the current exe.
        /// </summary>
        /// <returns>true if the exe starts with a DOS stub; false otherwise</returns>
        private bool EnsureDosHeader(BinaryReader reader)
        {
            if (UInt32.MaxValue == this.peOffset)
            {
                byte[] bytes = reader.ReadBytes((int)IMAGE_DOS_HEADER_SIZE);

                // Verify the DOS 'MZ' signature.
                if (IMAGE_DOS_SIGNATURE != BurnCommon.ReadUInt16(bytes, IMAGE_DOS_HEADER_OFFSET_MAGIC))
                {
                    Messaging.Instance.OnMessage(WixErrors.InvalidStubExe(this.fileExe));
                    return(false);
                }

                this.peOffset = BurnCommon.ReadUInt32(bytes, IMAGE_DOS_HEADER_OFFSET_NTHEADER);
            }

            return(true);
        }
예제 #3
0
        /// <summary>
        /// Finds the ".wixburn" section in the current exe.
        /// </summary>
        /// <returns>true if the ".wixburn" section is successfully found; false otherwise</returns>
        private bool GetWixburnSectionInfo(BinaryReader reader)
        {
            if (UInt32.MaxValue == this.wixburnDataOffset)
            {
                if (!EnsureNTHeader(reader))
                {
                    return(false);
                }

                UInt32 wixburnSectionOffset = UInt32.MaxValue;
                byte[] bytes = new byte[IMAGE_SECTION_HEADER_SIZE];

                reader.BaseStream.Seek(this.firstSectionOffset, SeekOrigin.Begin);
                for (UInt16 sectionIndex = 0; sectionIndex < this.sections; ++sectionIndex)
                {
                    reader.Read(bytes, 0, bytes.Length);

                    if (IMAGE_SECTION_WIXBURN_NAME == BurnCommon.ReadUInt64(bytes, IMAGE_SECTION_HEADER_OFFSET_NAME))
                    {
                        wixburnSectionOffset = this.firstSectionOffset + (IMAGE_SECTION_HEADER_SIZE * sectionIndex);
                        break;
                    }
                }

                if (UInt32.MaxValue == wixburnSectionOffset)
                {
                    Messaging.Instance.OnMessage(WixErrors.StubMissingWixburnSection(this.fileExe));
                    return(false);
                }

                // we need 56 bytes for the manifest header, which is always going to fit in
                // the smallest alignment (512 bytes), but just to be paranoid...
                if (BURN_SECTION_SIZE > BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_SIZEOFRAWDATA))
                {
                    Messaging.Instance.OnMessage(WixErrors.StubWixburnSectionTooSmall(this.fileExe));
                    return(false);
                }

                this.wixburnDataOffset = BurnCommon.ReadUInt32(bytes, IMAGE_SECTION_HEADER_OFFSET_POINTERTORAWDATA);
            }

            return(true);
        }
예제 #4
0
        /// <summary>
        /// Checks for a valid Windows PE signature (IMAGE_NT_SIGNATURE) in the current exe.
        /// </summary>
        /// <returns>true if the exe is a Windows executable; false otherwise</returns>
        private bool EnsureNTHeader(BinaryReader reader)
        {
            if (UInt32.MaxValue == this.firstSectionOffset)
            {
                if (!EnsureDosHeader(reader))
                {
                    return(false);
                }

                reader.BaseStream.Seek(this.peOffset, SeekOrigin.Begin);
                byte[] bytes = reader.ReadBytes((int)IMAGE_NT_HEADER_SIZE);

                // Verify the NT signature...
                if (IMAGE_NT_SIGNATURE != BurnCommon.ReadUInt32(bytes, IMAGE_NT_HEADER_OFFSET_SIGNATURE))
                {
                    Messaging.Instance.OnMessage(WixErrors.InvalidStubExe(this.fileExe));
                    return(false);
                }

                ushort sizeOptionalHeader = BurnCommon.ReadUInt16(bytes, IMAGE_NT_HEADER_OFFSET_SIZEOFOPTIONALHEADER);

                this.sections           = BurnCommon.ReadUInt16(bytes, IMAGE_NT_HEADER_OFFSET_NUMBEROFSECTIONS);
                this.firstSectionOffset = this.peOffset + IMAGE_NT_HEADER_SIZE + sizeOptionalHeader;

                this.checksumOffset = this.peOffset + IMAGE_NT_HEADER_SIZE + IMAGE_OPTIONAL_OFFSET_CHECKSUM;
                this.certificateTableSignatureOffset = this.peOffset + IMAGE_NT_HEADER_SIZE + sizeOptionalHeader - IMAGE_OPTIONAL_NEGATIVE_OFFSET_CERTIFICATETABLE;
                this.certificateTableSignatureSize   = this.certificateTableSignatureOffset + 4; // size is in the DWORD after the offset.

                bytes                = reader.ReadBytes(sizeOptionalHeader);
                this.Checksum        = BurnCommon.ReadUInt32(bytes, IMAGE_OPTIONAL_OFFSET_CHECKSUM);
                this.SignatureOffset = BurnCommon.ReadUInt32(bytes, sizeOptionalHeader - IMAGE_OPTIONAL_NEGATIVE_OFFSET_CERTIFICATETABLE);
                this.SignatureSize   = BurnCommon.ReadUInt32(bytes, sizeOptionalHeader - IMAGE_OPTIONAL_NEGATIVE_OFFSET_CERTIFICATETABLE + 4);
            }

            return(true);
        }
예제 #5
0
 /// <summary>
 /// Reads a UInt64 value in little-endian format from an offset in an array of bytes.
 /// </summary>
 /// <param name="bytes">Array from which to read.</param>
 /// <param name="offset">Beginning offset from which to read.</param>
 /// <returns>value at offset</returns>
 private static UInt64 ReadUInt64(byte[] bytes, UInt32 offset)
 {
     Debug.Assert(offset + 8 <= bytes.Length);
     return(BurnCommon.ReadUInt32(bytes, offset) + ((UInt64)(BurnCommon.ReadUInt32(bytes, offset + 4)) << 32));
 }