예제 #1
0
        /// <summary>
        /// Parses the given buffer for the header of a PEFile. If it can be parsed correctly,
        /// a new PEHeader object is constructed from the buffer and returned. Otherwise, null
        /// is returned.
        /// </summary>
        internal static PEHeader FromBuffer(PEBuffer buffer, bool virt)
        {
            byte *            ptr    = buffer.Fetch(0, 0x300);
            IMAGE_DOS_HEADER *tmpDos = (IMAGE_DOS_HEADER *)ptr;
            int needed = tmpDos->e_lfanew + sizeof(IMAGE_NT_HEADERS);

            if (buffer.Length < needed)
            {
                ptr = buffer.Fetch(0, needed);

                if (buffer.Length < needed)
                {
                    return(null);
                }

                tmpDos = (IMAGE_DOS_HEADER *)ptr;
            }

            IMAGE_NT_HEADERS *tmpNt = (IMAGE_NT_HEADERS *)((byte *)tmpDos + tmpDos->e_lfanew);

            needed += tmpNt->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_SECTION_HEADER) * tmpNt->FileHeader.NumberOfSections;

            if (buffer.Length < needed)
            {
                ptr = buffer.Fetch(0, needed);
                if (buffer.Length < needed)
                {
                    return(null);
                }
            }

            return(new PEHeader(buffer, virt));
        }
예제 #2
0
        /// <summary>
        /// For side by side dlls, the manifest that decribes the binding information is stored as the RT_MANIFEST resource, and it
        /// is an XML string.   This routine returns this.
        /// </summary>
        /// <returns></returns>
        public string GetSxSManfest()
        {
            ResourceNode resources = GetResources();
            ResourceNode manifest  = ResourceNode.GetChild(ResourceNode.GetChild(resources, "RT_MANIFEST"), "1");

            if (manifest == null)
            {
                return(null);
            }

            if (!manifest.IsLeaf && manifest.Children.Count == 1)
            {
                manifest = manifest.Children[0];
            }

            PEBuffer buff  = AllocBuff();
            byte *   bytes = manifest.FetchData(0, manifest.DataLength, buff);
            string   ret   = null;

            using (UnmanagedMemoryStream stream = new UnmanagedMemoryStream(bytes, manifest.DataLength))
                using (StreamReader textReader = new StreamReader(stream))
                    ret = textReader.ReadToEnd();
            FreeBuff(buff);
            return(ret);
        }
예제 #3
0
        public FileVersionInfo GetFileVersionInfo()
        {
            PEBuffer        buff  = _file.AllocBuff();
            byte *          bytes = FetchData(0, DataLength, buff);
            FileVersionInfo ret   = new FileVersionInfo(bytes, DataLength);

            _file.FreeBuff(buff);
            return(ret);
        }
예제 #4
0
        /// <summary>
        /// Parses a PEFile from a given stream. If it is valid, a new PEFile object is
        /// constructed and returned. Otherwise, null is returned.
        /// </summary>
        public static PEFile TryLoad(Stream stream, bool virt)
        {
            PEBuffer headerBuff = new PEBuffer(stream);
            PEHeader hdr = PEHeader.FromBuffer(headerBuff, virt);

            if (hdr == null)
                return null;

            PEFile pefile = new PEFile();
            pefile.Init(stream, "stream", virt, headerBuff, hdr);
            return pefile;
        }
예제 #5
0
        internal PEBuffer AllocBuff()
        {
            PEBuffer ret = _freeBuff;

            if (ret == null)
            {
                return(new PEBuffer(_stream));
            }

            _freeBuff = null;
            return(ret);
        }
예제 #6
0
        /// <summary>
        /// Looks up the debug signature information in the EXE.   Returns true and sets the parameters if it is found.
        /// If 'first' is true then the first entry is returned, otherwise (by default) the last entry is used
        /// (this is what debuggers do today).   Thus NGEN images put the IL PDB last (which means debuggers
        /// pick up that one), but we can set it to 'first' if we want the NGEN PDB.
        /// </summary>
        public bool GetPdbSignature(out string pdbName, out Guid pdbGuid, out int pdbAge, bool first = false)
        {
            pdbName = null;
            pdbGuid = Guid.Empty;
            pdbAge  = 0;
            bool ret = false;

            if (Header == null)
            {
                return(false);
            }

            if (Header.DebugDirectory.VirtualAddress != 0)
            {
                PEBuffer buff = AllocBuff();
                IMAGE_DEBUG_DIRECTORY *debugEntries = (IMAGE_DEBUG_DIRECTORY *)FetchRVA((int)Header.DebugDirectory.VirtualAddress, (int)Header.DebugDirectory.Size, buff);
                if (Header.DebugDirectory.Size % sizeof(IMAGE_DEBUG_DIRECTORY) != 0)
                {
                    return(false);
                }

                int debugCount = (int)Header.DebugDirectory.Size / sizeof(IMAGE_DEBUG_DIRECTORY);
                for (int i = 0; i < debugCount; i++)
                {
                    if (debugEntries[i].Type == IMAGE_DEBUG_TYPE.CODEVIEW)
                    {
                        PEBuffer       stringBuff = AllocBuff();
                        int            ptr        = _virt ? debugEntries[i].AddressOfRawData : debugEntries[i].PointerToRawData;
                        CV_INFO_PDB70 *info       = (CV_INFO_PDB70 *)stringBuff.Fetch(ptr, debugEntries[i].SizeOfData);
                        if (info->CvSignature == CV_INFO_PDB70.PDB70CvSignature)
                        {
                            // If there are several this picks the last one.
                            pdbGuid = info->Signature;
                            pdbAge  = info->Age;
                            pdbName = info->PdbFileName;
                            ret     = true;
                            if (first)
                            {
                                break;
                            }
                        }

                        FreeBuff(stringBuff);
                    }
                }

                FreeBuff(buff);
            }

            return(ret);
        }
예제 #7
0
        private void Init(Stream stream, string filePath, bool virt)
        {
            m_virt = virt;
            m_stream = stream;
            m_headerBuff = new PEBuffer(m_stream);

            Header = new PEHeader(m_headerBuff.Fetch(0, 512), virt);
            // We did not read in the complete header, Try again using the right sized buffer.  
            if (Header.PEHeaderSize > m_headerBuff.Length)
                Header = new PEHeader(m_headerBuff.Fetch(0, Header.PEHeaderSize), virt);

            if (Header.PEHeaderSize > m_headerBuff.Length)
                throw new InvalidOperationException("Bad PE Header in " + filePath);
        }
예제 #8
0
        private void Init(Stream stream, string filePath, bool virt, PEBuffer buffer = null, PEHeader header = null)
        {
            if (buffer == null)
                buffer = new PEBuffer(stream);

            if (header == null)
                header = PEHeader.FromBuffer(buffer, virt);

            _virt = virt;
            _stream = stream;
            _headerBuff = buffer;
            Header = header;
            if (header != null && header.PEHeaderSize > _headerBuff.Length)
                throw new InvalidOperationException("Bad PE Header in " + filePath);
        }
예제 #9
0
        private PEHeader(PEBuffer buffer, bool virt)
        {
            _virt = virt;

            byte *ptr = buffer.Fetch(0, 0x300);

            _dosHeader = (IMAGE_DOS_HEADER *)ptr;
            _ntHeader  = (IMAGE_NT_HEADERS *)(ptr + _dosHeader->e_lfanew);
            _sections  = (IMAGE_SECTION_HEADER *)((byte *)_ntHeader + sizeof(IMAGE_NT_HEADERS) + _ntHeader->FileHeader.SizeOfOptionalHeader);

            if (buffer.Length < PEHeaderSize)
            {
                throw new BadImageFormatException();
            }
        }
예제 #10
0
        /// <summary>
        /// Parses a PEFile from a given stream. If it is valid, a new PEFile object is
        /// constructed and returned. Otherwise, null is returned.
        /// </summary>
        public static PEFile TryLoad(Stream stream, bool virt)
        {
            PEBuffer headerBuff = new PEBuffer(stream);
            PEHeader hdr        = PEHeader.FromBuffer(headerBuff, virt);

            if (hdr == null)
            {
                return(null);
            }

            PEFile pefile = new PEFile();

            pefile.Init(stream, "stream", virt, headerBuff, hdr);
            return(pefile);
        }
예제 #11
0
        internal ResourceNode(string name, int nodeFileOffset, PEFile file, bool isLeaf, bool isTop = false)
        {
            _file           = file;
            _nodeFileOffset = nodeFileOffset;
            _isTop          = isTop;
            IsLeaf          = isLeaf;
            Name            = name;

            if (isLeaf)
            {
                PEBuffer buff = _file.AllocBuff();
                IMAGE_RESOURCE_DATA_ENTRY *dataDescr = (IMAGE_RESOURCE_DATA_ENTRY *)buff.Fetch(nodeFileOffset, sizeof(IMAGE_RESOURCE_DATA_ENTRY));

                DataLength      = dataDescr->Size;
                _dataFileOffset = file.Header.RvaToFileOffset(dataDescr->RvaToData);
                byte *data = FetchData(0, DataLength, buff);
                _file.FreeBuff(buff);
            }
        }
예제 #12
0
        private void Init(Stream stream, string filePath, bool virt, PEBuffer buffer = null, PEHeader header = null)
        {
            if (buffer == null)
            {
                buffer = new PEBuffer(stream);
            }

            if (header == null)
            {
                header = PEHeader.FromBuffer(buffer, virt);
            }

            _virt       = virt;
            _stream     = stream;
            _headerBuff = buffer;
            Header      = header;
            if (header != null && header.PEHeaderSize > _headerBuff.Length)
            {
                throw new InvalidOperationException("Bad PE Header in " + filePath);
            }
        }
예제 #13
0
        /// <summary>
        /// Gets the File Version Information that is stored as a resource in the PE file.  (This is what the
        /// version tab a file's property page is populated with).
        /// </summary>
        public FileVersionInfo GetFileVersionInfo()
        {
            ResourceNode resources   = GetResources();
            ResourceNode versionNode = ResourceNode.GetChild(ResourceNode.GetChild(resources, "Version"), "1");

            if (versionNode == null)
            {
                return(null);
            }

            if (!versionNode.IsLeaf && versionNode.Children.Count == 1)
            {
                versionNode = versionNode.Children[0];
            }

            PEBuffer        buff  = AllocBuff();
            byte *          bytes = versionNode.FetchData(0, versionNode.DataLength, buff);
            FileVersionInfo ret   = new FileVersionInfo(bytes, versionNode.DataLength);

            FreeBuff(buff);
            return(ret);
        }
예제 #14
0
 internal PEBuffer AllocBuff()
 {
     var ret = _freeBuff;
     if (ret == null)
         return new PEBuffer(_stream);
     _freeBuff = null;
     return ret;
 }
예제 #15
0
 internal void FreeBuff(PEBuffer buffer)
 {
     _freeBuff = buffer;
 }
예제 #16
0
 internal unsafe string GetName(PEBuffer buff, int resourceStartFileOffset)
 {
     if (IsStringName)
     {
         int nameLen = *((ushort*)buff.Fetch(NameOffset + resourceStartFileOffset, 2));
         char* namePtr = (char*)buff.Fetch(NameOffset + resourceStartFileOffset + 2, nameLen);
         return new string(namePtr);
     }
     else
         return Id.ToString();
 }
예제 #17
0
 internal IntPtr SafeFetchRVA(int rva, int size, PEBuffer buffer)
 {
     return(new IntPtr(FetchRVA(rva, size, buffer)));
 }
예제 #18
0
        internal byte *FetchRVA(int rva, int size, PEBuffer buffer)
        {
            int offset = Header.RvaToFileOffset(rva);

            return(buffer.Fetch(offset, size));
        }
예제 #19
0
 internal byte* FetchRVA(int rva, int size, PEBuffer buffer)
 {
     int offset = Header.RvaToFileOffset(rva);
     return buffer.Fetch(offset, size);
 }
예제 #20
0
 internal void FreeBuff(PEBuffer buffer)
 {
     _freeBuff = buffer;
 }
예제 #21
0
        /// <summary>
        /// Parses the given buffer for the header of a PEFile. If it can be parsed correctly,
        /// a new PEHeader object is constructed from the buffer and returned. Otherwise, null
        /// is returned.
        /// </summary>
        internal static PEHeader FromBuffer(PEBuffer buffer, bool virt)
        {
            byte* ptr = buffer.Fetch(0, 0x300);
            var tmpDos = (IMAGE_DOS_HEADER*)ptr;
            int needed = tmpDos->e_lfanew + sizeof(IMAGE_NT_HEADERS);
            if (buffer.Length < needed)
            {
                ptr = buffer.Fetch(0, needed);

                if (buffer.Length < needed)
                    return null;

                tmpDos = (IMAGE_DOS_HEADER*)ptr;
            }

            IMAGE_NT_HEADERS* tmpNt = (IMAGE_NT_HEADERS*)((byte*)tmpDos + tmpDos->e_lfanew);
            needed += tmpNt->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_SECTION_HEADER) * tmpNt->FileHeader.NumberOfSections;

            if (buffer.Length < needed)
            {
                ptr = buffer.Fetch(0, needed);
                if (buffer.Length < needed)
                    return null;
            }

            return new PEHeader(buffer, virt);
        }
예제 #22
0
 internal IntPtr SafeFetchRVA(int rva, int size, PEBuffer buffer)
 {
     return new IntPtr(FetchRVA(rva, size, buffer));
 }
예제 #23
0
 public byte* FetchData(int offsetInResourceData, int size, PEBuffer buff)
 {
     return buff.Fetch(_dataFileOffset + offsetInResourceData, size);
 }
예제 #24
0
 public byte *FetchData(int offsetInResourceData, int size, PEBuffer buff)
 {
     return(buff.Fetch(_dataFileOffset + offsetInResourceData, size));
 }
예제 #25
0
        private PEHeader(PEBuffer buffer, bool virt)
        {
            _virt = virt;

            byte* ptr = buffer.Fetch(0, 0x300);
            _dosHeader = (IMAGE_DOS_HEADER*)ptr;
            _ntHeader = (IMAGE_NT_HEADERS*)((byte*)ptr + _dosHeader->e_lfanew);
            _sections = (IMAGE_SECTION_HEADER*)(((byte*)_ntHeader) + sizeof(IMAGE_NT_HEADERS) + _ntHeader->FileHeader.SizeOfOptionalHeader);

            if (buffer.Length < PEHeaderSize)
                throw new BadImageFormatException();
        }